通過JNI實現(xiàn)Java和C++的相互調(diào)用

           

          通過JNI實現(xiàn)JavaC++的相互調(diào)用

          一、Java調(diào)用C++DLL

          1.    創(chuàng)建Java文件

          創(chuàng)建名為TestNativeJava文件,注意包名。

          package org.druze.test;

          publicclass TestNative {

              publicnativevoid sayHello();

              publicvoid sayHello2(){

                 System.out.println("Say Hello From Java");

              }

          }

          如代碼所示,對于sayHello方法聲明為native,這一部分將由C++的動態(tài)庫來實現(xiàn)。

          2.    生成class文件

          使用javac org/druze/test/TestNative.java生成class文件

          注意:執(zhí)行該命令在org所在目錄執(zhí)行。

          3.    使用javah命令生成相應(yīng)的C++頭文件

          使用javah org.druze.test.TestNative生成名為

          org_druze_test_TestNative.h的頭文件

          注意:執(zhí)行該命令在org所在目錄執(zhí)行。

          該頭文件的內(nèi)容如下:

          /* DO NOT EDIT THIS FILE - it is machine generated */

          #include <jni.h>

          /* Header for class org_druze_test_TestNative */

          #ifndef _Included_org_druze_test_TestNative

          #define _Included_org_druze_test_TestNative

          #ifdef __cplusplus

          extern "C" {

          #endif

          /*

           * Class:     org_druze_test_TestNative

           * Method:    sayHello

           * Signature: ()V

           */

          JNIEXPORT void JNICALL Java_org_druze_test_TestNative_sayHello

           (JNIEnv *, jobject);

          #ifdef __cplusplus

          }

          #endif

          #endif

          4.    創(chuàng)建C++解決方案

          此處以VS2008為例。

          新建一個VC++Win32項目,選擇如圖所示的控制臺應(yīng)用程序。項目名稱為NativeCode

          點擊確定后,再點擊下一步,出現(xiàn)該頁面,應(yīng)用程序類型選擇DLL,附加選項選擇DLL

          5.    創(chuàng)建號工程之后,將org_druze_test_TestNative.h導(dǎo)入到工程里面,并創(chuàng)建名為source.cpp的源代碼,內(nèi)容如下:

          #include"org_druze_test_TestNative.h"  

          #include<iostream>  

          using namespace std;  

          JNIEXPORT void JNICALL Java_org_druze_test_TestNative_sayHello(JNIEnv *env, jobject obj)

          {  

              cout<<"Hello World!"<<endl;  

          6.    在工具->選項->項目和解決方案->VC++目錄菜單中,平臺選擇Win32,選擇“顯示以下內(nèi)容的目錄”為“包含文件”,導(dǎo)入jni.hjni_md.h的路徑。

          7.    編譯,生成NativeCode.dll,并將其copy到環(huán)境變量PATH的路徑下。

          8.    修改TestNative.java

          package org.druze.test;

          publicclass TestNative {

              publicnativevoid sayHello();

              publicstaticvoid main(String[] args) {

                  // 加載動態(tài)連接庫DLL,如果沒有找到的話,則會在運行時報錯  

                  System.loadLibrary("NativeCode");  

                    

                  TestNative tnt = new TestNative();  

                        

                  tnt.sayHello();  

              }

              publicvoid sayHello2(){

                 System.out.println("Say Hello From Java");

              }

          }

          運行,顯示“Hello World! 

          9.    注意頭文件jni.hjni_md.h可以直接導(dǎo)入到工程中也可以。

          10.注意NativeCode.dll必須放置在java命令能訪問的路徑中。

          二、C++調(diào)用Java

          1.創(chuàng)建TestNative2.Java

          package org.druze.test;

          publicclass TestNative2 {

              publicstaticvoid testPrint(){

                 System.out.println("this is from static method");

              }

              publicstaticint testReturn(){

                 return 22;

              }

              publicstaticint testInput(int number){

                 return 22+number;

              }

              publicint testInstance(int number){

                 System.out.println("this is from instance method");

                 return 11+number;

              }

          }

          2.VS2008中創(chuàng)建win32控制臺的應(yīng)用程序,命名為NativeCode2,在向?qū)е羞x擇空項目。

          3. 在工具->選項->項目和解決方案->VC++目錄菜單中,平臺選擇Win32,選擇“顯示以下內(nèi)容的目錄”為“包含文件”,導(dǎo)入jni.hjni_md.h的路徑。直接把jni.hjni_md.h導(dǎo)入到工程中。

          4. 在工具->選項->項目和解決方案->VC++目錄菜單中,平臺選擇Win32,選擇“顯示以下內(nèi)容的目錄”為“包含文件”,導(dǎo)入jvm.lib的路徑,并在項目->NativeCode2屬性->配置屬性->鏈接器->命令行中添加jvm.lib(這一步或者使用#pragma comment(lib,"jvm.lib")來代替)。或者將直接將jvm.lib添加到工程中。

          5.創(chuàng)建Test.cpp

          #include <jni.h>

          #include <iostream>

          using namespace std;

          int main()

          {

              JavaVMOption options[1];

              JNIEnv * env;

              JavaVM * jvm;

              JavaVMInitArgs vm_args;

              options[0].optionString = "-Djava.class.path=.";

              vm_args.version = JNI_VERSION_1_6;

              vm_args.nOptions = 1;

              vm_args.options = options;

              vm_args.ignoreUnrecognized = JNI_TRUE;

              long status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

              if (status == JNI_ERR)

              {

                  cout<<"Can not create JVM"<<endl;

                  return -1;

              }

              printf("Created JVM"n");

              jclass cls = env->FindClass("org/druze/test/TestNative2");

              printf("getCls"n");

               cout<<cls<<endl;

              if (cls !=0)

              {

                  jmethodID mid = env->GetStaticMethodID(cls, "testReturn", "()I");

                  printf("getMid"n");

                  if (mid !=0)

                  {

                      printf("testReturn"n");

                      int result=env->CallStaticIntMethod(cls, mid);

                      printf("call over result=%d"n",result);

                  }

                  mid = env->GetStaticMethodID(cls, "testPrint", "()V");

                  if (mid !=0)

                  {

                      printf("testPrint"n");

                      env->CallStaticVoidMethod(cls, mid);

                  }

                  mid = env->GetStaticMethodID(cls, "testInput", "(I)I");

                  if (mid !=0)

                  {

                      printf("testInput"n");

                      int result=env->CallStaticIntMethod(cls, mid,22);

                      printf("call over result=%d"n",result);

                  }

                  mid = env->GetMethodID(cls,"<init>","()V");

                  if (mid != 0)//獲取方法成功

                  {

                      printf("ctro!=0"n");

                      jobject obj=env->NewObject(cls, mid);

                      printf("new object"n");

                      mid = env->GetMethodID(cls, "testInstance","(I)I");

                      if (mid!=0)//獲取方法成功

                      {

                          printf("methodID!=0"n");

                          jint result=env->CallIntMethod( obj, mid,22);

                          cout<<result<<endl;

                      }

                  }

              }

              jvm->DestroyJavaVM();

              system("Pause");

              return 0;

          }

          6.jvm.dll目錄添加到PATH環(huán)境變量中,將org/druze/test/TestNative2復(fù)制到debug目錄下執(zhí)行。

          7.頭文件和庫文件的配置VC6VC2008類似,菜單名稱有所改變。

          VC6中,配置頭文件和庫文件的目錄在,工具(Tools)->選項(Options)->目錄(Directories)里面的頭文件”Include files”和庫文件”Library files”.添加相應(yīng)的目錄

          工程(Project)->設(shè)置(Setting)->鏈接(Link)->object/module library后面添加jvm.lib

          CodeBlocksProject->Build options->Linker setting and Search directories中配置相應(yīng)路徑。

          8.按如下結(jié)構(gòu)組織可不用配置jvm.dll到環(huán)境變量中

          創(chuàng)建存放目錄Run(下面的文件目錄在JDK安裝目錄中都能找倒):

          Run(手工建立目錄)

          ----bin(手工建立目錄)

                ----classic(手工建立目錄)

                      ----jvm.dll(文件,JDK安裝目錄中有)

                      ----自己的JAR包,如果是class文件把包目錄和文件一起拷貝過來

                           如果是jar文件,需要在options[1].optionString = "-Djava.class.path=.;./swt.jar";中設(shè)置

                      ----JniC.exe,C調(diào)用JAVA的程序

                ----hpi.dll(文件,JDK安裝目錄中有)

                ----ioser12.dll(文件,JDK安裝目錄中有)

                ----java.dll(文件,JDK安裝目錄中有)

                ----net.dll(文件,JDK安裝目錄中有)

                ----verify.dll(文件,JDK安裝目錄中有)

               ----zip.dll(文件,JDK安裝目錄中有)

          ----lib(手工建立目錄)

                ----zi(目錄,JDK安裝目錄中有,全部拷貝過來)

                ----rt.jar(文件,JDK安裝目錄中有)

                ----tzmappings(文件,JDK安裝目錄中有)

          三、JNI代碼分析(待續(xù))

          posted on 2008-07-29 12:48 role0523-- 閱讀(11428) 評論(23)  編輯  收藏

          評論

          # re: 通過JNI實現(xiàn)Java和C++的相互調(diào)用 2008-07-29 14:14 Always BaNg.

          不錯,把字符轉(zhuǎn)換也一并講了吧,比如UTF-8的處理,USC-2與MBCS轉(zhuǎn)換等。  回復(fù)  更多評論   

          # re: 通過JNI實現(xiàn)Java和C++的相互調(diào)用[未登錄] 2008-07-29 14:17 role0523

          你是指Java和C++之間的字符轉(zhuǎn)換?
          目前還沒有研究過字符轉(zhuǎn)換。
            回復(fù)  更多評論   

          # re: 通過JNI實現(xiàn)Java和C++的相互調(diào)用 2008-07-31 23:58 coldsummer

          如果是現(xiàn)成的dll呢?比如某硬件提供的開發(fā)dll開發(fā)包,我如何調(diào)用?  回復(fù)  更多評論   

          # re: 通過JNI實現(xiàn)Java和C++的相互調(diào)用[未登錄] 2008-08-01 00:05 role0523

          @coldsummer
          由于JAVA調(diào)用C++需要一定的格式,比如在JAVA中聲明native方法,然后通過javah生成一個頭文件,然后寫cpp文件,但必須實現(xiàn)這個頭文件中聲明的JNIEXPORT方法。這些方法是Java調(diào)用C++的入口。所以在這些方法內(nèi)部填寫對你的DLL的調(diào)用即可。  回復(fù)  更多評論   

          # re: 通過JNI實現(xiàn)Java和C++的相互調(diào)用 2008-08-26 17:14 lfking

          你的這個JAVA調(diào)用C++的例子,我試了一整天,沒試明白!~~
          在最后編譯成DLL文件時老是報錯,不知道是怎么回事!~~~
          錯誤代碼如下:請你幫分析一下!謝謝!~

          c:\documents and settings\william\my documents\visual studio 2005\projects\nativecode\nativecode\source.cpp(5) : error C2144: syntax error : 'void' should be preceded by ';'
          c:\documents and settings\william\my documents\visual studio 2005\projects\nativecode\nativecode\source.cpp(5) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
          c:\documents and settings\william\my documents\visual studio 2005\projects\nativecode\nativecode\source.cpp(5) : error C2146: syntax error : missing ';' before identifier 'Java_org_druze_test_TestNative_sayHello'
          c:\documents and settings\william\my documents\visual studio 2005\projects\nativecode\nativecode\source.cpp(5) : error C2182: 'JNICALL' : illegal use of type 'void'
          c:\documents and settings\william\my documents\visual studio 2005\projects\nativecode\nativecode\source.cpp(5) : error C2065: 'JNIEnv' : undeclared identifier
          c:\documents and settings\william\my documents\visual studio 2005\projects\nativecode\nativecode\source.cpp(5) : error C2065: 'env' : undeclared identifier
          c:\documents and settings\william\my documents\visual studio 2005\projects\nativecode\nativecode\source.cpp(5) : error C2065: 'jobject' : undeclared identifier
          c:\documents and settings\william\my documents\visual studio 2005\projects\nativecode\nativecode\source.cpp(5) : error C2146: syntax error : missing ')' before identifier 'obj'
          c:\documents and settings\william\my documents\visual studio 2005\projects\nativecode\nativecode\source.cpp(5) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
          c:\documents and settings\william\my documents\visual studio 2005\projects\nativecode\nativecode\source.cpp(5) : error C2078: too many initializers
          c:\documents and settings\william\my documents\visual studio 2005\projects\nativecode\nativecode\source.cpp(5) : error C2059: syntax error : ')'
          c:\documents and settings\william\my documents\visual studio 2005\projects\nativecode\nativecode\source.cpp(6) : error C2143: syntax error : missing ';' before '{'
          c:\documents and settings\william\my documents\visual studio 2005\projects\nativecode\nativecode\source.cpp(6) : error C2447: '{' : missing function header (old-style formal list?)
          Generating Code...
          生成日志保存在“file://c:\Documents and Settings\william\My Documents\Visual Studio 2005\Projects\NativeCode\NativeCode\Debug\BuildLog.htm”
          NativeCode - 13 個錯誤,0 個警告
          ========== 全部重新生成: 0 已成功, 1 已失敗, 0 已跳過 ==========
            回復(fù)  更多評論   

          # re: 通過JNI實現(xiàn)Java和C++的相互調(diào)用[未登錄] 2008-08-26 17:38 role0523

          你沒有指定jni.h,jni_md.h的include path,以及 jvm.dll的路徑,具體參考文章后半部分  回復(fù)  更多評論   

          # re: 通過JNI實現(xiàn)Java和C++的相互調(diào)用 2008-08-27 10:24 lfking

          你說要指定jni.h 和 jni_md.h的include path 這個我都做了,就是少做一個JVM.DLL的路徑,試過了,還是一樣的錯誤!~
          我做的是JAVA 連接 C++ 需要做這個JVM.DLL的路徑嗎?  回復(fù)  更多評論   

          # re: 通過JNI實現(xiàn)Java和C++的相互調(diào)用[未登錄] 2008-08-27 10:46 role0523

          sorry, jvm.dll不用指定,因為我們這里不需要它。

          這樣好了,你把org_druze_test_TestNative.h和jni.h復(fù)制到source.cpp相同的目錄下,將#include <jni.h>修改為#include "jni.h" 試試看。

          你的問題是jni.h的頭文件沒有在頭文件的搜索路徑當(dāng)中。  回復(fù)  更多評論   

          # re: 通過JNI實現(xiàn)Java和C++的相互調(diào)用 2008-08-27 12:01 lfking

          我按照你上面寫的步聚建立一個WIN32的工程,建好以后,會自動建立一個stdafx.h的頭文件和stdafx.cpp文件!然后運行source.cpp的時候提示錯誤說必須要用stdafx.h這個頭文件,加上去以后就出現(xiàn)這些錯誤了!

          唉!~把jni.h放到source.cpp同一個目錄下了,還是不行!~~
          我留個QQ號給你吧,Q上聊!47145748!
          你這BOLG上面不能發(fā)圖片!
            回復(fù)  更多評論   

          # re: 通過JNI實現(xiàn)Java和C++的相互調(diào)用 2008-08-27 12:04 lfking

          vc以前從來沒接觸過,只是聽說過!所以用起來有點愚純!~~抱歉!~~  回復(fù)  更多評論   

          # re: 通過JNI實現(xiàn)Java和C++的相互調(diào)用[未登錄] 2008-08-27 15:12 role0523

          你把stdafx.h的頭文件和stdafx.cpp刪除掉吧  回復(fù)  更多評論   

          # re: 通過JNI實現(xiàn)Java和C++的相互調(diào)用 2008-08-28 10:31 lfking

          無語了都.....
          如果把stdafx.h和stdafx.cpp刪除的話,會提示錯誤,說沒有加載stdafx.h文件。
          大哥,這個例子你試過沒啊??是否成功了?你那個版本的VC??我是用VC2005做的!  回復(fù)  更多評論   

          # re: 通過JNI實現(xiàn)Java和C++的相互調(diào)用[未登錄] 2008-08-28 11:00 role0523

          就如我文中所說,我用的VS2008,VC6,codeBlocks.我沒搞定,不會寫東西的。你的問題在于你對C++的編譯器不是很熟悉,這我?guī)筒涣四恪?

          BTW:如果把stdafx.h和stdafx.cpp刪除的話,會提示錯誤,說沒有加載stdafx.h文件。

          那是你的某個地方#include了這個文件,OK?  回復(fù)  更多評論   

          # re: 通過JNI實現(xiàn)Java和C++的相互調(diào)用 2008-08-28 14:53 lfking

          7.編譯,生成NativeCode.dll,并將其copy到環(huán)境變量PATH的路徑下。
          10.注意NativeCode.dll必須放置在java命令能訪問的路徑中。

          這個不是很了解。能不能在說的具體點!
          我是把NativeCode.dll放在與TestNative.java文件同一個目錄下!   回復(fù)  更多評論   

          # re: 通過JNI實現(xiàn)Java和C++的相互調(diào)用[未登錄] 2008-08-28 14:58 role0523

          NativeCode.dll是由java.exe->jvm.dll->NativeCode.dll這樣調(diào)用的。你把NativeCode.dll放到與java.exe同目錄下,OK?
            回復(fù)  更多評論   

          # re: 通過JNI實現(xiàn)Java和C++的相互調(diào)用 2009-05-21 18:10 Necho

          完全按照樓主的做法結(jié)果確報這個錯誤,請樓主幫我看下吧

          First-chance exception at 0x00411a20 in NativeCode2.exe: 0xC0000005: Access violation reading location 0x00000000.
          Unhandled exception at 0x00411a20 in NativeCode2.exe: 0xC0000005: Access violation reading location 0x00000000.  回復(fù)  更多評論   

          # re: 通過JNI實現(xiàn)Java和C++的相互調(diào)用 2009-05-21 18:21 Necho

          補充一下 應(yīng)該就是不能findclass  回復(fù)  更多評論   

          # re: 通過JNI實現(xiàn)Java和C++的相互調(diào)用 2009-05-21 18:24 Necho

          如果可以的話 請加我MSN:necho_leco@yhotmail.com
          或者QQ :55128128
          想向你請教,謝謝~!   回復(fù)  更多評論   

          # re: 通過JNI實現(xiàn)Java和C++的相互調(diào)用 2009-05-22 10:19 Necho

          測試成功了 感謝LZ提供這么詳細的說明 謝謝~~!!  回復(fù)  更多評論   

          # re: 通過JNI實現(xiàn)Java和C++的相互調(diào)用[未登錄] 2009-09-04 14:43 阿飛

          樓主,請問下:我在VC6。0控制臺下可以加載JAVA虛擬機了,為什么到了VC6.0的MFC下用同樣的方法加載不了(編譯不報錯,但是調(diào)試的時候通不過),盼回復(fù),謝謝!  回復(fù)  更多評論   

          # re: 通過JNI實現(xiàn)Java和C++的相互調(diào)用[未登錄] 2009-12-18 13:40 sunny

          樓主:
          請問我在編譯C++時,出現(xiàn)這個錯誤訊息:
          error C2065: 'JNI_VERSION_1_6' : undeclared identifier

          我使用的是JDK1.6  回復(fù)  更多評論   

          # re: 通過JNI實現(xiàn)Java和C++的相互調(diào)用 2009-12-18 23:39 nobody

          @sunny 看看這個聲明在哪個頭文件里面,把它include進來
            回復(fù)  更多評論   

          # re: 通過JNI實現(xiàn)Java和C++的相互調(diào)用 2010-01-09 11:52 next

          @lfking
          朋友,這個連接的最下方是你要的答案
          http://www.experts-exchange.com/Programming/Languages/CPP/Q_22048796.html

          引用:
          phongtran72:
          Well, this generates error:

          #include "jni.h"
          #include "stdafx.h"
          #include <stdlib.h>
          #include <stdio.h>

          And this is solution:

          #include "stdafx.h"
          #include <stdlib.h>
          #include <stdio.h>
          #include "jni.h"  回復(fù)  更多評論   


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


          網(wǎng)站導(dǎo)航:
           

          導(dǎo)航

          <2010年1月>
          272829303112
          3456789
          10111213141516
          17181920212223
          24252627282930
          31123456

          統(tǒng)計

          常用鏈接

          留言簿(3)

          隨筆檔案

          搜索

          最新評論

          主站蜘蛛池模板: 平凉市| 灵川县| 鲁甸县| 临沭县| 革吉县| 垫江县| 云和县| 来凤县| 合水县| 新密市| 玛纳斯县| 大余县| 永顺县| 新乐市| 乌审旗| 平和县| 桃源县| 舞钢市| 凌源市| 石河子市| 吉林市| 绥棱县| 肃南| 加查县| 东明县| 偏关县| 玛沁县| 浦北县| 隆回县| 灵丘县| 陆丰市| 宣城市| 吉首市| 海原县| 乡宁县| 馆陶县| 台山市| 通河县| 茌平县| 南木林县| 巴楚县|