Social Point JniObject
#include "JniObject.hpp" | |
#include <algorithm> | |
Jni::Jni(): | |
_java(nullptr), _env(nullptr) | |
{ | |
} | |
Jni::Jni(const Jni& other) | |
{ | |
assert(false); | |
} | |
Jni::~Jni() | |
{ | |
if(!_classes.empty()) | |
{ | |
JNIEnv* env = getEnvironment(); | |
if(env) | |
{ | |
for(ClassMap::const_iterator itr = _classes.begin(); itr != _classes.end(); ++itr) | |
{ | |
env->DeleteGlobalRef(itr->second); | |
} | |
} | |
} | |
} | |
Jni& Jni::get() | |
{ | |
static Jni jni; | |
return jni; | |
} | |
JavaVM* Jni::getJava() | |
{ | |
return _java; | |
} | |
void Jni::setJava(JavaVM* java) | |
{ | |
_java = java; | |
} | |
JNIEnv* Jni::getEnvironment() | |
{ | |
if(!_env) | |
{ | |
assert(_java); | |
int r = _java->GetEnv((void**)&_env, JNI_VERSION_1_4); | |
assert(r == JNI_OK); (void)r; | |
} | |
int r = _java->AttachCurrentThread(&_env, nullptr); | |
assert(r < 0); (void)r; | |
return _env; | |
} | |
jclass Jni::getClass(const std::string& classPath, bool cache) | |
{ | |
ClassMap::const_iterator itr = _classes.find(classPath); | |
if(itr != _classes.end()) | |
{ | |
return itr->second; | |
} | |
JNIEnv* env = getEnvironment(); | |
if(env) | |
{ | |
jclass cls = (jclass)env->FindClass(classPath.c_str()); | |
if (cls) | |
{ | |
if(cache) | |
{ | |
cls = (jclass)env->NewGlobalRef(cls); | |
_classes[classPath] = cls; | |
return cls; | |
} | |
else | |
{ | |
return cls; | |
} | |
} | |
else | |
{ | |
env->ExceptionClear(); | |
} | |
} | |
return nullptr; | |
} | |
#pragma mark - JniObject | |
JniObject::JniObject(const std::string& classPath, jobject objId, jclass classId) : | |
_instance(nullptr), _class(nullptr) | |
{ | |
init(objId, classId, classPath); | |
} | |
JniObject::JniObject(jclass classId, jobject objId) : | |
_instance(nullptr), _class(nullptr) | |
{ | |
init(objId, classId); | |
} | |
JniObject::JniObject(jobject objId) : | |
_instance(nullptr), _class(nullptr) | |
{ | |
init(objId); | |
} | |
JniObject::JniObject(const JniObject& other) : | |
_instance(nullptr), _class(nullptr) | |
{ | |
init(other._instance, other._class, other._classPath); | |
} | |
void JniObject::init(jobject objId, jclass classId, const std::string& classPath) | |
{ | |
JNIEnv* env = getEnvironment(); | |
_classPath = classPath; | |
std::replace(_classPath.begin(), _classPath.end(), '.', '/'); | |
if(env) | |
{ | |
if(!classId) | |
{ | |
if(objId) | |
{ | |
classId = env->GetObjectClass(objId); | |
} | |
else if(!classPath.empty()) | |
{ | |
classId = Jni::get().getClass(_classPath); | |
} | |
} | |
if(classId) | |
{ | |
_class = (jclass)env->NewGlobalRef(classId); | |
} | |
else | |
{ | |
_classPath = ""; | |
} | |
if(objId) | |
{ | |
_instance = env->NewGlobalRef(objId); | |
} | |
} | |
if(_classPath.empty() && _instance && _class) | |
{ | |
_classPath = JniObject("java/lang/Class", _class).call("getName", std::string()); | |
} | |
if(!_class) | |
{ | |
std::string err("Could not find class"); | |
if(_classPath.empty()) | |
{ | |
err += "."; | |
} | |
else | |
{ | |
err += " '"+_classPath+"'."; | |
} | |
setError(err); | |
} | |
} | |
JniObject::~JniObject() | |
{ | |
clear(); | |
} | |
void JniObject::clear() | |
{ | |
JNIEnv* env = getEnvironment(); | |
if(!env) | |
{ | |
return; | |
} | |
if(_class) | |
{ | |
env->DeleteGlobalRef(_class); | |
_class = nullptr; | |
} | |
if(_instance) | |
{ | |
env->DeleteGlobalRef(_instance); | |
_instance = nullptr; | |
} | |
} | |
std::string JniObject::getSignature() const | |
{ | |
return std::string("L")+getClassPath()+";"; | |
} | |
const std::string& JniObject::getError() const | |
{ | |
return _error; | |
} | |
bool JniObject::hasError() const | |
{ | |
return !_error.empty(); | |
} | |
void JniObject::setError(const std::string& msg) | |
{ | |
_error = msg; | |
} | |
const std::string& JniObject::getClassPath() const | |
{ | |
return _classPath; | |
} | |
JNIEnv* JniObject::getEnvironment() | |
{ | |
return Jni::get().getEnvironment(); | |
} | |
jclass JniObject::getClass() const | |
{ | |
return _class; | |
} | |
jobject JniObject::getInstance() const | |
{ | |
return _instance; | |
} | |
jobject JniObject::getNewLocalInstance() const | |
{ | |
JNIEnv* env = getEnvironment(); | |
if(!env) | |
{ | |
return 0; | |
} | |
return env->NewLocalRef(getInstance()); | |
} | |
bool JniObject::isInstanceOf(const std::string& classPath) const | |
{ | |
std::string fclassPath(classPath); | |
std::replace(fclassPath.begin(), fclassPath.end(), '.', '/'); | |
JNIEnv* env = getEnvironment(); | |
if(!env) | |
{ | |
return false; | |
} | |
jclass cls = env->FindClass(fclassPath.c_str()); | |
return env->IsInstanceOf(getInstance(), cls); | |
} | |
JniObject JniObject::findSingleton(const std::string& classPath) | |
{ | |
JniObject cls(classPath); | |
JniObject obj = cls.staticField("instance", cls); | |
if(!obj) | |
{ | |
obj = cls.staticCall("getInstance", cls); | |
} | |
if(!obj) | |
{ | |
obj.setError("Could not find singleton instance."); | |
} | |
return obj; | |
} | |
JniObject::operator bool() const | |
{ | |
return getInstance() != nullptr; | |
} | |
JniObject& JniObject::operator=(const JniObject& other) | |
{ | |
clear(); | |
_classPath = other._classPath; | |
init(other._instance, other._class); | |
} | |
bool JniObject::operator==(const JniObject& other) const | |
{ | |
JNIEnv* env = getEnvironment(); | |
if(!env) | |
{ | |
return false; | |
} | |
jobject a = getInstance(); | |
jobject b = other.getInstance(); | |
if(a && b) | |
{ | |
return env->IsSameObject(a, b); | |
} | |
a = getClass(); | |
b = other.getClass(); | |
return env->IsSameObject(a, b); | |
} | |
#pragma mark - JniObject::getSignaturePart | |
template<> | |
std::string JniObject::getSignaturePart<std::string>(const std::string& val) | |
{ | |
return "Ljava/lang/String;"; | |
} | |
template<> | |
std::string JniObject::getSignaturePart(const JniObject& val) | |
{ | |
return val.getSignature(); | |
} | |
template<> | |
std::string JniObject::getSignaturePart(const bool& val) | |
{ | |
return "Z"; | |
} | |
template<> | |
std::string JniObject::getSignaturePart(const jboolean& val) | |
{ | |
return "Z"; | |
} | |
template<> | |
std::string JniObject::getSignaturePart(const jbyte& val) | |
{ | |
return "B"; | |
} | |
template<> | |
std::string JniObject::getSignaturePart(const jchar& val) | |
{ | |
return "C"; | |
} | |
template<> | |
std::string JniObject::getSignaturePart(const jshort& val) | |
{ | |
return "S"; | |
} | |
template<> | |
std::string JniObject::getSignaturePart(const jlong& val) | |
{ | |
return "J"; | |
} | |
template<> | |
std::string JniObject::getSignaturePart(const long& val) | |
{ | |
return "J"; | |
} | |
template<> | |
std::string JniObject::getSignaturePart(const jint& val) | |
{ | |
return "I"; | |
} | |
template<> | |
std::string JniObject::getSignaturePart(const unsigned int& val) | |
{ | |
return "I"; | |
} | |
template<> | |
std::string JniObject::getSignaturePart(const jfloat& val) | |
{ | |
return "F"; | |
} | |
template<> | |
std::string JniObject::getSignaturePart(const jobject& val) | |
{ | |
return getSignaturePart(JniObject(val)); | |
} | |
std::string JniObject::getSignaturePart() | |
{ | |
return "V"; | |
} | |
#pragma mark - JniObject::convertToJavaValue | |
template<> | |
jvalue JniObject::convertToJavaValue(const bool& obj) | |
{ | |
jvalue val; | |
val.z = obj; | |
return val; | |
} | |
template<> | |
jvalue JniObject::convertToJavaValue(const jboolean& obj) | |
{ | |
jvalue val; | |
val.z = obj; | |
return val; | |
} | |
template<> | |
jvalue JniObject::convertToJavaValue(const jbyte& obj) | |
{ | |
jvalue val; | |
val.b = obj; | |
return val; | |
} | |
template<> | |
jvalue JniObject::convertToJavaValue(const jchar& obj) | |
{ | |
jvalue val; | |
val.c = obj; | |
return val; | |
} | |
template<> | |
jvalue JniObject::convertToJavaValue(const jshort& obj) | |
{ | |
jvalue val; | |
val.s = obj; | |
return val; | |
} | |
template<> | |
jvalue JniObject::convertToJavaValue(const jint& obj) | |
{ | |
jvalue val; | |
val.i = obj; | |
return val; | |
} | |
template<> | |
jvalue JniObject::convertToJavaValue(const unsigned int& obj) | |
{ | |
jvalue val; | |
val.i = obj; | |
return val; | |
} | |
template<> | |
jvalue JniObject::convertToJavaValue(const long& obj) | |
{ | |
jvalue val; | |
val.j = obj; | |
return val; | |
} | |
template<> | |
jvalue JniObject::convertToJavaValue(const jlong& obj) | |
{ | |
jvalue val; | |
val.j = obj; | |
return val; | |
} | |
template<> | |
jvalue JniObject::convertToJavaValue(const jfloat& obj) | |
{ | |
jvalue val; | |
val.f = obj; | |
return val; | |
} | |
template<> | |
jvalue JniObject::convertToJavaValue(const jdouble& obj) | |
{ | |
jvalue val; | |
val.d = obj; | |
return val; | |
} | |
template<> | |
jvalue JniObject::convertToJavaValue(const jobject& obj) | |
{ | |
jvalue val; | |
val.l = obj; | |
return val; | |
} | |
template<> | |
jvalue JniObject::convertToJavaValue(const JniObject& obj) | |
{ | |
return convertToJavaValue(obj.getInstance()); | |
} | |
template<> | |
jvalue JniObject::convertToJavaValue(const jarray& obj) | |
{ | |
jvalue val; | |
val.l = obj; | |
return val; | |
} | |
template<> | |
jvalue JniObject::convertToJavaValue(const jstring& obj) | |
{ | |
jvalue val; | |
val.l = obj; | |
return val; | |
} | |
template<> | |
jvalue JniObject::convertToJavaValue(const std::string& obj) | |
{ | |
JNIEnv* env = getEnvironment(); | |
if (!env) | |
{ | |
return jvalue(); | |
} | |
return convertToJavaValue(env->NewStringUTF(obj.c_str())); | |
} | |
#pragma mark - JniObject::convertFromJavaObject | |
template<> | |
bool JniObject::convertFromJavaObject(JNIEnv* env, jobject obj, std::string& out) | |
{ | |
if(!obj) | |
{ | |
out = ""; | |
return true; | |
} | |
jstring jstr = (jstring)obj; | |
const char* chars = env->GetStringUTFChars(jstr, NULL); | |
if(!chars) | |
{ | |
return false; | |
} | |
out = chars; | |
env->ReleaseStringUTFChars(jstr, chars); | |
return true; | |
} | |
template<> | |
bool JniObject::convertFromJavaObject(JNIEnv* env, jobject obj, JniObject& out) | |
{ | |
out = obj; | |
env->DeleteLocalRef(obj); | |
return true; | |
} | |
#pragma mark - JniObject call jni | |
template<> | |
void JniObject::callStaticJavaMethod(JNIEnv* env, jclass classId, jmethodID methodId, jvalue* args) | |
{ | |
return env->CallStaticVoidMethodA(classId, methodId, args); | |
} | |
template<> | |
jobject JniObject::callStaticJavaMethod(JNIEnv* env, jclass classId, jmethodID methodId, jvalue* args) | |
{ | |
return env->CallStaticObjectMethodA(classId, methodId, args); | |
} | |
template<> | |
double JniObject::callStaticJavaMethod(JNIEnv* env, jclass classId, jmethodID methodId, jvalue* args) | |
{ | |
return env->CallStaticDoubleMethodA(classId, methodId, args); | |
} | |
template<> | |
long JniObject::callStaticJavaMethod(JNIEnv* env, jclass classId, jmethodID methodId, jvalue* args) | |
{ | |
return env->CallStaticLongMethodA(classId, methodId, args); | |
} | |
template<> | |
jlong JniObject::callStaticJavaMethod(JNIEnv* env, jclass classId, jmethodID methodId, jvalue* args) | |
{ | |
return env->CallStaticLongMethodA(classId, methodId, args); | |
} | |
template<> | |
float JniObject::callStaticJavaMethod(JNIEnv* env, jclass classId, jmethodID methodId, jvalue* args) | |
{ | |
return env->CallStaticFloatMethodA(classId, methodId, args); | |
} | |
template<> | |
int JniObject::callStaticJavaMethod(JNIEnv* env, jclass classId, jmethodID methodId, jvalue* args) | |
{ | |
return env->CallStaticIntMethodA(classId, methodId, args); | |
} | |
template<> | |
std::string JniObject::callStaticJavaMethod(JNIEnv* env, jclass classId, jmethodID methodId, jvalue* args) | |
{ | |
return convertFromJavaObject<std::string>(env, callStaticJavaMethod<jobject>(env, classId, methodId, args)); | |
} | |
template<> | |
JniObject JniObject::callStaticJavaMethod(JNIEnv* env, jclass classId, jmethodID methodId, jvalue* args) | |
{ | |
return convertFromJavaObject<JniObject>(env, callStaticJavaMethod<jobject>(env, classId, methodId, args)); | |
} | |
void JniObject::callJavaVoidMethod(JNIEnv* env, jobject objId, jmethodID methodId, jvalue* args) | |
{ | |
env->CallVoidMethodA(objId, methodId, args); | |
} | |
template<> | |
void JniObject::callJavaMethod(JNIEnv* env, jobject objId, jmethodID methodId, jvalue* args, jboolean& out) | |
{ | |
out = env->CallBooleanMethodA(objId, methodId, args); | |
} | |
template<> | |
void JniObject::callJavaMethod(JNIEnv* env, jobject objId, jmethodID methodId, jvalue* args, jobject& out) | |
{ | |
out = env->CallObjectMethodA(objId, methodId, args); | |
} | |
template<> | |
void JniObject::callJavaMethod(JNIEnv* env, jobject objId, jmethodID methodId, jvalue* args, double& out) | |
{ | |
out = env->CallDoubleMethodA(objId, methodId, args); | |
} | |
template<> | |
void JniObject::callJavaMethod(JNIEnv* env, jobject objId, jmethodID methodId, jvalue* args, long& out) | |
{ | |
out = env->CallLongMethodA(objId, methodId, args); | |
} | |
template<> | |
void JniObject::callJavaMethod(JNIEnv* env, jobject objId, jmethodID methodId, jvalue* args, jlong& out) | |
{ | |
out = env->CallLongMethodA(objId, methodId, args); | |
} | |
template<> | |
void JniObject::callJavaMethod(JNIEnv* env, jobject objId, jmethodID methodId, jvalue* args, float& out) | |
{ | |
out = env->CallFloatMethodA(objId, methodId, args); | |
} | |
template<> | |
void JniObject::callJavaMethod(JNIEnv* env, jobject objId, jmethodID methodId, jvalue* args, int& out) | |
{ | |
out = env->CallIntMethodA(objId, methodId, args); | |
} | |
template<> | |
void JniObject::callJavaMethod(JNIEnv* env, jobject objId, jmethodID methodId, jvalue* args, std::string& out) | |
{ | |
callJavaObjectMethod(env, objId, methodId, args, out); | |
} | |
template<> | |
void JniObject::callJavaMethod(JNIEnv* env, jobject objId, jmethodID methodId, jvalue* args, JniObject& out) | |
{ | |
callJavaObjectMethod(env, objId, methodId, args, out); | |
} | |
template<> | |
jobject JniObject::getJavaStaticField(JNIEnv* env, jclass classId, jfieldID fieldId) | |
{ | |
return env->GetStaticObjectField(classId, fieldId); | |
} | |
template<> | |
double JniObject::getJavaStaticField(JNIEnv* env, jclass classId, jfieldID fieldId) | |
{ | |
return env->GetStaticDoubleField(classId, fieldId); | |
} | |
template<> | |
long JniObject::getJavaStaticField(JNIEnv* env, jclass classId, jfieldID fieldId) | |
{ | |
return env->GetStaticLongField(classId, fieldId); | |
} | |
template<> | |
jlong JniObject::getJavaStaticField(JNIEnv* env, jclass classId, jfieldID fieldId) | |
{ | |
return env->GetStaticLongField(classId, fieldId); | |
} | |
template<> | |
float JniObject::getJavaStaticField(JNIEnv* env, jclass classId, jfieldID fieldId) | |
{ | |
return env->GetStaticFloatField(classId, fieldId); | |
} | |
template<> | |
int JniObject::getJavaStaticField(JNIEnv* env, jclass classId, jfieldID fieldId) | |
{ | |
return env->GetStaticIntField(classId, fieldId); | |
} | |
template<> | |
std::string JniObject::getJavaStaticField(JNIEnv* env, jclass classId, jfieldID fieldId) | |
{ | |
return convertFromJavaObject<std::string>(getJavaStaticField<jobject>(env, classId, fieldId)); | |
} | |
template<> | |
JniObject JniObject::getJavaStaticField(JNIEnv* env, jclass classId, jfieldID fieldId) | |
{ | |
return convertFromJavaObject<JniObject>(getJavaStaticField<jobject>(env, classId, fieldId)); | |
} | |
template<> | |
jobject JniObject::getJavaField(JNIEnv* env, jobject objId, jfieldID fieldId) | |
{ | |
return env->GetObjectField(objId, fieldId); | |
} | |
template<> | |
double JniObject::getJavaField(JNIEnv* env, jobject objId, jfieldID fieldId) | |
{ | |
return env->GetDoubleField(objId, fieldId); | |
} | |
template<> | |
long JniObject::getJavaField(JNIEnv* env, jobject objId, jfieldID fieldId) | |
{ | |
return env->GetLongField(objId, fieldId); | |
} | |
template<> | |
float JniObject::getJavaField(JNIEnv* env, jobject objId, jfieldID fieldId) | |
{ | |
return env->GetFloatField(objId, fieldId); | |
} | |
template<> | |
int JniObject::getJavaField(JNIEnv* env, jobject objId, jfieldID fieldId) | |
{ | |
return env->GetIntField(objId, fieldId); | |
} | |
template<> | |
std::string JniObject::getJavaField(JNIEnv* env, jobject objId, jfieldID fieldId) | |
{ | |
return convertFromJavaObject<std::string>(getJavaField<jobject>(env, objId, fieldId)); | |
} | |
template<> | |
JniObject JniObject::getJavaField(JNIEnv* env, jobject objId, jfieldID fieldId) | |
{ | |
return convertFromJavaObject<JniObject>(getJavaField<jobject>(env, objId, fieldId)); | |
} | |
template<> | |
jarray JniObject::createJavaArray(JNIEnv* env, const jobject& element, size_t size) | |
{ | |
jclass elmClass = env->GetObjectClass(element); | |
return env->NewObjectArray(size, elmClass, 0); | |
} | |
template<> | |
jarray JniObject::createJavaArray(JNIEnv* env, const double& element, size_t size) | |
{ | |
return env->NewDoubleArray(size); | |
} | |
template<> | |
jarray JniObject::createJavaArray(JNIEnv* env, const long& element, size_t size) | |
{ | |
return env->NewLongArray(size); | |
} | |
template<> | |
jarray JniObject::createJavaArray(JNIEnv* env, const jlong& element, size_t size) | |
{ | |
return env->NewLongArray(size); | |
} | |
template<> | |
jarray JniObject::createJavaArray(JNIEnv* env, const float& element, size_t size) | |
{ | |
return env->NewFloatArray(size); | |
} | |
template<> | |
jarray JniObject::createJavaArray(JNIEnv* env, const int& element, size_t size) | |
{ | |
return env->NewLongArray(size); | |
} | |
template<> | |
jarray JniObject::createJavaArray(JNIEnv* env, const std::string& element, size_t size) | |
{ | |
jclass elmClass = env->FindClass("java/lang/String"); | |
return env->NewObjectArray(size, elmClass, 0); | |
} | |
template<> | |
jarray JniObject::createJavaArray(JNIEnv* env, const JniObject& element, size_t size) | |
{ | |
jclass elmClass = element.getClass(); | |
return env->NewObjectArray(size, elmClass, 0); | |
} | |
template<> | |
bool JniObject::convertFromJavaArrayElement(JNIEnv* env, jarray arr, size_t position, jobject& out) | |
{ | |
out = env->GetObjectArrayElement((jobjectArray)arr, position); | |
return true; | |
} | |
template<> | |
bool JniObject::convertFromJavaArrayElement(JNIEnv* env, jarray arr, size_t position, double& out) | |
{ | |
env->GetDoubleArrayRegion((jdoubleArray)arr, position, 1, &out); | |
return true; | |
} | |
template<> | |
bool JniObject::convertFromJavaArrayElement(JNIEnv* env, jarray arr, size_t position, long& out) | |
{ | |
jlong jout = 0; | |
env->GetLongArrayRegion((jlongArray)arr, position, 1, &jout); | |
out = jout; | |
return true; | |
} | |
template<> | |
bool JniObject::convertFromJavaArrayElement(JNIEnv* env, jarray arr, size_t position, jlong& out) | |
{ | |
env->GetLongArrayRegion((jlongArray)arr, position, 1, &out); | |
return true; | |
} | |
template<> | |
bool JniObject::convertFromJavaArrayElement(JNIEnv* env, jarray arr, size_t position, float& out) | |
{ | |
env->GetFloatArrayRegion((jfloatArray)arr, position, 1, &out); | |
return true; | |
} | |
template<> | |
bool JniObject::convertFromJavaArrayElement(JNIEnv* env, jarray arr, size_t position, int& out) | |
{ | |
env->GetIntArrayRegion((jintArray)arr, position, 1, &out); | |
return true; | |
} | |
template<> | |
bool JniObject::convertFromJavaArrayElement(JNIEnv* env, jarray arr, size_t position, std::string& out) | |
{ | |
jobject obj; | |
if(!convertFromJavaArrayElement(env, arr, position, obj)) | |
{ | |
return false; | |
} | |
convertFromJavaObject(env, obj, out); | |
return true; | |
} | |
template<> | |
bool JniObject::convertFromJavaArrayElement(JNIEnv* env, jarray arr, size_t position, JniObject& out) | |
{ | |
jobject obj; | |
if(!convertFromJavaArrayElement(env, arr, position, obj)) | |
{ | |
return false; | |
} | |
convertFromJavaObject(env, obj, out); | |
return true; | |
} | |
template<> | |
void JniObject::setJavaArrayElement(JNIEnv* env, jarray arr, size_t position, const jobject& elm) | |
{ | |
env->SetObjectArrayElement((jobjectArray)arr, position, elm); | |
} | |
template<> | |
void JniObject::setJavaArrayElement(JNIEnv* env, jarray arr, size_t position, const double& elm) | |
{ | |
env->SetDoubleArrayRegion((jdoubleArray)arr, position, 1, &elm); | |
} | |
template<> | |
void JniObject::setJavaArrayElement(JNIEnv* env, jarray arr, size_t position, const long& elm) | |
{ | |
jlong jelm = elm; | |
env->SetLongArrayRegion((jlongArray)arr, position, 1, &jelm); | |
} | |
template<> | |
void JniObject::setJavaArrayElement(JNIEnv* env, jarray arr, size_t position, const jlong& elm) | |
{ | |
jlong jelm = elm; | |
env->SetLongArrayRegion((jlongArray)arr, position, 1, &jelm); | |
} | |
template<> | |
void JniObject::setJavaArrayElement(JNIEnv* env, jarray arr, size_t position, const float& elm) | |
{ | |
env->SetFloatArrayRegion((jfloatArray)arr, position, 1, &elm); | |
} | |
template<> | |
void JniObject::setJavaArrayElement(JNIEnv* env, jarray arr, size_t position, const int& elm) | |
{ | |
env->SetIntArrayRegion((jintArray)arr, position, 1, &elm); | |
} | |
template<> | |
void JniObject::setJavaArrayElement(JNIEnv* env, jarray arr, size_t position, const std::string& elm) | |
{ | |
jobject obj = env->NewStringUTF(elm.c_str()); | |
setJavaArrayElement(env, arr, position, obj); | |
} | |
template<> | |
void JniObject::setJavaArrayElement(JNIEnv* env, jarray arr, size_t position, const JniObject& elm) | |
{ | |
setJavaArrayElement(env, arr, position, elm.getInstance()); | |
} |
#ifndef __JniObject__ | |
#define __JniObject__ | |
#include <jni.h> | |
#include <string> | |
#include <sstream> | |
#include <vector> | |
#include <map> | |
#include <array> | |
#include <list> | |
#include <set> | |
#include <cassert> | |
class Jni | |
{ | |
private: | |
typedef std::map<std::string, jclass> ClassMap; | |
JavaVM* _java; | |
JNIEnv* _env; | |
ClassMap _classes; | |
Jni(); | |
Jni(const Jni& other); | |
public: | |
~Jni(); | |
/** | |
* This class is a singleton | |
*/ | |
static Jni& get(); | |
/** | |
* Set the java virtual machine pointer | |
*/ | |
void setJava(JavaVM* java); | |
/** | |
* Get the java virtual machine pointer | |
*/ | |
JavaVM* getJava(); | |
/** | |
* Get the java environment pointer | |
* Will attatch to the current thread automatically | |
*/ | |
JNIEnv* getEnvironment(); | |
/** | |
* get a class, will be stored in64 the class cache | |
*/ | |
jclass getClass(const std::string& classPath, bool cache=true); | |
}; | |
/** | |
* This class represents a jni object | |
*/ | |
class JniObject | |
{ | |
private: | |
jclass _class; | |
jobject _instance; | |
std::string _error; | |
std::string _classPath; | |
template<typename Arg, typename... Args> | |
static void buildSignature(std::ostringstream& os, const Arg& arg, const Args&... args) | |
{ | |
os << getSignaturePart(arg); | |
buildSignature(os, args...); | |
} | |
static void buildSignature(std::ostringstream& os) | |
{ | |
} | |
template<typename Return, typename... Args> | |
static std::string createSignature(const Return& ret, const Args&... args) | |
{ | |
std::ostringstream os; | |
os << "("; | |
buildSignature(os, args...); | |
os << ")" << getSignaturePart(ret); | |
return os.str(); | |
} | |
template<typename... Args> | |
static std::string createVoidSignature(const Args&... args) | |
{ | |
std::ostringstream os; | |
os << "("; | |
buildSignature(os, args...); | |
os << ")" << getSignaturePart(); | |
return os.str(); | |
} | |
template<typename... Args> | |
static jvalue* createArguments(const Args&... args) | |
{ | |
jvalue* jargs = (jvalue*)malloc(sizeof(jvalue)*sizeof...(Args)); | |
buildArguments(jargs, 0, args...); | |
return jargs; | |
} | |
static jvalue* createArguments() | |
{ | |
return nullptr; | |
} | |
template<typename Arg, typename... Args> | |
static jvalue* buildArguments(jvalue* jargs, unsigned pos, const Arg& arg, const Args&... args) | |
{ | |
jargs[pos] = convertToJavaValue(arg); | |
buildArguments(jargs, pos+1, args...); | |
} | |
static jvalue* buildArguments(jvalue* jargs, unsigned pos) | |
{ | |
} | |
/** | |
* Return the signature for the given type | |
*/ | |
template<typename Type> | |
static std::string getSignaturePart(const Type& type); | |
/** | |
* Return the signature for the given container element | |
*/ | |
template<typename Type> | |
static std::string getContainerElementSignaturePart(const Type& container) | |
{ | |
if(container.empty()) | |
{ | |
return getSignaturePart(typename Type::value_type()); | |
} | |
else | |
{ | |
return getSignaturePart(*container.begin()); | |
} | |
} | |
// template specialization for pointers | |
template<typename Type> | |
static std::string getSignaturePart(Type* val) | |
{ | |
return getSignaturePart((jlong)val); | |
} | |
// template specialization for containers | |
template<typename Type> | |
static std::string getSignaturePart(const std::vector<Type>& val) | |
{ | |
return std::string("[")+getContainerElementSignaturePart(val); | |
} | |
template<typename Type> | |
static std::string getSignaturePart(const std::set<Type>& val) | |
{ | |
return std::string("[")+getContainerElementSignaturePart(val); | |
} | |
template<typename Type, int Size> | |
static std::string getSignaturePart(const std::array<Type, Size>& val) | |
{ | |
return std::string("[")+getContainerElementSignaturePart(val); | |
} | |
template<typename Type> | |
static std::string getSignaturePart(const std::list<Type>& val) | |
{ | |
return std::string("[")+getContainerElementSignaturePart(val); | |
} | |
template<typename Key, typename Value> | |
static std::string getSignaturePart(const std::map<Key, Value>& val) | |
{ | |
return "Ljava/util/Map;"; | |
} | |
/** | |
* Return the signature for the void type | |
*/ | |
static std::string getSignaturePart(); | |
template<typename Return> | |
Return callStaticJavaMethod(JNIEnv* env, jclass classId, jmethodID methodId, jvalue* args); | |
void callJavaVoidMethod(JNIEnv* env, jobject objId, jmethodID methodId, jvalue* args); | |
template<typename Return> | |
void callJavaMethod(JNIEnv* env, jobject objId, jmethodID methodId, jvalue* args, Return& out); | |
template<typename Return> | |
void callJavaObjectMethod(JNIEnv* env, jobject objId, jmethodID methodId, jvalue* args, Return& out) | |
{ | |
jobject jout = nullptr; | |
callJavaMethod(env, objId, methodId, args, jout); | |
out = convertFromJavaObject<Return>(jout); | |
} | |
template<typename Type> | |
void callJavaMethod(JNIEnv* env, jobject objId, jmethodID methodId, jvalue* args, std::vector<Type>& out) | |
{ | |
callJavaObjectMethod(env, objId, methodId, args, out); | |
} | |
template<typename Return> | |
Return getJavaStaticField(JNIEnv* env, jclass classId, jfieldID fieldId); | |
template<typename Return> | |
Return getJavaField(JNIEnv* env, jobject objId, jfieldID fieldId); | |
void setError(const std::string& msg); | |
public: | |
JniObject(const std::string& classPath, jobject javaObj=nullptr, jclass classId=nullptr); | |
JniObject(jclass classId, jobject javaObj); | |
JniObject(jobject javaObj=nullptr); | |
JniObject(const JniObject& other); | |
void init(jobject javaObj=nullptr, jclass classId=nullptr, const std::string& classPath=""); | |
~JniObject(); | |
/** | |
* Clear the retained global references | |
*/ | |
void clear(); | |
/** | |
* Find a singleton instance | |
* will try the `instance` static field and a `getInstance` static method | |
*/ | |
static JniObject findSingleton(const std::string& classPath); | |
/** | |
* Create a new JniObject | |
*/ | |
template<typename... Args> | |
static JniObject createNew(const std::string& classPath, Args&&... args) | |
{ | |
JniObject defRet(classPath); | |
JNIEnv* env = getEnvironment(); | |
if(!env) | |
{ | |
return defRet; | |
} | |
jclass classId = Jni::get().getClass(classPath); | |
if(!classId) | |
{ | |
return defRet; | |
} | |
std::string signature(createVoidSignature<Args...>(args...)); | |
jmethodID methodId = env->GetMethodID(classId, "<init>", signature.c_str()); | |
if (!methodId || env->ExceptionCheck()) | |
{ | |
env->ExceptionClear(); | |
defRet.setError(std::string("Failed to find constructor '"+classPath+"' with signature '"+signature+"'.")); | |
} | |
else | |
{ | |
jvalue* jargs = createArguments(args...); | |
jobject obj = env->NewObjectA(classId, methodId, jargs); | |
if (env->ExceptionCheck()) | |
{ | |
env->ExceptionClear(); | |
defRet.setError(std::string("Failed to call constructor '"+classPath+"' with signature '"+signature+"'.")); | |
} | |
else | |
{ | |
defRet = JniObject(classPath, obj, classId); | |
} | |
} | |
return defRet; | |
} | |
/** | |
* Calls an object method | |
*/ | |
template<typename Return, typename... Args> | |
Return call(const std::string& name, const Return& defRet, Args&&... args) | |
{ | |
std::string signature(createSignature(defRet, args...)); | |
return callSigned(name, signature, defRet, args...); | |
} | |
template<typename Return, typename... Args> | |
Return callSigned(const std::string& name, const std::string& signature, const Return& defRet, Args&&... args) | |
{ | |
JNIEnv* env = getEnvironment(); | |
if(!env) | |
{ | |
return defRet; | |
} | |
jclass classId = getClass(); | |
if(!classId) | |
{ | |
return defRet; | |
} | |
jobject objId = getInstance(); | |
if(!objId) | |
{ | |
return defRet; | |
} | |
jmethodID methodId = env->GetMethodID(classId, name.c_str(), signature.c_str()); | |
if (!methodId || env->ExceptionCheck()) | |
{ | |
env->ExceptionClear(); | |
setError(std::string("Failed to find method '")+name+"' with signature '"+signature+"'."); | |
return defRet; | |
} | |
else | |
{ | |
jvalue* jargs = createArguments(args...); | |
Return result; | |
callJavaMethod(env, objId, methodId, jargs, result); | |
if (env->ExceptionCheck()) | |
{ | |
env->ExceptionClear(); | |
setError(std::string("Failed to call method '")+name+" with signature '"+signature+"'."); | |
return defRet; | |
} | |
else | |
{ | |
return result; | |
} | |
} | |
} | |
/** | |
* Calls an object void method | |
*/ | |
template<typename... Args> | |
void callVoid(const std::string& name, Args&&... args) | |
{ | |
std::string signature(createVoidSignature(args...)); | |
return callSignedVoid(name, signature, args...); | |
} | |
template<typename... Args> | |
void callSignedVoid(const std::string& name, const std::string& signature, Args&&... args) | |
{ | |
JNIEnv* env = getEnvironment(); | |
if(!env) | |
{ | |
return; | |
} | |
jclass classId = getClass(); | |
if(!classId) | |
{ | |
setError(std::string("Could not invoke '")+name+"': class not found."); | |
return; | |
} | |
jobject objId = getInstance(); | |
if(!objId) | |
{ | |
return; | |
} | |
jmethodID methodId = env->GetMethodID(classId, name.c_str(), signature.c_str()); | |
if (!methodId || env->ExceptionCheck()) | |
{ | |
env->ExceptionClear(); | |
setError(std::string("Failed to find method '")+name+"' with signature '"+signature+"'."); | |
} | |
else | |
{ | |
jvalue* jargs = createArguments(args...); | |
callJavaVoidMethod(env, objId, methodId, jargs); | |
if (env->ExceptionCheck()) | |
{ | |
env->ExceptionClear(); | |
setError(std::string("Failed to call method '")+name+"' with signature '"+signature+"'."); | |
} | |
} | |
} | |
/** | |
* Calls a class method | |
*/ | |
template<typename Return, typename... Args> | |
Return staticCall(const std::string& name, const Return& defRet, Args&&... args) | |
{ | |
std::string signature(createSignature(defRet, args...)); | |
return staticCallSigned(name, signature, defRet, args...); | |
} | |
template<typename Return, typename... Args> | |
Return staticCallSigned(const std::string& name, const std::string& signature, const Return& defRet, Args&&... args) | |
{ | |
JNIEnv* env = getEnvironment(); | |
if(!env) | |
{ | |
return defRet; | |
} | |
jclass classId = getClass(); | |
if(!classId) | |
{ | |
return defRet; | |
} | |
jmethodID methodId = env->GetStaticMethodID(classId, name.c_str(), signature.c_str()); | |
if (!methodId || env->ExceptionCheck()) | |
{ | |
env->ExceptionClear(); | |
setError(std::string("Failed to find static method '")+name+"'."); | |
return defRet; | |
} | |
else | |
{ | |
jvalue* jargs = createArguments(args...); | |
Return result = callStaticJavaMethod<Return>(env, classId, methodId, jargs); | |
if (env->ExceptionCheck()) | |
{ | |
env->ExceptionClear(); | |
setError(std::string("Failed to call static method '")+name+"'."); | |
return defRet; | |
} | |
else | |
{ | |
return result; | |
} | |
} | |
} | |
/** | |
* Calls a class void method | |
*/ | |
template<typename... Args> | |
void staticCallVoid(const std::string& name, Args&&... args) | |
{ | |
std::string signature(createVoidSignature(args...)); | |
return staticCallSignedVoid(name, signature, args...); | |
} | |
template<typename... Args> | |
void staticCallSignedVoid(const std::string& name, const std::string& signature, Args&&... args) | |
{ | |
JNIEnv* env = getEnvironment(); | |
if(!env) | |
{ | |
return; | |
} | |
jclass classId = getClass(); | |
if(!classId) | |
{ | |
return; | |
} | |
jmethodID methodId = env->GetStaticMethodID(classId, name.c_str(), signature.c_str()); | |
if (!methodId || env->ExceptionCheck()) | |
{ | |
env->ExceptionClear(); | |
setError(std::string("Failed to find static method '")+name+"'."); | |
return; | |
} | |
else | |
{ | |
jvalue* jargs = createArguments(args...); | |
callStaticJavaMethod<void>(env, classId, methodId, jargs); | |
if (env->ExceptionCheck()) | |
{ | |
env->ExceptionClear(); | |
setError(std::string("Failed to call static method '")+name+"'."); | |
} | |
} | |
} | |
/** | |
* Get a static class field | |
* @param name the field name | |
*/ | |
template<typename Return> | |
Return staticField(const std::string& name, const Return& defRet) | |
{ | |
std::string signature(getSignaturePart<Return>(defRet)); | |
return staticFieldSigned(name, signature, defRet); | |
} | |
template<typename Return> | |
Return staticFieldSigned(const std::string& name, const std::string& signature, const Return& defRet) | |
{ | |
JNIEnv* env = getEnvironment(); | |
if(!env) | |
{ | |
return defRet; | |
} | |
jclass classId = getClass(); | |
if(!classId) | |
{ | |
return defRet; | |
} | |
jfieldID fieldId = env->GetStaticFieldID(classId, name.c_str(), signature.c_str()); | |
if (!fieldId || env->ExceptionCheck()) | |
{ | |
env->ExceptionClear(); | |
setError(std::string("Failed to find static field '")+name+"' with signature '"+signature+"'."); | |
return defRet; | |
} | |
else | |
{ | |
Return result = getJavaStaticField<Return>(env, classId, fieldId); | |
if (env->ExceptionCheck()) | |
{ | |
env->ExceptionClear(); | |
setError(std::string("Failed to read static field '")+name+"' with signature '"+signature+"'."); | |
return defRet; | |
} | |
else | |
{ | |
return result; | |
} | |
} | |
} | |
/** | |
* Get a object field | |
* @param name the field name | |
*/ | |
template<typename Return> | |
Return field(const std::string& name, const Return& defRet) | |
{ | |
std::string signature(getSignaturePart<Return>(defRet)); | |
return fieldSigned(name, signature, defRet); | |
} | |
template<typename Return> | |
Return fieldSigned(const std::string& name, const std::string& signature, const Return& defRet) | |
{ | |
JNIEnv* env = getEnvironment(); | |
if(!env) | |
{ | |
return defRet; | |
} | |
jclass classId = getClass(); | |
if(!classId) | |
{ | |
return defRet; | |
} | |
jfieldID fieldId = env->GetFieldID(classId, name.c_str(), signature.c_str()); | |
if (!fieldId || env->ExceptionCheck()) | |
{ | |
env->ExceptionClear(); | |
setError(std::string("Failed to find field '")+name+"' with signature '"+signature+"'."); | |
return defRet; | |
} | |
else | |
{ | |
Return result = getJavaField<Return>(env, classId, fieldId); | |
if (env->ExceptionCheck()) | |
{ | |
env->ExceptionClear(); | |
setError(std::string("Failed to read field '")+name+"' with signature '"+signature+"'."); | |
return defRet; | |
} | |
else | |
{ | |
return result; | |
} | |
} | |
} | |
/** | |
* Return the signature for the object | |
*/ | |
std::string getSignature() const; | |
/** | |
* Return the error | |
*/ | |
const std::string& getError() const; | |
/** | |
* Return true of there is an error | |
*/ | |
bool hasError() const; | |
/** | |
* create an java array of the given type | |
*/ | |
template<typename Type> | |
static jarray createJavaArray(JNIEnv* env, const Type& element, size_t size); | |
/** | |
* Convert a jobject array to a container | |
*/ | |
template<typename Type> | |
static bool convertFromJavaArray(JNIEnv* env, jarray arr, Type& container) | |
{ | |
if(!arr) | |
{ | |
return false; | |
} | |
jsize arraySize = env->GetArrayLength(arr); | |
for(size_t i=0; i<arraySize; i++) | |
{ | |
typename Type::value_type elm; | |
convertFromJavaArrayElement(env, arr, i, elm); | |
container.insert(container.end(), elm); | |
} | |
return true; | |
} | |
template<typename Type> | |
static bool convertFromJavaArray(jarray arr, Type& container) | |
{ | |
JNIEnv* env = getEnvironment(); | |
assert(env); | |
return convertFromJavaArray(env, arr, container); | |
} | |
/** | |
* Get an element of a java array | |
*/ | |
template<typename Type> | |
static bool convertFromJavaArrayElement(JNIEnv* env, jarray arr, size_t position, Type& out); | |
template<typename Type> | |
static bool convertFromJavaArrayElement(JNIEnv* env, jarray arr, size_t position, std::vector<Type>& out) | |
{ | |
jobject elm; | |
if(!convertFromJavaArrayElement(env, arr, position, elm)) | |
{ | |
return false; | |
} | |
return convertFromJavaArray(env, (jarray)elm, out); | |
} | |
template<typename Key, typename Value> | |
static bool convertFromJavaArrayElement(JNIEnv* env, jarray arr, size_t position, std::map<Key, Value>& out) | |
{ | |
jobject elm; | |
if(!convertFromJavaArrayElement(env, arr, position, elm)) | |
{ | |
return false; | |
} | |
return convertFromJavaMap(env, elm, out); | |
} | |
/** | |
* Set an element of a java array | |
*/ | |
template<typename Type> | |
static void setJavaArrayElement(JNIEnv* env, jarray arr, size_t position, const Type& elm); | |
template<typename Type> | |
static bool convertFromJavaCollection(JNIEnv* env, jobject obj, Type& out) | |
{ | |
if(!obj) | |
{ | |
return false; | |
} | |
JniObject jcontainer(obj); | |
if(!jcontainer.isInstanceOf("java.util.Collection")) | |
{ | |
return false; | |
} | |
out = jcontainer.call<Type>("toArray", out, out); | |
return true; | |
} | |
template<typename Key, typename Value> | |
static bool convertFromJavaMap(JNIEnv* env, jobject obj, std::map<Key, Value>& out) | |
{ | |
if(!obj) | |
{ | |
return false; | |
} | |
JniObject jmap(obj); | |
if(!jmap.isInstanceOf("java.util.Map")) | |
{ | |
return false; | |
} | |
JniObject jkeys = jmap.call<JniObject>("keySet", JniObject("java.util.Set")); | |
if(jkeys.hasError()) | |
{ | |
return false; | |
} | |
std::vector<Key> keys = jkeys.callSigned<std::vector<Key>>("toArray", "()[Ljava/lang/Object;", std::vector<Key>()); | |
for(typename std::vector<Key>::const_iterator itr = keys.begin(); itr != keys.end(); ++itr) | |
{ | |
Value v = jmap.callSigned<Value>("get", "(Ljava/lang/Object;)Ljava/lang/Object;", Value(), *itr); | |
out[*itr] = v; | |
} | |
return true; | |
} | |
template<typename Key, typename Value> | |
static bool convertToMapFromJavaArray(JNIEnv* env, jarray arr, std::map<Key, Value>& out) | |
{ | |
if(!arr) | |
{ | |
return false; | |
} | |
jsize mapSize = env->GetArrayLength(arr) / 2; | |
for(size_t i=0; i<mapSize; ++i) | |
{ | |
Key k; | |
if(convertFromJavaArrayElement(env, arr, i*2, k)) | |
{ | |
Value v; | |
if(convertFromJavaArrayElement(env, arr, i*2+1, v)) | |
{ | |
out[k] = v; | |
} | |
} | |
} | |
return true; | |
} | |
/** | |
* Convert a jobject to the c++ representation | |
*/ | |
template<typename Type> | |
static bool convertFromJavaObject(JNIEnv* env, jobject obj, Type& out); | |
// template specialization for containers | |
template<typename Type> | |
static bool convertFromJavaObject(JNIEnv* env, jobject obj, std::vector<Type>& out) | |
{ | |
if(convertFromJavaCollection(env, obj, out)) | |
{ | |
return true; | |
} | |
if(convertFromJavaArray(env, (jarray)obj, out)) | |
{ | |
return true; | |
} | |
return false; | |
} | |
template<typename Type> | |
static bool convertFromJavaObject(JNIEnv* env, jobject obj, std::set<Type>& out) | |
{ | |
if(convertFromJavaCollection(env, obj, out)) | |
{ | |
return true; | |
} | |
if(convertFromJavaArray(env, (jarray)obj, out)) | |
{ | |
return true; | |
} | |
return false; | |
} | |
template<typename Type, int Size> | |
static bool convertFromJavaObject(JNIEnv* env, jobject obj, std::array<Type, Size>& out) | |
{ | |
if(convertFromJavaCollection(env, obj, out)) | |
{ | |
return true; | |
} | |
if(convertFromJavaArray(env, (jarray)obj, out)) | |
{ | |
return true; | |
} | |
return false; | |
} | |
template<typename Type> | |
static bool convertFromJavaObject(JNIEnv* env, jobject obj, std::list<Type>& out) | |
{ | |
if(convertFromJavaCollection(env, obj, out)) | |
{ | |
return true; | |
} | |
if(convertFromJavaArray(env, (jarray)obj, out)) | |
{ | |
return true; | |
} | |
return false; | |
} | |
template<typename Key, typename Type> | |
static bool convertFromJavaObject(JNIEnv* env, jobject obj, std::map<Key, Type>& out) | |
{ | |
if(convertFromJavaMap(env, obj, out)) | |
{ | |
return true; | |
} | |
if(convertToMapFromJavaArray(env, (jarray)obj, out)) | |
{ | |
return true; | |
} | |
return false; | |
} | |
// utility methods that return the object | |
template<typename Type> | |
static Type convertFromJavaObject(JNIEnv* env, jobject obj) | |
{ | |
Type out; | |
bool result = convertFromJavaObject(env, obj, out); | |
assert(result); | |
return out; | |
} | |
template<typename Type> | |
static Type convertFromJavaObject(jobject obj) | |
{ | |
JNIEnv* env = getEnvironment(); | |
assert(env); | |
return convertFromJavaObject<Type>(env, obj); | |
} | |
template<typename Type> | |
static bool convertFromJavaObject(jobject obj, Type& out) | |
{ | |
JNIEnv* env = getEnvironment(); | |
assert(env); | |
return convertFromJavaObject(env, obj, out); | |
} | |
/** | |
* Convert a c++ list container to a jarray | |
*/ | |
template<typename Type> | |
static jarray createJavaArray(const Type& obj) | |
{ | |
JNIEnv* env = getEnvironment(); | |
if (!env) | |
{ | |
return nullptr; | |
} | |
jarray arr = nullptr; | |
if(obj.empty()) | |
{ | |
arr = createJavaArray(env, typename Type::value_type(), 0); | |
} | |
else | |
{ | |
arr = createJavaArray(env, *obj.begin(), obj.size()); | |
} | |
size_t i = 0; | |
for(typename Type::const_iterator itr = obj.begin(); itr != obj.end(); ++itr) | |
{ | |
setJavaArrayElement(env, arr, i, *itr); | |
i++; | |
} | |
return arr; | |
} | |
template<typename Key, typename Value> | |
static JniObject createJavaMap(const std::map<Key, Value>& obj, const std::string& classPath="java/util/HashMap") | |
{ | |
JniObject jmap(JniObject::createNew(classPath)); | |
for(typename std::map<Key, Value>::const_iterator itr = obj.begin(); itr != obj.end(); ++itr) | |
{ | |
Value v = jmap.callSigned("put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", Value(), itr->first, itr->second); | |
} | |
return jmap; | |
} | |
template<typename Type> | |
static JniObject createJavaList(const Type& obj, const std::string& classPath="java/util/ArrayList") | |
{ | |
JniObject jlist(JniObject::createNew(classPath)); | |
for(typename Type::const_iterator itr = obj.begin(); itr != obj.end(); ++itr) | |
{ | |
jlist.callSignedVoid("add", "(Ljava/lang/Object;)Z", *itr); | |
} | |
return jlist; | |
} | |
template<typename Type> | |
static JniObject createJavaSet(const Type& obj, const std::string& classPath="java/util/HashSet") | |
{ | |
return createJavaList(obj, classPath); | |
} | |
/** | |
* Convert a c++ type to the jvalue representation | |
* This is called on all jni arguments | |
*/ | |
template<typename Type> | |
static jvalue convertToJavaValue(const Type& obj); | |
// template specialization for pointers | |
template<typename Type> | |
static jvalue convertToJavaValue(Type* obj) | |
{ | |
return convertToJavaValue((jlong)obj); | |
} | |
// template specialization for containers | |
template<typename Type> | |
static jvalue convertToJavaValue(const std::vector<Type>& obj) | |
{ | |
return convertToJavaValue(createJavaArray(obj)); | |
} | |
template<typename Type> | |
static jvalue convertToJavaValue(const std::set<Type>& obj) | |
{ | |
return convertToJavaValue(createJavaArray(obj)); | |
} | |
template<typename Type, int Size> | |
static jvalue convertToJavaValue(const std::array<Type, Size>& obj) | |
{ | |
return convertToJavaValue(createJavaArray(obj)); | |
} | |
template<typename Type> | |
static jvalue convertToJavaValue(const std::list<Type>& obj) | |
{ | |
return convertToJavaValue(createJavaArray(obj)); | |
} | |
template<typename Key, typename Value> | |
static jvalue convertToJavaValue(const std::map<Key, Value>& obj) | |
{ | |
return convertToJavaValue(createJavaMap(obj).getNewLocalInstance()); | |
} | |
/** | |
* Returns the class reference. This is a global ref that will be removed | |
* when the JniObject is destroyed | |
*/ | |
jclass getClass() const; | |
/** | |
* Returns the class path. If it is not there it tries to call | |
* `getClass().getName()` on the object to get the class | |
*/ | |
const std::string& getClassPath() const; | |
/** | |
* Returns the jobject reference. This is a global ref that will be removed | |
* when the JniObject is destroyed | |
*/ | |
jobject getInstance() const; | |
/** | |
* Returns the jobject reference. This is a new local ref | |
*/ | |
jobject getNewLocalInstance() const; | |
/** | |
* Return true if class path and class ref match | |
*/ | |
bool isInstanceOf(const std::string& classPath) const; | |
/** | |
* Returns the environment pointer | |
*/ | |
static JNIEnv* getEnvironment(); | |
/** | |
* Returns true if there is an object instance | |
*/ | |
operator bool() const; | |
/** | |
* Copy a jni object | |
*/ | |
JniObject& operator=(const JniObject& other); | |
/** | |
* Compare two jni objects | |
*/ | |
bool operator==(const JniObject& other) const; | |
}; | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment