Java調用C++程序的實現方式
Java調用C++程序
這篇博文是自己在學習過程中,踩瞭很多坑之後,為瞭避免廣大熱愛編程的盆友再像我這樣浪費太多時間,索性將自己的實現方法總結出來,以供大傢參考。程序最終實現的是Hello World效果,話不多說,直接進入正題:
1、編寫Java程序:HelloWorld
代碼如下:
package HelloWorld; public class HelloWorld { public native void sayHello(); public static void main(String[] args) { System.loadLibrary("Win32Project1"); HelloWorld tNative = new HelloWorld(); tNative.sayHello(); } }
2、Windows環境下,在cmd中編譯以上程序
編譯通過後,使用 javah -jni HelloWorld.HelloWorld命令,在src文件夾下生成HelloWorld_HelloWorld.h文件(註意,此處我寫的兩個HelloWorld,前一個指包名,後一個指類名,由於我是寫在eclipse中的,所以需要寫明包名和類名,這樣在cmd中編譯、運行時才不會報錯)。
在執行完這一步後,能夠看到HelloWorld.java、HelloWorld.class、HelloWorld_HelloWorld.h這三個文件是位於同一個src文件夾下的,如下圖所示(註意,此處的src文件夾是在eclipse中創建HelloWorld這個java project時自動生成的,並非手動創建的):
3、編寫C++程序
打開Visual Studio 2013,執行“文件—>新建—>項目—>Visual C++—>Win32 項目—>確定—>下一步–>選擇DLL(D)–>完成”。
註意,設置好項目名稱以及項目文件所在的位置,如下圖標紅處所示:
創建好項目之後,將之前生成的HelloWorld_HelloWorld.h頭文件添加到項目的“頭文件”中,並在源文件中添加helloworld.cpp這一文件,如下圖所示:
接下來,在helloworld.cpp文件中輸入以下代碼:
// helloworld.cpp : 定義DLL應用程序的導出函數。 // #include "stdafx.h" #include "HelloWorld_HelloWorld.h" #include<iostream> using namespace std; JNIEXPORT void JNICALL Java_HelloWorld_HelloWorld_sayHello(JNIEnv *, jobject) { cout << "hello world" << endl; }
右鍵該項目的項目名,選擇“生成”。註意,此時會報錯‘error C1083: 無法打開包括文件: “jni.h”: No such file or directory’,解決的辦法是:將你電腦上Java文件夾下,jdk目錄的include目錄下的jni.h文件(比如,D:\Java\jdk1.8.0_144\include)以及win32目錄下的jni_md.h文件(比如,D:\Java\jdk1.8.0_144\include\win32)都拷貝到Visual Studio\vc\include目錄下即可解決該問題。然後再次右鍵項目名稱,選擇“生成”。
4、完成以上步驟後
打開你Visual Studio的C++項目源文件所在的文件夾(也就是在創建C++項目時你所選擇的“位置”的目錄),將Debug目錄下的dll文件拷貝到Java文件夾下,jdk目錄的bin目錄中,如下圖所示:
5、重新編譯HelloWorld.java程序
運行,即可得到Hello World這個結果。
Java與C++的互調
C++調用Java
1)Unix環境下安裝jdk,並且設置jdk和jre的環境變量,如下:
JRE_HOME=/usr/java/jdk1.6.0_04/jre CLASS_PATH=.:/usr/java/jdk1.6.0_04/lib/dt.jar:/usr/java/jdk1.6.0_04/lib/tools.jar JAVA_HOME=/usr/java/jdk1.6.0_04 LD_LIBRARY_PATH=/usr/java/jdk1.6.0_04/jre/lib/amd64:/usr/java/jdk1.6.0_04/jre/lib/amd64/server PATH=/usr/java/jdk1.6.0_04/bin
2)編寫java測試程序,代碼如下:
編譯,生成MyTest.jar,將jar放到unix環境測試目錄下。
3)編寫c++測試代碼
其中JNI_CreateJavaVM表示創建java虛擬機環境,
FindClass
獲取需要調用的類,GetMethodID
獲取類中的方法;CallStaticIntMethod
獲取返回整型靜態方法;CallBooleanMethod
獲取返回佈爾類型方法DestroyJavaVM
釋放虛擬機。stoJstring
和jstringTostring
函數,是將jvm中類型與c++類型轉換。
調用類中的方法GetMethodID調用時,第三個參數“(II)I”表示方法的輸入輸出參數類型,
“()”裡面的標識輸入參數類型,括號外面的表示輸出參數類型。參數類型查看,可以根據編譯的.class文件,使用命令javap -s -p 類名查看,如下圖:
註意:一個進程中隻能啟動一個java虛擬機。
4)編譯與運行
編譯時設置相關的頭文件和庫文件路徑,編譯命令:g++ testjava.cpp -o testjava -I${JAVA_HOME}/include-I${JAVA_HOME}/include/linux -L${JRE_HOME}/lib/amd64/server –ljvm
運行結果如下:
Java調用C++
1)編寫java代碼,如下:
使用native標識方法由c++實現;
System.loadLibrary表示加載c++庫,示例中加載的庫文件為libMyTest.so
2)將java文件編譯成.class文件,使用javah命令,根據class文件生成c++的接口頭文件
此時生成MyTest.h文件,內容如下:
3)編寫接口函數的實現,如下:
4)編譯c++文件,生成庫文件
這時生成瞭libMyTest.so庫文件。
配置庫文件到環境變量中
exportLD_LIBRARY_PATH=$LD_LIBRARY_PATH:/export/home/process/PM/testjava
5)將java程序的jar文件放到同一個目錄下,運行jar,運行結果如下,此時調用的sub函數,是C++程序實現的。
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- Mac下用Java調用c/c++的思路詳解
- windows下vscode+vs2019開發JNI的示例
- Java調用dll文件的實現解析
- 詳解JNI到底是什麼
- eclipse怎麼導入項目 eclipse導入項目的方法