<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    聚合 管理  

    Blog Stats

    News

    我使用新博客啦:
    http://www.linjunhai.com/
    大家到我的新博客上看看吧!

    隨筆分類(28)

    文章分類(4)

    隨筆檔案(53)

    文章檔案(4)

    相冊

    相關鏈接


    林俊海的博客

    超級大菜鳥,每天要自強!

    通過 JNI 讓 JAVA 與 Delphi 程序交互(五)

    之前,我們學了如何用 Java 調用 Delphi 程序的一個方法
    如果在Delphi 程序在適當時候需要調用 Java 程序,又要怎么做呢?

    首先,我們先定義如下的 Java 類:

    //------------------------------------------------------------------------------
    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;

    //今天的這個程序稍微的復雜一點,因為要調用 Java 對象的方法,在這里可以學到對 JObject 的操作
    procedure Java_alvinJNI_HelloWorld_callPrintText(PEnv: PJNIEnv; Obj: JObject; arg: JObject); stdcall;
    var
    ? JVM: TJNIEnv;
    ? c: JClass;? //類ID
    ? fid: JFieldID;? //屬性ID
    ? mid: JMethodID;? //方法ID
    ? tmpStr: JString;
    ? javaargs : array[0..0] of JValue; //調用方法時的參數
    begin
    ? JVM := TJNIEnv.Create(PEnv);

    ? {我們先來看下如何獲得一個對象的某個屬性值}
    ? {----------------------------------------}
    ? {我們對 Java 對象的操作要選獲取這個對象的 ClassID,我們可以用下面的方法來取得.}
    ? c := JVM.GetObjectClass(arg);

    ? {我們先來獲取參數 HelloWorld arg 對象的 String str 這個屬性的值
    ?? 這里我們先要獲得這個屬性在它所在類中的屬性 ID }
    ? fid := JVM.GetFieldID(c, 'str', 'Ljava/lang/String;');
    ? {上面調用的這個方法中的參數分別是: 所屬類ID, 屬性名, 屬性類型簽名
    ?? 關于屬性類型的簽名,將在下面 '說明1' 給出}

    ? {下面,我們就可以根據 屬性ID 來獲取屬性值了, 這里我們會取得到 arg.str 這個字符串}
    ? tmpStr := JVM.GetObjectField(arg, fid);
    ? {上面的這個 JVM.GetObjectField(arg, fid) 用來獲取屬性值
    ?? 參數分別是: 要取得其屬性的對象, 要取得的屬性的屬性ID
    ?? 這里取得的是一個 Java 的 String 對象,是 JString,其實它也就是 JObject 類型的}
    ? writeln('Delphi 輸出的: ' + JVM.UnicodeJStringToString(tmpStr));

    ?


    ? {我們再來看下如何調用一個 JObject 的方法, 這里我們要調用的是 arg.printText() 這個方法}
    ? {------------------------------------------------------------------------------------}
    ? //我們還是要用到上面的那個 類ID: c.
    ? //這一次我們要取得這個方法的 方法ID
    ? mid := JVM.GetMethodID(c, 'printText', '(Ljava/lang/String;)V');
    ? //上面調用的這個方法中的參數分別是: 所屬類ID, 方法名, 方法(參數+返回值)類型簽名
    ? //關于方法(參數+返回值)類型的簽名,將在下面 '說明2' 給出

    ? //有了 方法ID 后我們就可以用這個ID來調用這個方法了,我們這里要調用的方法是: arg.printText(參數);
    ? //因為我們要調用的這個方法有參數, 調用 Java 方法的時候如果有參數,要建立參數數組,這里我們就來建立數組
    ? javaargs[0].l := tmpStr;
    ? {這里這個 javaargs 是 JValue 類型. 它有點特殊,它的用法在下面 說明3 給出}

    ? {有了 類象, 方法ID, 參數. 下面我們就可以調用 arg.printText(javaargs) 這個方法了,使用下面這個方法就可實現}
    ? JVM.CallObjectMethodA(arg, mid, @javaargs);

    ? JVM.Free;
    end;

    exports
    ??????? Java_alvinJNI_HelloWorld_callPrintText;
    end.

    //--------------------------------------------------------------------------------

    到這里,我們已經可以從 Delphi 中獲得 Java 對象的屬性了, 還可以調用一個 Java 對象的方法,是不是很酷呢?
    你學到了沒?


    ###########################說明1###############################
    現在,我們還要再了解一個獲取 "屬性ID" 時的那個簽名
    上面例子中: fid := JVM.GetFieldID(c, 'str', 'Ljava/lang/String;'); 用的簽名是: 'Ljava/lang/String;'
    因為剛剛要獲得的屬性是 java.lang.String 類型的,所以它的簽名是: 'Ljava/lang/String;'
    如果,我們要獲得的屬性是其它類型,獲取 屬性ID 時又要怎樣簽名呢?下面給出一個對照表

    byte -- B
    char --- C
    double -- D
    float -- F
    int -- I
    long -- J (注意:是J不是L)
    short -- S
    void -- V
    boolean - Z(注意:是Z不是B)
    class(類對象類型) - 'L'+完整類名+';'? (包路徑分隔符為: '/'.?? 如上面例子中的 String 對型, 簽名為: 'Ljava/lang/String;')

    數組 type[] -- '['+type (例如 float[] 的簽名就是 '[float')
    (如果是二維數組,如float[][],則簽名為 '[[float')


    ############################說明2###############################
    現在,我們還要再了解一個獲取 "方法ID" 時的那個簽名
    上面例子中: mid := JVM.GetMethodID(c, 'printText', '(Ljava/lang/String;)V'); 用的簽名是: '(Ljava/lang/String;)V'
    方法ID 的簽名,分為兩部分
    一部分是前面括號中的,是參數類型的簽名
    另一部分是括號后的,是返回值類型的簽名
    其中某個簽數與返回值的類型簽名與獲取屬性ID時的簽名是一樣的
    上面要調用的方法只有一個參數,如果有多個參數時又怎樣呢?

    如: int getInt(long a, double b); 這樣的 Java 方法要這樣簽名: '(JD)I'
    (注意:參數簽名是連續的,沒有分隔符, 這里第一個參數 long 簽名為:J, 第二個參數簽名為: D, 返回值類型 int 簽名為: I)
    說到這里,相信大家都會使用這個簽名了


    ############################說明3###############################
    在調用一個 Java 方法時, 如果這個方法有參數, 我們就要傳遞一個參數數組的地址給 Java
    現在,我們還要再了解如何創建這樣的一個參數數組
    傳遞給 Java 方法的參數,類型均為 JValue. 它是一個packed record


    如果,我們要調用的方法 void myMethod(int a, long b, String c); 有 3 個參數
    那么
    1.我們先要聲明如下數組:
    var
    ? args : array[0..1] of JValue;
    2.給數組賦值
    ? args[0].i := 100;
    ? args[1].j := 100;
    ? args[2].l := JVM.StringToJString(pchar(UTF8Encode('雅林網絡 )));
    3.調用
    ? JVM.CallVoidMethodA(Java對象, 方法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;

    調用方法時,TJNIEnv 還有:
    ??? 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 的話題就先說到這里
    如果有興趣,大家可以打開 jni.pas 了解更多


    評論

    # re: 通過 JNI 讓 JAVA 與 Delphi 程序交互(五) 2007-05-24 17:14 sunboylyg
    大俠,你這個在Delphi里調用java方法的例子好像沒法用:
    你的例子里面先是在java里調用Delphi方法,同時把自己當作參數(arg)傳給Delphi,然后才在Delphi里利用這個參數調用java方法。
    說白了,還是java調用delphi的例子,如果我想直接在delphi里調用java,那么上面說道的arg從哪里得來呢?困惑中……  回復  更多評論
      

    # re: 通過 JNI 讓 JAVA 與 Delphi 程序交互(五) 2007-05-24 17:22 sunboylyg
    高人啊!看了你這一系列的文章,真是收益匪淺,還望指點迷津,到底怎么樣才能在delphi里調用java呢,上面的疑問怎么解決?  回復  更多評論
      

    # re: 通過 JNI 讓 JAVA 與 Delphi 程序交互(五) 2007-05-25 08:14 林志斌
    http://www.tkk7.com/Files/alvin/DelphiCallJava.rar
    上面是 Delphi 主動調用 Java 的一個例子,sunboylyg 可以看一下  回復  更多評論
      

    # re: 通過 JNI 讓 JAVA 與 Delphi 程序交互(五) 2007-05-25 08:37 sunboylyg
    大俠行俠仗義,慷慨大方,實在令人敬佩!只可惜,鄙人才疏學淺,未有以報也……  回復  更多評論
      

    主站蜘蛛池模板: 久久久久久夜精品精品免费啦| 亚洲成年人免费网站| 亚洲成亚洲乱码一二三四区软件| 91免费在线视频| 99亚偷拍自图区亚洲| 亚洲人成无码网站久久99热国产| 暖暖在线视频免费视频| 亚洲一区二区三区在线| 亚洲一级Av无码毛片久久精品| 99re在线这里只有精品免费| 欧美色欧美亚洲另类二区| 亚洲国产成人精品无码区在线观看| 国产精品视频免费一区二区| sss在线观看免费高清| 亚洲一卡二卡三卡| 亚洲精品国产成人片| 在线视频免费观看www动漫| 免费萌白酱国产一区二区三区 | 国产高清免费观看| 无码日韩精品一区二区三区免费 | 国产日韩在线视频免费播放| 亚洲天堂福利视频| 亚洲精品无码乱码成人| 免费网站看v片在线香蕉| 99精品视频在线观看免费专区| 亚州**色毛片免费观看| 亚洲一久久久久久久久| 久久久久亚洲AV成人无码| 亚洲 小说区 图片区 都市| 色影音免费色资源| 男人的天堂网免费网站| xxxxx做受大片在线观看免费| 亚洲AV无码一区二区三区牛牛| 久久九九亚洲精品| 相泽亚洲一区中文字幕| 免费一级一片一毛片| 国产人在线成免费视频| 无码精品一区二区三区免费视频| 国产精品免费久久| 深夜福利在线视频免费| 综合一区自拍亚洲综合图区|