现在项目做移植的。
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,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