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

如何通过JNI将C++的std::vector<std::vector<float>>返回至Java

解决C++二维std::vector转JNI jobjectArray的问题

没问题,我来一步步帮你搞定这个转换。本质上我们要把C++的std::vector<std::vector<float>>转换成Java的二维float数组(对应JNI里的jobjectArray,每个元素是jfloatArray)。下面是完整的实现思路和代码:

核心步骤拆解

  1. 获取Java float数组的类引用:JNI里表示Java float数组的类签名是[F,我们需要用FindClass拿到这个类的引用,作为外层jobjectArray的元素类型。
  2. 创建外层jobjectArray:对应C++外层vector的长度,每个位置将存放一个Java float数组。
  3. 遍历并转换每个子vector:把每个std::vector<float>转成jfloatArray,再放入外层数组。
  4. 清理局部引用:JNI中创建的局部引用会占用虚拟机资源,用完要及时释放。

完整实现代码

extern "C" JNIEXPORT jobjectArray JNICALL Java_com_google_ar_core_examples_java_helloar_HelloArActivity_fillListWithData(
    JNIEnv *env, jobject /* this */ ) {
    // 获取C++侧的二维vector
    std::vector<std::vector<float>> verticesVec = initializer->GetVertices();

    // 1. 获取Java float数组的类引用(签名[F表示float[])
    jclass floatArrayClass = env->FindClass("[F");
    if (floatArrayClass == nullptr) {
        // 处理类查找失败的异常,直接返回null
        return nullptr;
    }

    // 2. 创建外层jobjectArray,元素类型是float[],长度等于外层vector的大小
    jobjectArray verticesArr = env->NewObjectArray(verticesVec.size(), floatArrayClass, nullptr);
    if (verticesArr == nullptr) {
        // 创建数组失败,先释放之前的局部引用再返回
        env->DeleteLocalRef(floatArrayClass);
        return nullptr;
    }

    // 3. 遍历每个子vector,转换为jfloatArray并放入外层数组
    for (size_t i = 0; i < verticesVec.size(); ++i) {
        const std::vector<float>& subVec = verticesVec[i];
        // 创建对应长度的jfloatArray
        jfloatArray floatArr = env->NewFloatArray(subVec.size());
        if (floatArr == nullptr) {
            // 如果创建失败,提前清理所有已创建的资源
            env->DeleteLocalRef(floatArrayClass);
            env->DeleteLocalRef(verticesArr);
            return nullptr;
        }
        // 将C++ vector的float数据复制到jfloatArray中
        env->SetFloatArrayRegion(floatArr, 0, subVec.size(), subVec.data());
        // 将jfloatArray放入外层jobjectArray的对应位置
        env->SetObjectArrayElement(verticesArr, i, floatArr);
        // 释放局部引用:floatArr已经被外层数组持有,这里可以释放临时引用
        env->DeleteLocalRef(floatArr);
    }

    // 4. 释放floatArrayClass的局部引用
    env->DeleteLocalRef(floatArrayClass);

    return verticesArr;
}

优化建议(Java端)

你当前的Java本地方法声明是public native Object[] fillListWithData();,其实可以更精准地写成:

public native float[][] fillListWithData();

这样Java端直接拿到二维float数组,不需要强制类型转换,代码更清晰易读。

注意事项

  • 异常检查:代码里加了基本的空指针检查,避免JNI操作失败导致崩溃。如果你的项目需要更严谨的异常处理,可以调用env->ExceptionCheck()和env->ExceptionClear()来处理JNI层面的异常。
  • 局部引用管理:JNI的局部引用有数量限制,一定要及时释放不再使用的局部引用,避免内存泄漏或引用溢出问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:51:34