转:Java JNI 和 Delphi 相互調用(1)-JAVA調用DELPHI

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

相关推荐