1 /* 2 * Copyright (c) 2025 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 #ifndef ANI_UTILS_H 17 #define ANI_UTILS_H 18 19 #include <ani.h> 20 #include <cstdarg> 21 #include <memory> 22 #include <mutex> 23 #include <optional> 24 #include <string> 25 #include <unordered_map> 26 #include <variant> 27 #include <vector> 28 #include <iostream> 29 30 class AniObjectUtils { 31 public: Create(ani_env * env,const char * nsName,const char * clsName,...)32 static ani_object Create(ani_env *env, const char *nsName, const char *clsName, ...) 33 { 34 ani_object nullobj{}; 35 36 if (env == nullptr) { 37 return nullobj; 38 } 39 40 ani_namespace ns; 41 if (ANI_OK != env->FindNamespace(nsName, &ns)) { 42 return nullobj; 43 } 44 45 ani_class cls; 46 if (ANI_OK != env->Namespace_FindClass(ns, clsName, &cls)) { 47 return nullobj; 48 } 49 50 ani_method ctor; 51 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) { 52 return nullobj; 53 } 54 55 ani_object obj; 56 va_list args; 57 va_start(args, clsName); 58 ani_status status = env->Object_New_V(cls, ctor, &obj, args); 59 va_end(args); 60 if (ANI_OK != status) { 61 return nullobj; 62 } 63 return obj; 64 } 65 Create(ani_env * env,const char * clsName,...)66 static ani_object Create(ani_env *env, const char *clsName, ...) 67 { 68 ani_object nullobj{}; 69 70 if (env == nullptr) { 71 return nullobj; 72 } 73 74 ani_class cls; 75 if (ANI_OK != env->FindClass(clsName, &cls)) { 76 return nullobj; 77 } 78 79 ani_method ctor; 80 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) { 81 return nullobj; 82 } 83 84 ani_object obj; 85 va_list args; 86 va_start(args, clsName); 87 ani_status status = env->Object_New_V(cls, ctor, &obj, args); 88 va_end(args); 89 if (ANI_OK != status) { 90 return nullobj; 91 } 92 return obj; 93 } 94 Create(ani_env * env,ani_class cls,...)95 static ani_object Create(ani_env *env, ani_class cls, ...) 96 { 97 ani_object nullobj{}; 98 99 if (env == nullptr) { 100 return nullobj; 101 } 102 103 ani_method ctor; 104 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) { 105 return nullobj; 106 } 107 108 ani_object obj; 109 va_list args; 110 va_start(args, cls); 111 ani_status status = env->Object_New_V(cls, ctor, &obj, args); 112 va_end(args); 113 if (ANI_OK != status) { 114 return nullobj; 115 } 116 return obj; 117 } 118 CallObjMethod(ani_env * env,const char * ns,const char * cls,const char * method,ani_object obj)119 static ani_status CallObjMethod(ani_env *env, const char *ns, const char *cls, const char *method, ani_object obj) 120 { 121 if (env == nullptr) { 122 return ANI_ERROR; 123 } 124 125 ani_namespace nameSpace; 126 auto status = env->FindNamespace(ns, &nameSpace); 127 if (status != ANI_OK) { 128 return status; 129 } 130 131 ani_class clazz; 132 status = env->Namespace_FindClass(nameSpace, cls, &clazz); 133 if (status != ANI_OK) { 134 return status; 135 } 136 137 ani_method objMethod; 138 status = env->Class_FindMethod(clazz, method, ":V", &objMethod); 139 if (status != ANI_OK) { 140 return status; 141 } 142 status = env->Object_CallMethod_Void(obj, objMethod); 143 return status; 144 } 145 146 template<typename T> 147 static ani_status Wrap(ani_env *env, ani_object object, T *nativePtr, const char *propName = "nativePtr") 148 { 149 return env->Object_SetFieldByName_Long(object, propName, reinterpret_cast<ani_long>(nativePtr)); 150 } 151 152 template<typename T> 153 static T* Unwrap(ani_env *env, ani_object object, const char *propName = "nativePtr") 154 { 155 ani_long nativePtr; 156 if (ANI_OK != env->Object_GetFieldByName_Long(object, propName, &nativePtr)) { 157 return nullptr; 158 } 159 return reinterpret_cast<T*>(nativePtr); 160 } 161 }; 162 163 class AniStringUtils { 164 public: ToStd(ani_env * env,ani_string ani_str)165 static std::string ToStd(ani_env *env, ani_string ani_str) 166 { 167 if (env == nullptr) { 168 return std::string(); 169 } 170 171 ani_size strSize = 0; 172 auto status = env->String_GetUTF8Size(ani_str, &strSize); 173 if (ANI_OK != status) { 174 return std::string(); 175 } 176 177 std::vector<char> buffer(strSize + 1); // +1 for null terminator 178 char *utf8Buffer = buffer.data(); 179 180 // String_GetUTF8 Supportted by https://gitee.com/openharmony/arkcompiler_runtime_core/pulls/3416 181 ani_size bytesWritten = 0; 182 status = env->String_GetUTF8(ani_str, utf8Buffer, strSize + 1, &bytesWritten); 183 if (ANI_OK != status) { 184 return std::string(); 185 } 186 187 utf8Buffer[bytesWritten] = '\0'; 188 std::string content = std::string(utf8Buffer); 189 return content; 190 } 191 ToAni(ani_env * env,const std::string & str)192 static ani_string ToAni(ani_env *env, const std::string& str) 193 { 194 if (env == nullptr) { 195 return nullptr; 196 } 197 ani_string aniStr = nullptr; 198 if (ANI_OK != env->String_NewUTF8(str.data(), str.size(), &aniStr)) { 199 return nullptr; 200 } 201 return aniStr; 202 } 203 }; 204 205 class UnionAccessor { 206 public: UnionAccessor(ani_env * env,ani_object & obj)207 UnionAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj) 208 { 209 } 210 IsInstanceOf(const std::string & cls_name)211 bool IsInstanceOf(const std::string& cls_name) 212 { 213 ani_class cls; 214 env_->FindClass(cls_name.c_str(), &cls); 215 216 ani_boolean ret; 217 env_->Object_InstanceOf(obj_, cls, &ret); 218 return ret; 219 } 220 221 template<typename T> 222 bool IsInstanceOfType(); 223 224 template<typename T> 225 bool TryConvert(T &value); 226 227 template<typename... Types> TryConvertVariant(std::variant<Types...> & value)228 bool TryConvertVariant(std::variant<Types...> &value) 229 { 230 return GetNativeValue<decltype(value), Types...>(value); 231 } 232 233 template<typename T> GetNativeValue(T & value)234 bool GetNativeValue(T &value) 235 { 236 return false; 237 } 238 239 template<typename T, typename First, typename... Types> GetNativeValue(T & value)240 bool GetNativeValue(T &value) 241 { 242 First cValue; 243 auto ret = TryConvert(cValue); 244 if (ret == true) { 245 value = cValue; 246 return ret; 247 } 248 return GetNativeValue<T, Types...>(value); 249 } 250 251 template<typename T> 252 bool TryConvertArray(std::vector<T> &value); 253 254 bool GetObjectRefPropertyByName(std::string clsName, const char *name, ani_ref &val); 255 bool GetObjectStringPropertyByName(std::string clsName, const char *name, std::string &val); 256 bool GetObjectEnumValuePropertyByName(std::string clsName, const char *name, ani_int &val, bool optional = false); 257 ani_ref AniIteratorNext(ani_ref interator, bool &isSuccess); 258 259 private: 260 ani_env *env_; 261 ani_object obj_; 262 }; 263 264 class OptionalAccessor { 265 public: OptionalAccessor(ani_env * env,ani_object & obj)266 OptionalAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj) 267 { 268 } 269 IsUndefined()270 bool IsUndefined() 271 { 272 ani_boolean isUndefined; 273 env_->Reference_IsUndefined(obj_, &isUndefined); 274 return isUndefined; 275 } 276 277 template<typename T> 278 std::optional<T> Convert(); 279 280 private: 281 ani_env *env_; 282 ani_object obj_; 283 }; 284 285 class NativeObject { 286 public: 287 virtual ~NativeObject() = default; 288 }; 289 290 ani_status CleanerInit(ani_env *env); 291 #endif 292