Develop JNI (JAVA Native Interface) with Delphi (2)

zhaozj2021-02-17  51

To properly access the member properties (fields) and members of the class, the most important thing is to give the correct signature, and the signature of the data type and method in Java has the following agreement:

Data type / method

signature

BYTE B CHAR C DOUBLE D FLOAT F INT I Long J (Note: Is J Is L) Short S Void V Boolean Z (Note: Yes Z is B) Class Type L with the full class name, such as ljava / lang / string; Note: At the beginning of the L, it is necessary to include the package, separated by a slash, and finally there is a semicolon as the end of the type expression. The number of Type [] [Type, such as FLOAT [] is [FLOAT, if it is a two-dimensional array Such as float [] [], the signature is [[Float, (Note: Here is two [symbols).

Method (Parameter Type Sign) Return Value Type Signature, for example: Float Fun (INT A, INT B), its signature (ii) f, (Note: There is no comma between two I!), And for method String Tostring (), is () ljava / lang / string ;.

Through the example above, we understand the basic steps of the member attributes or methods of accessing the object parameters and the use of multiple GET methods. Tjnienv also provides a plurality of SET methods to modify the field values ​​of the incoming object parameters because the Java object parameters are transmitted in the way of address, so the modified results can be reflected in the Java program. The Get / SET method provided by Tjnienv requires two basic parameters: object instance (Jobject Type), and field ID (JFIELD type), you can get the value of this object in accordance with the provided objects and field IDs.

Now we understand the steps of using and modifying the Java object in Delphi code. Further, if you need to create a new Java object from the Delphi, can you? Let's take an example, create an instance of the Java class in Delphi, and the operation method is also very simple.

First add a local method in the Java code, as follows:

Public Native Book Findbook (String T);

Then, modify the Delphi code, add a function (because there is a return value, so no longer the process is functional):

function Java_HelloWorld_findBook (PEnv: PJNIEnv; Obj: JObject; t: JString): JObject; stdcall; var JVM: TJNIEnv; c: JClass; fid: JFieldID; b: JObject; mid: JMethodID; begin JVM: = TJNIEnv.Create (PEnv );

C: = JVM.FindClass ('Book'); MID: = JVM.GetMethodId (C, '', '() V'); B: = JVM.NewObjectv (C, MID, NIL); FID: = JVM.GetfieldID (C, 'Title', 'Ljava / Lang / String;'); JVM.SetObjectField (B, FID, T); FID: = JVM.GetfieldID (C, 'Price', 'D'); JVM.SETDOUBLEFIELD (B, FID, 99.8); Result: = B; JVM.Free; end;

Here, use the FINDCLASS method to find the class based on the class name, then obtain the method ID of the constructor, the constructor name is fixed to "", pay attention to signing "() v" Description Using an empty constructor of the Book class . Then use the method NewObjectv to create an instance of the class according to the method ID of the class and constructor. Create a class instance, and then operate with the previous example, there is no different example. For non-empty constructors, it is slightly more complicated. It is necessary to set its parameter table. Or the above example, add a non-air constructor in the Book class:

Public book (strint t, double p) {this.title = T; this.price = p;}

In the Delphi code, the code of the FindBook function modifies the acquisition method ID is as follows:

MID: = JVM.getMethodId (C, '', '(ljava / lang / string; d) v');

The constructor is still "", the method signature indicates that it has two parameters, respectively, String and Double. Then the incoming parameters, the method of calling the Java object in Delphi If you need to pass parameters, you need to construct a parameter array. Plus in variable declarations:

Args: array [0..1] of jvalue;

note! The parameters are the JVALUE type, whether it is the basic data type or an object, all as an array of JValue. In the code implementation is the parameter setting value, and the address of the array is passed to the NewObjecta method as the parameters:

Args [0] .l: = t; // T is incoming jstring parameter args [1] .d: = 9.8;

B: = JVM.NewObjecta (C, MID, @ args);

The statement of the data setting value for the JVALUE type is a bit special, is it? We open jni.pas, check out JValue's definition, which is a Packed Record, which already includes a variety of data types, and Jvalue is as follows:

Jvalue = Packed Record Case Integer of 0: (z: jboolean); 1: (B: JBYTE); 2: (c: jchar); 3: (s: jshort); 4: (i: jint); 5: ( J: jlong); 6: (f: jfloat); 7: (d: jdouble); 8: (l: jobject);

Let's take a look at the error handling. In the example in debugging, you may see that once an error occurs during the execution of Delphi, the console will output a lot of error messages. If you want to block this information, that is, I hope to capture errors in Delphi and process it directly. What should I do? It is also very simple, providing two methods in Tjnienv can easily handle errors that occur when accessing Java objects. Var ... AE: JTHROWABLE; Begin ... ae: = jvm.exceptionocurred; if (ae <> nil) THEN BEGIN WRITELN (Format ('Exception Handledin Main.cpp:% D', [Longword (AE)])) JVM.ExceptionDescribe; jvm.exceptionclear; end; ...

Method EXCEPTIONOCCURRED can capture the error thrown by Java and store it in a variable of the JTHROWABLE type. With ExceptionDescribe, you can display the Java error message, and ExceptionClear is clearly clearing the error, making it no longer thrown.

At this point, we have made a preliminary discussion from the step from Java code to access Delphi local code from JNI technology. In JNI.PAS, it also provides a method of opening a Java virtual machine in Delphi to perform Java code. Interested readers may wish to study themselves.

转载请注明原文地址:https://www.9cbs.com/read-30182.html

New Post(0)