问题1:c++ string 转 char*
data() 方法:
string str = "hello";
const char* p = str.data();
c_str()方法:
string str=“world”;
const char *p = str.c_str();
参考博客
问题2:jstring 转为 char*
const char* GetStringUTFChars(jstring string, jboolean* isCopy)
方法说明: j_str jstring 类型(Java传递给本地代码的字符串指针)
isCopy: 取值JNI_TRUE和JNI_FALSE,如果值为JNI_TRUE,表示返回JVM内部源字符串的一份拷贝,并为新产生的字符串分配内存空间。如果值为JNI_FALSE,表示返回JVM内部源字符串的指针,意味着可以通过指针修改源字符串的内容,不推荐这么做,因为这样做就打破了Java字符串不能修改的规定。但我们在开发当中,并不关心这个值是多少,通常情况下这个参数填NULL即可。
因为Java默认使用Unicode编码,而C/C++默认使用UTF编码,所以在本地代码中操作字符串的时候,必须使用合适的JNI函数把jstring转换成C风格的字符串。JNI支持字符串在Unicode和UTF-8两种编码之间转换,GetStringUTFChars可以把一个jstring指针(指向JVM内部的Unicode字符序列)转换成一个UTF-8格式的C字符串。在上例中sayHello函数中我们通过GetStringUTFChars正确取得了JVM内部的字符串内容。
问题3:打印Log
- 导入头文件:#include <android/log.h>
- 方法:
std::string hello = "Hello from C++";
__android_log_print(ANDROID_LOG_ERROR, kTAG, "%s", hello.c_str());
- 使用宏定义简化方法的使用
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, kTAG, __VA_ARGS__))
std::string hello = "Hello from C++";
LOGE("%s", hello.data());
问题4:meset 函数
1. 函数原型:
# include <string.h>
void *memset(void *s, int c, unsigned long n);
2. 函数功能: 将s所指向的某一块内存中的前n个字节的内容全部设置为ch指定的ASCII值, 第一个值为指定的内存地址,块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作, 其返回值为指向s的指针,它是对较大的结构体或数组进行清零操作的一种最快方法。
问题5:JavaVM 和 JNIEnv
1. JavaVM JavaVM 是虚拟机在JNI层的代表,一个进程只有一个JavaVM,所有的线程共用一个JavaVM 2. JNIEnv JNIEnv 表示Java调用native语言环境,是一个封装了几乎全部JNI方法的指针。 JNIEnv只在创建它的线程生效,不能跨进程传递,不同线程的JNIEnv彼此独立。 native环境创建的线程,如果需要访问JNI,必须要调用AttachCurrentThread关联,并使用DetachCurrentThread 解除连接。
JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env = NULL;
jint result = -1;
if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
return result;
}
return JNI_VERSION_1_6;
}
问题6 :JNIEnv* # NewGlobalRef {全局引用}
全局引用 作用域 :
空间 : 可以 跨方法 , 跨线程使用
时间 : 创建后可以使用 , 手动释放后全局引用失效
全局引用创建 : NewGlobalRef
全局引用释放 : DeleteGlobalRef
全局引用会阻止 JVM 回收该引用
jclass tmp_class = env->FindClass("kim/hsl/jni/Teacher");
class_teacher_global = static_cast<jclass>(env->NewGlobalRef(tmp_class));
env->DeleteLocalRef(tmp_class);
参考博客
问题7:JNI 创建java对象
jclass cls = env->FindClass("com/example/myapplication/Util");
jmethodID init = env->GetMethodID(cls, "<init>", "()V");
jmethodID init = env->GetMethodID(cls, "<init>", "(Ljava/lang/String;I)V");
jobject util = env->NewObject(cls, init);
参考博客
问题8:JNI 方法签名的类型
对应于Java端的数据类型,我们也可以看一下下面的表:
Java 类型 类型签名
boolean Z
byte B
char C
short S
int I
long L
float F
double D
类 L全限定名;,比如String, 其签名为Ljava/lang/util/String;
数组 [类型签名, 比如 [B
参考博客
问题9:JNI 调用 static Java 方法
jmethodID versionFun = env->GetStaticMethodID(g_ctx.jniHelperClz, "getBuildVersion", "()Ljava/lang/String;");
|