java宏定义_java和C++联姻:JNI常用代码模板

b36b8c893ea884bc3555b8c286629be0.png

Java的应用广,C++性能强,JNI就是两者连接的桥梁。一个安卓应用,做交互肯定是java,但是底层的音视频处理、机器学习,就必须要靠C++这个强悍的发动机。本文我们就一起做个改装,给java装个好发动机。

1. 在C++中读取和创建java String

extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_myapplication_JniRobotBCActivity_howToSpeakChinese(JNIEnv *env, jobject thiz,
                                                                    jstring english) {
    //1: java字符串转成C++字符串
    jboolean isTrue;
    char* strNative;
    strNative =(char *)(env->GetStringUTFChars(english, &isTrue));
    //2:做一些处理操作
    char* china=":你好";
    strcat( strNative,china);
    //3:再把字符串转回java字符串
    env->ReleaseStringUTFChars(english,strNative);
    jstring javaString= env->NewStringUTF(strNative);
    return javaString;
}

如果是c++的字符串,需要转成c风格的char*

std::string str="hello";   
jstring javaString= env->NewStringUTF(str.c_str());

2.在C++中创建Java对象

//(1)根据java类的文件目录找到该类
jclass robotClass=env->FindClass("com/example/myapplication/Robot");
//(2) 获取该类的构造方法ID
jmethodID robotConstruct=env->GetMethodID(robotClass,"<init>","(Ljava/lang/String;ILjava/util/HashMap;)V");
    // "<init>"表示构造方法
    //"(Ljava/lang/String;ILjava/util/HashMap;)V"是构造方法的参数,和返回值"void"
//(3) 创建一个该类的对象
jobject r =env->NewObject(robotClass,robotConstruct,name,age,skillsHashMap);
    //参数分别为:类名,构造方法ID,三个参数

3.在C++中创建一个Java的HashMap

// 1. 寻找hashmap类    
jclass hashMap= env->FindClass("java/util/HashMap");
// 2. 寻找构造方法ID
jmethodID hashMap_init=env->GetMethodID(hashMap,"<init>", "()V");
// 3. 创建hashmap
jobject skillsHashMap=env->NewObject(hashMap,hashMap_init);
// 4. 寻找插入方法的ID
jmethodID hashMap_add =env->GetMethodID(hashMap,"put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
// 5. 按你的需求插入元素
    using namespace std;
    string skills[]={"移动","说话","唱歌","图像识别"};
    int levels[]={5,4,4,2};

    jclass classInteger=env->FindClass("java/lang/Integer");
    jmethodID initInteger =env->GetMethodID(classInteger,"<init>", "(I)V");
    for (int i = 0; i < sizeof(levels)/ sizeof(int); ++i) {
        jstring s=env->NewStringUTF(skills[i].c_str());
        jobject newInteger=env->NewObject(classInteger,initInteger,levels[i]);
        env->CallObjectMethod(skillsHashMap,hashMap_add,s,newInteger);
    }

4. 调用Java方法的参数签名 解析

(1)

你可能会看到,调用Java方法时最后一个参数奇奇怪怪,比如:

jmethodID hashMap_init=env->GetMethodID(hashMap,"<init>", "()V");
jmethodID hashMap_add =env->GetMethodID(hashMap,"put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
jmethodID initInteger =env->GetMethodID(classInteger,"<init>", "(I)V");

最后一个参数其实是调用该方法的签名,就是输入参数和返回值:

格式为:

"(输入参数类型1,类型2,类型3)返回值参数类型"

(2)

例如"(I)V"表示输入参数为I,输出参数为V,这是一个宏定义,在jni.h中定义的映射类型如下:

typedef union jvalue {
    jboolean    z;
    jbyte       b;
    jchar       c;
    jshort      s;
    jint        i;
    jlong       j;
    jfloat      f;
    jdouble     d;
    jobject     l;
} jvalue;

其中V表示void,所以"(I)V"就是输入一个int返回void

(3)

对于非基本类型,要找到他们的类型位置。例如

"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"

表示输入两个参数,类型为Ljava/lang/Object;

输出一个参数,类型为Ljava/lang/Object

(4)

如果没有输入参数,括号内就写空,但没有返回值,就要写成void,例如

"()V" 表示无输入参数,输出为void

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值