標籤:
源:java調用C/C++寫的dll
Java語言本身具有跨平台性,如果通過Java調用DLL的技術方便易用,使用Java開發前台介面可以更快速,也能帶來跨平台性。
Java調用C/C++寫好的DLL庫時,由於基礎資料型別 (Elementary Data Type)不同、使用位元組序列可能有差異,所以在參數傳遞過程中容易出現問題,DLL中可能需要做相應的轉換。
使用Java調用DLL動態連結程式庫的方案通常有三種:JNI, Jawin, Jacob. 其JNI(Java Native Interface)是Java語言本身提供的調用本地已編譯的函數庫的方法,本身具有跨平台性,可以在不同的機器上調用不同的本地庫。Jawin和Jacob都是sourceforge.net的開源項目,都是基於JNI技術的依賴Windows的實現,使得在Windows平台下使用COM和DLL的更加方便。
下面,我們來詳細介紹一下使用JNI來實現Java與C/C++之間的調用。
一、 JNI簡介
JNI是Java Native Interface的縮寫。從Java 1.1開始,Java Native Interface(JNI)標準成為java平台的一部分,它允許Java代碼和其他語言寫的代碼進行互動。JNI一開始是為了本地已編譯語言,尤其是C和C++而設計的,但是它並不妨礙你使用其他語言,只要呼叫慣例受支援就可以了。
sun相關文檔:http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/jniTOC.html
二、 簡單步驟
第一步:
編寫Java類,用該類將DLL對外提供的函數服務進行聲明,其中的Java方法均聲明為native,其方法簽名可以自訂,不用實現函數體。一個例子如下:DllTest.java
public class DllTest
{
static
{
System.loadLibrary("chat");
}
public static native int connect(int i);
public static native String getstring(String src);
public static void main(String[] args)
{
DllTest dllTest = new DllTest();
System.out.println(dllTest.connect(5));
System.out.println(dllTest.getstring("java send"));
}
}
其中,chat為該動態庫的名字,它的副檔名字可以不用寫出來,究竟是DLL還是SO,由系統自己判斷。在這裡,定義了兩個介面函數,一個是具有int型的入參和傳回值的connect函數,一個是具有String字串對象的入參和傳回值的getstring函數。他們都不需要具體的實現。
第二步:
用Javah工具將該Java類產生對應的.h標頭檔。首先,用javac DllTest.java編譯成DllTest.class 檔案,然後用 javah DllTest 編譯出一個 DllTest.h 檔案。這個DllTest.h即是C/C++動態庫中的標頭檔,C/C++程式需要實現它。DllTest.h 的標頭檔內容:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class DllTest */
#ifndef _Included_DllTest
#define _Included_DllTest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: DllTest
* Method: connect
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_DllTest_connect
(JNIEnv *, jclass, jint);
/*
* Class: DllTest
* Method: getstring
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_DllTest_getstring
(JNIEnv *, jclass, jstring);
#ifdef __cplusplus
}
#endif
#endif
這裡JNIEXPORT和JNICALL都是JNI的關鍵字,表示此函數是要被JNI調用的。而jint、jstring是以JNI為中介使JAVA中的資料類型與C/C++中的資料類型之間的一種中間類型。Jint可以直接當做int使用,但是jstring不能和char *等同,需要做一定的轉換。函數的名稱是JAVA_再加上java程式的package路徑再加函數名組成的。參數中,我們也只需要關心在JAVA程式中存在的參數,至於JNIEnv*和jclass我們一般沒有必要去碰它。
第三步:
編寫C/C++代碼實現.h標頭檔中聲明的函數,該C/C++代碼中包含jni.h標頭檔。
int i = 2;
const char *teststr = "c/c++ return";
JNIEXPORT jint JNICALL Java_DllTest_connect
(JNIEnv *, jclass, jint j)
{
i = i + j;
return i;
}
JNIEXPORT jstring JNICALL Java_DllTest_getstring
(JNIEnv * env, jclass, jstring policy)
{
// jstring 轉換為char * (utf-8)
const char * s1 = env->GetStringUTFChars(policy, false);
printf("%s/n", s1);
// char * (utf-8) 轉換為jstring
jstring js = env->NewStringUTF(teststr);
return js;
}
然後用C/C++的編譯工具編譯產生char.dll動態庫。把這個動態庫放到第二步中的DllTest.class所在的檔案夾中。
第四步:
用java DllTest 執行調用,你就可以看到輸出結果:
7
Java send
c/c++ return
java調用C/C++寫的dll(轉)