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

如何通过JNI将C语言结构体传递给Java并映射对象属性

JNI中实现C结构体到Java对象的赋值

我来一步步教你怎么把C结构体里的值传到Java对象里,下面是具体的实现步骤和完整代码:

完整JNI实现代码

#include <jni.h>
#include <string.h>
#include <stdlib.h>

// 如果JNI文件没关联对应的C头文件,先声明结构体和创建函数
struct MyEntity { char *_myEntityType; };
struct MyEntity my_C_Entity();

extern "C" JNIEXPORT jobject JNICALL Java_myproject_1_FromCPP__1main(JNIEnv *env, jobject instance) {
    // 1. 调用C函数拿到结构体实例
    struct MyEntity cEntity = my_C_Entity();

    // 2. 获取Java端MyEntity类的引用
    jclass myEntityClass = env->FindClass("myproject/MyEntity");
    if (myEntityClass == NULL) {
        return NULL; // 找不到类直接返回
    }

    // 3. 获取MyEntity的无参构造方法ID(你的Java类默认有无参构造)
    // 方法签名()V表示无参数、返回值为void
    jmethodID constructor = env->GetMethodID(myEntityClass, "<init>", "()V");
    if (constructor == NULL) {
        env->DeleteLocalRef(myEntityClass); // 提前释放局部引用
        return NULL;
    }

    // 4. 创建Java端MyEntity对象实例
    jobject javaEntity = env->NewObject(myEntityClass, constructor);
    if (javaEntity == NULL) {
        env->DeleteLocalRef(myEntityClass);
        return NULL;
    }

    // 5. 获取set_myEntityType方法的ID
    // 方法签名(Ljava/lang/String;)V表示参数是String、返回值为void
    jmethodID setMethod = env->GetMethodID(myEntityClass, "set_myEntityType", "(Ljava/lang/String;)V");
    if (setMethod == NULL) {
        env->DeleteLocalRef(myEntityClass);
        env->DeleteLocalRef(javaEntity);
        return NULL;
    }

    // 6. 把C字符串转换成Java的String对象
    jstring jType = env->NewStringUTF(cEntity._myEntityType);
    if (jType == NULL) {
        env->DeleteLocalRef(myEntityClass);
        env->DeleteLocalRef(javaEntity);
        free(cEntity._myEntityType); // 释放strdup分配的内存,避免泄漏
        return NULL;
    }

    // 7. 调用set方法给Java对象赋值
    env->CallVoidMethod(javaEntity, setMethod, jType);

    // 8. 清理资源:释放局部引用和C层的动态内存
    env->DeleteLocalRef(myEntityClass);
    env->DeleteLocalRef(jType);
    free(cEntity._myEntityType); // 因为my_C_Entity用了strdup,必须手动释放

    // 返回赋值完成的Java对象
    return javaEntity;
}

几个必须注意的细节:

  • 方法签名:JNI调用Java方法必须用正确的签名,你可以通过javap -s myproject.MyEntity命令生成官方签名,确保和代码里的一致。
  • 局部引用释放:虽然JNI函数返回时会自动释放局部引用,但如果有分支提前返回,最好手动释放,避免内存泄漏。
  • 内存管理:my_C_Entity()里用strdup分配的内存,JNI不会帮你回收,必须用free手动释放,否则会造成内存泄漏。
  • 错误检查:每一步JNI调用后都做NULL检查,避免空指针导致程序崩溃。

内容的提问来源于stack exchange,提问作者Program-Me-Rev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:48:04