Skip to content

Instantly share code, notes, and snippets.

@mRB0
Created May 1, 2024 21:41
Show Gist options
  • Save mRB0/e3c15e2d88dc49ed1fa1ebb5bd5fd136 to your computer and use it in GitHub Desktop.
Save mRB0/e3c15e2d88dc49ed1fa1ebb5bd5fd136 to your computer and use it in GitHub Desktop.
// A simple wrapper.
//
// In Java:
//
// static String getString(String key);
//
// Calls the C++ function:
//
// C++: std::string openmpt::string::get(std::string &key);
//
// TODO: Might leak memory on exception throw. See within.
JNIEXPORT jstring JNICALL Java_com_mrb0_OpenMPT_getString
(JNIEnv *env, jclass, jstring keyJString) {
jstring charsetUtf8 = env->NewStringUTF("UTF-8");
if (charsetUtf8 == NULL) {
return NULL;
}
jclass clsString = env->FindClass("java/lang/String");
if (clsString == NULL) {
return NULL;
}
jmethodID getBytes = env->GetMethodID(clsString, "getBytes", "(Ljava/lang/String;)[B");
if (getBytes == NULL) {
return NULL;
}
jbyteArray keyStringBytesJArray = (jbyteArray)env->CallObjectMethod(keyJString, getBytes, charsetUtf8);
if (env->ExceptionOccurred()) {
return NULL;
}
jsize keyStringBytesLength = env->GetArrayLength(keyStringBytesJArray);
if (env->ExceptionOccurred()) {
return NULL;
}
jbyte *keyStringBytesArray = env->GetByteArrayElements(keyStringBytesJArray, NULL);
if (keyStringBytesArray == NULL) {
return NULL;
}
std::string keyStdString((char *)keyStringBytesArray, keyStringBytesLength);
// TODO: Call this even if an exception is thrown after GetByteArrayElements.
env->ReleaseByteArrayElements(keyStringBytesJArray, keyStringBytesArray, JNI_ABORT);
if (env->ExceptionOccurred()) {
return NULL;
}
std::string value = openmpt::string::get(keyStdString);
jbyteArray valueBytesJArray = (jbyteArray)env->NewByteArray(value.size());
if (valueBytesJArray == NULL) {
return NULL;
}
jbyte *valueBytesArray = env->GetByteArrayElements(valueBytesJArray, NULL);
if (valueBytesArray == NULL) {
return NULL;
}
jbyte *nextArrayPos = valueBytesArray;
for (char &c : value) {
*(nextArrayPos++) = c;
}
// TODO: Call this even if an exception is thrown after GetByteArrayElements.
env->ReleaseByteArrayElements(valueBytesJArray, valueBytesArray, 0);
if (env->ExceptionOccurred()) {
return NULL;
}
jmethodID newStringBytesCharset = env->GetMethodID(clsString, "<init>", "([BLjava/lang/String;)V");
if (newStringBytesCharset == NULL) {
return NULL;
}
return (jstring)env->NewObject(clsString, newStringBytesCharset, valueBytesJArray, charsetUtf8);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment