??xml version="1.0" encoding="utf-8" standalone="yes"?>
]]>
源文?点击下蝲
文章来源:
http://www.ialvin.cn/blog/article-150.xml
]]>
功能较简单的那种, 界面上模仿了 Discuz
JSP 本来学的不? 只是量实现?MVC
源码下蝲:http://www.iscripts.org/bbs/viewthread.php?tid=87
文章来源:http://www.iscripts.org/bbs/viewthread.php?tid=87
之前,我们学了如何?Java 调用 Delphi E序的一个方?br />如果在Delphi E序在适当时候需要调?Java E序,又要怎么做呢?
首先,我们先定义如下的 Java c?
//------------------------------------------------------------------------------
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;
//今天的这个程序稍微的复杂一?因ؓ(f)要调?Java 对象的方?在这里可以学到对 JObject 的操?br />procedure Java_alvinJNI_HelloWorld_callPrintText(PEnv: PJNIEnv; Obj: JObject; arg: JObject); stdcall;
var
JVM: TJNIEnv;
c: JClass; //cID
fid: JFieldID; //属性ID
mid: JMethodID; //Ҏ(gu)ID
tmpStr: JString;
javaargs : array[0..0] of JValue; //调用Ҏ(gu)时的参数
begin
JVM := TJNIEnv.Create(PEnv);
{我们先来看下如何获得一个对象的某个属性值}
{----------------------------------------}
{我们?Java 对象的操作要选获取这个对象的 ClassID,我们可以用下面的Ҏ(gu)来取?}
c := JVM.GetObjectClass(arg);
{我们先来获取参数 HelloWorld arg 对象?String str q个属性的?br /> q里我们先要获得q个属性在它所在类中的属?ID }
fid := JVM.GetFieldID(c, 'str', 'Ljava/lang/String;');
{上面调用的这个方法中的参数分别是: 所属类ID, 属性名, 属性类型签?br /> 关于属性类型的{,在下面 '说明1' l出}
{下面,我们可以根?属性ID 来获取属性g, q里我们?x)取得?arg.str q个字符串}
tmpStr := JVM.GetObjectField(arg, fid);
{上面的这?JVM.GetObjectField(arg, fid) 用来获取属性?br /> 参数分别? 要取得其属性的对象, 要取得的属性的属性ID
q里取得的是一?Java ?String 对象,?JString,其实它也是 JObject cd的}
writeln('Delphi 输出? ' + JVM.UnicodeJStringToString(tmpStr));
{我们再来看下如何调用一?JObject 的方? q里我们要调用的?arg.printText() q个Ҏ(gu)}
{------------------------------------------------------------------------------------}
//我们q是要用C面的那个 cID: c.
//q一ơ我们要取得q个Ҏ(gu)?Ҏ(gu)ID
mid := JVM.GetMethodID(c, 'printText', '(Ljava/lang/String;)V');
//上面调用的这个方法中的参数分别是: 所属类ID, Ҏ(gu)? Ҏ(gu)(参数+q回?cd{
//关于Ҏ(gu)(参数+q回?cd的签?在下面 '说明2' l出
//有了 Ҏ(gu)ID 后我们就可以用这个ID来调用这个方法了,我们q里要调用的Ҏ(gu)? arg.printText(参数);
//因ؓ(f)我们要调用的q个Ҏ(gu)有参? 调用 Java Ҏ(gu)的时候如果有参数,要徏立参数数l?q里我们来建立数组
javaargs[0].l := tmpStr;
{q里q个 javaargs ?JValue cd. 它有点特D?它的用法在下?说明3 l出}
{有了 c象, Ҏ(gu)ID, 参数. 下面我们可以调?arg.printText(javaargs) q个Ҏ(gu)?使用下面q个Ҏ(gu)可实现}
JVM.CallObjectMethodA(arg, mid, @javaargs);
JVM.Free;
end;
exports
Java_alvinJNI_HelloWorld_callPrintText;
end.
//--------------------------------------------------------------------------------
到这?我们已经可以?Delphi 中获?Java 对象的属性了, q可以调用一?Java 对象的方?是不是很酷呢?
你学C?
###########################说明1###############################
现在,我们q要再了解一个获?"属性ID" 时的那个{
上面例子? fid := JVM.GetFieldID(c, 'str', 'Ljava/lang/String;'); 用的{? 'Ljava/lang/String;'
因ؓ(f)刚刚要获得的属性是 java.lang.String cd?所以它的签名是: 'Ljava/lang/String;'
如果,我们要获得的属性是其它cd,获取 属性ID 时又要怎样{?下面l出一个对照表
byte -- B
char --- C
double -- D
float -- F
int -- I
long -- J (注意Q是J不是L)
short -- S
void -- V
boolean - ZQ注意:(x)是Z不是BQ?br />class(cd象类? - 'L'+完整cd+';' (包\径分隔符? '/'. 如上面例子中?String 对型, {? 'Ljava/lang/String;')
数组 type[] -- '['+type (例如 float[] 的签名就?'[float')
(如果是二l数l,如float[][]Q则{?'[[float')
############################说明2###############################
现在,我们q要再了解一个获?"Ҏ(gu)ID" 时的那个{
上面例子? mid := JVM.GetMethodID(c, 'printText', '(Ljava/lang/String;)V'); 用的{? '(Ljava/lang/String;)V'
Ҏ(gu)ID 的签?分ؓ(f)两部?br />一部分是前面括号中?是参数类型的{
另一部分是括号后?是返回值类型的{
其中某个{数与返回值的cd{与获取属性ID时的{是一L(fng)
上面要调用的Ҏ(gu)只有一个参?如果有多个参数时又怎样?
? int getInt(long a, double b); q样?Java Ҏ(gu)要这L(fng)? '(JD)I'
(注意:参数{是连l的,没有分隔W? q里W一个参?long {?J, W二个参数签名ؓ(f): D, q回值类?int {? I)
说到q里,怿大家都会(x)使用q个{?/p>
############################说明3###############################
在调用一?Java Ҏ(gu)? 如果q个Ҏ(gu)有参? 我们p传递一个参数数l的地址l?Java
现在,我们q要再了解如何创L(fng)一个参数数l?br />传递给 Java Ҏ(gu)的参?cd均ؓ(f) JValue. 它是一个packed record
如果,我们要调用的Ҏ(gu) void myMethod(int a, long b, String c); ?3 个参?br />那么
1.我们先要声明如下数组:
var
args : array[0..1] of JValue;
2.l数l赋?br /> args[0].i := 100;
args[1].j := 100;
args[2].l := JVM.StringToJString(pchar(UTF8Encode('雅林|络 )));
3.调用
JVM.CallVoidMethodA(Java对象, Ҏ(gu)ID, @args);
JValue 是一?packed record,它的定义如下:
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;
调用Ҏ(gu)?TJNIEnv q有:
CallObjectMethodA: function(Env: PJNIEnv; Obj: JObject; MethodID: JMethodID; Args: PJValue): JObject; {$IFDEF MSWINDOWS} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
CallBooleanMethodA: function(Env: PJNIEnv; Obj: JObject; MethodID: JMethodID; Args: PJValue): JBoolean; {$IFDEF MSWINDOWS} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
CallByteMethodA: function(Env: PJNIEnv; Obj: JObject; MethodID: JMethodID; Args: PJValue): JByte; {$IFDEF MSWINDOWS} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
CallCharMethodA: function(Env: PJNIEnv; Obj: JObject; MethodID: JMethodID; Args: PJValue): JChar; {$IFDEF MSWINDOWS} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
CallShortMethodA: function(Env: PJNIEnv; Obj: JObject; MethodID: JMethodID; Args: PJValue): JShort; {$IFDEF MSWINDOWS} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
CallIntMethodA: function(Env: PJNIEnv; Obj: JObject; MethodID: JMethodID; Args: PJValue): JInt; {$IFDEF MSWINDOWS} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
CallLongMethodA: function(Env: PJNIEnv; Obj: JObject; MethodID: JMethodID; Args: PJValue): JLong; {$IFDEF MSWINDOWS} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
CallFloatMethodA: function(Env: PJNIEnv; Obj: JObject; MethodID: JMethodID; Args: PJValue): JFloat; {$IFDEF MSWINDOWS} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
CallDoubleMethodA: function(Env: PJNIEnv; Obj: JObject; MethodID: JMethodID; Args: PJValue): JDouble; {$IFDEF MSWINDOWS} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
CallVoidMethodA: procedure(Env: PJNIEnv; Obj: JObject; MethodID: JMethodID; Args: PJValue); {$IFDEF MSWINDOWS} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
CallNonvirtualObjectMethodA: function(Env: PJNIEnv; Obj: JObject; AClass: JClass; MethodID: JMethodID; Args: PJValue): JObject; {$IFDEF MSWINDOWS} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
CallNonvirtualBooleanMethodA: function(Env: PJNIEnv; Obj: JObject; AClass: JClass; MethodID: JMethodID; Args: PJValue): JBoolean; {$IFDEF MSWINDOWS} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
CallNonvirtualByteMethodA: function(Env: PJNIEnv; Obj: JObject; AClass: JClass; MethodID: JMethodID; Args: PJValue): JByte; {$IFDEF MSWINDOWS} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
CallNonvirtualCharMethodA: function(Env: PJNIEnv; Obj: JObject; AClass: JClass; MethodID: JMethodID; Args: PJValue): JChar; {$IFDEF MSWINDOWS} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
CallNonvirtualShortMethodA: function(Env: PJNIEnv; Obj: JObject; AClass: JClass; MethodID: JMethodID; Args: PJValue): JShort; {$IFDEF MSWINDOWS} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
CallNonvirtualIntMethodA: function(Env: PJNIEnv; Obj: JObject; AClass: JClass; MethodID: JMethodID; Args: PJValue): JInt; {$IFDEF MSWINDOWS} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
CallNonvirtualLongMethodA: function(Env: PJNIEnv; Obj: JObject; AClass: JClass; MethodID: JMethodID; Args: PJValue): JLong; {$IFDEF MSWINDOWS} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
CallNonvirtualFloatMethodA: function(Env: PJNIEnv; Obj: JObject; AClass: JClass; MethodID: JMethodID; Args: PJValue): JFloat; {$IFDEF MSWINDOWS} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
CallNonvirtualDoubleMethodA: function(Env: PJNIEnv; Obj: JObject; AClass: JClass; MethodID: JMethodID; Args: PJValue): JDouble; {$IFDEF MSWINDOWS} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
CallNonvirtualVoidMethodA: procedure(Env: PJNIEnv; Obj: JObject; AClass: JClass; MethodID: JMethodID; Args: PJValue); {$IFDEF MSWINDOWS} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
好了,到这?怿大家对做 Delphi ?JNI 已有一定的了解
关于 Delphi JNI 的话题就先说到这?br />如果有兴?大家可以打开 jni.pas 了解更多
在上一中,我们说了如何?Java 调用 Delphi E序的一个方法ƈ传递给其一个参?br />现在我们再来看一下如果如果要调用的方法有q回?又要怎么?
首先,我们先定义如下的 Java c?
//------------------------------------------------------------------------------
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;
//今天,因ؓ(f)q个Ҏ(gu)有返回?所以不再是 procedure q程,我们要变?function 函数, q回值类型ؓ(f) 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);
//我们q里先把参数提交q来?JString 转换?Delphi 中的 String 后就可以使用?br /> tmpStr := '你想输出的字W串? "' + JVM.UnicodeJStringToString(arg) + '"?;
//当字W串要{换成 JString 我们需要先对字W串q行 UTF8 ~码后再转换?PChar 再{换成 JString
//q样才能保证q回的字W串?JAVA 中不q
Result := JVM.StringToJString(pchar(UTF8Encode(tmpStr)));
JVM.Free;
end;
exports
Java_alvinJNI_HelloWorld_printText;
end.
//--------------------------------------------------------------------------------
再看看效果吧,是不是成功了?
q里如果q回值的cd是其它的其本cd,比如 JLong,JInt,JFloat,JDouble,JBoolean,JShort,JByte
q些cd的数据可以直接与 Delphi 中的数据q算,对应 Int64,Integer,Single,Double,Boolean,SmallInt,ShortInt
q回时可以直接给 Result ?Delphi 中的数? ?
function Java_alvinJNI_HelloWorld_getInt(PEnv: PJNIEnv; Obj: JObject): JInt; stdcall;
var
tmp: Integer;
begin
tmp := 10;
Result := tmp;
end;
如果q回值的cd?Object ?Java 对象,q回 JObject cd,它的用法我们在以后再来学?
如果q回值的cd?Type[] 数组,接收参数时要设ؓ(f) JObject cd,怎样创徏q样的数l对?我自׃q不知道,以后知道了我再来贴上
因ؓ(f) Java 是把数组作ؓ(f)对象看待?它要以以下的方式来?
例如: 我们要给 Delphi 的方法传入一?byte[] 型数l?在定?Delphi Ҏ(gu)时参数声明ؓ(f) bytearray: JObject
在方法中:
var
PByteArr: PJByte //PJByte ?JNI.pas 定义? 里面q有 PJBoolean, PJObject, PJInt {?.
JVM: TJNIEnv;
isCopy: Boolean;
begin
JVM:= TJNIEnv.Create(PEnv);
isCopy := false;
PByteArr := JVM.GetByteArrayElements(bytearray, isCopy); //调用q个Ҏ(gu),可以取得参?bytearray 的地址, isCopy 军_是否复制数组
//之后,我们可以通过 PByteArr l合 inc(PByteArr) q个指针来操作传q来的数l?
end;
好了,先说到q里,今天,你是不是又学C什?
在上一中,我们说了如何?Java 调用 Delphi E序的一个方法ƈ传递给其一个字W串参数,现在我们再来看一下如果传递的参数是其它基本类?又要怎么?
首先,我们先看一下如何传?int 型参?定义如下?Java c?
//----------------------------------------------------------------------------------------------------------
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;
//我们l这个方法加的参数是: i: JInt
procedure Java_alvinJNI_HelloWorld_printText(PEnv: PJNIEnv; Obj: JObject; i: JInt); stdcall;
var
tmpInt: Integer;
begin
//参数提交q来?int 型数?在这里是一?JInt 数据,它其实就是一?Integer 数据,它的使用更加方便
//它可以直接地参与 Interger cd数据的运?是不是很Ҏ(gu).
tmpInt := i + 100;
tmpInt := tmpInt - 100;
Writeln(tmpInt);
end;
exports
Java_alvinJNI_HelloWorld_printText;
end.
//----------------------------------------------------------------------------------------------------------
再看看效果吧,是不是成功了?
q里如果?long 型参?接收时要设ؓ(f) JLong cd,它也可以跟对应的整型数运?我们常用它跟 Int64 一赯?br />如果参数cd?float ,接收参数时要设ؓ(f) JFloat cd,它也可以跟跟 Single 一赯?br />如果参数cd?double ,接收参数时要设ؓ(f) JDouble cd,它也可以跟跟 Delphi 中的 Double 型数据一赯?br />如果参数cd?boolean ,接收参数时要设ؓ(f) JBoolean cd,它也可以跟跟 Delphi 中的布尔型数据一赯?br />如果参数cd?short ,接收参数时要设ؓ(f) JShort cd,它也可以跟跟 SmallInt 型数据一赯?br />如果参数cd?byte ,接收参数时要设ؓ(f) JByte cd,它也可以跟跟 ShortInt 型数据一赯?br />如果参数cd?Object ?Java 对象,接收时要设ؓ(f) JObject cd,它的用法比较复杂(涉及(qing)到对 Java cd对象的操?,我们在以后再来学?
如果参数cd?Type[] 数组,接收参数时要设ؓ(f) JObject cd,因ؓ(f) Java 是把数组作ؓ(f)对象看待?它要以以下的方式来?
例如: 我们要给 Delphi 的方法传入一?byte[] 型数l?在定?Delphi Ҏ(gu)时参数声明ؓ(f) bytearray: JObject
在方法中:
var
PByteArr: PJByte //PJByte ?JNI.pas 定义? 里面q有 PJBoolean, PJObject, PJInt {?.
JVM: TJNIEnv;
isCopy: Boolean;
begin
JVM:= TJNIEnv.Create(PEnv);
isCopy := false;
PByteArr := JVM.GetByteArrayElements(bytearray, isCopy); //调用q个Ҏ(gu),可以取得参?bytearray 的地址, isCopy 军_是否复制数组
//之后,我们可以通过 PByteArr l合 inc(PByteArr) q个指针来操作传q来的数l?
end;
好了,先说到q里,今天,你是不是又学C什?
在上一中,我们说了如何?Java 调用 Delphi E序的一个方?今天我们再深入一?是怎样提交参数?Delphi 的方?以动态的控制 Delphi 的方?
下面,我们切入正题.
首先,我们定义如下?Java c?
//----------------------------------------------------------------------------------------------------------
package alvinJNI;
class HelloWorld {
static {
System.loadLibrary("DelphiAction");
}
public native void printText(String str);
public static void main(String[] args) {
HelloWorld hw = new HelloWorld();
hw.printText("(zhn)好Q看到效果了吧?);
}
}
//----------------------------------------------------------------------------------------------------------
我们再像上次一样在 Delphi 中徏?DLL 工程,写下面的代码(有注?:
//----------------------------------------------------------------------------------------------------------
library DelphiAction;
uses
JNI;
//q一ơ我们要写的q个Ҏ(gu)因ؓ(f)要接收一?Java 传过来的参数,所以我们来说一下这个参数列表的问题
//参数列表中的W一个参?PEnv cd?PJNIEnv, 它是 JNI.pas中定义的cd,我们好多工作要通过它来实现,可以把它看成是一个帮你的E序?Java 沟通的桥梁.
//参数列表中的W一个参?obj cd?JObject.前面q两个参数是固定?q第二个参数暂时我们q不?x)用?
//今天,我们q要l这个方法多加一个参?用来接受 Java 传过来的参数. str: JString
procedure Java_alvinJNI_HelloWorld_printText(PEnv: PJNIEnv; Obj: JObject; str: JString); stdcall;
//q回我们需要用C?TJNIEnv 对象,我们来声?br />var
JVM: TJNIEnv;
tmpStr: String;
begin
//实例?JVM, q个对象可以看成?Java 的虚拟机.(自己的理?
JVM := TJNIEnv.Create(PEnv);
//参数提交q来的字W串,实际上是一?JString 对象,我们在这里要?JVM 来{化它.
//我们调用 JVM ?UnicodeJStringToString 函数可以实?JString ?String 的{化了.
tmpStr := JVM.UnicodeJStringToString(str);
Writeln(tmpStr);
//我们使用?JVM ?要将光?
JVM.Free;
end;
exports
Java_alvinJNI_HelloWorld_printText; //为函数做引出声明,q样才能真正的被调用?br />end.
//----------------------------------------------------------------------------------------------------------
我们现在可以生?DelphiAction.dll 其攑֜ Java 工程目录? 再执?alvinJNI.HelloWorld 看看效果?
好了,我们今天主要是实现了一?如何?Java 调用 Delphi 的方法时,l其提交一个参?
是不是很?
今天先说到q里.接下?我会(x)快的再贴上一些文?/p>