1 /* 2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #pragma once 17 18 #include <unordered_map> 19 #include <map> 20 #include <tuple> 21 22 #include <jni.h> 23 24 class JNIBridge { 25 JavaVM* jvm; 26 JNIEnv* env; 27 std::unordered_map<std::string, jclass> classes; 28 // Using tuples as unordered maps keys in not very good in C++. 29 std::map<std::tuple<jclass, std::string, std::string>, jmethodID> methods; 30 31 public: JNIBridge(JavaVM * jvm)32 JNIBridge(JavaVM* jvm) : jvm(jvm), env(nullptr) {} ~JNIBridge()33 ~JNIBridge() { 34 if (env) { 35 for (const auto& kv : classes) { 36 env->DeleteGlobalRef(kv.second); 37 } 38 jvm->DetachCurrentThread(); 39 } 40 } 41 init()42 bool init() { 43 if (jvm->AttachCurrentThreadAsDaemon(&env, nullptr) != 0) { 44 fprintf(stderr, "Cannot attach current thread to JVM\n"); 45 return false; 46 } 47 return true; 48 } 49 makeString(const char * str)50 jstring makeString(const char* str) { 51 return env->NewStringUTF(str); 52 } 53 getStringUTFChars(jstring str,jboolean * isCopy)54 const char* getStringUTFChars(jstring str, jboolean *isCopy) { 55 return env->GetStringUTFChars(str, isCopy); 56 } 57 releaseStringUTFChars(jstring str,const char * chars)58 void releaseStringUTFChars(jstring str, const char* chars) { 59 env->ReleaseStringUTFChars(str, chars); 60 } 61 getObjectClass(jobject obj)62 jclass getObjectClass(jobject obj) { 63 return env->GetObjectClass(obj); 64 } 65 findClass(const char * clazz)66 jclass findClass(const char* clazz) { 67 auto it = classes.find(clazz); 68 if (it == classes.end()) { 69 auto result = env->FindClass(clazz); 70 classes[clazz] = (jclass)env->NewGlobalRef(result); 71 return result; 72 } else { 73 return it->second; 74 } 75 } 76 newObject(jclass clazz,jmethodID methodID,...)77 jobject newObject(jclass clazz, jmethodID methodID, ...) { 78 va_list args; 79 jobject result; 80 va_start(args, methodID); 81 result = env->NewObjectV(clazz, methodID, args); 82 va_end(args); 83 return result; 84 } 85 getMethodID(jclass clazz,const char * method,const char * sig)86 jmethodID getMethodID(jclass clazz, const char* method, const char* sig) { 87 auto key = std::make_tuple(clazz, method, sig); 88 auto it = methods.find(key); 89 if (it == methods.end()) { 90 auto result = env->GetMethodID(clazz, method, sig); 91 methods[key] = result; 92 return result; 93 } else { 94 return it->second; 95 } 96 } 97 getStaticMethodID(jclass clazz,const char * method,const char * sig)98 jmethodID getStaticMethodID(jclass clazz, const char* method, const char* sig) { 99 return env->GetStaticMethodID(clazz, method, sig); 100 } 101 callStaticVoidMethod(jclass clazz,jmethodID methodID,...)102 void callStaticVoidMethod(jclass clazz, jmethodID methodID, ...) { 103 va_list args; 104 va_start(args, methodID); 105 env->CallStaticVoidMethodV(clazz, methodID, args); 106 va_end(args); 107 } 108 callStaticObjectMethod(jclass clazz,jmethodID methodID,...)109 jobject callStaticObjectMethod(jclass clazz, jmethodID methodID, ...) { 110 va_list args; 111 jobject result; 112 va_start(args, methodID); 113 result = env->CallStaticObjectMethodV(clazz, methodID, args); 114 va_end(args); 115 return result; 116 } 117 callObjectMethod(jobject obj,jmethodID methodID,...)118 jobject callObjectMethod(jobject obj, jmethodID methodID, ...) { 119 va_list args; 120 jobject result; 121 va_start(args, methodID); 122 result = env->CallObjectMethodV(obj, methodID, args); 123 va_end(args); 124 return result; 125 } 126 callVoidMethod(jobject obj,jmethodID methodID,...)127 void callVoidMethod(jobject obj, jmethodID methodID, ...) { 128 va_list args; 129 va_start(args, methodID); 130 env->CallVoidMethodV(obj, methodID, args); 131 va_end(args); 132 } 133 callBooleanMethod(jobject obj,jmethodID methodID,...)134 jboolean callBooleanMethod(jobject obj, jmethodID methodID, ...) { 135 va_list args; 136 jboolean result; 137 va_start(args, methodID); 138 result = env->CallBooleanMethodV(obj, methodID, args); 139 va_end(args); 140 return result; 141 } 142 getStaticFieldID(jclass clazz,const char * name,const char * sig)143 jfieldID getStaticFieldID(jclass clazz, const char *name, const char *sig) { 144 return env->GetStaticFieldID(clazz, name, sig); 145 } 146 getStaticIntField(jclass clazz,jfieldID fieldID)147 jint getStaticIntField(jclass clazz, jfieldID fieldID) { 148 return env->GetStaticIntField(clazz, fieldID); 149 } 150 getStaticObjectField(jclass clazz,jfieldID fieldID)151 jobject getStaticObjectField(jclass clazz, jfieldID fieldID) { 152 return env->GetStaticObjectField(clazz, fieldID); 153 } 154 callIntMethod(jobject obj,jmethodID methodID,...)155 jint callIntMethod(jobject obj, jmethodID methodID, ...) { 156 va_list args; 157 jint result; 158 va_start(args, methodID); 159 result = env->CallIntMethodV(obj, methodID, args); 160 va_end(args); 161 return result; 162 } 163 callFloatMethod(jobject obj,jmethodID methodID,...)164 jfloat callFloatMethod(jobject obj, jmethodID methodID, ...) { 165 va_list args; 166 jint result; 167 va_start(args, methodID); 168 result = env->CallFloatMethodV(obj, methodID, args); 169 va_end(args); 170 return result; 171 } 172 check()173 bool check() { 174 if (env->ExceptionCheck()) { 175 env->ExceptionDescribe(); 176 env->ExceptionClear(); 177 return false; 178 } 179 return true; 180 } 181 makeArray(jclass clazz,jsize length,jobject initialElement)182 jobjectArray makeArray(jclass clazz, jsize length, jobject initialElement) { 183 return env->NewObjectArray(length, clazz, initialElement); 184 } 185 setArrayElement(jobjectArray array,jsize index,jobject value)186 void setArrayElement(jobjectArray array, jsize index, jobject value) { 187 env->SetObjectArrayElement(array, index, value); 188 } 189 getArrayElement(jobjectArray array,jsize index)190 jobject getArrayElement(jobjectArray array, jsize index) { 191 return env->GetObjectArrayElement(array, index); 192 } 193 getFloatArrayElement(jfloatArray array)194 jfloat* getFloatArrayElement(jfloatArray array) { 195 return env->GetFloatArrayElements(array, 0); 196 } 197 };