Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ std::string to jstring with a fixed length

I'm trying to turn a C++ std::string into a jstring and return it. This would be easy enough with

JNIEnv*->NewStringUTF(stdString.c_str())

but the problem is that the string I'm converting has almost randomly interspersed null characters in it. This is a problem for the c_str(), but not the std::string. NewStringUTF will only catch a portion of the full std::string. There is some hope in that the std::string has a length() function, which gets the full length, ignoring the problematic char* \0 characters.

There's a separate function NewString that takes in a jchar* and a jsize*, so that looks promising, but I can't get the std::string converted properly to the jchar*. I tried making it a byte array, but I probably wasn't doing it right. I had further problems converting the int given by the length() into a jsize, which was required by the NewString call.

I have done a bit of work with vector<char> byteArray(stdString.begin(), stdString.end()), but that didn't get me very far, probably because that is messing up what the original string is.

Here is the basic starter function I have, which worked with strings without null chars:

jstring StringToJString(JNIEnv * env, const std::string & nativeString) {
    return env->NewStringUTF(nativeString.c_str());
}

As a side note, this function is being used inside a JNI wrapper file for returning an object's std::string.

Thanks for any help or information sources!

like image 510
Eli Rising Avatar asked Dec 04 '14 20:12

Eli Rising


1 Answers

I made my own workaround solution taking RedAlert's advice.

Java now expects a byte[] from the native call:

private native byte[] toString(long thiz);

The toString method now calls this method inside it on a std::string:

jbyteArray StringToJByteArray(JNIEnv * env, const std::string &nativeString) {
    jbyteArray arr = env->NewByteArray(nativeString.length());
    env->SetByteArrayRegion(arr,0,nativeString.length(),(jbyte*)nativeString.c_str());
    return arr;
}

And the java level receives the data like this:

byte[] byteArray = toString(mNativeInstance);
String nativeString = "";
try {
    nativeString = new String(byteArray, "UTF-8");
} catch (UnsupportedEncodingException e) {
    Log.e(TAG, "Couldn't convert the jbyteArray to UTF-8");
    e.printStackTrace();
}
like image 64
Eli Rising Avatar answered Sep 22 '22 18:09

Eli Rising