YukiRain 2020-04-11
JNI 不是什麼新技術,英文全稱是:Java Native Interface,JAVA本地化代碼接口。本地化代碼是指直接編譯成的與機器相關的二進制代碼,而不是Java字節碼之類的中間代碼。對於 JNI 的來龍去脈,不作介紹了,在 java.sun.com 有介紹,另外 BAIDU/GOOGLE 搜索,也有大把的。這裏僅僅做一個入門級的介紹和實現。
JAVA發佈的是C/C++的接口文檔,DELPHI想調用,首先要轉換成DELPHI的接口文檔。很幸運,已經有人完成此項工作了,請看網站:http://delphi-jedi.org/ ,在網站中下載 JNI-JEDI.zip ,解出來後,將pas文件放在我們要創建的工程的源文件一塊就可以了。
好,下面準備進入主題。
一、先介紹 JAVA 調用 DELPHI 的過程
1、創建一個 JavaCallDelphi.java,文件的內容:
public class JavaCallDelphi {
static {
System.loadLibrary("JavaCallDelphi");
}
public native void sayHello(String s);
public native String echo(String s);
public native void showForm(String s);
public static void main(String[] args) {
JavaCallDelphi jc = new JavaCallDelphi();
System.out.println("java say: echo() returned:"+jc.echo("華夏上下午千年") );
jc.sayHello("橙子");
jc.showForm("華夏上下午千年");
}
}
為了簡單,這裏就不創建“包”了。我們將這個 class 保存成無 BOM 的 UTF-8 格式文件。再用下面這個命令行進行編譯:
javac -encoding utf-8 JavaCallDelphi.java
這個 class 現在是不能執行的,因為還沒有 JavaCallDelphi.dll 。
2、創建 Delphi 的庫工程
先提一下JAVA的類和方法的命名和DELPHI中的函數的命名的規律。
在DELPHI中的函數,以Java開頭,用下劃線將Java類的包名、類名和方法名連起來。本例中沒有包名,忽略了。同時,在Win32平台上,此過程的調用方式只能聲明為 stdcall。
例如,Delphi中的方法:
procedure Java_JavaCallDelphi_sayHello(PEnv: PJNIEnv; Obj: JObject; S: jstring); stdcall;
方法中的參數,前兩個是固定的,有什麼用請看後面的 DELPHI 的代碼,不深入講解;後面的參數就是 JAVA 和 DELPHI 之間傳送的參數。JAVA 的數據類型轉換到 DELPHI 的數據類型,在 jni.pas 中有定義。
JavaCallDelphi.dpr 的代碼:
library JavaCallDelphi;
uses windows, SysUtils, Classes, jni, Forms, StdCtrls;
procedure Java_JavaCallDelphi_sayHello(PEnv: PJNIEnv; Obj: JObject; S: jstring); stdcall;
var JVM: TJNIEnv;
begin
JVM:= TJNIEnv.Create(PEnv);
Writeln(‘Delphi say:‘+JVM.UnicodeJStringToString(s)+‘,您好!看到效果了吧。‘);
JVM.Free;
end;
function Java_JavaCallDelphi_echo(PEnv: PJNIEnv; Obj: JObject; arg: JString): JString; stdcall;
var tmpStr, s1: String; JVM: TJNIEnv;
begin
JVM:= TJNIEnv.Create(PEnv);
Write(‘Delphi say:jvm Version :‘);
Write(jvm.MajorVersion); Write(‘.‘);
Write(jvm.MinorVersion);
Writeln(‘‘);
s1:=JVM.UnicodeJStringToString(arg);
tmpStr := ‘傳入的參數是: "‘ + s1 + ‘"。‘;
Writeln(‘Delphi say: parameter is:‘+s1);
Writeln(‘Delphi say: return string:‘+tmpStr);
result := JVM.StringToJString( PChar(UTF8Encode(tmpstr)) );
JVM.Free;
end;
procedure Java_JavaCallDelphi_showForm(PEnv: PJNIEnv; Obj: JObject; arg: JString);stdcall;
var f:TForm; edit: TEdit; tmpStr: String; jvm:TJniEnv;
begin
jvm:=TJniEnv.Create(PEnv);
tmpStr := JVM.UnicodeJStringToString(arg);
f:=TForm.Create(nil);
f.SetBounds(100, 100, 400, 200 );
Edit := TEdit.Create(f);
Edit.Parent := f;
Edit.Show();
Edit.Left := 0;
Edit.Top := 0;
Edit.Width := 390;
edit.Text := ‘Java傳過來的參數是:‘+tmpstr;
f.ShowModal();
freeAndNil(f);
freeAndNil(jvm);
end;
exports
Java_JavaCallDelphi_sayHello, //為函數做引出聲明,這樣才能被調用
Java_JavaCallDelphi_echo,
Java_JavaCallDelphi_showForm
;
begin
end.
準備做命令行編譯,別忘記jni.pas和jni_md.inc放在一塊,編譯命令:
dcc32 /B JavaCallDelphi.dpr
3、執行、測試
將這幾個命令行的編譯做成一個批處理文件:
@ECHO OFF
rem java的執行的參數. 根據實際的環境,修改參數中的編碼名稱/語言名稱/地區名稱
rem 編碼名稱/語言名稱/地區名稱, 要和操作系統相對應,否則會出現亂碼.
SET PA=-Dclient.encoding.override=big5 -Dfile.encoding=big5 -Duser.language=zh -Duser.region=TW
rem jre所在的路徑,像 JAVA_HOME 一樣指向安裝的目錄
SET JRE_HOME=C:sdk/jdk1.5.0_15jre
SET PATH=%PATH%;C:/Program Files/borland/Delphi7/Bin
SET PATH=%PATH%;%JRE_HOME%/bin/client
REM 編譯delphi的工程
dcc32 /B JavaCallDelphi.dpr
rem java 的編譯命令行
javac -encoding big5 JavaCallDelphi.java
echo.
rem 執行demo
java %PA% JavaCallDelphi
————————————————
版权声明:本文为CSDN博主「cangwu_lee」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/cangwu_lee/java/article/details/2211517