⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 delphi-jni-1.html

📁 JNI(java本地接口)之delphi版
💻 HTML
📖 第 1 页 / 共 3 页
字号:
implemented in <tt>HelloWorldImpl.dll</tt>. This displays the text <i><tt>Hello World!</tt></i> on the screen. This "routing" of method calls from a 
Java object to a native-code DLL is all transparent to the calling class, <tt>Main</tt>.
</ol>
Graphically, the process looks like this:
<p>
<IMG SRC="gifs/Process_small.gif" WIDTH=882 HEIGHT=220>
<p>
View a large image <a href="gifs/Process_large.gif" WIDTH=1149 HEIGHT=286>here</a>.
<p>
These are the explanations of the circled numbers in the graphic:
<ol>
<li>Java loads <tt>Main.class</tt> and calls the <b><tt>public static</tt></b> method <b><tt>main</tt></b>.
<li>Java creates a new <tt>HelloWorld</tt> object.
<li>When the <tt>HelloWorld</tt> object is created, it implicitly calls <tt>System.loadLibrary("HelloWorldImpl");</tt> (because it is in the
<b><tt>static</tt></b> section of the class) which loads the DLL into memory.
<li>The DLL is loaded into memory by the operating system.
<li>Any initialization routines within the DLL are called. (Our example has no initialization.)
<li>Java executes the statement: <tt>hw.displayHelloWorld();</tt>
<li><tt>HelloWorld.displayHelloWorld()</tt> is a <b><tt>native</tt></b> method so its implementation is in the Delphi DLL
(<tt>Java_HelloWorld_displayHelloWorld</tt>.)
<li>The Delphi code executes the <tt>WriteLn('Hello World!');</tt> statement which displays the text <i><tt>Hello World!</tt></i> on the screen.
</ol>
</BLOCKQUOTE>

<blockquote>

Whew. That sure seemed like a lot of work. Actually, the explanation of what is going on is far more verbose than the actual code. If you
look at the Java files, you'll see that each file has about 4 lines of Java code. The Delphi DLL source file contains about 10 or so
(depending how you want to format the code.) There's really only 1 line of executable code in the DLL; the line that prints 
'Hello World!' to the screen. It's important to realize that (in the graphic above) steps 1 - 5 are executed only once, regardless 
of how many times <tt>hw.displayHelloWorld()</tt> (or any other native method of the <tt>HelloWorld</tt> class) is called. This is 
similar to how DLLs work with regular executables (.exe) programs: the DLL is loaded and any overhead associated with the loading and 
initialization of the DLL is done once at load time.
<p>
Also, this is just a very high-level view of what's going on. There are some pretty interesting things going on 
under the covers. But, that's beauty of it: you don't need to know or worry about those details.
<p>
<a href="#Top">Back to top</a>
</BLOCKQUOTE>




<div class="SectionHeader">
<A NAME="Troubleshooting">Troubleshooting</A>
</div>
<BLOCKQUOTE>
For the most part, programming with the JNI is a pretty straight-forward process. However, there are a lot of details involved. As is true with
most programming, one missing piece can cause the whole program to fail. In this section, I will show you most of the mistakes that you are
likely to make. (I've made them all at one time or another!) Understanding the error messages and exceptions will help you to locate the
problems within your code. I was able to cause all of these errors by modifying the example above. Hence, some of the error messages will refer to the
files in the <i>HelloWorld</i> example. If you are trying this example on your own
I highly encourage you to cause these errors to occur. You will see first-hand what I'm talking about and learn from these common errors.
By far, the most popular is the <i>java.lang.UnsatisfiedLinkError</i>:
<p>
<b>java.lang.UnsatisfiedLinkError</b>
<p>
There are basically two categories of <tt>UnsatisfiedLinkError</tt> errors.
<ol>
<li>The first type of <i>java.lang.UnsatisfiedLinkError</i> looks something like:
<blockquote>
<pre>Exception in thread "main" java.lang.UnsatisfiedLinkError: no HelloWorldImpl
in java.library.path
</pre>
</blockquote>
This message says that Java can't locate the <tt>HelloWorldImpl</tt> DLL. Here are some common causes:
<p>
<ul>
<li><b>The DLL is named incorrectly.</b> Make sure that the name of the DLL you are loading in the <b><tt>static</tt></b> section matches
the name of the DLL on the disk. Be sure that you are <i>not</i> including the <tt>.dll</tt> extension in the call to
<tt>System.loadLibrary</tt>:
<pre>
  <b>static</b>
  {
    System.loadLibrary("HelloWorldImpl");         // correct
    System.loadLibrary("HelloWorldImpl.dll");     // WRONG!
  }
</pre>
<li><b>The DLL is not in the search path.</b> In Windows (DOS) by default, the directory you are in (at a command prompt) is included in the search path. 
If you want Java to be able to find the DLL from another directory, make sure that you add that directory to the system path or move the DLL into a 
directory that is already in the system path.
</ul>
<p>
<li>Another <i>java.lang.UnsatisfiedLinkError</i> error might look like this:
<blockquote>
<pre>Exception in thread "main" java.lang.UnsatisfiedLinkError: displayHelloWorld 
at Main.main(Main.java:6)
</pre>
</blockquote>

This message indicates that the <tt>HelloWorldImpl</tt> DLL was located and loaded by the system. However, it says it can't find the indicated method
(<tt>displayHelloWorld</tt> in the example.) There are several reasons that this might happen:
<p>
<ul>
<li><b>The name of the method is incorrect</b>. Make sure that the name in the DLL matches the name in the Java class <i>exactly</i>.
You may have made one or more of these errors:
<p>
<ul>
<li>You spelled the method name differently. (It happens!)
<li>The case is incorrect. Remember, Java is case-sensitive and Delphi is not, so you may have inadvertently used the wrong case.
<li>You decorated the method name incorrectly. It <i>must</i> start with <tt>Java_</tt> then the class name <tt>HelloWorld</tt>, then
and underscore _, then the name of the method <tt>displayHelloWorld</tt>. (For classes other than our <tt>HelloWorld</tt> example, you
would substitute that class name in place of <tt>HelloWorld</tt>.)
</ul>
<p>
<li><b>The method is not exported.</b> The method must be added to the <b><tt>exports</tt></b> section of the project file. (It is common to forget this
when you first start writing DLLs.)

</ul>
</ul>

<p>
<b>Run-time exceptions</b>
<p>
There are many ways that a native DLL can cause an exception. However, the errors I show are unique to JNI programming and not programming in general.
For example, dividing by zero can cause an exception, but that isn't related to JNI programming. 
<p>
It's also important to realize that the compiler
can't help you here by detecting potential conflicts. This is because the Delphi compiler has no knowledge of the Java code and the Java compiler has
no knowledge of the Delphi code. Sure, we've mapped the types and decorated the function names, but there is no way for the compiler to check that
for us. A tool like <tt>javah</tt> would help minimize the problems, but it still wouldn't be fool-proof.
<p>
Since these are Windows DLLs, exceptions are likely to cause a dialog box to be displayed (as opposed to the Java exceptions listed above 
that printed error messages to the screen.) Rather than describing these "cryptic" error messages, I'll just insert screen shots so you
can see for yourself. (<i>Note that the hex numbers and addresses may be different on your machine</i>.)
<p>
Most of the exceptions generate similar error messages so it is usually difficult (if not impossible) to tell what caused
the error simply by looking at the dialog box. However, I'll point out some subtle clues that can help you locate the problems.
<p>
<ul>
<li><b>Missing <tt>stdcall</tt> directive.</b> 
The most common mistake made by Delphi programmers is forgetting to add the <b><tt>stdcall</tt></b> directive at the end of the procedure/function.
(I'm guessing about the other Delphi programmers because, frankly, I haven't talked with any other Delphites about their JNI experiences. I'm just
<i>assuming</i> that they would make this mistake because I made it often!)
<p>
A subtle difference in this exception as opposed to other exceptions is that the method call fails immediately. What I mean to say is that the call
itself causes the exception. None of the code is executed within the native method. This can be helpful because some exceptions (as we'll see shortly)
occur when the method returns, so all of the code within the method is executed. When I remove the <b><tt>stdcall</tt></b> directive in our example, 
the text <i>Hello World!</i> never gets displayed. This is an indication that the <i>calling convention</i> is incorrect.
<p>
This is the message I get when I remove the <b><tt>stdcall</tt></b> directive:
<p>
<IMG SRC="gifs/GPF1.gif" WIDTH=446 HEIGHT=152>
<p>
<li><b>Incorrect <tt>procedure/function</tt> signature</b>. 
This happens when the number, type, and order of parameters in the Java class don't match the number, type, and order of the parameters in the Delphi
code. In our example, the <tt>displayHelloWorld</tt> method was declared as taking 0 parameters. In the Delphi code, we made sure that the procedure
expected 0 parameters. (This is not counting the two <i>hidden</i> arguments I discussed that all JNI methods include.) If we add a parameter to the
Delphi procedure (an extra integer parameter) we can force this error to happen:
<pre class="sourcecode"><code><b>procedure</b> Java_HelloWorld_displayHelloWorld(PEnv: PJNIEnv; Obj: JObject; Extra: JInt); <b>stdcall</b>;
</code></pre>
This is the error message I receive:
<p>
<IMG SRC="gifs/GPF2.gif" WIDTH=446 HEIGHT=152>
<p>
The subtle difference between this exception and the previous one (where I removed the <b><tt>stdcall</tt></b> directive) is that this time the text
<i>Hello World!</i> is displayed on the screen <i>before</i> the error message is displayed. It's subtle differences like this that can help you locate
where the problems are. 
</ul>
<p>
<a href="#Top">Back to top</a>
</BLOCKQUOTE>





<div class="SectionHeader">
<A NAME="Debugging">Debugging the DLL</A>
</div>
<BLOCKQUOTE>
It is not difficult to debug your DLLs. Most modern Integrated Development Environments allow you to specify the <i>host</i>
application: the executable program that loads the DLL at run-time. For JNI debugging, the host application is <tt>java.exe</tt>. To specify the 
name and location of the application to use to debug the DLL, choose <b>Parameters...</b> from the <b>Run</b> menu: 
<p>
<IMG SRC="gifs/RunMenu.gif" WIDTH=220 HEIGHT=367>
<p>
This displays the <i>Run Parameters</i> dialog box:
<p>
<IMG SRC="gifs/RunParams.gif" WIDTH=447 HEIGHT=278>
<p>
In the <i>Host Application</i> edit box, enter the full path to <tt>java.exe</tt>. (Your path will probably be different.)<br>
In the <i>Parameters</i> edit box, enter <tt>Main</tt> for our example.
<p>
At this point, you can set a break point on the <tt>WriteLn('Hello World!')</tt> statement in the Delphi <tt>Java_HelloWorld_displayHelloWorld</tt> procedure.
Now, press <tt>F9</tt> to run the program within the debugger. The debugger should stop on the <tt>WriteLn('Hello World!')</tt> statement.
<p>
<i>Note that you will not be able to step through the Java code. The Delphi debugger has no knowledge of the Java code. 
Maybe the next release of JBuilder from Inprise/Borland will support this.</i>
<p>
<a href="#Top">Back to top</a>
</BLOCKQUOTE>





<div class="SectionHeader">
<A NAME="Summary">Summary</A>
</div>
<BLOCKQUOTE>
In this document, I showed you how easy it is to access code from a DLL that was created with Delphi. However, 95% of what I discussed applies equally
well to C/C++ or any other <i>native</i> language. This introduction to <i>Using the Java Native Interface with Delphi</i> is more of a tutorial than
a reference. If you remove all of the detailed explanations above, you will see that the amount of code necessary to call a DLL from Java is
quite trivial. Newcomers to Delphi, DLLs, and/or JNI may find this detail necessary and enlightening. More advanced developers may already understand these points.
<p>
Before proceeding onto <a href="delphi-jni-2.html">Part Two</a>, I strongly encourage you to try this example on your own. The main reason is to 
prove to yourself that your machine is properly configured to compile and execute Java code. If you are currently able to do so, then it is likely that this
example will work just fine. It's a lot easier to troubleshoot problems when the example is trivial. 
<p>
<a href="zips/helloworld.zip">Download</a> the files used in this tutorial.
<br>
<a href="delphi-jni-2.html">Using the Java Native Interface with Delphi (Part Two)</a>
<br>
<a href="delphi-jni-3.html">Using the Java Native Interface with Delphi (Part Three)</a>
<p>
<p>
<a href="#Top">Back to top</a>
</BLOCKQUOTE>





<div class="SectionHeader">
<A NAME="Resources">Helpful Resources</A>
</div>
<BLOCKQUOTE>
JNI Specifications
<ul>
<li><A HREF="http://java.sun.com/products/jdk/1.2/docs/guide/jni/index.html">
JNI - Java Native Interface.</A> This link points to the JNI specification set forth by Sun.
Consider this the <i>JNI Bible</i> This link includes the specifications for both JDK 1.1 and JDK 1.2 as
well as a <a href="http://java.sun.com/products/jdk/faq/jni-j2sdk-faq.html">JNI FAQ</a>. 
This is the place to start on Sun's page.
</ul>
Books:
<ul>
<li><a href="http://www.phptr.com/ptrbooks/ptr_0136798950.html"><i>Essential JNI: Java Native Interface (Essential Java)</a></i> 
by Rob Gordon, Robert Gordon, Alan McClellan (Prentice Hall Computer Books, April 1998. ISBN 0136798950)
<li><a href="http://www.amazon.com/exec/obidos/ASIN/0201325772/qid=967608927/sr=1-2/103-8853813-7903806">
<i>The Java Native Interface: Programmer's Guide and Specification</a></i> 
by Sheng Liang (Addison-Wesley Publishing Company, June 1999. ISBN 0201325772)
<li><a href="http://www.oreilly.com/catalog/delphi/"><i>Delphi in a Nutshell</i></a>
 by Ray Lischner (O'Reilly and Associates, March 2000. ISBN 1-56592-659-5)
<li><a href="http://www.amazon.com/exec/obidos/ASIN/0672317818/qid=967610156/sr=1-2/103-8853813-7903806">
<i>Delphi 4 Developer's Guide</i></a> by Xavier Pacheco, Steve Teixeira (Sams Publishing, August 1998. ISBN 0672312840)
</ul>
Delphi on the Web:
<ul>
<li><a href="http://www.delphi-jedi.org">Project JEDI</a> From their mission statement: "An international community of Delphi developers with a mission to
exploit our pooled efforts, experiences and resources to make Delphi--the greatest Windows development tool--even greater."
<li><a href="http://community.borland.com/article/0,1410,10281,00.html">Pascal Header Translations</a> by Charlie Calvert. This is 
geared towards achieving "JEDI status." There is a lot of information regarding translating C/C++ header files
to Delphi.
<li><a href="http://www.drbob42.com/delphi/headconv.htm">Dr. Bob's Header Conversion</a> I stumbled across this while
creating these references. Looks cool!
<li><a href="http://www.marcocantu.com/epascal/default.htm">Marco Cantu's Essential Pascal</a>
This is from his <i>Mastering Delphi</i> series and is an excellent document on Delphi's Pascal-based language.
</ul>
My other JNI work:
<ul>
<li><A HREF="http://www.cs.pdx.edu/~antoy/Courses/Advanced/units/jni/index.html">
Programming with the Java Native Interface</a> This is a tutorial that shows how to use C++ with
the Java Native Interface on Linux, Solaris, and Windows NT. 
<li><A HREF="http://www.pacifier.com/~mmead/jni/cs510jip/index.html">
Using the Java Native Interface with C++.</A> This document has a wealth 
of examples and techniques for using the JNI with C++. There is a detailed comparison
between Microsoft's implementation and Sun's implementation, including the
differences in syntax and runtime performance. In addition to the basics, 
there are examples that demonstrate two-dimensional arrays, 
callbacks, and exceptions, among other concepts.
</ul>
<p>
<a href="#Top">Back to top</a>
</BLOCKQUOTE>

<hr>
<center>Copyright &copy 2001 <a href="mailto:jni@matthewmead.com">Matthew Mead</a> All Rights Reserved.</center>
<a href="http://www.delphi-jedi.org"><img src="gifs/btn_jedinow.gif" width="116" height="31"></a>
<br><br>
<p>

</BODY>
</HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -