JNI (Java Native Interface, Java Local Interface) Technology is not unfamiliar, it can help solve the limitations and efficiency of Java access to the underlying hardware. With regard to the development of JNI, how many data discusses how to develop JNI with C / C language, and even JDK also provides a JavaH tool to automatically generate a C language program framework. However, do you have to communicate with Java with Java with your favorite Delphi?
Through the analysis of JNI.h files generated by Javah, we found that Java uses JNI to access the local code key in jninativeInterface_ this structure defined in jni.h, if you use DELHPI language to rewrite Its definition should also develop JNI local code. Fortunately, there is ready-made code on the Internet to help you complete this complicated job, providing a jni.pas file on http://delphi-jedi.org, is a JNI.h rewritten with Delphi language. We only need to join JNI.PAS in our Delphi project, you can easily develop a Delphi language-based JNI local code.
This article will use jni.pas to discuss the basic method of developing JNI local code with Delphi language.
Let's first look at a classic HelloWorld example. Write the following Java code:
Class HelloWorld {Public Native Void DisplayHelloWorld (); static {system.loadLibrary ("HelloWorldImpl");}}
This code declares a local method DisplayHelloWorld, it doesn't have a parameter, and there is no return value, but I hope it can print "Hello! China." On the screen. This task we intend to hand it over to the local Delphi. At the same time, in the static domain of this class, load HelloWorldImpl.dll with the System.LoadLibrary () method. Note that only the file name is required without the need to give the extension DLL.
At this time, if you use the HelloWorld class of the HelloWorld class in our Java program, the system will throw a java.lang.unsatisfiedLinkerRror, because we have not implemented local code for it.
Let's take a look at the implementation of the local code in Delphi. Newly built a DLL project, the project is called HelloWorldImpl, enter the following code:
Uses jni; procedure java_helloWorld_DisplayHelloWorld (Penv: PjNienv; Obj: Jobject); stdcall; begin writeln ('Hello! China.'); End; exports java_helloworld_displayhelloworld; end.
This code first imports jni.pas unit. Then there is a process called java_helloWorld_DisplayHelloWorld, which is naming in this process. It starts with Java, using the underline to connect the Java class's package, class name, and method. This naming method cannot be incorrect, otherwise the Java class will not be able to correspond to it with it. At the same time, on the Win32 platform, the call mode of this process can only be declared as stdcall. Although there is no parameters declared in the HelloWorld class, the specific processes implemented in Delphi have two parameters: Penv: Pjnienv and Obj: Jobject. (These two types are defined in jni.pas). The PENV parameter represents the JVM environment, while the OBJ parameter represents the Java object that calls this process. Of course, these two parameters will not be used in our simple example. Because we compile a DLL file, this method needs to be output in Exports. Compile Delphi Engineering, generate a HelloWorldimp.dll file, placed on the runtime system to find the directory, usually in the current directory, and write the Java class that calls the HelloWorld class as follows:
Class maintest {public static void main (String [] args) {new helloworld (). DisplayHelloWorld ();}}
Run it, if the console outputs "Hello! China.", Congratulations, you have successfully developed the first JNI application with Delphi.
Next, we will raise a little bit to study the passage of the parameters. Or HelloWorld, modify the displayhelloworld method just written, let the displayed string dynamically determine by the Java class. The Java code for the new DisplayHelloWorld method is as follows:
Public Native Void DisplayHelloWorld (String Str);
Modify the Delphi code, this time is used up to the first inherent parameter PENV of the process, as follows:
procedure Java_HelloWorld_displayHelloWorld (PEnv: PJNIEnv; Obj: JObject; str: JString); stdcall; var JVM: TJNIEnv; begin JVM: = TJNIEnv.Create (PEnv); Writeln (JVM.UnicodeJStringToString (str)); JVM.Free; end;
In the parameter table of the process, we add a parameter str: JString, which is responsible for receiving Striang arguments from HelloWorld. Note that the implementation of the code is different because the parameters are used, which involves the conversion between the data types of the parameters. The String object of Java from the Java program is now a special jstring type, and JString is not available in Delphi. The unicodejstringtostring () method provided by Tjnienv is required to convert the String type that Delphi can recognize. Therefore, it is necessary to construct the example object of Tjnienv. Use it (Tjnienv provides a number of methods, here only one of its most commonly used methods), and finally, remember to release it. For the parameters of the basic data type, the steps you use from Java to Delphi and used in Delphi are as simple.
We will increase a little difficulty, build a custom class book, and pass it as a parameter into Delphi, study how the public fields of the object parameters in the local code are studied. First, define a simple Java class book, in order to make the problem slightly more complicated, we add a java.util.date type field in Book, the code is as follows:
Public class book {public string title; // Title public double price; // Price public date pdate; // Purchase Date}
Similarly, add a local method DisplayBookInfo in the HelloWorld class, the code is as follows:
Public Native Void DisplayBookInfo (Book B);
Delphi's code is complicated with a few examples, first look at the code:
procedure Java_HelloWorld_displayBookInfo (PEnv: PJNIEnv; Obj: JObject; b: JObject); stdcall; var JVM: TJNIEnv; c, c2: JClass; fid: JFieldID; mid: JMethodID; title, datestr: string; price: double; pdate: JObject Begin JVM: = Tjnienv.create (PENV); C: = JVM.GetObjectClass (b); FID: = JVM.GetfieldID (C, 'Title', 'Ljava / Lang / String;'); title: = JVM. UnicodejStringTString (JVM.GetObjectfield (B, FID)); FID: = JVM.GetfieldID (C, 'Price', 'D'); Price: = JVM.GETDOUBLIELD (B, FID); FID: = JVM.GetFieldId (C , 'pdate', 'ljava / util / date;'); pdate: = jvm.getObjectfield (b, fid); C2: = jvm.getObjectClass (pdate); MID: = JVM.getMethodID (C2, 'Tostring', '() Ljava / lang / string;'); DateStr: = jvm.jstringtostring (jvm.callobjectMethoda (PDATE, MID, NIL)); Writeln (Format ('% s% f% s', [Title, Price, DateStr ]));
JVM.Free; end;