JNI call convert jstring to char*

匿名 (未验证) 提交于 2019-12-03 09:18:39

问题:

I my cpp code contains a jni function that i wish to convert to const char*. This is the code i am using

extern "C" { void Java_com_sek_test_JNITest_printSomething(JNIEnv * env, jclass cl, jstring str) {      const char* mystring = env->GetStringUTFChars(env, str, 0);     PingoScreen::notify(); } 

I get an error that

no matching function for call to '_JNIEnv::GetStringUTFChars(JNIEnv*&, _jstring*&, int) 

What am i doing wrong ?

回答1:

According to the documentation,

GetStringUTFChars const jbyte* GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy);

Returns a pointer to an array of bytes representing the string in modified UTF-8 encoding. This array is valid until it is released by ReleaseStringUTFChars().

If isCopy is not NULL, then *isCopy is set to JNI_TRUE if a copy is made; or it is set to JNI_FALSE if no copy is made.

So the last parameter should be a jboolean;



回答2:

There several things that aren't quite right with your code and approach:

  1. As you've discovered, (env*)->JNIFunc(env,...) should be env->JNIFunc(...) in C++. Your vendor's (Google Android's) jni.h simplifies the C++ syntax over the C syntax.
  2. You're not calling the "Release" function (ReleaseStringUTFChars) corresponding to the "pinning" function (GetStringUTFChars). This is very important because pinned objects reduce the memory efficiency of the JVM's garbage collector.
  3. You've misinterpreted the final argument to GetStringUTFChars. It's a pointer for an output parameter. The result isn't very interesting so pass nullptr.
  4. You're using JNI functions that deal with the modified UTF-8 encoding (GetStringUTFChars et al). There should be no need to ever use that encoding. Java classes are very capable at converting encodings. They also give you control over what happens when a character cannot be encoded in the target encoding. (The default is to convert it to a ?.)
  5. The idea of converting a JVM object reference (jstring) to a pointer to one byte storage (char*) needs a lot of refinement. You probably want to copy the characters in a JVM java.lang.String to a "native" string using a specific or OS-default encoding. The Java string has Unicode characters with a UTF-16 encoding. Android generally uses the Unicode character set with the UTF-8 encoding. If do you need something else, you can specify it with a Charset object.
  6. Also, in C++, it is more convenient to use STL std::string to hold counted byte-sequences for a string. You can get a pointer to a null-terminated buffer from a std::string if you need it.

Be sure to read Android's JNI Tips.

Here is an implementation of your function that lets the vendor's JVM implementation pick the target encoding (which is UTF-8 for Android):

extern "C" JNIEXPORT void Java_com_sek_test_JNITest_printSomething   (JNIEnv * env, jclass cl, jstring str) {     // TODO check for JVM exceptions where appropriate       //  javap -s -public java.lang.String | egrep -A 2 "getBytes"     const auto stringClass = env->FindClass("java/lang/String");     const auto getBytes = env->GetMethodID(stringClass, "getBytes", "()[B");      const auto stringJbytes = (jbyteArray) env->CallObjectMethod(str, getBytes);      const auto length = env->GetArrayLength(stringJbytes);     const auto pBytes = env->GetByteArrayElements(stringJbytes, nullptr);      std::string s((char *)pBytes, length);     env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT);         const auto pChars = s.c_str(); // if you really do need a pointer } 

However, I'd probably do the call to String.getBytes on the Java side, defining the native method to take a byte array instead of a string.

(Of course, implementations that use GetStringUTFChars do work for some subset of Unicode strings but why impose an esoteric and needless limit?)



回答3:

Try... Change this line

const char* mystring = env->GetStringUTFChars(env, str, 0); 

to

const char *mystring = (*env)->GetStringUTFChars(env, str, 0); 

Hope it works:)



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!