Java中调用Delphi编写的DLL(3)

再看看效果吧,是不是成功了?

这里如果返回值的类型是其它的其本类型,比如 JLong,JInt,JFloat,JDouble,JBoolean,JShort,JByte
这些类型的数据可以直接与 Delphi 中的数据运算,对应 Int64,Integer,Single,Double,Boolean,SmallInt,ShortInt
返回时可以直接给 Result 赋 Delphi 中的数值. 如:
function Java_alvinJNI_HelloWorld_getInt(PEnv: PJNIEnv; Obj: JObject): JInt; stdcall;
var
tmp: Integer;
begin
tmp := 10;
Result := tmp;
end;

如果返回值的类型是 Object 的 Java 对象,返回 JObject 类型,它的用法我们在以后再来学习.
如果返回值的类型是 Type[] 数组,接收参数时要设为 JObject 类型,怎样创建这样的数组对象,我自己也还不知道,以后知道了我再来贴上
因为 Java 是把数组作为对象看待的.它要以以下的方式来使用:

例如: 我们要给 Delphi 的方法传入一个 byte[] 型数组,在定义 Delphi 方法时参数声明为 bytearray: JObject

在方法中:
var
PByteArr: PJByte //PJByte 是 JNI.pas 定义的, 里面还有 PJBoolean, PJObject, PJInt 等..
JVM: TJNIEnv;
isCopy: Boolean;
begin
JVM:= TJNIEnv.Create(PEnv);
isCopy := false;
PByteArr := JVM.GetByteArrayElements(bytearray, isCopy); //调用这个方法,可以将取得参数 bytearray 的地址, isCopy 决定是否复制数组
//之后,我们可以通过 PByteArr 结合 inc(PByteArr) 这个指针来操作传过来的数组.
end;

之前,我们学了如何用 Java 调用 Delphi 程序的一个方法
如果在Delphi 程序在适当时候需要调用 Java 程序,又要怎么做呢?

首先,我们先定义如下的 Java 类:

//------------------------------------------------------------------------------
package alvinJNI;

class HelloWorld {
static {
System.loadLibrary("DelphiAction");
}
String str = "你好";

public native void callPrintText(HelloWorld hw);

public void printText(String arg) {
System.out.println(arg);
}

public static void main(String[] args) {
HelloWorld hw = new HelloWorld();
hw.callPrintText(hw);
}

}
//-------------------------------------------------------------------------------

我们再像上次一样在 Delphi 中建立 DLL 工程,写下面的代码(有注释):

//-------------------------------------------------------------------------------
library DelphiAction;

uses
JNI;

//今天的这个程序稍微的复杂一点,因为要调用 Java 对象的方法,在这里可以学到对 JObject 的操作
procedure Java_alvinJNI_HelloWorld_callPrintText(PEnv: PJNIEnv; Obj: JObject; arg: JObject); stdcall;
var
JVM: TJNIEnv;
c: JClass; //类ID
fid: JFieldID; //属性ID
mid: JMethodID; //方法ID
tmpStr: JString;
javaargs : array[0..0] of JValue; //调用方法时的参数
begin
JVM := TJNIEnv.Create(PEnv);

{我们先来看下如何获得一个对象的某个属性值}
{----------------------------------------}
{我们对 Java 对象的操作要选获取这个对象的 ClassID,我们可以用下面的方法来取得.}
c := JVM.GetObjectClass(arg);

{我们先来获取参数 HelloWorld arg 对象的 String str 这个属性的值
这里我们先要获得这个属性在它所在类中的属性 ID }
fid := JVM.GetFieldID(c, 'str', 'Ljava/lang/String;');
{上面调用的这个方法中的参数分别是: 所属类ID, 属性名, 属性类型签名
关于属性类型的签名,将在下面 '说明1' 给出}

{下面,我们就可以根据 属性ID 来获取属性值了, 这里我们会取得到 arg.str 这个字符串}
tmpStr := JVM.GetObjectField(arg, fid);
{上面的这个 JVM.GetObjectField(arg, fid) 用来获取属性值
参数分别是: 要取得其属性的对象, 要取得的属性的属性ID
这里取得的是一个 Java 的 String 对象,是 JString,其实它也就是 JObject 类型的}
writeln('Delphi 输出的: ' + JVM.UnicodeJStringToString(tmpStr));

{我们再来看下如何调用一个 JObject 的方法, 这里我们要调用的是 arg.printText() 这个方法}
{------------------------------------------------------------------------------------}
//我们还是要用到上面的那个 类ID: c.
//这一次我们要取得这个方法的 方法ID
mid := JVM.GetMethodID(c, 'printText', '(Ljava/lang/String;)V');
//上面调用的这个方法中的参数分别是: 所属类ID, 方法名, 方法(参数+返回值)类型签名
//关于方法(参数+返回值)类型的签名,将在下面 '说明2' 给出

//有了 方法ID 后我们就可以用这个ID来调用这个方法了,我们这里要调用的方法是: arg.printText(参数);
//因为我们要调用的这个方法有参数, 调用 Java 方法的时候如果有参数,要建立参数数组,这里我们就来建立数组
javaargs[0].l := tmpStr;
{这里这个 javaargs 是 JValue 类型. 它有点特殊,它的用法在下面 说明3 给出}

{有了 类象, 方法ID, 参数. 下面我们就可以调用 arg.printText(javaargs) 这个方法了,使用下面这个方法就可实现}
JVM.CallObjectMethodA(arg, mid, @javaargs);

JVM.Free;
end;

exports
Java_alvinJNI_HelloWorld_callPrintText;
end.

//--------------------------------------------------------------------------------

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwsfjy.html