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

我们现在就可以生成 DelphiAction.dll 将其放在 Java 工程目录下, 再执行 alvinJNI.HelloWorld 看看效果了.

好了,我们今天主要就是实现了一下,如何在 Java 调用 Delphi 的方法时,给其提交一个参数.
是不是很爽?

在上一篇中,我们说了如何用 Java 调用 Delphi 程序的一个方法并传递给其一个字符串参数,现在我们再来看一下如果传递的参数是其它基本类型,又要怎么做.


首先,我们先看一下如何传递 int 型参数,定义如下的 Java 类:

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

class HelloWorld {
static {
System.loadLibrary("DelphiAction");
}

public native void printText(int i);

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

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

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

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

uses
JNI;

//我们给这个方法加的参数是: i: JInt
procedure Java_alvinJNI_HelloWorld_printText(PEnv: PJNIEnv; Obj: JObject; i: JInt); stdcall;
var
tmpInt: Integer;

begin
//参数提交过来的 int 型数据,在这里是一个 JInt 数据,它其实就是一个 Integer 数据,它的使用更加方便
//它可以直接地参与 Interger 类型数据的运算,是不是很容易.
tmpInt := i + 100;
tmpInt := tmpInt - 100;
Writeln(tmpInt);
end;

exports
Java_alvinJNI_HelloWorld_printText;
end.
//----------------------------------------------------------------------------------------------------------

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

这里如果是 long 型参数,接收时要设为 JLong 类型,它也可以跟对应的整型数运算,我们常用它跟 Int64 一起运算
如果参数类型是 float ,接收参数时要设为 JFloat 类型,它也可以跟跟 Single 一起运算
如果参数类型是 double ,接收参数时要设为 JDouble 类型,它也可以跟跟 Delphi 中的 Double 型数据一起运算
如果参数类型是 boolean ,接收参数时要设为 JBoolean 类型,它也可以跟跟 Delphi 中的布尔型数据一起运算
如果参数类型是 short ,接收参数时要设为 JShort 类型,它也可以跟跟 SmallInt 型数据一起运算
如果参数类型是 byte ,接收参数时要设为 JByte 类型,它也可以跟跟 ShortInt 型数据一起运算
如果参数类型是 Object 的 Java 对象,接收时要设为 JObject 类型,它的用法比较复杂(涉及到对 Java 类和对象的操作),我们在以后再来学习.
如果参数类型是 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 程序的一个方法并传递给其一个参数
现在我们再来看一下如果如果要调用的方法有返回值,又要怎么做.


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

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

class HelloWorld {
static {
System.loadLibrary("DelphiAction");
}

public native String printText(String arg);

public static void main(String[] args) {
HelloWorld hw = new HelloWorld();
System.out.println(hw.printText("你好"));
}

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

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

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

uses
JNI;

//今天,因为这个方法有返回值,所以不再是 procedure 过程,我们要变成 function 函数, 返回值类型为 JString
function Java_alvinJNI_HelloWorld_printText(PEnv: PJNIEnv; Obj: JObject; arg: JString): JString; stdcall;
var
tmpStr: String;
JVM: TJNIEnv;
tt: Boolean;
begin
JVM:= TJNIEnv.Create(PEnv);

//我们这里先把参数提交过来的 JString 转换成 Delphi 中的 String 后就可以使用了
tmpStr := '你想输出的字符串是: "' + JVM.UnicodeJStringToString(arg) + '"。';

//当字符串要转换成 JString 我们需要先对字符串进行 UTF8 编码后再转换成 PChar 再转换成 JString
//这样才能保证返回的字符串在 JAVA 中不乱码
Result := JVM.StringToJString(pchar(UTF8Encode(tmpStr)));
JVM.Free;
end;

exports
Java_alvinJNI_HelloWorld_printText;
end.
//--------------------------------------------------------------------------------

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

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