java jni函数指针_Android开发实践:JNI层线程回调Java函数示例

JNI是Java Native Interface的缩写,是Java平台的重要特性,使得Java代码可以方便地与C/C++代码编译生成的动态链接库进行交互。本文主要给出一份示例代码(工程文件见附件),描述如何在Android的JNI层开启一个线程,并在线程中回调Java层的函数。

代码主要分为Java层(java代码)和JNI层(c语言代码),首先看看Java层的代码(Native.java)。

e0779903cd65e6c9e619a489add7ad15.png

如上所示,Java层与JNI层的接口代码主要封装在Native类中,该类定义了三个native函数,分别完成jni库的初始化,调用jni层开启线程,调用jni层关闭线程等功能。并且提供一个回调函数(onNativeCallback),供jni层调用,并在回调函数中打印count的值。

再看看JNI层是如何开启线程并回调Java层的(native.c),关键的地方都在代码中进行了注释:

native C实现:

1. 头文件包含和全局变量的定义

255d6a5ddfac09512083af4d3c9bf68b.png

2. 初始化函数的实现

dbbaacca968cd880b83a61d28400dd05.png

3. 开启关闭线程的实现

775ec0f4c3c8f84c3b93c98005b1e98c.png

4. 线程的实现(关键)

77fb92cad7432319be728dbe311b90ca.png

native C++实现

#include

#include

#include

#include

#define TAG "JniNative"

#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__)

JavaVM *gJavaVM;

jobject gJavaObj;

int volatile gIsThreadStop = 0;

static const char *classPath = "com/jni/test/JniNativeCallback";

static void* native_thread_exec(void *arg)

{

LOGI("nativeThreadExec");

JNIEnv *env;

//get env From gJavaVm

gJavaVM->AttachCurrentThread(&env,NULL);

//get Java class by classPath

//    jclass thiz = env->FindClass(classPath);

jclass thiz = env->GetObjectClass(gJavaObj);

//get Java method from thiz

jmethodID nativeCallback = env->GetMethodID(thiz,"nativeCallback","(I)V");

int count = 0;

while(!gIsThreadStop)

{

sleep(2);

//env->CallVoidMethod(thiz,nativeCallback,count++);

env->CallVoidMethod(gJavaObj,nativeCallback,count++);

}

gJavaVM->DetachCurrentThread();

LOGI("thread stoped");

}

JNIEXPORT void JNICALL native_init(JNIEnv *env,jobject thiz)

{

LOGI("native_init");

gIsThreadStop = 0;

env->GetJavaVM(&gJavaVM);

gJavaObj = env->NewGlobalRef(thiz);

}

JNIEXPORT void JNICALL native_thread_start(JNIEnv *env,jobject jthiz)

{

LOGI("native_thread_start");

gIsThreadStop = 0;

pthread_t id;

if(pthread_create(&id,NULL,native_thread_exec,NULL)!=0)

{

LOGI("native thread create fail");

return;

}

LOGI("native thread creat success");

}

JNIEXPORT void JNICALL native_thread_stop(JNIEnv *env,jobject jthiz)

{

gIsThreadStop = 1;

LOGI("native_thread_stop");

}

static JNINativeMethod methods[] = {

{"nativeInit","()V",(void*)native_init},

{"nativeThreadStart","()V",(void*)native_thread_start},

{"nativeThreadStop","()V",(void*)native_thread_stop}

};

jint JNI_OnLoad(JavaVM *vm, void *reserve)

{

LOGI("JNI_OnLoad");

JNIEnv *env;

if(vm->GetEnv((void**)&env,JNI_VERSION_1_4)!=JNI_OK)

{

return -1;

}

jclass jthiz = env->FindClass(classPath);

if(env->RegisterNatives(jthiz,methods,sizeof(methods)/sizeof(methods[0]))<0)

{

return -1;

}

return JNI_VERSION_1_4;

}

由上述代码可以看到,JNI层通过pthread库完成了线程的创建,需要特别注意的是,JNI层的线程中,必须通过全局的JavaVM来获取到环境变量,也必须通过全局的jobject获取java类对象,从而找到java端的函数,进行回调。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值