lokinet/jni/lokinet_jni_common.hpp

80 lines
2.3 KiB
C++
Raw Normal View History

#pragma once
2019-10-08 14:52:01 +00:00
#include <jni.h>
#include <string_view>
2019-10-08 14:52:01 +00:00
#include <functional>
/// visit string as native bytes
2019-10-09 12:40:40 +00:00
/// jvm uses some unholy encoding internally so we convert it to utf-8
template <typename T, typename V>
2019-10-08 14:52:01 +00:00
static T
VisitStringAsStringView(JNIEnv* env, jobject str, V visit)
{
const jclass stringClass = env->GetObjectClass(str);
const jmethodID getBytes = env->GetMethodID(stringClass, "getBytes", "(Ljava/lang/String;)[B");
2019-10-08 14:52:01 +00:00
const jstring charsetName = env->NewStringUTF("UTF-8");
const jbyteArray stringJbytes = (jbyteArray)env->CallObjectMethod(str, getBytes, charsetName);
2019-10-08 14:52:01 +00:00
env->DeleteLocalRef(charsetName);
2019-10-09 12:40:40 +00:00
const size_t length = env->GetArrayLength(stringJbytes);
jbyte* pBytes = env->GetByteArrayElements(stringJbytes, NULL);
2019-10-08 14:52:01 +00:00
T result = visit(std::string_view((const char*)pBytes, length));
2019-10-08 14:52:01 +00:00
env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT);
env->DeleteLocalRef(stringJbytes);
return result;
2019-10-08 14:52:01 +00:00
}
/// cast jni buffer to T *
template <typename T>
2019-10-08 14:52:01 +00:00
static T*
FromBuffer(JNIEnv* env, jobject o)
{
if (o == nullptr)
2019-10-08 14:52:01 +00:00
return nullptr;
return static_cast<T*>(env->GetDirectBufferAddress(o));
2019-10-08 14:52:01 +00:00
}
/// get T * from object member called membername
template <typename T>
2019-10-08 14:52:01 +00:00
static T*
FromObjectMember(JNIEnv* env, jobject self, const char* membername)
{
jclass cl = env->GetObjectClass(self);
jfieldID name = env->GetFieldID(cl, membername, "Ljava/nio/ByteBuffer;");
2019-10-08 14:52:01 +00:00
jobject buffer = env->GetObjectField(self, name);
return FromBuffer<T>(env, buffer);
2019-10-08 14:52:01 +00:00
}
/// visit object string member called membername as bytes
template <typename T, typename V>
2019-10-08 14:52:01 +00:00
static T
VisitObjectMemberStringAsStringView(JNIEnv* env, jobject self, const char* membername, V v)
2019-10-08 14:52:01 +00:00
{
jclass cl = env->GetObjectClass(self);
2019-10-08 14:52:01 +00:00
jfieldID name = env->GetFieldID(cl, membername, "Ljava/lang/String;");
jobject str = env->GetObjectField(self, name);
return VisitStringAsStringView<T, V>(env, str, v);
2019-10-08 14:52:01 +00:00
}
/// get object member int called membername
template <typename Int_t>
2019-10-09 12:40:40 +00:00
Int_t
GetObjectMemberAsInt(JNIEnv* env, jobject self, const char* membername)
2019-10-08 14:52:01 +00:00
{
jclass cl = env->GetObjectClass(self);
2019-10-08 14:52:01 +00:00
jfieldID name = env->GetFieldID(cl, membername, "I");
2019-10-09 12:40:40 +00:00
return env->GetIntField(self, name);
}
/// get implementation on jni type
template <typename T>
2019-10-09 12:40:40 +00:00
T*
GetImpl(JNIEnv* env, jobject self)
{
return FromObjectMember<T>(env, self, "impl");
2019-10-08 14:52:01 +00:00
}