Android: Fixed problems with memory leaks due to absent ReleaseStringUTFChars calls.
This commit is contained in:
parent
f0f277faf1
commit
1073f0b423
@ -31,6 +31,7 @@
|
|||||||
#include "dir_access_jandroid.h"
|
#include "dir_access_jandroid.h"
|
||||||
#include "core/print_string.h"
|
#include "core/print_string.h"
|
||||||
#include "file_access_jandroid.h"
|
#include "file_access_jandroid.h"
|
||||||
|
#include "string_android.h"
|
||||||
#include "thread_jandroid.h"
|
#include "thread_jandroid.h"
|
||||||
|
|
||||||
jobject DirAccessJAndroid::io = NULL;
|
jobject DirAccessJAndroid::io = NULL;
|
||||||
@ -69,7 +70,7 @@ String DirAccessJAndroid::get_next() {
|
|||||||
if (!str)
|
if (!str)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
String ret = String::utf8(env->GetStringUTFChars((jstring)str, NULL));
|
String ret = jstring_to_string((jstring)str, env);
|
||||||
env->DeleteLocalRef((jobject)str);
|
env->DeleteLocalRef((jobject)str);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
#include "java_class_wrapper.h"
|
#include "java_class_wrapper.h"
|
||||||
|
#include "string_android.h"
|
||||||
#include "thread_jandroid.h"
|
#include "thread_jandroid.h"
|
||||||
|
|
||||||
bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error, Variant &ret) {
|
bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error, Variant &ret) {
|
||||||
@ -553,7 +554,7 @@ void JavaClassWrapper::_bind_methods() {
|
|||||||
bool JavaClassWrapper::_get_type_sig(JNIEnv *env, jobject obj, uint32_t &sig, String &strsig) {
|
bool JavaClassWrapper::_get_type_sig(JNIEnv *env, jobject obj, uint32_t &sig, String &strsig) {
|
||||||
|
|
||||||
jstring name2 = (jstring)env->CallObjectMethod(obj, Class_getName);
|
jstring name2 = (jstring)env->CallObjectMethod(obj, Class_getName);
|
||||||
String str_type = env->GetStringUTFChars(name2, NULL);
|
String str_type = jstring_to_string(name2, env);
|
||||||
env->DeleteLocalRef(name2);
|
env->DeleteLocalRef(name2);
|
||||||
uint32_t t = 0;
|
uint32_t t = 0;
|
||||||
|
|
||||||
@ -697,7 +698,7 @@ bool JavaClass::_convert_object_to_variant(JNIEnv *env, jobject obj, Variant &va
|
|||||||
} break;
|
} break;
|
||||||
case ARG_TYPE_STRING: {
|
case ARG_TYPE_STRING: {
|
||||||
|
|
||||||
var = String::utf8(env->GetStringUTFChars((jstring)obj, NULL));
|
var = jstring_to_string((jstring)obj, env);
|
||||||
return true;
|
return true;
|
||||||
} break;
|
} break;
|
||||||
case ARG_TYPE_CLASS: {
|
case ARG_TYPE_CLASS: {
|
||||||
@ -1030,7 +1031,7 @@ bool JavaClass::_convert_object_to_variant(JNIEnv *env, jobject obj, Variant &va
|
|||||||
if (!o)
|
if (!o)
|
||||||
ret.push_back(Variant());
|
ret.push_back(Variant());
|
||||||
else {
|
else {
|
||||||
String val = String::utf8(env->GetStringUTFChars((jstring)o, NULL));
|
String val = jstring_to_string((jstring)o, env);
|
||||||
ret.push_back(val);
|
ret.push_back(val);
|
||||||
}
|
}
|
||||||
env->DeleteLocalRef(o);
|
env->DeleteLocalRef(o);
|
||||||
@ -1075,7 +1076,7 @@ Ref<JavaClass> JavaClassWrapper::wrap(const String &p_class) {
|
|||||||
ERR_CONTINUE(!obj);
|
ERR_CONTINUE(!obj);
|
||||||
|
|
||||||
jstring name = (jstring)env->CallObjectMethod(obj, getName);
|
jstring name = (jstring)env->CallObjectMethod(obj, getName);
|
||||||
String str_method = env->GetStringUTFChars(name, NULL);
|
String str_method = jstring_to_string(name, env);
|
||||||
env->DeleteLocalRef(name);
|
env->DeleteLocalRef(name);
|
||||||
|
|
||||||
Vector<String> params;
|
Vector<String> params;
|
||||||
@ -1204,7 +1205,7 @@ Ref<JavaClass> JavaClassWrapper::wrap(const String &p_class) {
|
|||||||
ERR_CONTINUE(!obj);
|
ERR_CONTINUE(!obj);
|
||||||
|
|
||||||
jstring name = (jstring)env->CallObjectMethod(obj, Field_getName);
|
jstring name = (jstring)env->CallObjectMethod(obj, Field_getName);
|
||||||
String str_field = env->GetStringUTFChars(name, NULL);
|
String str_field = jstring_to_string(name, env);
|
||||||
env->DeleteLocalRef(name);
|
env->DeleteLocalRef(name);
|
||||||
int mods = env->CallIntMethod(obj, Field_getModifiers);
|
int mods = env->CallIntMethod(obj, Field_getModifiers);
|
||||||
if ((mods & 0x8) && (mods & 0x10) && (mods & 0x1)) { //static final public!
|
if ((mods & 0x8) && (mods & 0x10) && (mods & 0x1)) { //static final public!
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include "main/input_default.h"
|
#include "main/input_default.h"
|
||||||
#include "main/main.h"
|
#include "main/main.h"
|
||||||
#include "os_android.h"
|
#include "os_android.h"
|
||||||
|
#include "string_android.h"
|
||||||
#include "thread_jandroid.h"
|
#include "thread_jandroid.h"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@ -223,7 +224,7 @@ String _get_class_name(JNIEnv *env, jclass cls, bool *array) {
|
|||||||
jboolean isarr = env->CallBooleanMethod(cls, isArray);
|
jboolean isarr = env->CallBooleanMethod(cls, isArray);
|
||||||
(*array) = isarr ? true : false;
|
(*array) = isarr ? true : false;
|
||||||
}
|
}
|
||||||
String name = env->GetStringUTFChars(clsName, NULL);
|
String name = jstring_to_string(clsName, env);
|
||||||
env->DeleteLocalRef(clsName);
|
env->DeleteLocalRef(clsName);
|
||||||
|
|
||||||
return name;
|
return name;
|
||||||
@ -241,7 +242,7 @@ Variant _jobject_to_variant(JNIEnv *env, jobject obj) {
|
|||||||
|
|
||||||
if (name == "java.lang.String") {
|
if (name == "java.lang.String") {
|
||||||
|
|
||||||
return String::utf8(env->GetStringUTFChars((jstring)obj, NULL));
|
return jstring_to_string((jstring)obj, env);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (name == "[Ljava.lang.String;") {
|
if (name == "[Ljava.lang.String;") {
|
||||||
@ -252,7 +253,7 @@ Variant _jobject_to_variant(JNIEnv *env, jobject obj) {
|
|||||||
|
|
||||||
for (int i = 0; i < stringCount; i++) {
|
for (int i = 0; i < stringCount; i++) {
|
||||||
jstring string = (jstring)env->GetObjectArrayElement(arr, i);
|
jstring string = (jstring)env->GetObjectArrayElement(arr, i);
|
||||||
sarr.push_back(String::utf8(env->GetStringUTFChars(string, NULL)));
|
sarr.push_back(jstring_to_string(string, env));
|
||||||
env->DeleteLocalRef(string);
|
env->DeleteLocalRef(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -487,7 +488,7 @@ public:
|
|||||||
case Variant::STRING: {
|
case Variant::STRING: {
|
||||||
|
|
||||||
jobject o = env->CallObjectMethodA(instance, E->get().method, v);
|
jobject o = env->CallObjectMethodA(instance, E->get().method, v);
|
||||||
ret = String::utf8(env->GetStringUTFChars((jstring)o, NULL));
|
ret = jstring_to_string((jstring)o, env);
|
||||||
env->DeleteLocalRef(o);
|
env->DeleteLocalRef(o);
|
||||||
} break;
|
} break;
|
||||||
case Variant::POOL_STRING_ARRAY: {
|
case Variant::POOL_STRING_ARRAY: {
|
||||||
@ -634,20 +635,20 @@ static String _get_user_data_dir() {
|
|||||||
|
|
||||||
JNIEnv *env = ThreadAndroid::get_env();
|
JNIEnv *env = ThreadAndroid::get_env();
|
||||||
jstring s = (jstring)env->CallObjectMethod(godot_io, _getDataDir);
|
jstring s = (jstring)env->CallObjectMethod(godot_io, _getDataDir);
|
||||||
return String(env->GetStringUTFChars(s, NULL));
|
return jstring_to_string(s, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
static String _get_locale() {
|
static String _get_locale() {
|
||||||
|
|
||||||
JNIEnv *env = ThreadAndroid::get_env();
|
JNIEnv *env = ThreadAndroid::get_env();
|
||||||
jstring s = (jstring)env->CallObjectMethod(godot_io, _getLocale);
|
jstring s = (jstring)env->CallObjectMethod(godot_io, _getLocale);
|
||||||
return String(env->GetStringUTFChars(s, NULL));
|
return jstring_to_string(s, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
static String _get_clipboard() {
|
static String _get_clipboard() {
|
||||||
JNIEnv *env = ThreadAndroid::get_env();
|
JNIEnv *env = ThreadAndroid::get_env();
|
||||||
jstring s = (jstring)env->CallObjectMethod(_godot_instance, _getClipboard);
|
jstring s = (jstring)env->CallObjectMethod(_godot_instance, _getClipboard);
|
||||||
return String(env->GetStringUTFChars(s, NULL));
|
return jstring_to_string(s, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _set_clipboard(const String &p_text) {
|
static void _set_clipboard(const String &p_text) {
|
||||||
@ -661,7 +662,7 @@ static String _get_model() {
|
|||||||
|
|
||||||
JNIEnv *env = ThreadAndroid::get_env();
|
JNIEnv *env = ThreadAndroid::get_env();
|
||||||
jstring s = (jstring)env->CallObjectMethod(godot_io, _getModel);
|
jstring s = (jstring)env->CallObjectMethod(godot_io, _getModel);
|
||||||
return String(env->GetStringUTFChars(s, NULL));
|
return jstring_to_string(s, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _get_screen_dpi() {
|
static int _get_screen_dpi() {
|
||||||
@ -674,7 +675,7 @@ static String _get_unique_id() {
|
|||||||
|
|
||||||
JNIEnv *env = ThreadAndroid::get_env();
|
JNIEnv *env = ThreadAndroid::get_env();
|
||||||
jstring s = (jstring)env->CallObjectMethod(godot_io, _getUniqueID);
|
jstring s = (jstring)env->CallObjectMethod(godot_io, _getUniqueID);
|
||||||
return String(env->GetStringUTFChars(s, NULL));
|
return jstring_to_string(s, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _show_vk(const String &p_existing) {
|
static void _show_vk(const String &p_existing) {
|
||||||
@ -694,7 +695,7 @@ static String _get_system_dir(int p_dir) {
|
|||||||
|
|
||||||
JNIEnv *env = ThreadAndroid::get_env();
|
JNIEnv *env = ThreadAndroid::get_env();
|
||||||
jstring s = (jstring)env->CallObjectMethod(godot_io, _getSystemDir, p_dir);
|
jstring s = (jstring)env->CallObjectMethod(godot_io, _getSystemDir, p_dir);
|
||||||
return String(env->GetStringUTFChars(s, NULL));
|
return jstring_to_string(s, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _get_gles_version_code() {
|
static int _get_gles_version_code() {
|
||||||
@ -891,12 +892,14 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jo
|
|||||||
ThreadAndroid::setup_thread();
|
ThreadAndroid::setup_thread();
|
||||||
|
|
||||||
const char **cmdline = NULL;
|
const char **cmdline = NULL;
|
||||||
|
jstring *j_cmdline = NULL;
|
||||||
int cmdlen = 0;
|
int cmdlen = 0;
|
||||||
if (p_cmdline) {
|
if (p_cmdline) {
|
||||||
cmdlen = env->GetArrayLength(p_cmdline);
|
cmdlen = env->GetArrayLength(p_cmdline);
|
||||||
if (cmdlen) {
|
if (cmdlen) {
|
||||||
cmdline = (const char **)malloc((env->GetArrayLength(p_cmdline) + 1) * sizeof(const char *));
|
cmdline = (const char **)malloc((cmdlen + 1) * sizeof(const char *));
|
||||||
cmdline[cmdlen] = NULL;
|
cmdline[cmdlen] = NULL;
|
||||||
|
j_cmdline = (jstring *)malloc(cmdlen * sizeof(jstring));
|
||||||
|
|
||||||
for (int i = 0; i < cmdlen; i++) {
|
for (int i = 0; i < cmdlen; i++) {
|
||||||
|
|
||||||
@ -904,12 +907,19 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jo
|
|||||||
const char *rawString = env->GetStringUTFChars(string, 0);
|
const char *rawString = env->GetStringUTFChars(string, 0);
|
||||||
|
|
||||||
cmdline[i] = rawString;
|
cmdline[i] = rawString;
|
||||||
|
j_cmdline[i] = string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Error err = Main::setup("apk", cmdlen, (char **)cmdline, false);
|
Error err = Main::setup("apk", cmdlen, (char **)cmdline, false);
|
||||||
if (cmdline) {
|
if (cmdline) {
|
||||||
|
if (j_cmdline) {
|
||||||
|
for (int i = 0; i < cmdlen; ++i) {
|
||||||
|
env->ReleaseStringUTFChars(j_cmdline[i], cmdline[i]);
|
||||||
|
}
|
||||||
|
free(j_cmdline);
|
||||||
|
}
|
||||||
free(cmdline);
|
free(cmdline);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1313,7 +1323,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, j
|
|||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged(JNIEnv *env, jobject obj, jint p_device, jboolean p_connected, jstring p_name) {
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged(JNIEnv *env, jobject obj, jint p_device, jboolean p_connected, jstring p_name) {
|
||||||
if (os_android) {
|
if (os_android) {
|
||||||
String name = env->GetStringUTFChars(p_name, NULL);
|
String name = jstring_to_string(p_name, env);
|
||||||
os_android->joy_connection_changed(p_device, p_connected, name);
|
os_android->joy_connection_changed(p_device, p_connected, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1386,7 +1396,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_audio(JNIEnv *env, jo
|
|||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_singleton(JNIEnv *env, jobject obj, jstring name, jobject p_object) {
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_singleton(JNIEnv *env, jobject obj, jstring name, jobject p_object) {
|
||||||
|
|
||||||
String singname = env->GetStringUTFChars(name, NULL);
|
String singname = jstring_to_string(name, env);
|
||||||
JNISingleton *s = memnew(JNISingleton);
|
JNISingleton *s = memnew(JNISingleton);
|
||||||
s->set_instance(env->NewGlobalRef(p_object));
|
s->set_instance(env->NewGlobalRef(p_object));
|
||||||
jni_singletons[singname] = s;
|
jni_singletons[singname] = s;
|
||||||
@ -1463,21 +1473,21 @@ static const char *get_jni_sig(const String &p_type) {
|
|||||||
|
|
||||||
JNIEXPORT jstring JNICALL Java_org_godotengine_godot_GodotLib_getGlobal(JNIEnv *env, jobject obj, jstring path) {
|
JNIEXPORT jstring JNICALL Java_org_godotengine_godot_GodotLib_getGlobal(JNIEnv *env, jobject obj, jstring path) {
|
||||||
|
|
||||||
String js = env->GetStringUTFChars(path, NULL);
|
String js = jstring_to_string(path, env);
|
||||||
|
|
||||||
return env->NewStringUTF(ProjectSettings::get_singleton()->get(js).operator String().utf8().get_data());
|
return env->NewStringUTF(ProjectSettings::get_singleton()->get(js).operator String().utf8().get_data());
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_method(JNIEnv *env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args) {
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_method(JNIEnv *env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args) {
|
||||||
|
|
||||||
String singname = env->GetStringUTFChars(sname, NULL);
|
String singname = jstring_to_string(sname, env);
|
||||||
|
|
||||||
ERR_FAIL_COND(!jni_singletons.has(singname));
|
ERR_FAIL_COND(!jni_singletons.has(singname));
|
||||||
|
|
||||||
JNISingleton *s = jni_singletons.get(singname);
|
JNISingleton *s = jni_singletons.get(singname);
|
||||||
|
|
||||||
String mname = env->GetStringUTFChars(name, NULL);
|
String mname = jstring_to_string(name, env);
|
||||||
String retval = env->GetStringUTFChars(ret, NULL);
|
String retval = jstring_to_string(ret, env);
|
||||||
Vector<Variant::Type> types;
|
Vector<Variant::Type> types;
|
||||||
String cs = "(";
|
String cs = "(";
|
||||||
|
|
||||||
@ -1486,9 +1496,9 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_method(JNIEnv *env, j
|
|||||||
for (int i = 0; i < stringCount; i++) {
|
for (int i = 0; i < stringCount; i++) {
|
||||||
|
|
||||||
jstring string = (jstring)env->GetObjectArrayElement(args, i);
|
jstring string = (jstring)env->GetObjectArrayElement(args, i);
|
||||||
const char *rawString = env->GetStringUTFChars(string, 0);
|
const String rawString = jstring_to_string(string, env);
|
||||||
types.push_back(get_jni_type(String(rawString)));
|
types.push_back(get_jni_type(rawString));
|
||||||
cs += get_jni_sig(String(rawString));
|
cs += get_jni_sig(rawString);
|
||||||
}
|
}
|
||||||
|
|
||||||
cs += ")";
|
cs += ")";
|
||||||
@ -1511,7 +1521,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_callobject(JNIEnv *en
|
|||||||
int res = env->PushLocalFrame(16);
|
int res = env->PushLocalFrame(16);
|
||||||
ERR_FAIL_COND(res != 0);
|
ERR_FAIL_COND(res != 0);
|
||||||
|
|
||||||
String str_method = env->GetStringUTFChars(method, NULL);
|
String str_method = jstring_to_string(method, env);
|
||||||
|
|
||||||
int count = env->GetArrayLength(params);
|
int count = env->GetArrayLength(params);
|
||||||
Variant *vlist = (Variant *)alloca(sizeof(Variant) * count);
|
Variant *vlist = (Variant *)alloca(sizeof(Variant) * count);
|
||||||
@ -1543,7 +1553,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv *
|
|||||||
int res = env->PushLocalFrame(16);
|
int res = env->PushLocalFrame(16);
|
||||||
ERR_FAIL_COND(res != 0);
|
ERR_FAIL_COND(res != 0);
|
||||||
|
|
||||||
String str_method = env->GetStringUTFChars(method, NULL);
|
String str_method = jstring_to_string(method, env);
|
||||||
|
|
||||||
int count = env->GetArrayLength(params);
|
int count = env->GetArrayLength(params);
|
||||||
Variant args[VARIANT_ARG_MAX];
|
Variant args[VARIANT_ARG_MAX];
|
||||||
|
58
platform/android/string_android.h
Normal file
58
platform/android/string_android.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*************************************************************************/
|
||||||
|
/* string_android.h */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#ifndef STRING_ANDROID_H
|
||||||
|
#define STRING_ANDROID_H
|
||||||
|
#include "core/ustring.h"
|
||||||
|
#include "thread_jandroid.h"
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts JNI jstring to Godot String.
|
||||||
|
* @param source Source JNI string. If null an empty string is returned.
|
||||||
|
* @param env JNI environment instance. If null obtained by ThreadAndroid::get_env().
|
||||||
|
* @return Godot string instance.
|
||||||
|
*/
|
||||||
|
static inline String jstring_to_string(jstring source, JNIEnv *env = NULL) {
|
||||||
|
String result;
|
||||||
|
if (source) {
|
||||||
|
if (!env) {
|
||||||
|
env = ThreadAndroid::get_env();
|
||||||
|
}
|
||||||
|
const char *const source_utf8 = env->GetStringUTFChars(source, NULL);
|
||||||
|
if (source_utf8) {
|
||||||
|
result.parse_utf8(source_utf8);
|
||||||
|
env->ReleaseStringUTFChars(source, source_utf8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // STRING_ANDROID_H
|
Loading…
Reference in New Issue
Block a user