Question

I want to pass String array from C++ to Java by JNI, means return String[] to java.

When I print the char* in C++ is correct, but when I print the String in Java is incorrect. For example, in C++ char* is "AdaptationSet 1", but in Java sometimes is "AdaptationSe" sometimes is "tring;" (I don't know what's this).

I'm not sure where is incorrect in my code, please give me any helps.

This is my C++ code

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;
}

and

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);
}

Java code

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]);
        }
    }
}

SOLUTION:

The problem is at this line:

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

The solution is copy the content, like this:

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

Thanks for your suggestions.

Was it helpful?

Solution 2

Here might be a problem array[i] = (char*) ss.str().c_str(); .
You must copy the string content instead of the pointer in C/C++.

Try the following example:

#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;
}

You will have the output s2s2 not s1s2.

OTHER TIPS

I tested this and it works..

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);
        }
    }

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top