手上一個項目需要通過usb口去讀取usbkey的信息,廠家提供的只有C/C++的接口,而主應用是java的,所以需要使用java去調用動態鏈接庫,所以花了點時間研究了下JNI技術,jdk對JNI技術封裝得很到位,使用起來非常簡單,JNI技術最關鍵還是在於jni數據類型和本地數據類型的轉換。先簡單羅列下JNI的創建過程:
首先需要寫一個java類,然後定義需要使用C/C++去實現的方法(雖然說jni是java native interface,但是目前只支持c/c++實現),使用native關鍵字聲明。這裡寫一個簡單的例子:
TestJNI.java
[java:nogutter]
- package test.jni;
-
- public class TestJNI
- {
-
- static
- {
- System.loadLibrary("TestJNI");
- //這個是之後產生的庫的名字,不需要加後綴,
- //自動根據系統找.dll或者.so;
- }
-
- public native String helloWorld();
-
- public static void main(String[] args)
- {
- TestJNI t = new TestJNI();
- System.out.println(t.helloWorld());
- }
- }
然後將以上文件使用javac編譯,然後使用javah命令,如下:
javac test/jni/TestJNI.java
javah test.jni.TestJNI
之後會得到一個test_jni_TestJNI.h的頭文件,內容如下:
test_jni_TestJNI.h
[cpp]
- /* DO NOT EDIT THIS FILE - it is machine generated */
- #include <jni.h>
- /* Header for class test_jni_TestJNI */
-
- #ifndef _Included_test_jni_TestJNI
- #define _Included_test_jni_TestJNI
- #ifdef __cplusplus
- extern "C" {
- #endif
- /*
- * Class: test_jni_TestJNI
- * Method: helloWorld
- * Signature: ()Ljava/lang/String;
- */
- JNIEXPORT jstring JNICALL Java_test_jni_TestJNI_helloWorld
- (JNIEnv *, jobject);
-
- #ifdef __cplusplus
- }
- #endif
- #endif
然後編寫c/c++實現,如下:
TestJNI.c
[cpp]
- #include <stdio.h>
- #include <jni.h>
- #include <windows.h>
-
- #include "test_jni_TestJNI.h"
-
- JNIEXPORT jstring JNICALL Java_test_jni_TestJNI_helloWorld
- (JNIEnv * env, jobject object){
- //在c中必須給形式參數聲明變量名,C++中可以不用,頭文件中不需要修改;
- const char* str = "helloWorld";
- return (*env)->NewStringUTF(env,str);
- //C++中可以直接env->NewStringUTF(str),這個函數編碼中文會亂碼;
-
- }
使用VC編譯成TestJNI.dll,編譯是需要引入jre/include文件夾和jre/include/win32文件夾。
將TestJNI.dll拷貝至剛才test.jni.TestJNI的classpath下面,然後運行java test.jni.TestJNI就能得到輸出了,一些在編寫C程序時遇到的問題都在c代碼中注釋了,希望能給遇到同樣問題的朋友一個借鑒。