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 #ifndef RUNTIME_INCLUDE_TAIHE_PLATFORM_ANI_HPP_
16 #define RUNTIME_INCLUDE_TAIHE_PLATFORM_ANI_HPP_
17 // NOLINTBEGIN
18
19 #include <taihe/runtime.hpp>
20
21 #include <taihe.platform.ani.proj.hpp>
22
23 namespace taihe {
24 // convert between ani types and taihe types
25
26 template <typename cpp_owner_t>
27 struct from_ani_t;
28
29 template <typename cpp_owner_t>
30 struct into_ani_t;
31
32 template <typename cpp_owner_t>
33 constexpr inline from_ani_t<cpp_owner_t> from_ani;
34
35 template <typename cpp_owner_t>
36 constexpr inline into_ani_t<cpp_owner_t> into_ani;
37 } // namespace taihe
38
39 namespace taihe {
40 // Reference management
41
42 class sref_guard {
43 protected:
44 ani_ref ref;
45
46 public:
sref_guard(ani_env * env,ani_ref val)47 sref_guard(ani_env *env, ani_ref val)
48 {
49 env->GlobalReference_Create(val, &ref);
50 }
51
~sref_guard()52 ~sref_guard() {}
53
54 sref_guard(sref_guard const &) = delete;
55 sref_guard &operator=(sref_guard const &) = delete;
56 sref_guard(sref_guard &&) = delete;
57 sref_guard &operator=(sref_guard &&) = delete;
58
get_ref()59 ani_ref get_ref()
60 {
61 return ref;
62 }
63 };
64
65 class dref_guard : public sref_guard {
66 public:
dref_guard(ani_env * env,ani_ref val)67 dref_guard(ani_env *env, ani_ref val) : sref_guard(env, val) {}
68
~dref_guard()69 ~dref_guard()
70 {
71 env_guard guard;
72 ani_env *env = guard.get_env();
73 env->GlobalReference_Delete(ref);
74 }
75 };
76
77 template <typename AniRefGuard>
78 struct same_impl_t<AniRefGuard, std::enable_if_t<std::is_base_of_v<sref_guard, AniRefGuard>>> {
operator ()taihe::same_impl_t79 bool operator()(data_view lhs, data_view rhs) const
80 {
81 auto lhs_as_ani = ::taihe::platform::ani::weak::AniObject(lhs);
82 auto rhs_as_ani = ::taihe::platform::ani::weak::AniObject(rhs);
83 if (lhs_as_ani.is_error() || rhs_as_ani.is_error()) {
84 return false;
85 }
86 env_guard guard;
87 ani_env *env = guard.get_env();
88 ani_ref lhs_ref = reinterpret_cast<ani_ref>(lhs_as_ani->getGlobalReference());
89 ani_ref rhs_ref = reinterpret_cast<ani_ref>(rhs_as_ani->getGlobalReference());
90 ani_boolean result;
91 return env->Reference_Equals(lhs_ref, rhs_ref, &result) == ANI_OK && result;
92 }
93 };
94
95 template <typename AniRefGuard>
96 struct hash_impl_t<AniRefGuard, std::enable_if_t<std::is_base_of_v<sref_guard, AniRefGuard>>> {
operator ()taihe::hash_impl_t97 std::size_t operator()(data_view) const
98 {
99 TH_THROW(std::runtime_error, "Hashing of ani_ref is not implemented yet.");
100 }
101 };
102 } // namespace taihe
103
104 #if __cplusplus >= 202002L
105 namespace taihe {
106 template <std::size_t N = 0>
107 struct nullable_fixed_string {
108 bool is_null;
109 char value[N];
110
nullable_fixed_stringtaihe::nullable_fixed_string111 constexpr nullable_fixed_string(std::nullptr_t) : is_null {true}, value {} {}
112
nullable_fixed_stringtaihe::nullable_fixed_string113 constexpr nullable_fixed_string(char const (&sv)[N]) : is_null {false}
114 {
115 for (std::size_t i = 0; i < N; ++i) {
116 value[i] = sv[i];
117 }
118 }
119
c_strtaihe::nullable_fixed_string120 constexpr char const *c_str() const
121 {
122 return is_null ? nullptr : value;
123 }
124 };
125
126 template <nullable_fixed_string descriptor_t>
ani_find_module(ani_env * env)127 inline ani_module ani_find_module(ani_env *env)
128 {
129 static sref_guard guard(env, [env]() -> ani_module {
130 char const *descriptor = descriptor_t.c_str();
131 ani_module mod;
132 if (ANI_OK != env->FindModule(descriptor, &mod)) {
133 std::cerr << "Module not found: " << descriptor << std::endl;
134 return nullptr;
135 }
136 return mod;
137 }());
138 return static_cast<ani_module>(guard.get_ref());
139 }
140
141 template <nullable_fixed_string descriptor_t>
ani_find_namespace(ani_env * env)142 inline ani_namespace ani_find_namespace(ani_env *env)
143 {
144 static sref_guard guard(env, [env]() -> ani_namespace {
145 char const *descriptor = descriptor_t.c_str();
146 ani_namespace ns;
147 if (ANI_OK != env->FindNamespace(descriptor, &ns)) {
148 std::cerr << "Namespace not found: " << descriptor << std::endl;
149 return nullptr;
150 }
151 return ns;
152 }());
153 return static_cast<ani_namespace>(guard.get_ref());
154 }
155
156 template <nullable_fixed_string descriptor_t>
ani_find_class(ani_env * env)157 inline ani_class ani_find_class(ani_env *env)
158 {
159 static sref_guard guard(env, [env]() -> ani_class {
160 char const *descriptor = descriptor_t.c_str();
161 ani_class cls;
162 if (ANI_OK != env->FindClass(descriptor, &cls)) {
163 std::cerr << "Class not found: " << descriptor << std::endl;
164 return nullptr;
165 }
166 return cls;
167 }());
168 return static_cast<ani_class>(guard.get_ref());
169 }
170
171 template <nullable_fixed_string descriptor_t, nullable_fixed_string name_t, nullable_fixed_string signature_t>
ani_find_module_function(ani_env * env)172 inline ani_function ani_find_module_function(ani_env *env)
173 {
174 static ani_function function = [env]() -> ani_function {
175 char const *descriptor = descriptor_t.c_str();
176 char const *name = name_t.c_str();
177 char const *signature = signature_t.c_str();
178 ani_module mod = ani_find_module<descriptor_t>(env);
179 if (mod == nullptr) {
180 return nullptr;
181 }
182 ani_function fn;
183 if (ANI_OK != env->Module_FindFunction(mod, name, signature, &fn)) {
184 std::cerr << "Function not found: " << descriptor << "::" << name << " with signature: " << signature
185 << std::endl;
186 return nullptr;
187 }
188 return fn;
189 }();
190 return function;
191 }
192
193 template <nullable_fixed_string descriptor_t, nullable_fixed_string name_t, nullable_fixed_string signature_t>
ani_find_namespace_function(ani_env * env)194 inline ani_function ani_find_namespace_function(ani_env *env)
195 {
196 static ani_function function = [env]() -> ani_function {
197 char const *descriptor = descriptor_t.c_str();
198 char const *name = name_t.c_str();
199 char const *signature = signature_t.c_str();
200 ani_namespace ns = ani_find_namespace<descriptor_t>(env);
201 if (ns == nullptr) {
202 return nullptr;
203 }
204 ani_function fn;
205 if (ANI_OK != env->Namespace_FindFunction(ns, name, signature, &fn)) {
206 std::cerr << "Function not found: " << descriptor << "::" << name << " with signature: " << signature
207 << std::endl;
208 return nullptr;
209 }
210 return fn;
211 }();
212 return function;
213 }
214
215 template <nullable_fixed_string descriptor_t, nullable_fixed_string name_t, nullable_fixed_string signature_t>
ani_find_class_method(ani_env * env)216 inline ani_method ani_find_class_method(ani_env *env)
217 {
218 static ani_method method = [env]() -> ani_method {
219 char const *descriptor = descriptor_t.c_str();
220 char const *name = name_t.c_str();
221 char const *signature = signature_t.c_str();
222 ani_class cls = ani_find_class<descriptor_t>(env);
223 if (cls == nullptr) {
224 return nullptr;
225 }
226 ani_method mtd;
227 if (ANI_OK != env->Class_FindMethod(cls, name, signature, &mtd)) {
228 std::cerr << "Method not found: " << descriptor << "::" << name << " with signature: " << signature
229 << std::endl;
230 return nullptr;
231 }
232 return mtd;
233 }();
234 return method;
235 }
236
237 template <nullable_fixed_string descriptor_t, nullable_fixed_string name_t, nullable_fixed_string signature_t>
ani_find_class_static_method(ani_env * env)238 inline ani_static_method ani_find_class_static_method(ani_env *env)
239 {
240 static ani_static_method method = [env]() -> ani_static_method {
241 char const *descriptor = descriptor_t.c_str();
242 char const *name = name_t.c_str();
243 char const *signature = signature_t.c_str();
244 ani_class cls = ani_find_class<descriptor_t>(env);
245 if (cls == nullptr) {
246 return nullptr;
247 }
248 ani_static_method mtd;
249 if (ANI_OK != env->Class_FindStaticMethod(cls, name, signature, &mtd)) {
250 std::cerr << "Static method not found: " << descriptor << "::" << name << " with signature: " << signature
251 << std::endl;
252 return nullptr;
253 }
254 return mtd;
255 }();
256 return method;
257 }
258
259 template <nullable_fixed_string descriptor_t, nullable_fixed_string name_t>
ani_find_module_variable(ani_env * env)260 inline ani_variable ani_find_module_variable(ani_env *env)
261 {
262 static ani_variable variable = [env]() -> ani_variable {
263 char const *descriptor = descriptor_t.c_str();
264 char const *name = name_t.c_str();
265 ani_module mod = ani_find_module<descriptor_t>(env);
266 if (mod == nullptr) {
267 return nullptr;
268 }
269 ani_variable var;
270 if (ANI_OK != env->Module_FindVariable(mod, name, &var)) {
271 std::cerr << "Variable not found: " << descriptor << "::" << name << std::endl;
272 return nullptr;
273 }
274 return var;
275 }();
276 return variable;
277 }
278
279 template <nullable_fixed_string descriptor_t, nullable_fixed_string name_t>
ani_find_namespace_variable(ani_env * env)280 inline ani_variable ani_find_namespace_variable(ani_env *env)
281 {
282 static ani_variable variable = [env]() -> ani_variable {
283 char const *descriptor = descriptor_t.c_str();
284 char const *name = name_t.c_str();
285 ani_namespace ns = ani_find_namespace<descriptor_t>(env);
286 if (ns == nullptr) {
287 return nullptr;
288 }
289 ani_variable var;
290 if (ANI_OK != env->Namespace_FindVariable(ns, name, &var)) {
291 std::cerr << "Variable not found: " << descriptor << "::" << name << std::endl;
292 return nullptr;
293 }
294 return var;
295 }();
296 return variable;
297 }
298
299 template <nullable_fixed_string descriptor_t, nullable_fixed_string name_t>
ani_find_class_field(ani_env * env)300 inline ani_field ani_find_class_field(ani_env *env)
301 {
302 static ani_field field = [env]() -> ani_field {
303 char const *descriptor = descriptor_t.c_str();
304 char const *name = name_t.c_str();
305 ani_class cls = ani_find_class<descriptor_t>(env);
306 if (cls == nullptr) {
307 return nullptr;
308 }
309 ani_field fld;
310 if (ANI_OK != env->Class_FindField(cls, name, &fld)) {
311 std::cerr << "Field not found: " << descriptor << "::" << name << std::endl;
312 return nullptr;
313 }
314 return fld;
315 }();
316 return field;
317 }
318
319 template <nullable_fixed_string descriptor_t, nullable_fixed_string name_t>
ani_find_class_static_field(ani_env * env)320 inline ani_static_field ani_find_class_static_field(ani_env *env)
321 {
322 static ani_static_field field = [env]() -> ani_static_field {
323 char const *descriptor = descriptor_t.c_str();
324 char const *name = name_t.c_str();
325 ani_class cls = ani_find_class<descriptor_t>(env);
326 if (cls == nullptr) {
327 return nullptr;
328 }
329 ani_static_field fld;
330 if (ANI_OK != env->Class_FindStaticField(cls, name, &fld)) {
331 std::cerr << "Static field not found: " << descriptor << "::" << name << std::endl;
332 return nullptr;
333 }
334 return fld;
335 }();
336 return field;
337 }
338 } // namespace taihe
339
340 #define TH_ANI_FIND_MODULE(env, descriptor) ::taihe::ani_find_module<descriptor>(env)
341 #define TH_ANI_FIND_NAMESPACE(env, descriptor) ::taihe::ani_find_namespace<descriptor>(env)
342 #define TH_ANI_FIND_CLASS(env, descriptor) ::taihe::ani_find_class<descriptor>(env)
343
344 #define TH_ANI_FIND_MODULE_FUNCTION(env, descriptor, name, signature) \
345 ::taihe::ani_find_module_function<descriptor, name, signature>(env)
346 #define TH_ANI_FIND_NAMESPACE_FUNCTION(env, descriptor, name, signature) \
347 ::taihe::ani_find_namespace_function<descriptor, name, signature>(env)
348 #define TH_ANI_FIND_CLASS_METHOD(env, descriptor, name, signature) \
349 ::taihe::ani_find_class_method<descriptor, name, signature>(env)
350 #define TH_ANI_FIND_CLASS_STATIC_METHOD(env, descriptor, name, signature) \
351 ::taihe::ani_find_class_static_method<descriptor, name, signature>(env)
352
353 #define TH_ANI_FIND_MODULE_VARIABLE(env, descriptor, name) ::taihe::ani_find_module_variable<descriptor, name>(env)
354 #define TH_ANI_FIND_NAMESPACE_VARIABLE(env, descriptor, name) \
355 ::taihe::ani_find_namespace_variable<descriptor, name>(env)
356 #define TH_ANI_FIND_CLASS_FIELD(env, descriptor, name) ::taihe::ani_find_class_field<descriptor, name>(env)
357 #define TH_ANI_FIND_CLASS_STATIC_FIELD(env, descriptor, name) \
358 ::taihe::ani_find_class_static_field<descriptor, name>(env)
359 #else // __cplusplus >= 202002L
360 #define TH_ANI_FIND_MODULE(env, descriptor) \
361 ([env] { \
362 static ::taihe::sref_guard __guard(env, [env]() -> ani_module { \
363 ani_module __mod; \
364 if (ANI_OK != env->FindModule(descriptor, &__mod)) { \
365 std::cerr << "Module not found: " << descriptor << std::endl; \
366 return nullptr; \
367 } \
368 return __mod; \
369 }()); \
370 return static_cast<ani_module>(__guard.get_ref()); \
371 }())
372
373 #define TH_ANI_FIND_NAMESPACE(env, descriptor) \
374 ([env] { \
375 static ::taihe::sref_guard __guard(env, [env]() -> ani_namespace { \
376 ani_namespace __ns; \
377 if (ANI_OK != env->FindNamespace(descriptor, &__ns)) { \
378 std::cerr << "Namespace not found: " << descriptor << std::endl; \
379 return nullptr; \
380 } \
381 return __ns; \
382 }()); \
383 return static_cast<ani_namespace>(__guard.get_ref()); \
384 }())
385
386 #define TH_ANI_FIND_CLASS(env, descriptor) \
387 ([env] { \
388 static ::taihe::sref_guard __guard(env, [env]() -> ani_class { \
389 ani_class __cls; \
390 if (ANI_OK != env->FindClass(descriptor, &__cls)) { \
391 std::cerr << "Class not found: " << descriptor << std::endl; \
392 return nullptr; \
393 } \
394 return __cls; \
395 }()); \
396 return static_cast<ani_class>(__guard.get_ref()); \
397 }())
398
399 #define TH_ANI_FIND_MODULE_FUNCTION(env, descriptor, name, signature) \
400 ([env] { \
401 static ani_function __function = [env]() -> ani_function { \
402 ani_module __mod = TH_ANI_FIND_MODULE(env, descriptor); \
403 if (__mod == nullptr) { \
404 return nullptr; \
405 } \
406 ani_function __fn; \
407 if (ANI_OK != env->Module_FindFunction(__mod, name, signature, &__fn)) { \
408 std::cerr << "Function not found: " << descriptor << "::" << name << " with signature: " << signature \
409 << std::endl; \
410 return nullptr; \
411 } \
412 return __fn; \
413 }(); \
414 return __function; \
415 }())
416
417 #define TH_ANI_FIND_NAMESPACE_FUNCTION(env, descriptor, name, signature) \
418 ([env] { \
419 static ani_function __function = [env]() -> ani_function { \
420 ani_namespace __ns = TH_ANI_FIND_NAMESPACE(env, descriptor); \
421 if (__ns == nullptr) { \
422 return nullptr; \
423 } \
424 ani_function __fn; \
425 if (ANI_OK != env->Namespace_FindFunction(__ns, name, signature, &__fn)) { \
426 std::cerr << "Function not found: " << descriptor << "::" << name << " with signature: " << signature \
427 << std::endl; \
428 return nullptr; \
429 } \
430 return __fn; \
431 }(); \
432 return __function; \
433 }())
434
435 #define TH_ANI_FIND_CLASS_METHOD(env, descriptor, name, signature) \
436 ([env] { \
437 static ani_method __method = [env]() -> ani_method { \
438 ani_class __cls = TH_ANI_FIND_CLASS(env, descriptor); \
439 if (__cls == nullptr) { \
440 return nullptr; \
441 } \
442 ani_method __mtd; \
443 if (ANI_OK != env->Class_FindMethod(__cls, name, signature, &__mtd)) { \
444 std::cerr << "Method not found: " << descriptor << "::" << name << " with signature: " << signature \
445 << std::endl; \
446 return nullptr; \
447 } \
448 return __mtd; \
449 }(); \
450 return __method; \
451 }())
452
453 #define TH_ANI_FIND_CLASS_STATIC_METHOD(env, descriptor, name, signature) \
454 ([env] { \
455 static ani_static_method __method = [env]() -> ani_static_method { \
456 ani_class __cls = TH_ANI_FIND_CLASS(env, descriptor); \
457 if (__cls == nullptr) { \
458 return nullptr; \
459 } \
460 ani_static_method __mtd; \
461 if (ANI_OK != env->Class_FindStaticMethod(__cls, name, signature, &__mtd)) { \
462 std::cerr << "Static method not found: " << descriptor << "::" << name \
463 << " with signature: " << signature << std::endl; \
464 return nullptr; \
465 } \
466 return __mtd; \
467 }(); \
468 return __method; \
469 }())
470
471 #define TH_ANI_FIND_MODULE_VARIABLE(env, descriptor, name) \
472 ([env] { \
473 static ani_variable __variable = [env]() -> ani_variable { \
474 ani_module __mod = TH_ANI_FIND_MODULE(env, descriptor); \
475 if (__mod == nullptr) { \
476 return nullptr; \
477 } \
478 ani_variable __var; \
479 if (ANI_OK != env->Module_FindVariable(__mod, name, &__var)) { \
480 std::cerr << "Variable not found: " << descriptor << "::" << name << std::endl; \
481 return nullptr; \
482 } \
483 return __var; \
484 }(); \
485 return __variable; \
486 }())
487
488 #define TH_ANI_FIND_NAMESPACE_VARIABLE(env, descriptor, name) \
489 ([env] { \
490 static ani_variable __variable = [env]() -> ani_variable { \
491 ani_namespace __ns = TH_ANI_FIND_NAMESPACE(env, descriptor); \
492 if (__ns == nullptr) { \
493 return nullptr; \
494 } \
495 ani_variable __var; \
496 if (ANI_OK != env->Namespace_FindVariable(__ns, name, &__var)) { \
497 std::cerr << "Variable not found: " << descriptor << "::" << name << std::endl; \
498 return nullptr; \
499 } \
500 return __var; \
501 }(); \
502 return __variable; \
503 }())
504
505 #define TH_ANI_FIND_CLASS_FIELD(env, descriptor, name) \
506 ([env] { \
507 static ani_field __field = [env]() -> ani_field { \
508 ani_class __cls = TH_ANI_FIND_CLASS(env, descriptor); \
509 if (__cls == nullptr) { \
510 return nullptr; \
511 } \
512 ani_field __fld; \
513 if (ANI_OK != env->Class_FindField(__cls, name, &__fld)) { \
514 std::cerr << "Field not found: " << descriptor << "::" << name << std::endl; \
515 return nullptr; \
516 } \
517 return __fld; \
518 }(); \
519 return __field; \
520 }())
521
522 #define TH_ANI_FIND_CLASS_STATIC_FIELD(env, descriptor, name) \
523 ([env] { \
524 static ani_static_field __field = [env]() -> ani_static_field { \
525 ani_class __cls = TH_ANI_FIND_CLASS(env, descriptor); \
526 if (__cls == nullptr) { \
527 return nullptr; \
528 } \
529 ani_static_field __fld; \
530 if (ANI_OK != env->Class_FindStaticField(__cls, name, &__fld)) { \
531 std::cerr << "Static field not found: " << descriptor << "::" << name << std::endl; \
532 return nullptr; \
533 } \
534 return __fld; \
535 }(); \
536 return __field; \
537 }())
538 #endif // __cplusplus >= 202002L
539 // NOLINTEND
540 #endif // RUNTIME_INCLUDE_TAIHE_PLATFORM_ANI_HPP_