JNI native層、C++非同步回撥JAVA程式碼。JNI資料型別轉換
阿新 • • 發佈:2019-02-12
現在專案做移植的。
windows轉移到Linux下,多程序的程式。
本來windows下用MFC做的介面,現在決定Linux下介面用java或者python做。。。
java和其他C++程序用JNI來融合到一起。。。
java部分的程式碼如下:
其中只有一個函式是需要CPP這邊實現。public class NativeTool implements Serializable { /** * */ private static final long serialVersionUID = 1L; static { try { System.loadLibrary("nativeCpp_NativeTool"); } catch(UnsatisfiedLinkError e) { System.out.println( "Cannot load nativeCpp_NativeTool library:\n " + e.toString() ); } } private Service service; public NativeTool() { } public native boolean readyToPlay(); public void setService(Service service) { this.service = service; } public void nativeCallBack(byte[] imageData) { //service.nativeToolCallBack(imageData); System.out.println("java nativeCallBack system out"); for (int i = 0; i < imageData.length; i++) { System.out.println(imageData[i]); } } }
設想的是通過這個函式高速CPP,java這邊OK,CPP可以隨時回撥nativeCallBack把資料給java介面顯示。
java程式碼完成後要通過javah生成標頭檔案,然後CPP去實現。
C++程式碼:
#include "nativeCpp_NativeTool.h" #include <string.h> #include <pthread.h> #include <unistd.h> JavaVM* g_jvm; jobject g_obj; //HANDLE hThread=NULL; //DWORD dwThreadID=0; void* thread(void* ptr) { FILE* fp = fopen("a.bmp", "rb"); if (fp != NULL) { fclose(fp); } JNIEnv *env; g_jvm->AttachCurrentThread((void **)&env, NULL); jclass cls = env->GetObjectClass(g_obj); jmethodID id_nativeCallBack = env->GetMethodID(cls,"nativeCallBack","([B)V"); unsigned char param[5] = {'1', '2', '3', '4', '5'}; while(1) { //usleep(5000); sleep(5); printf("c++ thread running... \n"); //////////// jbyteArray jarrRV = env->NewByteArray(5); jbyte* jby = env->GetByteArrayElements(jarrRV, 0); memcpy(jby, param, 5); env->SetByteArrayRegion(jarrRV, 0, 5, jby); //////////// env->CallVoidMethod(g_obj, id_nativeCallBack, jarrRV); } return 0; } JNIEXPORT jboolean JNICALL Java_nativeCpp_NativeTool_readyToPlay (JNIEnv * env, jobject obj) { env->GetJavaVM(&g_jvm); g_obj = env->NewGlobalRef(obj); jclass class_NativeTool = env->GetObjectClass(obj); //hThread=CreateThread(0,0,ThreadMethod,NULL,0,&dwThreadID); //CloseHandle(hThread); pthread_t id; int ret = pthread_create(&id, NULL, thread, NULL); if(ret) { printf("create pthread error!... \n"); return 1; } //pthread_join(id, NULL); printf("c++ source printf... \n"); jmethodID id_nativeCallBack = env->GetMethodID(class_NativeTool,"nativeCallBack","([B)V"); unsigned char param[5] = {'1', '2', '3', '4', '5'}; //////////// jbyteArray jarrRV = env->NewByteArray(5); jbyte* jby = env->GetByteArrayElements(jarrRV, 0); memcpy(jby, param, 5); env->SetByteArrayRegion(jarrRV, 0, 5, jby); //////////// env->CallVoidMethod(obj, id_nativeCallBack, jarrRV); return true; }
CPP程式碼有些問題,沒做完,但是能完成CPP這邊非同步回撥java的函式。
關鍵在於儲存了JNIENV和JOBJECT這兩個物件。
查資料是說他們是執行緒敏感的,必須先在java呼叫C++時把JVM拿到。
在之後任意時候都可以通過JVM拿到當前執行緒的ENV對JAVA的函式進行呼叫。
關於JNI的資料型別轉換資料:
http://blog.csdn.net/jinhill/article/details/6918821