cmake编写jni传递对象

本文假设读者使用cmake方式编写jni代码,并且已经学会基本数据类型的jni传递!
一、传递对象,这里使用自定义User对象举例:
1、首先在java层定义native函数,并且loadLibrary库

    public static native User sendUser(User obj);
    static {
        System.loadLibrary("JNIDemo");
    }

2、编写测试类代码,这里就是在Activity加了个TextView,显示jni返回的值

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView tv = findViewById(R.id.sample_text);
        User user = new User();
        User.BaseUser baseUser = user.new BaseUser();
        baseUser.setBaseName("李世民");
        user.setName("大唐");
        user.setAge(619);
        tv.setText(JniUtils.sendUser(user).toString());
    }

}

3、cmakelists.txt文件中

cmake_minimum_required(VERSION 3.4.1)
add_library(JNIDemo SHARED JNIDemo.cpp)
find_library(log-lib log)
target_link_libraries(JNIDemo ${log-lib})

4、JNIDemo.cpp文件中实现对应的代码

#include <jni.h>
#include <string>
#include <android/log.h>

#define  LOG_TAG    "JniDome"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)

const char *userCalssName = "com/example/jnidemo/User";

jobject sendUser(JNIEnv *env, jobject job, jobject objData) {

    //根据全路径类名查找到java对象
    jclass user = env->FindClass(userCalssName);
    //根据java对象、成员属性名、属性签名查找 到对象的成员变量
    jfieldID userName = env->GetFieldID(user, "name", "Ljava/lang/String;");
    jfieldID userAge = env->GetFieldID(user, "age", "I");
    jstring jniStrUserName = (jstring) env->GetObjectField(objData, userName);
    const char *usetNameStr = env->GetStringUTFChars(jniStrUserName, 0);
    jint jniUserAge = (jint) env->GetIntField(objData, userAge);
    LOGI("%s%d", usetNameStr, jniUserAge);

    //创建Object,返回java上层
    jmethodID jObjectUserConstructor = env->GetMethodID(user,"<init>","()V");
    jobject jObjectUser = env->NewObject(user,jObjectUserConstructor);
    env->SetIntField(jObjectUser,userAge,15);
    jstring jStringUserName = env->NewStringUTF(usetNameStr);
    env->SetObjectField(jObjectUser,userName,jStringUserName);

    //释放内存
    //env->ReleaseByteArrayElements(byteArry,byteArray,0);

    return jObjectUser;
}

const char *jniClassName = "com/example/jnidemo/JniUtils";
const JNINativeMethod getMethods[] = {{"sendUser",
                                              "(Lcom/example/jnidemo/User;)Lcom/example/jnidemo/User;",
                                              (void *) sendUser}};

jint RegisterNative(JNIEnv *env) {
    //获取映射的Java类
    jclass javaClass = env->FindClass(jniClassName);
    if (javaClass == NULL) {
        printf("cannot get class : %s\n", jniClassName);
        return -1;
    }
    return env->RegisterNatives(javaClass, getMethods, sizeof(getMethods) / sizeof(getMethods[0]));
}

//jni函数入口,类似main函数
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    LOGE("jni_onload_start");
    //注册时在JNIEnv中实现,所以必须首先获取它
    JNIEnv *env = NULL;
    jint result = -1;
    //从JavaVM中获取JNIEnv,一般使用1.4的版本
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
        return result;
    }
    result = RegisterNative(env);
    LOGE("RegisterNatives result:%d", result);
    LOGE("jni_onload_end");
    return JNI_VERSION_1_4;//必须返回版本,否则加载会失败
}


demo很简单,注释基本上看明白流程,跑一遍代码应当就能学会,有问题欢迎大佬们斧正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值