You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JNI下C++与Kotlin传递uint64_t联合结构体的优化方案问询

解决方案:C++联合结构体与Kotlin的JNI原生交互方案

核心思路

直接在JNI层完成字段的解析与组装,Kotlin端仅需接收/传递封装好的数据对象,彻底避开大小端转换和位操作,同时满足后续结构体变更的扩展性要求。

具体实现步骤

1. Kotlin端定义对应数据类

定义与C++ union中结构体字段一一对应的数据类,后续结构体变更时仅需修改此类:

data class UnionData(
    val a: UInt,
    val b: UByte,
    val c: UByte,
    val d: UInt
)

2. JNI层处理C++到Kotlin的传递

在JNI函数中直接读取C++ union的结构体字段,创建Kotlin的UnionData对象返回,无需传递uint64_t或ByteBuffer:

extern "C" JNIEXPORT jobject JNICALL
Java_com_your_package_YourClass_getUnionData(JNIEnv* env, jobject thiz) {
    // 假设已初始化好目标union实例
    uns unionInstance;
    // 获取UnionData类的构造方法
    jclass unionDataCls = env->FindClass("com/your/package/UnionData");
    jmethodID constructor = env->GetMethodID(unionDataCls, "<init>", "(Ljava/lang/Integer;Ljava/lang/Byte;Ljava/lang/Byte;Ljava/lang/Integer;)V");
    
    // 转换字段类型并创建对应包装类对象
    jobject aObj = env->NewObject(env->FindClass("java/lang/Integer"), 
                                  env->GetMethodID(env->FindClass("java/lang/Integer"), "<init>", "(I)V"), 
                                  (int)unionInstance.m.a);
    jobject bObj = env->NewObject(env->FindClass("java/lang/Byte"), 
                                  env->GetMethodID(env->FindClass("java/lang/Byte"), "<init>", "(B)V"), 
                                  (byte)unionInstance.m.b);
    jobject cObj = env->NewObject(env->FindClass("java/lang/Byte"), 
                                  env->GetMethodID(env->FindClass("java/lang/Byte"), "<init>", "(B)V"), 
                                  (byte)unionInstance.m.c);
    jobject dObj = env->NewObject(env->FindClass("java/lang/Integer"), 
                                  env->GetMethodID(env->FindClass("java/lang/Integer"), "<init>", "(I)V"), 
                                  (int)unionInstance.m.d);
    
    // 创建UnionData对象并返回
    jobject result = env->NewObject(unionDataCls, constructor, aObj, bObj, cObj, dObj);
    
    // 释放局部引用
    env->DeleteLocalRef(unionDataCls);
    env->DeleteLocalRef(aObj);
    env->DeleteLocalRef(bObj);
    env->DeleteLocalRef(cObj);
    env->DeleteLocalRef(dObj);
    
    return result;
}

3. JNI层处理Kotlin到C++的回传

Kotlin端传递UnionData对象,JNI层读取字段值后组装成C++的union:

extern "C" JNIEXPORT void JNICALL
Java_com_your_package_YourClass_sendUnionData(JNIEnv* env, jobject thiz, jobject unionData) {
    // 获取UnionData类的字段ID
    jclass unionDataCls = env->FindClass("com/your/package/UnionData");
    jfieldID aField = env->GetFieldID(unionDataCls, "a", "Ljava/lang/Integer;");
    jfieldID bField = env->GetFieldID(unionDataCls, "b", "Ljava/lang/Byte;");
    jfieldID cField = env->GetFieldID(unionDataCls, "c", "Ljava/lang/Byte;");
    jfieldID dField = env->GetFieldID(unionDataCls, "d", "Ljava/lang/Integer;");
    
    // 读取字段的实际值
    jint a = env->CallIntMethod(env->GetObjectField(unionData, aField), env->GetMethodID(env->FindClass("java/lang/Integer"), "intValue", "()I"));
    jbyte b = env->CallByteMethod(env->GetObjectField(unionData, bField), env->GetMethodID(env->FindClass("java/lang/Byte"), "byteValue", "()B"));
    jbyte c = env->CallByteMethod(env->GetObjectField(unionData, cField), env->GetMethodID(env->FindClass("java/lang/Byte"), "byteValue", "()B"));
    jint d = env->CallIntMethod(env->GetObjectField(unionData, dField), env->GetMethodID(env->FindClass("java/lang/Integer"), "intValue", "()I"));
    
    // 组装成C++ union实例
    uns unionInstance;
    unionInstance.m.a = (uint32_t)a;
    unionInstance.m.b = (uint64_t)b;
    unionInstance.m.c = (uint64_t)c;
    unionInstance.m.d = (uint64_t)d;
    
    // 此处可使用unionInstance.data做后续业务处理
    
    // 释放局部引用
    env->DeleteLocalRef(unionDataCls);
}

方案优势

  • 无底层操作依赖:所有位解析与组装都在JNI层完成,依托C++原生union内存布局,Kotlin端无需关心大小端、位运算等底层细节
  • 扩展性强:后续C++结构体字段变更时,仅需同步修改Kotlin数据类和JNI层的字段映射代码,不影响Kotlin端业务逻辑
  • 原生兼容:完全基于JNI原生API实现,不依赖任何第三方库,满足uint64_t类型的使用要求

内容的提问来源于stack exchange,提问作者Anumey Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 11:07:01