• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_