本次学习的主要内容:

1、java给delphi传递一个String类型的参数,由delphi打印出来;

2、delphi返回一个int类型的结果给java;

3、java调用delphi显示一个最简单的窗体。

—————————————————————————————————————————————————————————————————————————————

1、准备工作:

下载大神编写的delphi和java 数据互通的delphi单元文件:JNI.pas,下载地址:http://www.blogjava.net/Files/alvin/jni_pas.zip。

注:由于我用的delphi xe版本,而最新的JNI.pas据说可以在http://www.delphi-jedi.org/上边下载,但是我英语太烂,确实没有找到,知道的大神请告知一下, 谢谢!下载下来的JNI.pas是很老的版本,所以我对JNI中包PChar和PAnsiChar转换错误的地方做了修改。

2、写java类:

我们需要写一个java的类,通过申明调用由delphi实现的native方法来达到目的,很明显,native的方法需要有delphi来实现,而我们java代码不需要实现该方法:

package test.nativeTest;
/**
* java与delphi的数据交换
*
* @author dendy
*
*/
public class NativeTestByDelphi {
static {
// 加载动态链接库
System.loadLibrary("nativetest");
}
/**
* 直接打印一个字符串
*
* @param s
*/
public static native void say(String s);
/**
* 显示一个窗体界面
*/
public static native void showWindow();
/**
* 获取一个整型数据
*
* @return
*/
public static native int getVisitedCount();
public static void main(String[] args) {
say("你还好吗?");
showWindow();
System.out.println("visited count : " + getVisitedCount());
}
}
3、创建delphi的工程:
直接新建一个dll工程,在工程中加入JNI.pas,这样可以自动引入到dll项目文件中。
在delphi这边编写java能够访问的方法时,JNI.pas帮我们写好了java和delphi数据交互的各个类和数据类型,需要用到时可以参看JNI.pas的源码。
java与jni.pas对应的类型对照
java的数据类型
JNI.pas中定义的数据类型
delphi的数据类型
byte
JByte
ShortInt
char
JChar
WideChar
short
JShort
SmallInt
int
JInt
Integer
long
JLong
Int64
float
JFloat
Single
double
JDouble
Double
boolean
JBoolean
Boolean
JNI.pas中数据类型的定义如下:
// JNI Types
JBoolean = Boolean;
JChar = WideChar;
JShort = Smallint;
JFloat = Single;
JDouble = Double;
JSize = JInt;
_JObject = record
end;
JObject = ^_JObject;
JClass = JObject;
JThrowable = JObject;
JString = JObject;
JArray = JObject;
JBooleanArray = JArray;
JByteArray = JArray;
JCharArray = JArray;
JShortArray = JArray;
JIntArray = JArray;
JLongArray = JArray;
JFloatArray = JArray;
JDoubleArray = JArray;
JObjectArray = JArray;
JWeak = JObject;
JRef = JObject;
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);
end;
JFieldID = ^_JFieldID;
_JFieldID = record
end;
JMethodID = ^_JMethodID;
_JMethodID = record
end;
PPointer = ^Pointer;
PJByte = ^JByte;
PJBoolean = ^JBoolean;
PJChar = ^JChar;
PJShort = ^JShort;
PJInt = ^JInt;
PJLong = ^JLong;
PJFloat = ^JFloat;
PJDouble = ^JDouble;
PJString = ^JString;
PJSize = ^JSize;
PJClass = ^JClass;
PJObject = ^JObject;
PJThrowable = ^JThrowable;
PJArray = ^JArray;
PJByteArray = ^JByteArray;
PJBooleanArray = ^JBooleanArray;
PJCharArray = ^JCharArray;
PJShortArray = ^JShortArray;
PJIntArray = ^JIntArray;
PJLongArray = ^JLongArray;
PJFloatArray = ^JFloatArray;
PJDoubleArray = ^JDoubleArray;
PJObjectArray = ^JObjectArray;
PJFieldID = ^JFieldID;
PJMethodID = ^JMethodID;
PJValue = ^JValue;
PJWeak = ^JWeak;
PJRef = ^JRef;
delphi dll代码:
library nativetest;
{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }
uses
SysUtils,
Classes,
JNI in '..\jni_pas\JNI.pas',
form in 'form.pas' {Form1};
var
cnt : Integer;
{$R *.res}
{******************************************************************************
注意命名规则:Java和方法的完整名称(带全类名),其中的点号修改为下划线
参数:
PEnv:JNI.pas中定义的类型,delphi与Java数据交互的通道。
Obj:暂时不知道是干什么的?
s :java传递过来的参数,java的String类型对应JNI.pas中定义的JString类型.
******************************************************************************}
procedure Java_test_nativeTest_NativeTestByDelphi_say(PEnv: PJNIenv;
Obj: JObject; s: JString); stdcall;
var
JVM: TJNIEnv;
begin
JVM := TJNIEnv.Create(PEnv);
writeln(JVM.UnicodeJStringToString(s));
JVM.Free;
end;
function Java_test_nativeTest_NativeTestByDelphi_getVisitedCount(PEnv: PJNIenv;
Obj: JObject) : JInt; stdcall;
var
JVM: TJNIEnv;
begin
cnt := cnt + 1;
JVM := TJNIEnv.Create(PEnv);
JVM.Free;
Result := cnt;
end;
procedure Java_test_nativeTest_NativeTestByDelphi_showWindow(PEnv: PJNIenv;
Obj: JObject); stdcall;
var
form: TForm1;
begin
form := TForm1.Create(nil);
form.ShowModal;
end;
{导出方法,这样java那边才可以调用}
exports
Java_test_nativeTest_NativeTestByDelphi_say,
Java_test_nativeTest_NativeTestByDelphi_showWindow,
Java_test_nativeTest_NativeTestByDelphi_getVisitedCount;
begin
end.

form的代码很简单,就一个label打印一句话而已,这里就不贴出来了.

4、注意:

运行的时候,需要将dll放到class文件的根目录,我这里放到跟test文件夹同一级中的,然后调用java命令执行类:java test/nativeTest/NativeTestByDelphi,在eclipse执行不成功,应该是要修改执行参数,还没研究,搞定了再来写上……