Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifndef METERSNAP_ANDROID_JNICLASS_H
- #define METERSNAP_ANDROID_JNICLASS_H
- #include <jni.h>
- #include <string>
- #include <sstream>
- class JniClass;
- class JniObject;
- namespace impl{
- template <typename T>
- std::string GetTypeName();
- typedef unsigned char jboolean; /* unsigned 8 bits */
- typedef signed char jbyte; /* signed 8 bits */
- typedef unsigned short jchar; /* unsigned 16 bits */
- typedef short jshort; /* signed 16 bits */
- typedef int jint; /* signed 32 bits */
- typedef long long jlong; /* signed 64 bits */
- typedef float jfloat; /* 32-bit IEEE 754 */
- typedef double jdouble; /* 64-bit IEEE 754 */
- #define REGISTER_TYPE(type, name) template<> std::string GetTypeName<type>() { return name; }
- REGISTER_TYPE(jboolean, "Z");
- REGISTER_TYPE(jbyte , "B");
- REGISTER_TYPE(jchar , "C");
- REGISTER_TYPE(jshort , "S");
- REGISTER_TYPE(jint , "I");
- REGISTER_TYPE(jlong , "J");
- REGISTER_TYPE(jfloat , "F");
- REGISTER_TYPE(jdouble , "D");
- REGISTER_TYPE(void , "V");
- REGISTER_TYPE(const char *, "Ljava/lang/String;");
- #undef REGISTER_TYPE
- class JniHolder{
- jvalue m_val;
- class Holder{
- JNIEnv *m_env;
- jobject m_obj;
- public:
- Holder(JNIEnv *env = nullptr, jobject obj = nullptr):
- m_env(env), m_obj(obj){
- }
- ~Holder(){
- }
- jobject obj() const {
- return m_obj;
- }
- } m_holder;
- public:
- #define CONSTRUCTOR(type, field) explicit JniHolder(JNIEnv *env, type val) : m_val(), m_holder() { field = val; }
- CONSTRUCTOR(jboolean, m_val.z);
- CONSTRUCTOR(jbyte , m_val.b);
- CONSTRUCTOR(jchar , m_val.c);
- CONSTRUCTOR(jshort , m_val.s);
- CONSTRUCTOR(jint , m_val.i);
- CONSTRUCTOR(jlong , m_val.j);
- CONSTRUCTOR(jfloat , m_val.f);
- CONSTRUCTOR(jdouble , m_val.d);
- #undef CONSTRUCTOR
- explicit JniHolder(JNIEnv *env, const std::string &val) : m_val(), m_holder(env, env->NewStringUTF(val.c_str())) { m_val.l = m_holder.obj(); }
- explicit JniHolder(JNIEnv *env, jobject obj) : m_val(), m_holder(env, obj) { m_val.l = m_holder.obj(); }
- const jvalue &value() const {
- return m_val;
- }
- };
- template <typename Ret>
- struct CallStaticMethodImp;
- template <typename Ret>
- struct CallInstanceMethodImp;
- #define STATIC_METHOD_IMP(type, _jname) \
- template <>\
- struct CallStaticMethodImp<type>{\
- static type CallMethod(JNIEnv *env, jclass clazz, jmethodID method, size_t args_size, jvalue *values){\
- if(args_size != 0)\
- return env->CallStatic##_jname##MethodA(clazz, method, values);\
- return env->CallStatic##_jname##Method(clazz, method);\
- }\
- };\
- template <>\
- struct CallInstanceMethodImp<type>{\
- static type CallMethod(JNIEnv *env, jobject object, jmethodID method, size_t args_size, jvalue *values){\
- if(args_size != 0)\
- return env->Call##_jname##MethodA(object, method, values);\
- return env->Call##_jname##Method(object, method);\
- }\
- };
- STATIC_METHOD_IMP(jboolean, Boolean);
- STATIC_METHOD_IMP(jbyte , Byte);
- STATIC_METHOD_IMP(jchar , Char);
- STATIC_METHOD_IMP(jshort , Short);
- STATIC_METHOD_IMP(jint , Int);
- STATIC_METHOD_IMP(jlong , Long);
- STATIC_METHOD_IMP(jfloat , Float);
- STATIC_METHOD_IMP(jdouble , Double);
- STATIC_METHOD_IMP(void , Void);
- STATIC_METHOD_IMP(jobject , Object);
- #undef STATIC_METHOD_IMP
- template <typename... Args>
- std::string GenerateTypesString(){
- constexpr size_t count = sizeof...(Args);
- const std::string typeNames[count] = { GetTypeName<Args>()... };
- std::string signature;
- signature.append("(");
- for(const std::string &s : typeNames)
- signature.append(s);
- signature.append(")");
- return signature;
- };
- template <typename... Args>
- jmethodID GetConstructorId(JNIEnv *env, jclass clazz){
- std::string signature = GenerateTypesString<Args...>() + "V";
- return env->GetMethodID(clazz, "<init>", signature.c_str());
- };
- template <typename Ret, typename... Args>
- jmethodID GetMethodId(JNIEnv *env, jclass clazz, const std::string &name){
- std::string signature = GenerateTypesString<Args...>() + GetTypeName<Ret>();
- return env->GetMethodID(clazz, name.c_str(), signature.c_str());
- };
- template <typename Ret>
- struct CallStatic {
- template<typename... Args>
- static Ret CallStaticMethod(JniClass *clazz, const std::string &name, Args... args);
- };
- template <>
- struct CallStatic<jobject> {
- template<typename... Args>
- static jobject CallStaticMethod(JniClass *clazz, const std::string &name, const JniClass *returnType, Args... args);
- template<typename... Args>
- static jobject CallStaticMethod(JniClass *clazz, const std::string &name, const JniClass &returnType, Args... args);
- };
- template <>
- struct CallStatic<JniObject> {
- template<typename... Args>
- static JniObject CallStaticMethod(JniClass *clazz, const std::string &name, const JniClass *returnType, Args... args);
- template<typename... Args>
- static JniObject CallStaticMethod(JniClass *clazz, const std::string &name, const JniClass &returnType, Args... args);
- };
- template <typename Ret>
- struct CallInstance{
- template <typename... Args>
- static Ret CallInstanceMethod(JniObject *obj, const std::string &name, Args... args);
- };
- template <typename Ret>
- struct CallInstanceSignature{
- template<typename... Args>
- static Ret CallInstanceSignatureMethod(JniObject *obj, const std::string &name, const std::string &signature, Args... args);
- };
- }
- template<typename T>
- std::string to_string(T value) {
- std::ostringstream os;
- os << value;
- return os.str();
- }
- class JniObject {
- public:
- JniObject(const JniClass *clazz = nullptr, jobject obj = nullptr):
- m_object(obj),
- m_class(clazz){
- }
- bool isValid() const{
- return m_object != nullptr;
- }
- jobject object() const {
- return m_object;
- }
- const JniClass *clazz() const {
- return m_class;
- }
- template <typename Ret, typename... Args>
- Ret invoke(const std::string &method, Args... args){
- return impl::CallInstance<Ret>::CallInstanceMethod(this, method, std::move(args)...);
- };
- template <typename Ret, typename... Args>
- Ret invokeSignature(const std::string &method, const std::string &signature, Args... args){
- return impl::CallInstanceSignature<Ret>::CallInstanceSignatureMethod(this, method, signature, std::move(args)...);
- };
- private:
- jobject m_object;
- const JniClass * m_class;
- };
- class JniClass {
- public:
- JniClass(JNIEnv *env, const std::string &name):
- m_env(env),
- m_name(name),
- m_clazz(env->FindClass(name.c_str())) {
- }
- template <typename Ret, typename... Args>
- Ret invokeStatic(const std::string &method, Args... args){
- return impl::CallStatic<Ret>::CallStaticMethod(this, method.c_str(), std::move(args)...);
- };
- template <typename... Args>
- JniObject newInstance(Args... args){
- jmethodID constructor = impl::GetConstructorId<Args...>(m_env, m_clazz);
- if(constructor != 0) {
- constexpr size_t arg_count = sizeof...(Args);
- impl::JniHolder holder[arg_count] = { std::move(impl::JniHolder(m_env, args))... };
- jvalue values[arg_count] {};
- for(int i = 0; i < arg_count; i++){
- values[i] = holder[i].value();
- }
- return { this, m_env->NewObjectA(m_clazz, constructor, values) };
- }
- return {};
- }
- JNIEnv *env() const {
- return m_env;
- }
- jclass clazz() const {
- return m_clazz;
- }
- const std::string &name() const {
- return m_name;
- }
- private:
- JNIEnv *m_env;
- std::string m_name;
- jclass m_clazz;
- };
- namespace impl{
- template<typename Ret>
- template<typename... Args>
- Ret CallStatic<Ret>::CallStaticMethod(JniClass *clazz, const std::string &name, Args... args) {
- constexpr size_t arg_count = sizeof...(Args);
- JniHolder holder[arg_count] = {std::move(JniHolder(clazz->env(), args))...};
- jvalue values[arg_count]{};
- for (int i = 0; i < arg_count; i++) {
- values[i] = holder[i].value();
- }
- std::string signature = GenerateTypesString<Args...>() + GetTypeName<Ret>();
- jmethodID method = clazz->env()->GetStaticMethodID(clazz->clazz(), name.c_str(),
- signature.c_str());
- return CallStaticMethodImp<Ret>::CallMethod(clazz->env(), clazz->clazz(), method, arg_count, values);
- };
- template<>
- template<typename... Args>
- jobject CallStatic<jobject>::CallStaticMethod(JniClass *clazz, const std::string &name, const JniClass *returnType, Args... args) {
- constexpr size_t arg_count = sizeof...(Args);
- JniHolder holder[arg_count] = {std::move(JniHolder(clazz->env(), args))...};
- jvalue values[arg_count]{};
- for (int i = 0; i < arg_count; i++) {
- values[i] = holder[i].value();
- }
- std::string signature = GenerateTypesString<Args...>() + "L" + returnType->name() + ";";
- jmethodID method = clazz->env()->GetStaticMethodID(clazz->clazz(), name.c_str(),
- signature.c_str());
- return CallStaticMethodImp<jobject>::CallMethod(clazz->env(), clazz->clazz(), method, arg_count, values);
- };
- template<>
- template<typename... Args>
- jobject CallStatic<jobject>::CallStaticMethod(JniClass *clazz, const std::string &name, const JniClass &returnType, Args... args) {
- return CallStaticMethod(clazz, name, &returnType, std::move(args)...);
- };
- template<>
- template<typename... Args>
- JniObject CallStatic<JniObject>::CallStaticMethod(JniClass *clazz, const std::string &name, const JniClass *returnType, Args... args) {
- constexpr size_t arg_count = sizeof...(Args);
- JniHolder holder[arg_count] = {std::move(JniHolder(clazz->env(), args))...};
- jvalue values[arg_count]{};
- for (int i = 0; i < arg_count; i++) {
- values[i] = holder[i].value();
- }
- std::string signature = GenerateTypesString<Args...>() + "L" + returnType->name() + ";";
- jmethodID method = clazz->env()->GetStaticMethodID(clazz->clazz(), name.c_str(), signature.c_str());
- return { returnType, CallStaticMethodImp<jobject>::CallMethod(clazz->env(), clazz->clazz(), method, arg_count, values) };
- };
- template<>
- template<typename... Args>
- JniObject CallStatic<JniObject>::CallStaticMethod(JniClass *clazz, const std::string &name, const JniClass &returnType, Args... args) {
- return CallStaticMethod(clazz, name, &returnType, std::move(args)...);
- };
- template <typename Ret>
- template <typename... Args>
- Ret CallInstance<Ret>::CallInstanceMethod(JniObject *obj, const std::string &name, Args... args){
- jmethodID method = GetMethodId<Ret, Args...>(obj->clazz()->env(), obj->clazz()->clazz(), name);
- constexpr size_t arg_count = sizeof...(Args);
- JniHolder holder[arg_count] = {std::move(JniHolder(obj->clazz()->env(), args))...};
- jvalue values[arg_count]{};
- for (int i = 0; i < arg_count; i++) {
- values[i] = holder[i].value();
- }
- return CallInstanceMethodImp<Ret>::CallMethod(obj->clazz()->env(), obj->object(), method, arg_count, values);
- };
- template <typename Ret>
- template <typename... Args>
- Ret CallInstanceSignature<Ret>::CallInstanceSignatureMethod(JniObject *obj, const std::string &name, const std::string &signature, Args... args){
- jmethodID method = obj->clazz()->env()->GetMethodID(obj->clazz()->clazz(), name.c_str(), signature.c_str());
- constexpr size_t arg_count = sizeof...(Args);
- JniHolder holder[arg_count] = {std::move(JniHolder(obj->clazz()->env(), args))...};
- jvalue values[arg_count]{};
- for (int i = 0; i < arg_count; i++) {
- values[i] = holder[i].value();
- }
- return CallInstanceMethodImp<Ret>::CallMethod(obj->clazz()->env(), obj->object(), method, arg_count, values);
- };
- }
- #endif //METERSNAP_ANDROID_JNICLASS_H
Add Comment
Please, Sign In to add comment