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

如何在C++程序中调用返回Java类对象的方法并处理该对象

JNI中Java对象与C++对象的互转问题解答

问题1:将JNI获取的jobject转换为C++的Test1对象

首先,你得在C++里定义一个和Java端Test1结构完全匹配的类,这样才能存储对应的数据:

// C++端的Test1类,和Java字段一一对应
class Test1 {
public:
    int a;
    int b;
};

接下来,你需要通过JNI的API读取Java对象里的字段值,再赋值给C++对象。具体步骤如下:

  1. 找到Java端Test1类的jclass引用
  2. 获取a和b两个字段的jfieldID(JNI用来定位字段的唯一标识)
  3. 从拿到的jobject中取出字段的int值,转成C++的int类型后赋值

把这段代码加到你获取jobject obj之后的位置:

// 找到Test1类,如果有包名要写完整路径,比如"com/yourpackage/Test1"
jclass test1Cls = env->FindClass("Test1");
if (test1Cls != nullptr) {
    // 获取字段ID,第二个参数是字段名,第三个是字段签名:"I"表示int类型
    jfieldID fieldA = env->GetFieldID(test1Cls, "a", "I");
    jfieldID fieldB = env->GetFieldID(test1Cls, "b", "I");
    
    if (fieldA != nullptr && fieldB != nullptr) {
        // 读取Java对象中的字段值
        jint javaA = env->GetIntField(obj, fieldA);
        jint javaB = env->GetIntField(obj, fieldB);
        
        // 赋值给C++的Test1对象
        Test1 cppTest1;
        cppTest1.a = static_cast<int>(javaA);
        cppTest1.b = static_cast<int>(javaB);
        
        // 现在就可以正常使用cppTest1了
        std::cout << "C++ Test1对象: a=" << cppTest1.a << ", b=" << cppTest1.b << std::endl;
    } else {
        std::cerr << "无法获取Test1的字段ID" << std::endl;
    }
} else {
    std::cerr << "找不到Test1类" << std::endl;
}

注意:如果Java的Test1不在默认包下,FindClass的参数必须是完整的类路径,用斜杠代替点,比如"com/example/Test1"


补充问题:将C++的Test1对象传递给Java方法

要实现这个,需要分两步:在Java端准备接收方法,然后在C++端创建Java对象并传递,具体如下:

1. Java端准备接收方法

先在Server11类里定义一个静态方法,用来接收Test1对象:

public class Server11 {
    // 其他已有方法...
    
    public static void acceptTest1(Test1 testObj) {
        System.out.println("Java收到Test1对象: a=" + testObj.a + ", b=" + testObj.b);
    }
}

2. C++端创建Java的Test1对象并传递

你需要先创建一个Java的Test1实例,把C++对象的字段值赋值给它,再调用Java的接收方法:

// 先定义一个C++的Test1对象,准备传递
Test1 cppTest1;
cppTest1.a = 100;
cppTest1.b = 200;

// 找到Java的Test1类
jclass test1Cls = env->FindClass("Test1");
if (test1Cls != nullptr) {
    // 获取Test1的无参构造方法ID,"<init>"是构造方法的固定名称,"()V"是无参构造的签名
    jmethodID test1Ctor = env->GetMethodID(test1Cls, "<init>", "()V");
    if (test1Ctor != nullptr) {
        // 创建Java的Test1对象实例
        jobject javaTest1 = env->NewObject(test1Cls, test1Ctor);
        
        // 获取字段ID,给Java对象赋值
        jfieldID fieldA = env->GetFieldID(test1Cls, "a", "I");
        jfieldID fieldB = env->GetFieldID(test1Cls, "b", "I");
        
        if (fieldA != nullptr && fieldB != nullptr) {
            env->SetIntField(javaTest1, fieldA, cppTest1.a);
            env->SetIntField(javaTest1, fieldB, cppTest1.b);
            
            // 找到Server11类,调用acceptTest1方法
            jclass serverCls = env->FindClass("Server11");
            if (serverCls != nullptr) {
                // 方法签名:(LTest1;)V,其中LTest1;表示参数是Test1对象,V表示返回值是void
                jmethodID acceptMethod = env->GetStaticMethodID(serverCls, "acceptTest1", "(LTest1;)V");
                if (acceptMethod != nullptr) {
                    // 调用静态方法,传递JavaTest1对象
                    env->CallStaticVoidMethod(serverCls, acceptMethod, javaTest1);
                } else {
                    std::cerr << "找不到acceptTest1方法ID" << std::endl;
                }
            } else {
                std::cerr << "找不到Server11类" << std::endl;
            }
        } else {
            std::cerr << "无法获取Test1的字段ID" << std::endl;
        }
    } else {
        std::cerr << "找不到Test1的构造方法ID" << std::endl;
    }
} else {
    std::cerr << "找不到Test1类" << std::endl;
}

关于方法签名的说明

如果Java的Test1在包下,比如com.example.Test1,那么方法签名里的参数部分要写成(Lcom/example/Test1;)V,完整的签名规则是:

  • ( 表示参数开始
  • L 表示引用类型,后面跟完整类路径(斜杠分隔),最后加;
  • ) 表示参数结束
  • V 表示返回值是void

通用注意事项

  • 所有JNI返回的jclass、jmethodID、jfieldID都必须做非空检查,否则一旦为空就会导致JNI调用崩溃
  • 局部引用(比如FindClass返回的jclass)不需要手动释放,JNI会在当前线程的方法执行完毕后自动回收;如果是全局引用(用NewGlobalRef创建的),则需要手动调用DeleteGlobalRef释放
  • 类路径和签名一定要准确,JNI对这些字符串的格式要求非常严格,写错会直接找不到类或方法/字段

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:20:43