Guest User

Untitled

a guest
May 23rd, 2018
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.52 KB | None | 0 0
  1. #ifndef METERSNAP_ANDROID_JNICLASS_H
  2. #define METERSNAP_ANDROID_JNICLASS_H
  3.  
  4. #include <jni.h>
  5. #include <string>
  6. #include <sstream>
  7.  
  8.  
  9. class JniClass;
  10. class JniObject;
  11.  
  12. namespace impl{
  13. template <typename T>
  14. std::string GetTypeName();
  15.  
  16. typedef unsigned char jboolean; /* unsigned 8 bits */
  17. typedef signed char jbyte; /* signed 8 bits */
  18. typedef unsigned short jchar; /* unsigned 16 bits */
  19. typedef short jshort; /* signed 16 bits */
  20. typedef int jint; /* signed 32 bits */
  21. typedef long long jlong; /* signed 64 bits */
  22. typedef float jfloat; /* 32-bit IEEE 754 */
  23. typedef double jdouble; /* 64-bit IEEE 754 */
  24.  
  25. #define REGISTER_TYPE(type, name) template<> std::string GetTypeName<type>() { return name; }
  26. REGISTER_TYPE(jboolean, "Z");
  27. REGISTER_TYPE(jbyte , "B");
  28. REGISTER_TYPE(jchar , "C");
  29. REGISTER_TYPE(jshort , "S");
  30. REGISTER_TYPE(jint , "I");
  31. REGISTER_TYPE(jlong , "J");
  32. REGISTER_TYPE(jfloat , "F");
  33. REGISTER_TYPE(jdouble , "D");
  34. REGISTER_TYPE(void , "V");
  35. REGISTER_TYPE(const char *, "Ljava/lang/String;");
  36. #undef REGISTER_TYPE
  37.  
  38. class JniHolder{
  39. jvalue m_val;
  40. class Holder{
  41. JNIEnv *m_env;
  42. jobject m_obj;
  43. public:
  44. Holder(JNIEnv *env = nullptr, jobject obj = nullptr):
  45. m_env(env), m_obj(obj){
  46. }
  47. ~Holder(){
  48. }
  49. jobject obj() const {
  50. return m_obj;
  51. }
  52. } m_holder;
  53.  
  54. public:
  55. #define CONSTRUCTOR(type, field) explicit JniHolder(JNIEnv *env, type val) : m_val(), m_holder() { field = val; }
  56. CONSTRUCTOR(jboolean, m_val.z);
  57. CONSTRUCTOR(jbyte , m_val.b);
  58. CONSTRUCTOR(jchar , m_val.c);
  59. CONSTRUCTOR(jshort , m_val.s);
  60. CONSTRUCTOR(jint , m_val.i);
  61. CONSTRUCTOR(jlong , m_val.j);
  62. CONSTRUCTOR(jfloat , m_val.f);
  63. CONSTRUCTOR(jdouble , m_val.d);
  64. #undef CONSTRUCTOR
  65. explicit JniHolder(JNIEnv *env, const std::string &val) : m_val(), m_holder(env, env->NewStringUTF(val.c_str())) { m_val.l = m_holder.obj(); }
  66. explicit JniHolder(JNIEnv *env, jobject obj) : m_val(), m_holder(env, obj) { m_val.l = m_holder.obj(); }
  67.  
  68. const jvalue &value() const {
  69. return m_val;
  70. }
  71. };
  72.  
  73. template <typename Ret>
  74. struct CallStaticMethodImp;
  75. template <typename Ret>
  76. struct CallInstanceMethodImp;
  77.  
  78. #define STATIC_METHOD_IMP(type, _jname) \
  79. template <>\
  80. struct CallStaticMethodImp<type>{\
  81. static type CallMethod(JNIEnv *env, jclass clazz, jmethodID method, size_t args_size, jvalue *values){\
  82. if(args_size != 0)\
  83. return env->CallStatic##_jname##MethodA(clazz, method, values);\
  84. return env->CallStatic##_jname##Method(clazz, method);\
  85. }\
  86. };\
  87. template <>\
  88. struct CallInstanceMethodImp<type>{\
  89. static type CallMethod(JNIEnv *env, jobject object, jmethodID method, size_t args_size, jvalue *values){\
  90. if(args_size != 0)\
  91. return env->Call##_jname##MethodA(object, method, values);\
  92. return env->Call##_jname##Method(object, method);\
  93. }\
  94. };
  95. STATIC_METHOD_IMP(jboolean, Boolean);
  96. STATIC_METHOD_IMP(jbyte , Byte);
  97. STATIC_METHOD_IMP(jchar , Char);
  98. STATIC_METHOD_IMP(jshort , Short);
  99. STATIC_METHOD_IMP(jint , Int);
  100. STATIC_METHOD_IMP(jlong , Long);
  101. STATIC_METHOD_IMP(jfloat , Float);
  102. STATIC_METHOD_IMP(jdouble , Double);
  103. STATIC_METHOD_IMP(void , Void);
  104. STATIC_METHOD_IMP(jobject , Object);
  105. #undef STATIC_METHOD_IMP
  106.  
  107. template <typename... Args>
  108. std::string GenerateTypesString(){
  109. constexpr size_t count = sizeof...(Args);
  110. const std::string typeNames[count] = { GetTypeName<Args>()... };
  111. std::string signature;
  112. signature.append("(");
  113. for(const std::string &s : typeNames)
  114. signature.append(s);
  115. signature.append(")");
  116. return signature;
  117. };
  118.  
  119. template <typename... Args>
  120. jmethodID GetConstructorId(JNIEnv *env, jclass clazz){
  121. std::string signature = GenerateTypesString<Args...>() + "V";
  122. return env->GetMethodID(clazz, "<init>", signature.c_str());
  123. };
  124.  
  125.  
  126. template <typename Ret, typename... Args>
  127. jmethodID GetMethodId(JNIEnv *env, jclass clazz, const std::string &name){
  128. std::string signature = GenerateTypesString<Args...>() + GetTypeName<Ret>();
  129. return env->GetMethodID(clazz, name.c_str(), signature.c_str());
  130. };
  131.  
  132. template <typename Ret>
  133. struct CallStatic {
  134. template<typename... Args>
  135. static Ret CallStaticMethod(JniClass *clazz, const std::string &name, Args... args);
  136. };
  137.  
  138. template <>
  139. struct CallStatic<jobject> {
  140. template<typename... Args>
  141. static jobject CallStaticMethod(JniClass *clazz, const std::string &name, const JniClass *returnType, Args... args);
  142. template<typename... Args>
  143. static jobject CallStaticMethod(JniClass *clazz, const std::string &name, const JniClass &returnType, Args... args);
  144. };
  145.  
  146. template <>
  147. struct CallStatic<JniObject> {
  148. template<typename... Args>
  149. static JniObject CallStaticMethod(JniClass *clazz, const std::string &name, const JniClass *returnType, Args... args);
  150.  
  151. template<typename... Args>
  152. static JniObject CallStaticMethod(JniClass *clazz, const std::string &name, const JniClass &returnType, Args... args);
  153. };
  154.  
  155. template <typename Ret>
  156. struct CallInstance{
  157. template <typename... Args>
  158. static Ret CallInstanceMethod(JniObject *obj, const std::string &name, Args... args);
  159. };
  160.  
  161. template <typename Ret>
  162. struct CallInstanceSignature{
  163. template<typename... Args>
  164. static Ret CallInstanceSignatureMethod(JniObject *obj, const std::string &name, const std::string &signature, Args... args);
  165. };
  166. }
  167.  
  168.  
  169. template<typename T>
  170. std::string to_string(T value) {
  171. std::ostringstream os;
  172. os << value;
  173. return os.str();
  174. }
  175.  
  176. class JniObject {
  177. public:
  178. JniObject(const JniClass *clazz = nullptr, jobject obj = nullptr):
  179. m_object(obj),
  180. m_class(clazz){
  181. }
  182.  
  183. bool isValid() const{
  184. return m_object != nullptr;
  185. }
  186.  
  187. jobject object() const {
  188. return m_object;
  189. }
  190.  
  191.  
  192. const JniClass *clazz() const {
  193. return m_class;
  194. }
  195.  
  196. template <typename Ret, typename... Args>
  197. Ret invoke(const std::string &method, Args... args){
  198. return impl::CallInstance<Ret>::CallInstanceMethod(this, method, std::move(args)...);
  199. };
  200.  
  201. template <typename Ret, typename... Args>
  202. Ret invokeSignature(const std::string &method, const std::string &signature, Args... args){
  203. return impl::CallInstanceSignature<Ret>::CallInstanceSignatureMethod(this, method, signature, std::move(args)...);
  204. };
  205.  
  206. private:
  207. jobject m_object;
  208. const JniClass * m_class;
  209. };
  210.  
  211. class JniClass {
  212.  
  213. public:
  214. JniClass(JNIEnv *env, const std::string &name):
  215. m_env(env),
  216. m_name(name),
  217. m_clazz(env->FindClass(name.c_str())) {
  218. }
  219.  
  220. template <typename Ret, typename... Args>
  221. Ret invokeStatic(const std::string &method, Args... args){
  222. return impl::CallStatic<Ret>::CallStaticMethod(this, method.c_str(), std::move(args)...);
  223. };
  224.  
  225. template <typename... Args>
  226. JniObject newInstance(Args... args){
  227. jmethodID constructor = impl::GetConstructorId<Args...>(m_env, m_clazz);
  228. if(constructor != 0) {
  229. constexpr size_t arg_count = sizeof...(Args);
  230. impl::JniHolder holder[arg_count] = { std::move(impl::JniHolder(m_env, args))... };
  231. jvalue values[arg_count] {};
  232. for(int i = 0; i < arg_count; i++){
  233. values[i] = holder[i].value();
  234. }
  235. return { this, m_env->NewObjectA(m_clazz, constructor, values) };
  236. }
  237. return {};
  238. }
  239.  
  240. JNIEnv *env() const {
  241. return m_env;
  242. }
  243.  
  244. jclass clazz() const {
  245. return m_clazz;
  246. }
  247.  
  248.  
  249. const std::string &name() const {
  250. return m_name;
  251. }
  252.  
  253. private:
  254. JNIEnv *m_env;
  255. std::string m_name;
  256. jclass m_clazz;
  257. };
  258.  
  259.  
  260.  
  261. namespace impl{
  262.  
  263. template<typename Ret>
  264. template<typename... Args>
  265. Ret CallStatic<Ret>::CallStaticMethod(JniClass *clazz, const std::string &name, Args... args) {
  266. constexpr size_t arg_count = sizeof...(Args);
  267. JniHolder holder[arg_count] = {std::move(JniHolder(clazz->env(), args))...};
  268. jvalue values[arg_count]{};
  269. for (int i = 0; i < arg_count; i++) {
  270. values[i] = holder[i].value();
  271. }
  272.  
  273. std::string signature = GenerateTypesString<Args...>() + GetTypeName<Ret>();
  274.  
  275. jmethodID method = clazz->env()->GetStaticMethodID(clazz->clazz(), name.c_str(),
  276. signature.c_str());
  277.  
  278. return CallStaticMethodImp<Ret>::CallMethod(clazz->env(), clazz->clazz(), method, arg_count, values);
  279. };
  280.  
  281. template<>
  282. template<typename... Args>
  283. jobject CallStatic<jobject>::CallStaticMethod(JniClass *clazz, const std::string &name, const JniClass *returnType, Args... args) {
  284. constexpr size_t arg_count = sizeof...(Args);
  285. JniHolder holder[arg_count] = {std::move(JniHolder(clazz->env(), args))...};
  286. jvalue values[arg_count]{};
  287. for (int i = 0; i < arg_count; i++) {
  288. values[i] = holder[i].value();
  289. }
  290.  
  291. std::string signature = GenerateTypesString<Args...>() + "L" + returnType->name() + ";";
  292.  
  293. jmethodID method = clazz->env()->GetStaticMethodID(clazz->clazz(), name.c_str(),
  294. signature.c_str());
  295.  
  296. return CallStaticMethodImp<jobject>::CallMethod(clazz->env(), clazz->clazz(), method, arg_count, values);
  297. };
  298.  
  299. template<>
  300. template<typename... Args>
  301. jobject CallStatic<jobject>::CallStaticMethod(JniClass *clazz, const std::string &name, const JniClass &returnType, Args... args) {
  302. return CallStaticMethod(clazz, name, &returnType, std::move(args)...);
  303. };
  304.  
  305. template<>
  306. template<typename... Args>
  307. JniObject CallStatic<JniObject>::CallStaticMethod(JniClass *clazz, const std::string &name, const JniClass *returnType, Args... args) {
  308. constexpr size_t arg_count = sizeof...(Args);
  309. JniHolder holder[arg_count] = {std::move(JniHolder(clazz->env(), args))...};
  310. jvalue values[arg_count]{};
  311. for (int i = 0; i < arg_count; i++) {
  312. values[i] = holder[i].value();
  313. }
  314. std::string signature = GenerateTypesString<Args...>() + "L" + returnType->name() + ";";
  315.  
  316. jmethodID method = clazz->env()->GetStaticMethodID(clazz->clazz(), name.c_str(), signature.c_str());
  317.  
  318. return { returnType, CallStaticMethodImp<jobject>::CallMethod(clazz->env(), clazz->clazz(), method, arg_count, values) };
  319. };
  320.  
  321. template<>
  322. template<typename... Args>
  323. JniObject CallStatic<JniObject>::CallStaticMethod(JniClass *clazz, const std::string &name, const JniClass &returnType, Args... args) {
  324. return CallStaticMethod(clazz, name, &returnType, std::move(args)...);
  325. };
  326.  
  327.  
  328. template <typename Ret>
  329. template <typename... Args>
  330. Ret CallInstance<Ret>::CallInstanceMethod(JniObject *obj, const std::string &name, Args... args){
  331. jmethodID method = GetMethodId<Ret, Args...>(obj->clazz()->env(), obj->clazz()->clazz(), name);
  332. constexpr size_t arg_count = sizeof...(Args);
  333. JniHolder holder[arg_count] = {std::move(JniHolder(obj->clazz()->env(), args))...};
  334. jvalue values[arg_count]{};
  335. for (int i = 0; i < arg_count; i++) {
  336. values[i] = holder[i].value();
  337. }
  338. return CallInstanceMethodImp<Ret>::CallMethod(obj->clazz()->env(), obj->object(), method, arg_count, values);
  339. };
  340.  
  341. template <typename Ret>
  342. template <typename... Args>
  343. Ret CallInstanceSignature<Ret>::CallInstanceSignatureMethod(JniObject *obj, const std::string &name, const std::string &signature, Args... args){
  344. jmethodID method = obj->clazz()->env()->GetMethodID(obj->clazz()->clazz(), name.c_str(), signature.c_str());
  345. constexpr size_t arg_count = sizeof...(Args);
  346. JniHolder holder[arg_count] = {std::move(JniHolder(obj->clazz()->env(), args))...};
  347. jvalue values[arg_count]{};
  348. for (int i = 0; i < arg_count; i++) {
  349. values[i] = holder[i].value();
  350. }
  351. return CallInstanceMethodImp<Ret>::CallMethod(obj->clazz()->env(), obj->object(), method, arg_count, values);
  352. };
  353.  
  354. }
  355.  
  356.  
  357. #endif //METERSNAP_ANDROID_JNICLASS_H
Add Comment
Please, Sign In to add comment