NDK开发之c++调用java
2016-04-12 16:53
190 查看
文章摘自:http://blog.csdn.net/lamp_zy/article/details/8218963
在NDK中创建的线程中, 只允许调用静态的Java API. 当在线程中调用env->FindClass(), 系统就会发出异常
JAVA 代码:
package com.myndk;
...
public class simple_test extends Activity {
...
public void PrintNdkLog(String slog) { // 成员函数, 不可在线程中被调用
Log.e("NDK", slog);
}
public static void PrintNdkLogThread(String slog) { // 静态函数, 可在主线中被调用
Log.e("NDK-THREAD", slog);
}
}
C++
代码:
static
JavaVM* g_JavaVM = NULL;
static jobject g_InterfaceObject = 0;
static const char *g_JavaClassName = "com/myndk/simple_test";
//传入class,输出这个class的一个object
static jobject getInstance(JNIEnv *env, jclass obj_class)
{
jmethodID c_id = env->GetMethodID(obj_class, "<init>", "()V");//得到构造函数,得到构造函数ID必须这样写
jobject obj = env->NewObject(obj_class, c_id);//new 一个对象,并调用构造函数
return obj;
}
//线程中无法调用FindClass,所有要在JniLoad中提前得到object
static void GetInterfaceObject(JNIEnv *env, const char *path, jobject *objptr)
{
jclass cls = env->FindClass(path);
if (!cls)
{
return;
}
jmethodID constr = env->GetMethodID(cls, "<init>", "()V");
if (!constr)
{
return;
}
jobject obj = env->NewObject(cls, constr);
if (!obj)
{
return;
}
(*objptr) = env->NewGlobalRef(obj);
}
//线程中无法调用FindClass,所有要在JniLoad中提前得到object
int JniLoad(JavaVM* jvm, void* reserved)
{
g_JavaVM = jvm;
JNIEnv *env;
if (jvm->GetEnv((void**) &env, JNI_VERSION_1_6) != JNI_OK)
{
return -1;
}
GetInterfaceObject(env, g_JavaClassName, &g_InterfaceObject);
return JNI_VERSION_1_6;
}
void JniUnLoad(JavaVM* jvm, void* reserved)
{
JNIEnv *env;
if (jvm->GetEnv((void**) &env, JNI_VERSION_1_6) != JNI_OK)
{
return;
}
env->DeleteGlobalRef(g_InterfaceObject);
}
void
PrintNdkLog(const char *format, ...)
{
va_list arg_ptr;
char sLogBuff[1024];
if (g_JavaVM == NULL)
return;
//把可变个数的参数一个个写到sLogBuff中
va_start(arg_ptr, format);
vsprintf(sLogBuff, format, arg_ptr);
va_end(arg_ptr);
int status;
JNIEnv *env = NULL;
bool isAttached = false;
status = g_JavaVM->GetEnv((void**) &env, JNI_VERSION_1_6);
//如果PrintNdkLog是在线程中调用
if (status < 0) //表示PrintNdkLog是在线程中被调用的
{
status = g_JavaVM->AttachCurrentThread(&env, NULL);
if (status < 0)
{
return;
}
isAttached = true;
}
if (isAttached) // PrintNdkLog在线程中被调用, 调用Java静态API
{
jclass cls = env->GetObjectClass(g_InterfaceObject);
if (cls != 0)
{
jmethodID mid = env->GetStaticMethodID(cls, "PrintNdkLogThread", "(Ljava/lang/String;)V");
if (mid != 0)
{
jstring jstrMSG = env->NewStringUTF(sLogBuff);
env->CallStaticVoidMethod(cls, mid, jstrMSG);
}
}
g_JavaVM->DetachCurrentThread();
}
else // PrintNdkLog不是在线程中被调用, 调用Java类成员API
{
jclass cls = env->FindClass(g_JavaClassName);
if (cls != 0)
{
jobject obj = getInstance(env, cls);
jmethodID mid = env->GetMethodID(cls, "PrintNdkLog", "(Ljava/lang/String;)V");
if (mid != 0)
{
jstring jstrMSG = env->NewStringUTF(sLogBuff);
env->CallVoidMethod(obj, mid, jstrMSG);
}
}
}
}
在NDK中创建的线程中, 只允许调用静态的Java API. 当在线程中调用env->FindClass(), 系统就会发出异常
JAVA 代码:
package com.myndk;
...
public class simple_test extends Activity {
...
public void PrintNdkLog(String slog) { // 成员函数, 不可在线程中被调用
Log.e("NDK", slog);
}
public static void PrintNdkLogThread(String slog) { // 静态函数, 可在主线中被调用
Log.e("NDK-THREAD", slog);
}
}
C++
代码:
static
JavaVM* g_JavaVM = NULL;
static jobject g_InterfaceObject = 0;
static const char *g_JavaClassName = "com/myndk/simple_test";
//传入class,输出这个class的一个object
static jobject getInstance(JNIEnv *env, jclass obj_class)
{
jmethodID c_id = env->GetMethodID(obj_class, "<init>", "()V");//得到构造函数,得到构造函数ID必须这样写
jobject obj = env->NewObject(obj_class, c_id);//new 一个对象,并调用构造函数
return obj;
}
//线程中无法调用FindClass,所有要在JniLoad中提前得到object
static void GetInterfaceObject(JNIEnv *env, const char *path, jobject *objptr)
{
jclass cls = env->FindClass(path);
if (!cls)
{
return;
}
jmethodID constr = env->GetMethodID(cls, "<init>", "()V");
if (!constr)
{
return;
}
jobject obj = env->NewObject(cls, constr);
if (!obj)
{
return;
}
(*objptr) = env->NewGlobalRef(obj);
}
//线程中无法调用FindClass,所有要在JniLoad中提前得到object
int JniLoad(JavaVM* jvm, void* reserved)
{
g_JavaVM = jvm;
JNIEnv *env;
if (jvm->GetEnv((void**) &env, JNI_VERSION_1_6) != JNI_OK)
{
return -1;
}
GetInterfaceObject(env, g_JavaClassName, &g_InterfaceObject);
return JNI_VERSION_1_6;
}
void JniUnLoad(JavaVM* jvm, void* reserved)
{
JNIEnv *env;
if (jvm->GetEnv((void**) &env, JNI_VERSION_1_6) != JNI_OK)
{
return;
}
env->DeleteGlobalRef(g_InterfaceObject);
}
void
PrintNdkLog(const char *format, ...)
{
va_list arg_ptr;
char sLogBuff[1024];
if (g_JavaVM == NULL)
return;
//把可变个数的参数一个个写到sLogBuff中
va_start(arg_ptr, format);
vsprintf(sLogBuff, format, arg_ptr);
va_end(arg_ptr);
int status;
JNIEnv *env = NULL;
bool isAttached = false;
status = g_JavaVM->GetEnv((void**) &env, JNI_VERSION_1_6);
//如果PrintNdkLog是在线程中调用
if (status < 0) //表示PrintNdkLog是在线程中被调用的
{
status = g_JavaVM->AttachCurrentThread(&env, NULL);
if (status < 0)
{
return;
}
isAttached = true;
}
if (isAttached) // PrintNdkLog在线程中被调用, 调用Java静态API
{
jclass cls = env->GetObjectClass(g_InterfaceObject);
if (cls != 0)
{
jmethodID mid = env->GetStaticMethodID(cls, "PrintNdkLogThread", "(Ljava/lang/String;)V");
if (mid != 0)
{
jstring jstrMSG = env->NewStringUTF(sLogBuff);
env->CallStaticVoidMethod(cls, mid, jstrMSG);
}
}
g_JavaVM->DetachCurrentThread();
}
else // PrintNdkLog不是在线程中被调用, 调用Java类成员API
{
jclass cls = env->FindClass(g_JavaClassName);
if (cls != 0)
{
jobject obj = getInstance(env, cls);
jmethodID mid = env->GetMethodID(cls, "PrintNdkLog", "(Ljava/lang/String;)V");
if (mid != 0)
{
jstring jstrMSG = env->NewStringUTF(sLogBuff);
env->CallVoidMethod(obj, mid, jstrMSG);
}
}
}
}