分为四步走,如果是调用的是与native方法同一个类里的方法,则可以跳过第三步,直接用jni的object参数就行
主要介绍一下env->GetMethodID的最后一个参数吧,表示签名,规则为:(参数签名)+返回值签名
示例
Java层方法 JNI函数签名
String test ( ) (Ljava/lang/String)V ;
int f (int i, Object object) (ILjava/lang/Object;)I
void set (byte[ ] bytes) ([B)V
jni中主线程调用:
//1、找到jclass
jclass j_class = env->FindClass("com/http_interface/Golde");
//2、获取要调用方法的id
jmethodID id = env->GetMethodID(j_class, "addData", "(Ljava/lang/String;)I");
//3、利用默认构造方法,获取得到Golde对象的jobject
jmethodID construct_id = env->GetMethodID(j_class, "<init>", "()V");
jobject glode_object= env->NewObject(j_class,construct_id,NULL);
//4、进行调用
jstring name = env->NewStringUTF("jni_name");
jint index =env->CallIntMethod(glode_object, id,name);
jni中 子线程调用,因为env每个线程不能共用,要通过javavm获取,而javavm又通过重写 JNI_OnLoad得到
这些参数都有了后,就跟上面的步骤一样进行就行了
JavaVM *jvm;
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
jvm = vm;
JNIEnv *env;
//如果异常没有得到jvm的时候返回-1
if (vm->GetEnv((void **) (&env), JNI_VERSION_1_6) != JNI_OK) {
return -1;
}
return JNI_VERSION_1_6;
}
void getThreadEnv(JavaVM *jvm, _JNIEnv *jenv, jobject jobj) {
JNIEnv *env;
jvm->AttachCurrentThread(&env,0);//得到线程对应的env
jvm->DetachCurrentThread();//记得释放
}
java代码
package com.http_interface;
import android.util.Log;
public class Golde {
public int addData(String name){
Log.e("-----", "addData: "+name );
return 90;
}
}
顺便记录 jstring和 char的互转吧
const char *name_char = env->GetStringUTFChars(name_string, 0);
std::string hello = "Hello from C++";
//或者 char* hello=“sss”
//env->NewStringUTF(hello);
env->NewStringUTF(hello.c_str());