📄 delphi-jni-2.html
字号:
<HTML>
<HEAD>
<meta name="keywords" content="Delphi, JNI, Java Native Interface, jni.pas, jni_md.pas, Borland, Inprise, Java">
<xxxlink rel="stylesheet" type="text/css" href="jni.css">
<style>
<!--
.Note1
{
margin-left: 0;
xfont-style: Italic;
background-color: rgb(255,255,240);
border-style: outset;
border-color: teal;
border-width: thin;
font-weight: normal;
vertical-align: top;
padding-top: 5px;
padding-bottom: 5px;
padding-left: 5px;
padding-right: 5px;
}
.SectionHeader
{
margin-left: 0;
font-size : 14pt;
font-weight : bold;
background-color: rgb(255,255,204);
border-style: solid;
border-color: black;
border-width: thin;
xvertical-align: top;
padding-top: 5px;
padding-bottom : 5px;
padding-left: 20px;
padding-right: 20px;
}
-->
</style>
<TITLE>Using the Java Native Interface with Delphi (Part Two - Techniques and Examples)</TITLE>
</HEAD>
<BODY BGCOLOR="#e0e0e0">
<a name="Top">
<H2><center>
Using the Java Native Interface with Delphi<br>
<font size=+1>(Part Two - Techniques and Examples)</font>
</center></H2>
<center><a href="mailto:jni@matthewmead.com">Matthew Mead</a></center>
<p>
<a href="http://www.pacifier.com/~mmead/jni/delphi/index.html">Home Page (on the Web) - News and Updates</a>
<p>
<a href="delphi-jni-1.html">Part One - Introduction and Tutorial</a>
<br>
Part Two - Techniques and Examples
<br>
<a href="delphi-jni-3.html">Part Three - The Invocation API</a>
<p>
<a href="http://www.delphi-jedi.org"><img src="gifs/btn_jedinow.gif" width="116" height="31"></a>
<br>
<h3><A NAME="Contents">Contents</A></h3>
<blockquote>
<table border=0 cellspacing=0 cellpadding=4>
<tr valign=top><td align=right colspan=1><A HREF="#Overview">Overview</A></td><td>What's here?</td></tr>
<tr valign=top><td align=right colspan=1><A HREF="#Signatures">Signatures</A></td><td>How to describe a function's parameters and
return type</td></tr>
<tr valign=top><td align=right colspan=1><A HREF="#Concepts">Concepts</A></td><td>These are examples of what you will
learn here. The test in brackets (e.g. [Test 4]), indicates the test number that demonstrates this in the included
code. Examples that don't include a test number are still present in the code, however, they were not part of
the original C++ implementation so they don't have a test case assigned.</td></tr>
</table>
<blockquote>
<ol>
<li><A HREF="#Concept1">Simple Function Call</A> - Call a Delphi procedure that doesn't take any arguments. [Test 1]
<li><A HREF="#Concept2">Passing/Returning Simple Types</A> - Demonstrates passing 2 integer values to
a function that multiplies them together and then returns the result. [Test A]
<li><A HREF="#Concept3">Passing an Array of Primitive Types to Delphi</A> - Demonstrates passing a Java Array (of type byte) to
the Delphi DLL. The DLL initializes each element of the Java Array. This example also shows how to overload a native method.
<li><A HREF="#Concept4">Passing an Array of Objects to Delphi</A> - Demonstrates passing a Java Array of objects to the Delphi DLL. This
example also shows how to access each object in the array and print it out using the object's <tt><b>toString</b></tt> method. (This
method is present in almost all Java objects.) In order to invoke the <tt><b>toString</b></tt> method, the Delphi DLL will need to
call back into Java. [Tests 5, 6]
<li><A HREF="#Concept5">Passing a 2-Dimensional Array to Delphi</A> - Demonstrates passing a 2-dimensional array
to Delphi. The method shown here can be applied to 3-dimensional arrays as well. [Test 10]
<li><A HREF="#Concept6">Calling a Method of a Java Object from Delphi</A> - Demonstrates invoking a method on a Java object
that was passed into the DLL. (See Concept #4, <a href="#Concept4">Passing an Array of Objects to Delphi</a> for the example.)
<li><A HREF="#Concept7">Creating Java Objects within Delphi</a> - Demonstrates creating Java objects in Delphi and
passing them back to Java. [Test 7]
<li><A HREF="#Concept8">Accessing Fields of a Java Object from Delphi</A> - Demonstrates accessing fields (members) of a
Java object that was passed into the DLL. [Test 4]
<li><A HREF="#Concept9">Handling Java Exceptions within Delphi</A> - Demonstrates how to detect and suppress Java
exceptions within Delphi. [Test 8]
<li><A HREF="#Concept10">Causing a Java Exception within Delphi</A> - Demonstrates how to cause (throw) a Java exception. [Test 9]
</ul>
</blockquote>
<table border=0 cellspacing=0 cellpadding=4>
<tr valign=top><td align=right colspan=1><A HREF="#TJNIEnv">TJNIEnv</A></td><td> A closer look at the
TJNIEnv wrapper class.</td></tr>
<tr valign=top><td align=right colspan=1><A HREF="#Summary">Summary</A></td><td> What's next?</td></tr>
</table>
</blockquote>
<div class="SectionHeader">
<A NAME="Overview">Overview</A>
</div>
<BLOCKQUOTE>
In <a href="delphi-jni-1.html">Part One</a>, I gave an introduction to <i>Using the Java Native Interface with Delphi</i>. I showed
(in painful detail) an example of printing <i>"Hello World!"</i> from a Delphi DLL called from Java. In Part Two, I will
show more sophisticated techniques using the Java Native Interface with Delphi. You will learn concepts such as how to access
fields of Java objects and how to call methods of a Java class. You will also see how to create Java
objects within a Delphi DLL and pass them back and forth between Java and Delphi. Essentially, these are some of the
concepts discussed in this document:
<ul>
<li>Calling Delphi code from Java.
<li>Passing parameters to Delphi code from Java. This includes Java Strings, arrays, and other Java objects, as well as basic types (e.g. int, long, etc.)
<li>Returning values from Delphi code to Java. This includes Java Strings, arrays, and other Java objects, as well as basic types (e.g. int, long, etc.)
<li>Calling Java methods from Delphi code (callbacks). This should include both static and non-static methods.
<li>Accessing fields of Java classes and objects from Delphi code. This should include both static and non-static fields.
<li>Detecting and handling Java exceptions from within Delphi code.
</ul>
<p>
This part of <i>Using the Java Native Interface with Delphi</i> is based on some JNI research I did using C++ a couple of
years or so ago. This work can be found <a href="http://www.pacifier.com/~mmead/jni/cs510jip/index.html">here</a>.
For this document, I essentially translated the C++ DLL to a Delphi DLL. (The lines of C++ code translated to Delphi code almost one-for-one.)
In this version of that work, I won't be explaining a lot of the fundamentals of using the JNI. You can refer to
<a href="delphi-jni-1.html">Part One</a> of <i>Using the Java Native Interface with Delphi</i> for explanations of those
concepts. This document focuses on putting those fundamentals to use.
<p>
This part takes more of a <i>Learn By Example</i> approach to the JNI. Because of this, I don't
spend a lot of time explaining in detail each of the many JNI functions that are used. I leave that up to
<a href="http://java.sun.com/products/jdk/1.2/docs/guide/jni/spec/functions.doc.html">Sun's JNI Documentation</a>. This
document is meant to provide a convenient place to find out how to do common tasks when using the Java Native Interface. The
examples here are not exhaustive, meaning that I don't have examples for <i>everything</i> you'd want to do with the JNI. As
I encounter other/better examples, I will add them here.
<p>
One last thing: My original work with these JNI concepts also included some rudimentary benchmarks. One of the goals was to
compare the performance between Sun's JDK and Microsoft's JDK, as well as the performance differences on Windows, Solaris, and
Linux. This document doesn't discuss those goals, however, some of those tests still exist in the Java files. Rather than remove
them, I just left them in the files with the hope that, at some later point, I might come back and revisted them.
<p>
<a href="#Top">Back to top</a>
</BLOCKQUOTE>
<div class="SectionHeader">
<A NAME="Signatures">Signatures</A>
</div>
<BLOCKQUOTE>
A function's <i>signature</i> consists of the function's name and parameters. The function's parameters
are subject to these constraints:
<ul>
<li><b>number</b> - A function expects a certain number of parameters (some can handle a variable number of parameters)
<li><b>type</b> - A function expects each parameter to be of a specific type
<li><b>order</b> - A function expects the parameters in a known (fixed) order
</ul>
<blockquote>
<i>Note that not all languages have these criteria. For example, Ada, Python, and Visual Basic (among others) can
pass parameters by Name, so the order is not required.</i>
</blockquote>
There are several functions in the JNI that require, as a parameter, the signature of another function.
The type of this parameter is a string. The table below shows how Java types are mapped into characters
(e.g. boolean is mapped as the uppercase letter <b>Z</b>) and strings
(e.g. Java String is mapped as the literal string <b>Ljava/lang/String;</b>). It then just becomes a
matter of building these strings up based on the parameters and return types of Java methods.
<p>
<table border=1 cellpadding=3>
<tr>
<td><b>Java Type</b><td><b>Signature</b></td>
</tr>
<td>boolean<td>Z</td>
</tr>
<td>byte<td>B</td>
</tr>
<td>char<td>C</td>
</tr>
<td>double<td>D</td>
</tr>
<td>float<td>F</td>
</tr>
<td>int<td>I</td>
</tr>
<td>long<td>J</td>
</tr>
<td>void<td>V</td>
</tr>
<td>object<td>L<i>fully-qualified-class</i>;</td>
</tr>
<td><i>type</i>[]<td>[<i>type</i></td>
</tr>
<td>method signature<td><i>( <i>arg-types</i>) <i>ret-type</i></td>
</tr>
</table>
<p>
<b>Examples:</b>
<p>
<table border=1 cellpadding=3>
<tr>
<td align="center"><b>Method</b><td><b>Signature</b></td>
</tr>
<td><tt>void f1()</tt><td><tt>()V</tt></td>
</tr>
<td><tt>int f2(int, long)</tt><td><tt>(IJ)I</tt></td>
</tr>
<td><tt>boolean f3(int[])</tt><td><tt>([I)B</tt></td>
</tr>
<td><tt>double f4(String, int)</tt><td><tt>(Ljava/lang/String;I)D</tt></td>
</tr>
<td><tt>void f5(int, String [], char)</tt><td><tt>(I[Ljava/lang/String;C)V</tt></td>
</tr>
</table>
<p>
If you recall from <a href="delphi-jni-1.html">Part One</a>, all native functions have two hidden parameters. These parameters
are not included in this signature (since these signatures refer to Java methods.) So, for example, a Java method that doesn't
take any arguments and doesn't return a value would have the signature:
<blockquote>
<pre>
()V
</pre>
</blockquote>
Later, you will see how these signatures are used by Delphi when invoking Java methods.
<p>
<a href="#Top">Back to top</a>
</BLOCKQUOTE>
<div class="SectionHeader">
<A NAME="Concepts">Concepts</A>
</div>
<BLOCKQUOTE>
In this document, each <i>concept</i> is explained with an example that implements some code in Java and/or Delphi. For example, one
concept to learn is how to call a <i>void function</i> (a <tt><b>procedure</b></tt> in Delphi) that doesn't take any arguments. This is done
in this document by creating a procedure in Delphi and printing the words <i>Hello World!</i> to the screen.
<p>
As in <a href="delphi-jni-1.html">Part One</a>, this part is implemented in 3 files:
<ul>
<li><a href="src/Native_java.html">Native.java</a> This is a Java class that <i>declares</i> the native methods.
<li><a href="src/Native_dpr.html">Native.dpr</a> This is the Delphi code that <i>implements</i> the native methods.
<li><a href="src/Main_java.html">Main.java</a> This is the Java program that <i>calls</i> the native (Delphi) methods.
</ul>
Each function contains a header comment that shows:
<ul>
<li>The Java declaration - This is how the Delphi function/procedure would be declared in a Java class.
<li>The Java class that declares the function - Our functions are declared in <i>Native.java</i>.
<li>The name of the method - This is the name that the Java class sees (without the decorations.)
<li>The <i>signature</i> - The format of these signatures is defined by the JNI and is <A HREF="#Signatures">described</a> above.
</ul>
Incidentally, most of the function comments can be automatically generated with <b>javah</b>, a tool that creates C/C++ header files
from Java class files. I used this tool to create this information and then copied it into the Delphi code.
<p>
<a href="#Top">Back to top</a>
</blockquote>
<div class="SectionHeader">
<A NAME="Concept1">Concept #1 - Simple Function Call</A>
</div>
<BLOCKQUOTE>
This is an example of a function that doesn't take any parameters and doesn't return any value. This is essentially the
<i>Hello World</i> function described in <a href="delphi-jni-1.html">Part One</a>.
<pre class="sourcecode"><code><font color="#003399"><i>(****************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -