如何在 JniWrapper 中将 Java ArrayList<float[]> 映射到 C++ Vector<array<float,size>>?

Posted

技术标签:

【中文标题】如何在 JniWrapper 中将 Java ArrayList<float[]> 映射到 C++ Vector<array<float,size>>?【英文标题】:How to map Java ArrayList<float[]> to C++ Vector<array<float,size>> in JniWrapper? 【发布时间】:2019-10-18 16:23:02 【问题描述】:

我有一个浮点数组的 ArrayList 为 ArrayList&lt;float[]&gt;,我想在 JniWrapper 中将其映射到 C++ Vector&lt;array&lt;float,size&gt;&gt;

我点击了这个链接:

“Returning an arraylist of string from Native java to JNI”

并根据我的要求对代码进行了一些更改。

static jclass java_util_ArrayList;
static jmethodID java_util_ArrayList_;
jmethodID java_util_ArrayList_size;
jmethodID java_util_ArrayList_get;
jmethodID java_util_ArrayList_add;
static thread_local JNIEnv *env;

void java2cpp(jobject arrayList, vector<array<float, 320>> &result) 
    java_util_ArrayList = static_cast<jclass>(env->NewGlobalRef(
            env->FindClass("java/util/ArrayList")));
    java_util_ArrayList_ = env->GetMethodID(java_util_ArrayList, "init", "(I)V");
    java_util_ArrayList_size = env->GetMethodID(java_util_ArrayList, "size", "()I");
    java_util_ArrayList_get = env->GetMethodID(java_util_ArrayList, "get", "(I)Ljava/lang/Object;");
    java_util_ArrayList_add = env->GetMethodID(java_util_ArrayList, "add", "(Ljava/lang/Object;)V");


    jint len = env->CallIntMethod(arrayList, java_util_ArrayList_size);
    result.reserve(len);
    for (jint i = 0; i < len; i++) 
        jfloatArray element = static_cast<jfloatArray>(env->CallObjectMethod(arrayList,
                                                                             java_util_ArrayList_get,
                                                                             i));
        const float *pchars = env->GetFloatArrayElements(element, nullptr);
        result.emplace_back(pchars);
        env->ReleaseFloatArrayElements(element, const_cast<jfloat *>(pchars), 0);
        env->DeleteLocalRef(element);
    


jfloatArray cpp2java(array<float, 320> output) 
    jfloatArray result;
    result = env->NewFloatArray(320);

    float *data;
    data = output.data();

    env->SetFloatArrayRegion(result, 0, 320, data);
    free(data);
    return result;


错误:

note: in instantiation of function template specialization 'std::__ndk1::vector<std::__ndk1::array<float, 320>, std::__ndk1::allocator<std::__ndk1::array<float, 320> > >::emplace_back<const float *&>' requested here
        result.emplace_back(pchars);
           ^

我是 JNI Wrappers 开发的新手。我需要帮助将ArrayList&lt;float[]&gt; 映射到Vector&lt;array&lt;float,320&gt;&gt;

【问题讨论】:

您的向量包含array&lt;float, 320&gt;,但您传递给它的是const float *。您需要创建正确类型的数组并用适当的数据填充它。 嗨@ChrisMM,你能解释一下吗? 【参考方案1】:

结果类型为:vector&lt;array&lt;float, 320&gt;&gt;,通过引用传递。 不过你emplace_backconst float*

const float *pchars = env->GetFloatArrayElements(element, nullptr);
 result.emplace_back(pchars);

您可以通过使用pchar 指向的数据创建一个数组来解决问题,例如

std::array<float, 320> res;
for (int i = 0; i < end; ++i)
     res[i] = pchars[i];
result.emplace_back(res);

确保检查pchar(结束)您可能会越界访问。

【讨论】:

那我该怎么办..?? 好的,非常感谢。让我试试解决方案。 @KhubaibAhmad “我的问题已解决” - 那么您应该接受解决问题的答案,而不是留下“谢谢”评论。 @JesperJuhl 我很抱歉.. 有一些技术问题,我无法做到。【参考方案2】:

您的向量包含array&lt;float, 320&gt;,但您传递给它的是const float *。您需要创建正确类型的数组并用适当的数据填充它。您绝不会创建array&lt;float, 320&gt;,也不会填写它。自从我使用 JNI 已经有一段时间了,所以我真的不记得语法了,但是您必须将 jfloatarray 中的元素复制到新的 array&lt;float, 320&gt; 中。

假设pchars 包含适当的数据,那么您应该能够执行以下操作:

const float *pchars = env->GetFloatArrayElements(element, nullptr);
array<float, 320> newArray;
for ( size_t i = 0; i < 320; ++i ) newArray[i] = pchars[i];
result.emplace_back(newArray);

【讨论】:

非常感谢@ChrisMM。我认为这是正确的解决方案。

以上是关于如何在 JniWrapper 中将 Java ArrayList<float[]> 映射到 C++ Vector<array<float,size>>?的主要内容,如果未能解决你的问题,请参考以下文章

CMake JNI 错误

在 install4j 安装程序中使用 jniwrapper 自定义代码

在java中将整数列表转换为整数数组[重复]

如何在php中将字节数组转换为整数?

AR入门系列-03-在unity中将调试好的Vuforia项目导出为APK

如何在 PHP 中将默认日期设置为波斯日期?