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

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

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

    Java世界

    學習筆記

    常用鏈接

    統(tǒng)計

    積分與排名

    天籟村

    新華網(wǎng)

    雅虎

    最新評論

    如何在c++中調(diào)用java代碼(轉(zhuǎn)載)

    在我們的日常工作中,可能會遇到不同語言之間相互調(diào)用的問題,常見的有java調(diào)用C/C++或者在C/C++中調(diào)用java,我們可以基于sun提供的jni技術來實現(xiàn)這兩種語言之間的相互調(diào)用,這篇文章來說一下在c++中調(diào)用java的情況,至于java如何調(diào)用c我會在另外一篇文章中單獨講。

     

    c++調(diào)用java其實并不復雜,分為幾個步驟:

     

    在說調(diào)用之前,我們先來看看我們需要調(diào)用的java類

    public class Test {

    Java代碼  收藏代碼
    1. public Test() {  
    2.       
    3. }  
    4.   
    5. public String getMessage(){  
    6.     return "test ok";  
    7. }  
    8.   
    9. public TestObject getObject() {  
    10.     System.out.println("invoke getObject ok***");  
    11.     TestObject to = new TestObject();  
    12.     to.setName("name");  
    13.     to.setPwd("pwd");  
    14.     return to;  
    15. }  
    16.   
    17. public void test() {  
    18.     System.out.println("%%% invoke test ok***");  
    19. }  

      這是一個很簡單的類,他有一個無參的構(gòu)造函數(shù),有三個方法,一個帶有String返回值的方法,一個是返回一個我們自定義的對象TestObject,另外還有一個沒有返回值的test方法。

    接下來是TestObject類

     

    Java代碼  收藏代碼
    1. public class TestObject {  
    2.     public String name;  
    3.       
    4.     public String pwd;  
    5.   
    6.     public String getName() {  
    7.         return name;  
    8.     }  
    9.   
    10.     public void setName(String name) {  
    11.         this.name = name;  
    12.     }  
    13.   
    14.     public String getPwd() {  
    15.         return pwd;  
    16.     }  
    17.   
    18.     public void setPwd(String pwd) {  
    19.         this.pwd = pwd;  
    20.     }  
    21.       
    22.     public void callback(String content) {  
    23.         System.out.println("%%%call back ok*** cotnent is: " + content);  
    24.         System.out.println("name is: " + name);  
    25.         System.out.println("pwd is: " + pwd);  
    26.     }  
    27.       
    28. }  

     

      也是一個很簡單的類,有兩個屬性,還有一個回調(diào)函數(shù),主要是想演示一下我們?nèi)缭贑++中獲取該對象以后,進行回調(diào),這也是我們經(jīng)常會遇到的問題。

     

    上面看了我們的java測試類,接下來,我們來具體看看如何進行調(diào)用

     

    創(chuàng)建jvm

    我們首先需要初始化一些jvm的參數(shù),然后創(chuàng)建出jenv和jvm以便我們之后的調(diào)用

     

    Cpp代碼  收藏代碼
    1.        JavaVMOption options[1];  
    2. JNIEnv *env;  
    3. JavaVM *jvm;  
    4. JavaVMInitArgs vm_args;  
    5. long status;  
    6. jclass testCls;  
    7. jmethodID testMid;  
    8. jobject testJobj;     
    9. jobject tookitReturnObj;  
    10. //設置Java類的路徑  
    11. options[0].optionString = "-Djava.class.path=. ;D:\\workspace\\my\\JniTest\\jnitest.jar";  
    12. vm_args.version = JNI_VERSION_1_6;  
    13.        vm_args.nOptions = 1;  
    14.        vm_args.options = options;  
    15.        vm_args.ignoreUnrecognized = JNI_TRUE;  
    16.        status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);  

     

     這里需要指出的是,在設置classpath的時候,如果需要引用的是jar包,需要把jar包的名稱一并引入,而不能是只指定jar所在目錄,這就會造成一個問題,如果我們依賴的jar很多,那么classPath就需要逐一寫出jar包名稱來,這對于有著幾十個引用jar的項目來說還是會造成一定的麻煩,我推薦大家使用fatjar的一個工具,fatjar可以把依賴的jar合并打成一個jar包,這樣的話,可以減少我們在書寫classpath的過程中,寫太多的jar包,為我們省點事,而且對于維護來講也比較清晰。

     

    加載調(diào)用的java類

    當我們創(chuàng)建完jvm后,會得到一個返回值,如果為0說明創(chuàng)建成功,如果否則創(chuàng)建失敗。

    當我們成功創(chuàng)建完jvm后,接下來我們找到需要調(diào)用的java類

     

    Cpp代碼  收藏代碼
    1. if (status != JNI_ERR)  
    2. {  
    3.     testCls = env->FindClass("jni/test/Test");  
    4. }  

     

    這里我們要使用Test的一個java類,它所在的包尾jni.test。

    如果加載成功,那么testCls不為0,否則將返回0

     

    調(diào)用構(gòu)造函數(shù),創(chuàng)建對象

    像我們在java語言中一樣,我們首先需要調(diào)用構(gòu)造函數(shù)創(chuàng)建一個對象實例,然后再進行方法調(diào)用,那么在C++中同樣需要我們這么做,當然調(diào)用靜態(tài)方法例外。

          testMid = env->GetMethodID( testCls, "<init>", "()V");

    Java代碼  收藏代碼
    1. if (testMid != 0)  
    2. {  
    3.     testJobj = env->NewObject(testCls,testMid);  
    4.     std::cout << "init test class ok" << std::endl;  
    5. }  

      我們可以看到我們首先進行GetMethodID調(diào)用,這個函數(shù)有三個參數(shù),一個是我們之前獲取的jclass對象,第二參數(shù)是需要調(diào)用的java類中的方法名稱,由于我們是調(diào)用構(gòu)造函數(shù),所以<init>是個固定的寫法,他就是說明我們要調(diào)用構(gòu)造函數(shù),第三參數(shù)是調(diào)用方法的參數(shù)類型,關于這個參數(shù)的類型,我們可以使用javap命令來獲取,具體命令如下:

    javap -p -s jni.test.Test

    然后我們會得到這樣的信息

     

    Java代碼  收藏代碼
    1. Compiled from "Test.java"  
    2. public class jni.test.Test extends java.lang.Object{  
    3. public jni.test.Test();  
    4.   Signature: ()V  
    5. public java.lang.String getMessage();  
    6.   Signature: ()Ljava/lang/String;  
    7. public jni.test.domain.TestObject getObject();  
    8.   Signature: ()Ljni/test/domain/TestObject;  
    9. public void test();  
    10.   Signature: ()V  
    11. }  

     

      我們可以看到Test()構(gòu)造函數(shù),在Signature后面就是該方法的參數(shù)類型。

    當我們獲取構(gòu)造函數(shù)以后,我們就可以對其進行實例化了,使用NewObject

     

    方法調(diào)用

    接下來我們就可以進行方法調(diào)用了

    Cpp代碼  收藏代碼
    1. testMid = env->GetMethodID( testCls, "test","()V");  
    2. if (testMid != 0)  
    3. {  
    4.     env->CallVoidMethod(testJobj,testMid);             
    5. }  
    6.   
    7. testMid = env->GetMethodID( testCls, "getMessage","()Ljava/lang/String;");  
    8. if (testMid != 0)  
    9. {  
    10.     jobject msg = env->CallObjectMethod(testJobj,testMid);  
    11.     std::cout << msg << std::endl;  
    12.     printf("msg : %d",msg);  
    13. }  

      上面的代碼里我們調(diào)用兩個方法,分別是test和getMessage,我們都是先調(diào)用GetmethodID來獲取一個jmethodID對象,然后調(diào)用CallXXXMethod來進行調(diào)用,跟java中的反射調(diào)用是一樣的。

    如果我們需要調(diào)用靜態(tài)方法,我們只需先GetStaticMethodID然后調(diào)用CallStaticXXXMethod即可,jni.h中定義了很多Call的方法,比如CallIntMethod,CallBooleanMethod等等,有興趣可以去查看jni.h

     

    下面我們來說一下如何進行回調(diào)

    我們的java測試類Test中有一個getObject的測試方法,得到了一個java對象,我們拿到該獨享后如何進行下一步的調(diào)用呢,其實很簡單,跟咱們之前的例子是類似的

    Cpp代碼  收藏代碼
    1. testMid = env->GetMethodID( testCls, "getObject","()Ljni/test/domain/TestObject;");  
    2.         if (testMid != 0)  
    3.         {  
    4.             jobject obj = env->CallObjectMethod(testJobj,testMid);  
    5.             jobject listener = env->NewGlobalRef(obj);  
    6.             jclass clsj = env->GetObjectClass(listener);  
    7.             jmethodID func = env->GetMethodID(clsj, "callback", "(Ljava/lang/String;)V");  
    8.             if(func != NULL)   
    9.             {  
    10.                 jobject msg1 = env->CallObjectMethod(testJobj,testMid);  
    11.                 env->CallVoidMethod(listener, func, msg1);  
    12.             }  
    13.             std::cout << obj << std::endl;  
    14.             printf("obj : %d",obj);  
    15.         }  
     

    同樣我們通過GetMethodID獲取getObject方法,然后調(diào)用該方法,得到一個返回的對象obj,我在代碼里進行一下處理,創(chuàng)建了一個全局引用,如果大家只想把他當做局部變量使用,那么不創(chuàng)建全局引用也可以;然后通過GetObjectClass我們得到了jclass對象,接下來就跟我們之前的過程一樣了,獲取方法,進行調(diào)用即可。

    上面的代碼中我在調(diào)用callback方法前有調(diào)用了一次getObject方法,主要是測試一下,獲取的對象,在進行callback的時候能不能保持其狀態(tài)。經(jīng)驗證是可以的。

    posted on 2012-06-07 09:22 Rabbit 閱讀(7447) 評論(2)  編輯  收藏

    評論

    # re: 如何在c++中調(diào)用java代碼(轉(zhuǎn)載) 2013-12-12 10:51 custjcy

    good post.

    In Java 6 and higher, one can add all jar-files in a specific directory to the classpath using wildcard notation.

    Windows example:
    java -classpath ".;c:\mylib\*" MyApp

    Linux example:
    java -classpath '.:/mylib/*' MyApp  回復  更多評論   

    # re: 如何在c++中調(diào)用java代碼(轉(zhuǎn)載) 2013-12-12 10:52 custjcy

    http://en.wikipedia.org/wiki/Classpath_(Java)  回復  更多評論   


    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導航:
     
    主站蜘蛛池模板: 亚洲国产精品久久人人爱| 免费h成人黄漫画嘿咻破解版| 国产a v无码专区亚洲av| 亚洲欧美成人综合久久久| 永久免费的网站在线观看| 亚洲特级aaaaaa毛片| 免费看男女下面日出水来| 激情综合亚洲色婷婷五月APP| 99久久免费精品国产72精品九九| 国产精品亚洲午夜一区二区三区| 色婷婷7777免费视频在线观看 | 亚洲精品无码乱码成人| 成人片黄网站色大片免费观看cn| 亚洲中文字幕第一页在线| 精品四虎免费观看国产高清午夜 | 91精品免费国产高清在线| 亚洲国产精品无码久久久| 免费中文熟妇在线影片| 人人狠狠综合久久亚洲| 亚洲熟伦熟女新五十路熟妇| 三根一起会坏掉的好痛免费三级全黄的视频在线观看 | 日韩精品免费在线视频| 亚洲综合久久成人69| 毛片免费观看视频| 日韩毛片在线免费观看| 青柠影视在线观看免费| 亚洲成AV人片在线播放无码| 99爱在线观看免费完整版 | 亚洲欧美日韩中文无线码| 亚洲av无码专区在线观看素人| 一个人看的www在线免费视频| 亚洲va在线va天堂va四虎 | 亚洲欧洲久久av| 先锋影音资源片午夜在线观看视频免费播放| 亚洲网址在线观看| 国产精品99久久免费| 成全视频免费观看在线看| 精品日韩99亚洲的在线发布 | 亚洲熟妇av一区二区三区下载| 免费网站看v片在线香蕉| 中文字幕成人免费高清在线|