如何通過JNI傳遞對象執行回調

JNI的全稱是java native interface,用來調用某些特定於系統平臺或者硬件的操作,但是它只能調用c/c++的代碼,若是其它語言代碼,只能通過c/c++進行二次調用。
關於JNI的完整技術文檔,大家可以查看下面這個網址:
 
下面我們看下JNI如何執行回調函數:
我們知道在c/c++回調函數可以通過函數指針執行,但是在Java中已經沒有指針的概念,在這裏,我們先傳遞一個類對象給native函數,然後再dll中調用期望的函數即可。
下面的這個例子中,我們通過回調傳遞一個字符串給java,這在java和c/c++混合編程時傳遞dll內部的出錯或其他信息到java層是很有用的。
1.  首先創建一個java類文件,封裝一個native函數和一個用於回調的函數
package jni;

public class Log{

    
static{
              System.loadLibrary(
"mylib");
    }

    
        
//用來回調,輸出c代碼層的信息
    public void output(String out){
               System.out.println(out);
    }

    
        
//native函數,用來傳遞對象
       public native void test(Log log);
    
    
public static void main(String[] args){
        Log log 
= new Log();
        
        log.test(log);    
    }

}
2.  調用javah命令,生成對應的c/c++都文件
/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
<jni.h>
/* Header for class jni_Log */

#ifndef _Included_jni_Log
#define _Included_jni_Log
#ifdef __cplusplus
extern 
"C" {
#endif
/*
 * Class:     jni_Log
 * Method:    test
 * Signature: (Ljni/Log;)V
 
*/

JNIEXPORT 
void JNICALL Java_jni_Log_test
  (JNIEnv 
*, jobject, jobject);

#ifdef __cplusplus
}

#endif
#endif
3.  利用vc和生成的頭文件完成一個dll
        #include <windows.h>

#include 
"jni_Log.h"

int WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReasion,PVOID pvReserved)
{
    
return TRUE;
}


JNIEXPORT 
void JNICALL Java_jni_Log_test(JNIEnv * env, jobject obj, jobject log)
{
    jclass cls 
= (*env)->GetObjectClass(env, log);
    jmethodID jmid 
= (*env)->GetMethodID(env, cls, "output""(Ljava/lang/String;)V");
    jstring info 
= (*env)->NewStringUTF(env, "i am a error!");
    (
*env)->CallVoidMethod(env,log, jmid,info);
    (
*env)->ReleaseStringUTFChars(env,info,(*env)->GetStringUTFChars(env, info, FALSE));
}

                 編譯完成後,將mylib.dll放到與jni同級的目錄中,運行命令java jni.Log,即可看到控制檯成功打印信息

                "i am a error!"。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章