1. 程式人生 > >JNI native層、C++非同步回撥JAVA程式碼。JNI資料型別轉換

JNI native層、C++非同步回撥JAVA程式碼。JNI資料型別轉換

現在專案做移植的。

windows轉移到Linux下,多程序的程式。

本來windows下用MFC做的介面,現在決定Linux下介面用java或者python做。。。

java和其他C++程序用JNI來融合到一起。。。

java部分的程式碼如下:

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這邊實現。

設想的是通過這個函式高速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