简介:
本篇通过一个jni错误,来说明c/c++编译器在处理jni代码时,引用到JNIEnv时的注意事项。
1. 问题描述:
在调试jni代码时,出现如下错误:error: request for member 'FindClass' in something not a structure or union
2. 分析:
从错误信息可以看出,找不到FindClass。但是,FindClass是jni中env标准的方法呀,怎么会找不到?再仔细一想,env不可能没有FindClass,除非env本身没有被正确引用。
3. 关于jni中env的简单介绍:
jni中的env,即JNIEnv_(c++) 或 JNINativeInterface_(c),声明在jni.h中, 如下:
jni.h代码截取:
详情可以参考:jni.h Source File
struct JNINativeInterface_;
struct JNIEnv_;
#ifdef __cplusplus
typedef JNIEnv_ JNIEnv;
#else
typedef const struct JNINativeInterface_ *JNIEnv;
#endif
......
struct JNINativeInterface_ {
void *reserved0;
void *reserved1;
void *reserved2;
void *reserved3;
jint (JNICALL *GetVersion)(JNIEnv *env);
jclass (JNICALL *DefineClass)
(JNIEnv *env, const char *name, jobject loader, const jbyte *buf,
jsize len);
jclass (JNICALL *FindClass)
(JNIEnv *env, const char *name);
......
};
/*
* We use inlined functions for C++ so that programmers can write:
*
* env->FindClass("java/lang/String")
*
* in C++ rather than:
*
* (*env)->FindClass(env, "java/lang/String")
*
* in C.
*/
struct JNIEnv_ {
const struct JNINativeInterface_ *functions;
#ifdef __cplusplus
jint GetVersion() {
return functions->GetVersion(this);
}
jclass DefineClass(const char *name, jobject loader, const jbyte *buf,
jsize len) {
return functions->DefineClass(this, name, loader, buf, len);
}
jclass FindClass(const char *name) {
return functions->FindClass(this, name);
}
......
#endif /* __cplusplus */
};
注释已经明确说明,在使用方式上的区别:
如果是C++要用 env->FindClass("java/lang/String")
如果是c程序,要用 (*env)->FindClass(env, "java/lang/String")
所以,在linux下如果.c文件中用 “env->” 编译会找不到此结构,必须用“(*env)->”,或者改成.cpp文件,以 c++的方式来编译。
同理,ReleaseStringUTFChars函数也有可能出现这样的问题。
4. c/c++的兼容方式:
在代码中也可以看到,用如下的宏指令来进行c/c++的兼容:
#ifdef __cplusplus
......
#else
......
#endif
下面,是一个典型的自定义.h头文件:
#include <jni.h>
#ifndef _Included_com_a_b_Utils
#define _Included_com_a_b_Utils
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jboolean JNICALL Java_com_a_b_Utils_setConfig(JNIEnv*, jclass, jboolean enabled);
JNIEXPORT jboolean JNICALL Java_com_a_b_Utils_getConfig(JNIEnv*, jclass);
#ifdef __cplusplus
}
#endif
#endif
在进行代码开发时,想一想你的系统是否需要做兼容。