将jobjectArray从c++传递到Java,返回的字符串不完整

Pass jobjectArray from C++ to Java, returned strings are not completed

本文关键字:返回 字符串 Java jobjectArray c++      更新时间:2023-10-16

我想通过JNI将字符串数组从c++传递到Java,这意味着返回String[]到Java。

当我在c++中打印char*时是正确的,但当我在Java中打印String时是不正确的。例如,在c++中char*是"AdaptationSet 1",但在Java中有时是"AdaptationSe"有时是"string";(我不知道这是什么)。

我不知道我的代码哪里不对,请给我一些帮助。

这是我的c++代码

jobjectArray getJavaStringArray(JNIEnv *env, char ** array, int size)
{
    jobjectArray ret;
    int i;
    ret = (jobjectArray) env->NewObjectArray(size, env->FindClass("java/lang/String"), NULL);
    for (i = 0; i < size; i++)
    {
        env->SetObjectArrayElement(ret, i, env->NewStringUTF(array[i]));
    }
    return ret;
}

extern "C" JNIEXPORT jobjectArray Java_com_example_test_MainActivity_nGetStrings(JNIEnv *env, jobject obj)
{
    int i, size = 1;
    jobjectArray ret = NULL;
    char **array = (char**) calloc(size, sizeof(char*));
    for (i = 0; i < size; i++) {
        std::stringstream ss;
        ss << "AdaptationSet " << i+1;
        array[i] = (char*) ss.str().c_str();
    }
    return getJavaStringArray(env, array, size);
}
<<p> Java代码/strong>
package com.example.test
import ...;
public class MainActivity extends Activity {
    private native String[] nGetStrings();
    static {
        System.loadLibrary("myLib");
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        String[] arrays = nGetStrings();
        for(int i = 0; i < arrays.length; i++) {
            System.out.println("arrays[" + i + "] = " + arrays[i]);
        }
    }
}

解决方案:

问题在这一行:

array[i] = (char*) ss.str().c_str();

解决方法是复制内容,像这样:

array[i] = (char*) calloc(ss.str().size()+1, sizeof(char));
memcpy(array[i], ss.str().c_str(), ss.str().size());

谢谢你的建议

我测试了一下,它可以工作。

main.cpp:

#include "jni.h"
#if defined _WIN32 || defined _WIN64
#include <windows.h>
#endif
extern "C" jobjectArray JNIEXPORT Java_natives_Natives_getStringArray(JNIEnv* env, jobject obj)
{
    jobjectArray strarr = env->NewObjectArray(5, env->FindClass("java/lang/String"), nullptr);
    for (int i = 0; i < 5; ++i)
    {
        env->SetObjectArrayElement(strarr, i, env->NewStringUTF("Россия"));
    }
    return strarr;
}

#if defined _WIN32 || defined _WIN64
extern "C" __declspec(dllexport) bool __stdcall DllMain(HINSTANCE hinstDLL, DWORD fdwReason, void* lpvReserved)
{
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            break;
        case DLL_PROCESS_DETACH:
            break;
    }
    return true;
}
#endif

main.java:

package natives;
public class Natives {
    static {
        System.loadLibrary("Native");
    }
    public static native String[] getStringArray();
    public static void main(String[] args) {
        String[] res = getStringArray();
        for (String str : res) {
            System.out.println(str);
        }
    }
}

这里可能有问题array[i] = (char*) ss.str().c_str();
必须复制字符串内容,而不是C/c++中的指针。

试试下面的例子:

#include<iostream>
#include<sstream>
using namespace std;
int main()
{
    stringstream ss1,ss2;
    char *str1, *str2;
    ss1 << "s1";
    ss2 << "s2";
    str1 = (char*) ss1.str().c_str();
    str2 = (char*) ss2.str().c_str();
    cout << str1;
    cout << str2;
    return 0;
}

您将得到输出s2s2而不是s1s2