From fb476567ff7d48a11a29fdac96db903648181992 Mon Sep 17 00:00:00 2001 From: PixelyIon Date: Tue, 9 Nov 2021 21:18:47 +0530 Subject: [PATCH] Introduce `JniString` as C++ wrapper over `jstring` We used to manually call JNI UTF-8 string allocation and deallocation functions when utilizing a `jstring` but this could be erroneous and is just inconvenient. All of this has now been consolidated into an class `JniString` which is a wrapper around `std::string` and creates a copy of the contents of the `jstring` in its constructor and passes them into the `std::string` constructor. --- app/src/main/cpp/emu_jni.cpp | 11 ++++------- app/src/main/cpp/loader_jni.cpp | 5 +---- app/src/main/cpp/skyline/jvm.cpp | 7 +++++++ app/src/main/cpp/skyline/jvm.h | 11 +++++++++++ 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/app/src/main/cpp/emu_jni.cpp b/app/src/main/cpp/emu_jni.cpp index d4627b63..15ad4e86 100644 --- a/app/src/main/cpp/emu_jni.cpp +++ b/app/src/main/cpp/emu_jni.cpp @@ -76,8 +76,8 @@ extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_executeApplication( auto settings{std::make_shared(preferenceFd)}; close(preferenceFd); - auto appFilesPath{env->GetStringUTFChars(appFilesPathJstring, nullptr)}; - auto logger{std::make_shared(std::string(appFilesPath) + "skyline.log", settings->logLevel)}; + skyline::JniString appFilesPath(env, appFilesPathJstring); + auto logger{std::make_shared(appFilesPath + "skyline.log", settings->logLevel)}; auto start{std::chrono::steady_clock::now()}; @@ -92,7 +92,7 @@ extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_executeApplication( jvmManager, logger, settings, - std::string(appFilesPath), + appFilesPath, GetTimeZoneName(), static_cast(systemLanguage), std::make_shared(AAssetManager_fromJava(env, assetManager)) @@ -102,11 +102,8 @@ extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_executeApplication( AudioWeak = os->state.audio; InputWeak = os->state.input; jvmManager->InitializeControllers(); - env->ReleaseStringUTFChars(appFilesPathJstring, appFilesPath); - auto romUri{env->GetStringUTFChars(romUriJstring, nullptr)}; - logger->InfoNoPrefix("Launching ROM {}", romUri); - env->ReleaseStringUTFChars(romUriJstring, romUri); + logger->InfoNoPrefix("Launching ROM {}", skyline::JniString(env, romUriJstring)); os->Execute(romFd, static_cast(romType)); } catch (std::exception &e) { diff --git a/app/src/main/cpp/loader_jni.cpp b/app/src/main/cpp/loader_jni.cpp index 5e3ad7a5..2d278c9a 100644 --- a/app/src/main/cpp/loader_jni.cpp +++ b/app/src/main/cpp/loader_jni.cpp @@ -14,10 +14,7 @@ extern "C" JNIEXPORT jint JNICALL Java_emu_skyline_loader_RomFile_populate(JNIEnv *env, jobject thiz, jint jformat, jint fd, jstring appFilesPathJstring, jint systemLanguage) { skyline::loader::RomFormat format{static_cast(jformat)}; - auto appFilesPath{env->GetStringUTFChars(appFilesPathJstring, nullptr)}; - auto keyStore{std::make_shared(appFilesPath)}; - env->ReleaseStringUTFChars(appFilesPathJstring, appFilesPath); - + auto keyStore{std::make_shared(skyline::JniString(env, appFilesPathJstring))}; std::unique_ptr loader; try { auto backing{std::make_shared(fd)}; diff --git a/app/src/main/cpp/skyline/jvm.cpp b/app/src/main/cpp/skyline/jvm.cpp index ae7bdb51..a536f30c 100644 --- a/app/src/main/cpp/skyline/jvm.cpp +++ b/app/src/main/cpp/skyline/jvm.cpp @@ -4,6 +4,13 @@ #include "jvm.h" namespace skyline { + std::string JniString::GetJString(JNIEnv *env, jstring jString) { + auto utf{env->GetStringUTFChars(jString, nullptr)}; + std::string string{utf}; + env->ReleaseStringUTFChars(jString, utf); + return string; + } + /* * @brief A thread-local wrapper over JNIEnv and JavaVM which automatically handles attaching and detaching threads */ diff --git a/app/src/main/cpp/skyline/jvm.h b/app/src/main/cpp/skyline/jvm.h index b2b18397..d9d8ff94 100644 --- a/app/src/main/cpp/skyline/jvm.h +++ b/app/src/main/cpp/skyline/jvm.h @@ -7,6 +7,17 @@ #include namespace skyline { + /** + * @brief A wrapper over std::string that supports construction using a JNI jstring + */ + class JniString : public std::string { + private: + static std::string GetJString(JNIEnv *env, jstring jString); + + public: + JniString(JNIEnv *env, jstring jString) : std::string(GetJString(env, jString)) {} + }; + /** * @brief The JvmManager class is used to simplify transactions with the Java component */