• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 CONVERTORS_ETS_H
17 #define CONVERTORS_ETS_H
18 
19 #ifdef KOALA_ETS_NAPI
20 
21 #include <memory>
22 #include <vector>
23 #include <string>
24 #include <cmath>
25 #include <tuple>
26 #include <unordered_map>
27 
28 #include "etsapi.h"
29 #include "koala-types.h"
30 
31 template<class T>
32 struct InteropTypeConverter {
33     using InteropType = T;
convertFromInteropTypeConverter34     static T convertFrom(EtsEnv* env, InteropType value) { return value; }
convertToInteropTypeConverter35     static InteropType convertTo(EtsEnv* env, T value) { return value; }
releaseInteropTypeConverter36     static void release(EtsEnv* env, InteropType value, T converted) {}
37 };
38 
39 template<>
40 struct InteropTypeConverter<KStringPtr> {
41     using InteropType = ets_string;
42     static KStringPtr convertFrom(EtsEnv* env, InteropType value) {
43         if (value == nullptr) return KStringPtr();
44         KStringPtr result;
45         // Notice that we use UTF length for buffer size, but counter is expressed in number of Unicode chars.
46         result.resize(env->GetStringUTFLength(value));
47         env->GetStringUTFRegion(value, 0, env->GetStringLength(value), result.data());
48         return result;
49     }
50     static InteropType convertTo(EtsEnv* env, const KStringPtr& value) {
51       return env->NewStringUTF(value.c_str());
52     }
53     static void release(EtsEnv* env, InteropType value, const KStringPtr& converted) {}
54 };
55 
56 template<>
57 struct InteropTypeConverter<KNativePointer> {
58     using InteropType = ets_long;
59     static KNativePointer convertFrom(EtsEnv* env, InteropType value) {
60       return reinterpret_cast<KNativePointer>(value);
61     }
62     static InteropType convertTo(EtsEnv* env, KNativePointer value) {
63       return reinterpret_cast<ets_long>(value);
64     }
65     static void release(EtsEnv* env, InteropType value, KNativePointer converted) {}
66 };
67 
68 template<>
69 struct InteropTypeConverter<KInt*> {
70     using InteropType = ets_intArray;
71     static KInt* convertFrom(EtsEnv* env, InteropType value) {
72      if (!value) return nullptr;
73       return env->PinIntArray(value);
74     }
75     static InteropType convertTo(EtsEnv* env, KInt* value) = delete;
76     static void release(EtsEnv* env, InteropType value, KInt* converted) {
77       if (value) env->UnpinIntArray(value);
78     }
79 };
80 
81 template<>
82 struct InteropTypeConverter<KFloat*> {
83     using InteropType = ets_floatArray;
84     static KFloat* convertFrom(EtsEnv* env, InteropType value) {
85       if (!value) return nullptr;
86       return env->PinFloatArray(value);
87     }
88     static InteropType convertTo(EtsEnv* env, KFloat* value) = delete;
89     static void release(EtsEnv* env, InteropType value, KFloat* converted) {
90       if (value) env->UnpinFloatArray(value);
91     }
92 };
93 
94 template<>
95 struct InteropTypeConverter<KByte*> {
96     using InteropType = ets_byteArray;
97     static KByte* convertFrom(EtsEnv* env, InteropType value) {
98      if (!value) return nullptr;
99       return (KByte*)env->PinByteArray(value);
100     }
101     static InteropType convertTo(EtsEnv* env, KByte* value) = delete;
102     static void release(EtsEnv* env, InteropType value, KByte* converted) {
103       if (value) env->UnpinByteArray((ets_byteArray)value);
104     }
105 };
106 
107 template <> struct InteropTypeConverter<KInteropNumber> {
108   using InteropType = ets_double;
109   static KInteropNumber convertFrom(EtsEnv *env, InteropType value) {
110     return KInteropNumber::fromDouble(value);
111   }
112   static InteropType convertTo(EtsEnv *env, KInteropNumber value) {
113     return value.asDouble();
114   }
115   static void release(EtsEnv *env, InteropType value,
116                       KInteropNumber converted) {}
117 };
118 
119 template<>
120 struct InteropTypeConverter<KLength> {
121   using InteropType = ets_object;
122   static KLength convertFrom(EtsEnv* env, InteropType value) {
123     const static ets_class double_class = reinterpret_cast<ets_class>(env->NewGlobalRef(env->FindClass("std/core/Double")));
124     const static ets_class int_class = reinterpret_cast<ets_class>(env->NewGlobalRef(env->FindClass("std/core/Int")));
125     const static ets_class string_class = reinterpret_cast<ets_class>(env->NewGlobalRef(env->FindClass("std/core/String")));
126     const static ets_class resource_class = reinterpret_cast<ets_class>(
127       env->NewGlobalRef(env->FindClass("@koalaui/arkts-arkui/generated/ArkResourceInterfaces/Resource")));
128 
129     if (env->IsInstanceOf(value, double_class)) {
130       const static ets_method double_p = env->Getp_method(double_class, "unboxed", ":D");
131       return KLength{ 1, (KFloat)env->CallDoubleMethod(value, double_p), 1, 0 };
132     } else if (env->IsInstanceOf(value, int_class)) {
133       const static ets_method int_p = env->Getp_method(int_class, "unboxed", ":I");
134       return KLength{ 1, (KFloat)env->CallIntMethod(value, int_p), 1, 0 };
135     } else if (env->IsInstanceOf(value, string_class)) {
136       KStringPtr ptr = InteropTypeConverter<KStringPtr>::convertFrom(env, reinterpret_cast<ets_string>(value));
137       KLength length = { 0 };
138       parseKLength(ptr, &length);
139       length.type = 2;
140       length.resource = 0;
141       return length;
142     } else if (env->IsInstanceOf(value, resource_class)) {
143       const static ets_method resource_p = env->Getp_method(resource_class, "<get>id", ":D");
144       return KLength{ 3, 0, 1, (KInt)env->CallDoubleMethod(value, resource_p) };
145     } else {
146       return KLength( { 0, 0, 0, 0});
147     }
148   }
149   static InteropType convertTo(EtsEnv* env, KLength value) = delete;
150   static void release(EtsEnv* env, InteropType value, const KLength& converted) {}
151 };
152 
153 template <typename Type>
154 inline typename InteropTypeConverter<Type>::InteropType makeResult(EtsEnv* env, Type value) {
155   return InteropTypeConverter<Type>::convertTo(env, value);
156 }
157 
158 template <typename Type>
159 inline Type getArgument(EtsEnv* env, typename InteropTypeConverter<Type>::InteropType arg) {
160   return InteropTypeConverter<Type>::convertFrom(env, arg);
161 }
162 
163 template <typename Type>
164 inline void releaseArgument(EtsEnv* env, typename InteropTypeConverter<Type>::InteropType arg, Type& data) {
165   InteropTypeConverter<Type>::release(env, arg, data);
166 }
167 
168 #define ETS_SLOW_NATIVE_FLAG 1
169 
170 class EtsExports {
171     std::unordered_map<std::string,
172         std::vector<std::tuple<std::string, std::string, void*, int>>> implementations;
173     std::unordered_map<std::string, std::string> classpaths;
174 
175 public:
176     static EtsExports* getInstance();
177 
178     std::vector<std::string> getModules();
179     void addMethod(const char* module, const char* name, const char* type, void* impl, int flags);
180     const std::vector<std::tuple<std::string, std::string, void*, int>>& getMethods(const std::string& module);
181 
182     void setClasspath(const char* module, const char* classpath);
183     const std::string& getClasspath(const std::string& module);
184 };
185 
186 #define KOALA_QUOTE0(x) #x
187 #define KOALA_QUOTE(x) KOALA_QUOTE0(x)
188 
189 #ifdef _MSC_VER
190 #define MAKE_ETS_EXPORT(module, name, type, flag)                             \
191     static void __init_##name() {                               \
192         EtsExports::getInstance()->addMethod(KOALA_QUOTE(module), "_"#name, type, reinterpret_cast<void *>(Ark_##name), flag); \
193     }                                                           \
194     namespace {                                                 \
195       struct __Init_##name {                                    \
196         __Init_##name() {  __init_##name(); }                   \
197       } __Init_##name##_v;                                      \
198     }
199 #define KOALA_ETS_INTEROP_MODULE_CLASSPATH(module, classpath)                                 \
200     static void __init_classpath_##module() {                                                 \
201         EtsExports::getInstance()->setClasspath(KOALA_QUOTE(module), classpath); \
202     }                                                                                         \
203     namespace {                                                                               \
204       struct __Init_classpath_##module {                                                      \
205         __Init_classpath_##module() {  __init_classpath_##module(); }                         \
206       } __Init_classpath_##module##_v;                                                        \
207     }
208 #else
209 #define MAKE_ETS_EXPORT(module, name, type, flag) \
210     __attribute__((constructor)) \
211     static void __init_ets_##name() { \
212         EtsExports::getInstance()->addMethod(KOALA_QUOTE(module), "_"#name, type, reinterpret_cast<void *>(Ark_##name), flag); \
213     }
214 #define KOALA_ETS_INTEROP_MODULE_CLASSPATH(module, classpath)                                 \
215     __attribute__((constructor))                                                              \
216     static void __init_ets_classpath_##module() {                                             \
217         EtsExports::getInstance()->setClasspath(KOALA_QUOTE(module), classpath); \
218     }
219 #endif
220 
221 #define KOALA_INTEROP_0(name, Ret) \
222   InteropTypeConverter<Ret>::InteropType Ark_##name(EtsEnv *env, ets_class clazz) { \
223       KOALA_MAYBE_LOG(name)                       \
224       return makeResult<Ret>(env, impl_##name()); \
225   } \
226 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, #Ret, 0)
227 
228 #define KOALA_INTEROP_1(name, Ret, P0) \
229   InteropTypeConverter<Ret>::InteropType Ark_##name(EtsEnv *env, ets_class clazz, \
230    InteropTypeConverter<P0>::InteropType _p0) { \
231       KOALA_MAYBE_LOG(name)                   \
232       P0 p0 = getArgument<P0>(env, _p0); \
233       auto rv = makeResult<Ret>(env, impl_##name(p0)); \
234       releaseArgument(env, _p0, p0); \
235       return rv; \
236   } \
237 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, #Ret "|" #P0, 0)
238 
239 #define KOALA_INTEROP_2(name, Ret, P0, P1) \
240   InteropTypeConverter<Ret>::InteropType Ark_##name(EtsEnv *env, ets_class clazz, \
241     InteropTypeConverter<P0>::InteropType _p0, \
242     InteropTypeConverter<P1>::InteropType _p1) { \
243       KOALA_MAYBE_LOG(name)                   \
244       P0 p0 = getArgument<P0>(env, _p0); \
245       P1 p1 = getArgument<P1>(env, _p1); \
246       auto rv = makeResult<Ret>(env, impl_##name(p0, p1)); \
247       releaseArgument(env, _p0, p0); \
248       releaseArgument(env, _p1, p1); \
249       return rv; \
250   } \
251 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, #Ret "|" #P0 "|" #P1, 0)
252 
253 #define KOALA_INTEROP_3(name, Ret, P0, P1, P2) \
254   InteropTypeConverter<Ret>::InteropType Ark_##name(EtsEnv *env, ets_class clazz, \
255     InteropTypeConverter<P0>::InteropType _p0, \
256     InteropTypeConverter<P1>::InteropType _p1, \
257     InteropTypeConverter<P2>::InteropType _p2) { \
258       KOALA_MAYBE_LOG(name)                   \
259       P0 p0 = getArgument<P0>(env, _p0); \
260       P1 p1 = getArgument<P1>(env, _p1); \
261       P2 p2 = getArgument<P2>(env, _p2); \
262       auto rv = makeResult<Ret>(env, impl_##name(p0, p1, p2)); \
263       releaseArgument(env, _p0, p0); \
264       releaseArgument(env, _p1, p1); \
265       releaseArgument(env, _p2, p2); \
266       return rv; \
267   } \
268 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, #Ret "|" #P0 "|" #P1 "|" #P2, 0)
269 
270 #define KOALA_INTEROP_4(name, Ret, P0, P1, P2, P3) \
271   InteropTypeConverter<Ret>::InteropType Ark_##name(EtsEnv *env, ets_class clazz, \
272     InteropTypeConverter<P0>::InteropType _p0, \
273     InteropTypeConverter<P1>::InteropType _p1, \
274     InteropTypeConverter<P2>::InteropType _p2, \
275     InteropTypeConverter<P3>::InteropType _p3) { \
276       KOALA_MAYBE_LOG(name)                   \
277       P0 p0 = getArgument<P0>(env, _p0); \
278       P1 p1 = getArgument<P1>(env, _p1); \
279       P2 p2 = getArgument<P2>(env, _p2); \
280       P3 p3 = getArgument<P3>(env, _p3); \
281       auto rv = makeResult<Ret>(env, impl_##name(p0, p1, p2, p3)); \
282       releaseArgument(env, _p0, p0); \
283       releaseArgument(env, _p1, p1); \
284       releaseArgument(env, _p2, p2); \
285       releaseArgument(env, _p3, p3); \
286       return rv; \
287   } \
288 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, #Ret "|" #P0 "|" #P1 "|" #P2 "|" #P3, 0)
289 
290 #define KOALA_INTEROP_5(name, Ret, P0, P1, P2, P3, P4) \
291   InteropTypeConverter<Ret>::InteropType Ark_##name(EtsEnv *env, ets_class clazz, \
292     InteropTypeConverter<P0>::InteropType _p0, \
293     InteropTypeConverter<P1>::InteropType _p1, \
294     InteropTypeConverter<P2>::InteropType _p2, \
295     InteropTypeConverter<P3>::InteropType _p3, \
296     InteropTypeConverter<P4>::InteropType _p4) { \
297       KOALA_MAYBE_LOG(name) \
298       P0 p0 = getArgument<P0>(env, _p0); \
299       P1 p1 = getArgument<P1>(env, _p1); \
300       P2 p2 = getArgument<P2>(env, _p2); \
301       P3 p3 = getArgument<P3>(env, _p3); \
302       P4 p4 = getArgument<P4>(env, _p4); \
303       auto rv = makeResult<Ret>(env, impl_##name(p0, p1, p2, p3, p4)); \
304       releaseArgument(env, _p0, p0); \
305       releaseArgument(env, _p1, p1); \
306       releaseArgument(env, _p2, p2); \
307       releaseArgument(env, _p3, p3); \
308       releaseArgument(env, _p4, p4); \
309       return rv; \
310   } \
311 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, #Ret "|" #P0 "|" #P1 "|" #P2 "|" #P3 "|" #P4, 0)
312 
313 #define KOALA_INTEROP_6(name, Ret, P0, P1, P2, P3, P4, P5) \
314 InteropTypeConverter<Ret>::InteropType Ark_##name(EtsEnv *env, ets_class clazz, \
315   InteropTypeConverter<P0>::InteropType _p0, \
316   InteropTypeConverter<P1>::InteropType _p1, \
317   InteropTypeConverter<P2>::InteropType _p2, \
318   InteropTypeConverter<P3>::InteropType _p3, \
319   InteropTypeConverter<P4>::InteropType _p4, \
320   InteropTypeConverter<P5>::InteropType _p5) { \
321       KOALA_MAYBE_LOG(name) \
322       P0 p0 = getArgument<P0>(env, _p0); \
323       P1 p1 = getArgument<P1>(env, _p1); \
324       P2 p2 = getArgument<P2>(env, _p2); \
325       P3 p3 = getArgument<P3>(env, _p3); \
326       P4 p4 = getArgument<P4>(env, _p4); \
327       P5 p5 = getArgument<P5>(env, _p5); \
328       auto rv = makeResult<Ret>(env, impl_##name(p0, p1, p2, p3, p4, p5)); \
329       releaseArgument(env, _p0, p0); \
330       releaseArgument(env, _p1, p1); \
331       releaseArgument(env, _p2, p2); \
332       releaseArgument(env, _p3, p3); \
333       releaseArgument(env, _p4, p4); \
334       releaseArgument(env, _p5, p5); \
335       return rv; \
336   } \
337 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, #Ret "|" #P0 "|" #P1 "|" #P2 "|" #P3 "|" #P4 "|" #P5, 0)
338 
339 #define KOALA_INTEROP_7(name, Ret, P0, P1, P2, P3, P4, P5, P6) \
340   InteropTypeConverter<Ret>::InteropType Ark_##name(EtsEnv *env, ets_class clazz, \
341     InteropTypeConverter<P0>::InteropType _p0, \
342     InteropTypeConverter<P1>::InteropType _p1, \
343     InteropTypeConverter<P2>::InteropType _p2, \
344     InteropTypeConverter<P3>::InteropType _p3, \
345     InteropTypeConverter<P4>::InteropType _p4, \
346     InteropTypeConverter<P5>::InteropType _p5, \
347     InteropTypeConverter<P6>::InteropType _p6) { \
348       KOALA_MAYBE_LOG(name) \
349       P0 p0 = getArgument<P0>(env, _p0); \
350       P1 p1 = getArgument<P1>(env, _p1); \
351       P2 p2 = getArgument<P2>(env, _p2); \
352       P3 p3 = getArgument<P3>(env, _p3); \
353       P4 p4 = getArgument<P4>(env, _p4); \
354       P5 p5 = getArgument<P5>(env, _p5); \
355       P6 p6 = getArgument<P6>(env, _p6); \
356       auto rv = makeResult<Ret>(env, impl_##name(p0, p1, p2, p3, p4, p5, p6)); \
357       releaseArgument(env, _p0, p0); \
358       releaseArgument(env, _p1, p1); \
359       releaseArgument(env, _p2, p2); \
360       releaseArgument(env, _p3, p3); \
361       releaseArgument(env, _p4, p4); \
362       releaseArgument(env, _p5, p5); \
363       releaseArgument(env, _p6, p6); \
364       return rv; \
365   } \
366 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, #Ret "|" #P0 "|" #P1 "|" #P2 "|" #P3 "|" #P4 "|" #P5 "|" #P6, 0)
367 
368 #define KOALA_INTEROP_8(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7) \
369   InteropTypeConverter<Ret>::InteropType Ark_##name(EtsEnv *env, \
370     InteropTypeConverter<P0>::InteropType _p0, \
371     InteropTypeConverter<P1>::InteropType _p1, \
372     InteropTypeConverter<P2>::InteropType _p2, \
373     InteropTypeConverter<P3>::InteropType _p3, \
374     InteropTypeConverter<P4>::InteropType _p4, \
375     InteropTypeConverter<P5>::InteropType _p5, \
376     InteropTypeConverter<P6>::InteropType _p6, \
377     InteropTypeConverter<P7>::InteropType _p7) { \
378       KOALA_MAYBE_LOG(name) \
379       P0 p0 = getArgument<P0>(env, _p0); \
380       P1 p1 = getArgument<P1>(env, _p1); \
381       P2 p2 = getArgument<P2>(env, _p2); \
382       P3 p3 = getArgument<P3>(env, _p3); \
383       P4 p4 = getArgument<P4>(env, _p4); \
384       P5 p5 = getArgument<P5>(env, _p5); \
385       P6 p6 = getArgument<P6>(env, _p6); \
386       P7 p7 = getArgument<P7>(env, _p7); \
387       auto rv = makeResult<Ret>(env, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7)); \
388       releaseArgument(env, _p0, p0); \
389       releaseArgument(env, _p1, p1); \
390       releaseArgument(env, _p2, p2); \
391       releaseArgument(env, _p3, p3); \
392       releaseArgument(env, _p4, p4); \
393       releaseArgument(env, _p5, p5); \
394       releaseArgument(env, _p6, p6); \
395       releaseArgument(env, _p7, p7); \
396       return rv; \
397   } \
398 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, #Ret "|" #P0 "|" #P1 "|" #P2 "|" #P3 "|" #P4 "|" #P5 "|" #P6 "|" #P7, 0)
399 
400 #define KOALA_INTEROP_9(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8) \
401   InteropTypeConverter<Ret>::InteropType Ark_##name(EtsEnv *env, ets_class clazz, \
402     InteropTypeConverter<P0>::InteropType _p0, \
403     InteropTypeConverter<P1>::InteropType _p1, \
404     InteropTypeConverter<P2>::InteropType _p2, \
405     InteropTypeConverter<P3>::InteropType _p3, \
406     InteropTypeConverter<P4>::InteropType _p4, \
407     InteropTypeConverter<P5>::InteropType _p5, \
408     InteropTypeConverter<P6>::InteropType _p6, \
409     InteropTypeConverter<P7>::InteropType _p7, \
410     InteropTypeConverter<P8>::InteropType _p8) { \
411       KOALA_MAYBE_LOG(name) \
412       P0 p0 = getArgument<P0>(env, _p0); \
413       P1 p1 = getArgument<P1>(env, _p1); \
414       P2 p2 = getArgument<P2>(env, _p2); \
415       P3 p3 = getArgument<P3>(env, _p3); \
416       P4 p4 = getArgument<P4>(env, _p4); \
417       P5 p5 = getArgument<P5>(env, _p5); \
418       P6 p6 = getArgument<P6>(env, _p6); \
419       P7 p7 = getArgument<P7>(env, _p7); \
420       P8 p8 = getArgument<P8>(env, _p8); \
421       auto rv = makeResult<Ret>(env, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8)); \
422       releaseArgument(env, _p0, p0); \
423       releaseArgument(env, _p1, p1); \
424       releaseArgument(env, _p2, p2); \
425       releaseArgument(env, _p3, p3); \
426       releaseArgument(env, _p4, p4); \
427       releaseArgument(env, _p5, p5); \
428       releaseArgument(env, _p6, p6); \
429       releaseArgument(env, _p7, p7); \
430       releaseArgument(env, _p8, p8); \
431       return rv; \
432   } \
433   MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, #Ret "|" #P0 "|" #P1 "|" #P2 "|" #P3 "|" #P4 "|" #P5 "|" #P6 "|" #P7 "|" #P8, 0)
434 
435 #define KOALA_INTEROP_10(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9) \
436   InteropTypeConverter<Ret>::InteropType Ark_##name(EtsEnv *env, ets_class clazz, \
437     InteropTypeConverter<P0>::InteropType _p0, \
438     InteropTypeConverter<P1>::InteropType _p1, \
439     InteropTypeConverter<P2>::InteropType _p2, \
440     InteropTypeConverter<P3>::InteropType _p3, \
441     InteropTypeConverter<P4>::InteropType _p4, \
442     InteropTypeConverter<P5>::InteropType _p5, \
443     InteropTypeConverter<P6>::InteropType _p6, \
444     InteropTypeConverter<P7>::InteropType _p7, \
445     InteropTypeConverter<P8>::InteropType _p8, \
446     InteropTypeConverter<P9>::InteropType _p9) { \
447       KOALA_MAYBE_LOG(name) \
448       P0 p0 = getArgument<P0>(env, _p0); \
449       P1 p1 = getArgument<P1>(env, _p1); \
450       P2 p2 = getArgument<P2>(env, _p2); \
451       P3 p3 = getArgument<P3>(env, _p3); \
452       P4 p4 = getArgument<P4>(env, _p4); \
453       P5 p5 = getArgument<P5>(env, _p5); \
454       P6 p6 = getArgument<P6>(env, _p6); \
455       P7 p7 = getArgument<P7>(env, _p7); \
456       P8 p8 = getArgument<P8>(env, _p8); \
457       P9 p9 = getArgument<P9>(env, _p9); \
458       auto rv = makeResult<Ret>(env, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)); \
459       releaseArgument(env, _p0, p0); \
460       releaseArgument(env, _p1, p1); \
461       releaseArgument(env, _p2, p2); \
462       releaseArgument(env, _p3, p3); \
463       releaseArgument(env, _p4, p4); \
464       releaseArgument(env, _p5, p5); \
465       releaseArgument(env, _p6, p6); \
466       releaseArgument(env, _p7, p7); \
467       releaseArgument(env, _p8, p8); \
468       releaseArgument(env, _p9, p9); \
469       return rv; \
470    } \
471 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, #Ret "|" #P0 "|" #P1 "|" #P2 "|" #P3 "|" #P4 "|" #P5 "|" #P6 "|" #P7 "|" #P8 "|" #P9, 0)
472 
473 #define KOALA_INTEROP_11(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) \
474   InteropTypeConverter<Ret>::InteropType Ark_##name(EtsEnv *env, ets_class clazz, \
475     InteropTypeConverter<P0>::InteropType _p0, \
476     InteropTypeConverter<P1>::InteropType _p1, \
477     InteropTypeConverter<P2>::InteropType _p2, \
478     InteropTypeConverter<P3>::InteropType _p3, \
479     InteropTypeConverter<P4>::InteropType _p4, \
480     InteropTypeConverter<P5>::InteropType _p5, \
481     InteropTypeConverter<P6>::InteropType _p6, \
482     InteropTypeConverter<P7>::InteropType _p7, \
483     InteropTypeConverter<P8>::InteropType _p8, \
484     InteropTypeConverter<P9>::InteropType _p9, \
485     InteropTypeConverter<P10>::InteropType _p10) { \
486       KOALA_MAYBE_LOG(name) \
487       P0 p0 = getArgument<P0>(env, _p0); \
488       P1 p1 = getArgument<P1>(env, _p1); \
489       P2 p2 = getArgument<P2>(env, _p2); \
490       P3 p3 = getArgument<P3>(env, _p3); \
491       P4 p4 = getArgument<P4>(env, _p4); \
492       P5 p5 = getArgument<P5>(env, _p5); \
493       P6 p6 = getArgument<P6>(env, _p6); \
494       P7 p7 = getArgument<P7>(env, _p7); \
495       P8 p8 = getArgument<P8>(env, _p8); \
496       P9 p9 = getArgument<P9>(env, _p9); \
497       P10 p10 = getArgument<P10>(env, _p10); \
498       auto rv = makeResult<Ret>(env, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)); \
499       releaseArgument(env, _p0, p0); \
500       releaseArgument(env, _p1, p1); \
501       releaseArgument(env, _p2, p2); \
502       releaseArgument(env, _p3, p3); \
503       releaseArgument(env, _p4, p4); \
504       releaseArgument(env, _p5, p5); \
505       releaseArgument(env, _p6, p6); \
506       releaseArgument(env, _p7, p7); \
507       releaseArgument(env, _p8, p8); \
508       releaseArgument(env, _p9, p9); \
509       releaseArgument(env, _p10, p10); \
510       return rv; \
511   } \
512 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, #Ret "|" #P0 "|" #P1 "|" #P2 "|" #P3 "|" #P4 "|" #P5 "|" #P6 "|" #P7 "|" #P8 "|" #P9 "|" #P10, 0)
513 
514 #define KOALA_INTEROP_12(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11) \
515   InteropTypeConverter<Ret>::InteropType Ark_##name(EtsEnv *env, ets_class clazz, \
516     InteropTypeConverter<P0>::InteropType _p0, \
517     InteropTypeConverter<P1>::InteropType _p1, \
518     InteropTypeConverter<P2>::InteropType _p2, \
519     InteropTypeConverter<P3>::InteropType _p3, \
520     InteropTypeConverter<P4>::InteropType _p4, \
521     InteropTypeConverter<P5>::InteropType _p5, \
522     InteropTypeConverter<P6>::InteropType _p6, \
523     InteropTypeConverter<P7>::InteropType _p7, \
524     InteropTypeConverter<P8>::InteropType _p8, \
525     InteropTypeConverter<P9>::InteropType _p9, \
526     InteropTypeConverter<P10>::InteropType _p10, \
527     InteropTypeConverter<P11>::InteropType _p11) { \
528       KOALA_MAYBE_LOG(name) \
529       P0 p0 = getArgument<P0>(env, _p0); \
530       P1 p1 = getArgument<P1>(env, _p1); \
531       P2 p2 = getArgument<P2>(env, _p2); \
532       P3 p3 = getArgument<P3>(env, _p3); \
533       P4 p4 = getArgument<P4>(env, _p4); \
534       P5 p5 = getArgument<P5>(env, _p5); \
535       P6 p6 = getArgument<P6>(env, _p6); \
536       P7 p7 = getArgument<P7>(env, _p7); \
537       P8 p8 = getArgument<P8>(env, _p8); \
538       P9 p9 = getArgument<P9>(env, _p9); \
539       P10 p10 = getArgument<P10>(env, _p10); \
540       P11 p11 = getArgument<P11>(env, _p11); \
541       auto rv = makeResult<Ret>(env, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)); \
542       releaseArgument(env, _p0, p0); \
543       releaseArgument(env, _p1, p1); \
544       releaseArgument(env, _p2, p2); \
545       releaseArgument(env, _p3, p3); \
546       releaseArgument(env, _p4, p4); \
547       releaseArgument(env, _p5, p5); \
548       releaseArgument(env, _p6, p6); \
549       releaseArgument(env, _p7, p7); \
550       releaseArgument(env, _p8, p8); \
551       releaseArgument(env, _p9, p9); \
552       releaseArgument(env, _p10, p10); \
553       releaseArgument(env, _p11, p11); \
554       return rv; \
555   } \
556 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, #Ret "|" #P0 "|" #P1 "|" #P2 "|" #P3 "|" #P4 "|" #P5 "|" #P6 "|" #P7 "|" #P8 "|" #P9 "|" #P10 "|" #P11, 0)
557 
558 #define KOALA_INTEROP_13(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) \
559   InteropTypeConverter<Ret>::InteropType Ark_##name(EtsEnv *env, ets_class clazz, \
560     InteropTypeConverter<P0>::InteropType _p0, \
561     InteropTypeConverter<P1>::InteropType _p1, \
562     InteropTypeConverter<P2>::InteropType _p2, \
563     InteropTypeConverter<P3>::InteropType _p3, \
564     InteropTypeConverter<P4>::InteropType _p4, \
565     InteropTypeConverter<P5>::InteropType _p5, \
566     InteropTypeConverter<P6>::InteropType _p6, \
567     InteropTypeConverter<P7>::InteropType _p7, \
568     InteropTypeConverter<P8>::InteropType _p8, \
569     InteropTypeConverter<P9>::InteropType _p9, \
570     InteropTypeConverter<P10>::InteropType _p10, \
571     InteropTypeConverter<P11>::InteropType _p11, \
572     InteropTypeConverter<P12>::InteropType _p12) { \
573       KOALA_MAYBE_LOG(name) \
574       P0 p0 = getArgument<P0>(env, _p0); \
575       P1 p1 = getArgument<P1>(env, _p1); \
576       P2 p2 = getArgument<P2>(env, _p2); \
577       P3 p3 = getArgument<P3>(env, _p3); \
578       P4 p4 = getArgument<P4>(env, _p4); \
579       P5 p5 = getArgument<P5>(env, _p5); \
580       P6 p6 = getArgument<P6>(env, _p6); \
581       P7 p7 = getArgument<P7>(env, _p7); \
582       P8 p8 = getArgument<P8>(env, _p8); \
583       P9 p9 = getArgument<P9>(env, _p9); \
584       P10 p10 = getArgument<P10>(env, _p10); \
585       P11 p11 = getArgument<P11>(env, _p11); \
586       P12 p12 = getArgument<P12>(env, _p12); \
587       auto rv = makeResult<Ret>(env, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)); \
588       releaseArgument(env, _p0, p0); \
589       releaseArgument(env, _p1, p1); \
590       releaseArgument(env, _p2, p2); \
591       releaseArgument(env, _p3, p3); \
592       releaseArgument(env, _p4, p4); \
593       releaseArgument(env, _p5, p5); \
594       releaseArgument(env, _p6, p6); \
595       releaseArgument(env, _p7, p7); \
596       releaseArgument(env, _p8, p8); \
597       releaseArgument(env, _p9, p9); \
598       releaseArgument(env, _p10, p10); \
599       releaseArgument(env, _p11, p11); \
600       releaseArgument(env, _p12, p12); \
601       return rv; \
602   } \
603   MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, #Ret "|" #P0 "|" #P1 "|" #P2 "|" #P3 "|" #P4 "|" #P5 "|" #P6 "|" #P7 "|" #P8 "|" #P9 "|" #P10 "|" #P11 "|" #P12, 0)
604 
605 #define KOALA_INTEROP_14(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13) \
606   InteropTypeConverter<Ret>::InteropType Ark_##name(EtsEnv *env, ets_class clazz, \
607     InteropTypeConverter<P0>::InteropType _p0, \
608     InteropTypeConverter<P1>::InteropType _p1, \
609     InteropTypeConverter<P2>::InteropType _p2, \
610     InteropTypeConverter<P3>::InteropType _p3, \
611     InteropTypeConverter<P4>::InteropType _p4, \
612     InteropTypeConverter<P5>::InteropType _p5, \
613     InteropTypeConverter<P6>::InteropType _p6, \
614     InteropTypeConverter<P7>::InteropType _p7, \
615     InteropTypeConverter<P8>::InteropType _p8, \
616     InteropTypeConverter<P9>::InteropType _p9, \
617     InteropTypeConverter<P10>::InteropType _p10, \
618     InteropTypeConverter<P11>::InteropType _p11, \
619     InteropTypeConverter<P12>::InteropType _p12, \
620     InteropTypeConverter<P13>::InteropType _p13) { \
621       KOALA_MAYBE_LOG(name) \
622       P0 p0 = getArgument<P0>(env, _p0); \
623       P1 p1 = getArgument<P1>(env, _p1); \
624       P2 p2 = getArgument<P2>(env, _p2); \
625       P3 p3 = getArgument<P3>(env, _p3); \
626       P4 p4 = getArgument<P4>(env, _p4); \
627       P5 p5 = getArgument<P5>(env, _p5); \
628       P6 p6 = getArgument<P6>(env, _p6); \
629       P7 p7 = getArgument<P7>(env, _p7); \
630       P8 p8 = getArgument<P8>(env, _p8); \
631       P9 p9 = getArgument<P9>(env, _p9); \
632       P10 p10 = getArgument<P10>(env, _p10); \
633       P11 p11 = getArgument<P11>(env, _p11); \
634       P12 p12 = getArgument<P12>(env, _p12); \
635       P13 p13 = getArgument<P13>(env, _p13); \
636       auto rv = makeResult<Ret>(env, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)); \
637       releaseArgument(env, _p0, p0); \
638       releaseArgument(env, _p1, p1); \
639       releaseArgument(env, _p2, p2); \
640       releaseArgument(env, _p3, p3); \
641       releaseArgument(env, _p4, p4); \
642       releaseArgument(env, _p5, p5); \
643       releaseArgument(env, _p6, p6); \
644       releaseArgument(env, _p7, p7); \
645       releaseArgument(env, _p8, p8); \
646       releaseArgument(env, _p9, p9); \
647       releaseArgument(env, _p10, p10); \
648       releaseArgument(env, _p11, p11); \
649       releaseArgument(env, _p12, p12); \
650       releaseArgument(env, _p13, p13); \
651       return rv; \
652     } \
653 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, #Ret "|" #P0 "|" #P1 "|" #P2 "|" #P3 "|" #P4 "|" #P5 "|" #P6 "|" #P7 "|" #P8 "|" #P9 "|" #P10 "|" #P11 "|" #P12 "|" #P13, 0)
654 
655 #define KOALA_INTEROP_V0(name) \
656   void Ark_##name(EtsEnv *env) { \
657       KOALA_MAYBE_LOG(name)                   \
658       impl_##name(); \
659   } \
660 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, "void", 0)
661 
662 #define KOALA_INTEROP_V1(name, P0) \
663   void Ark_##name(EtsEnv *env, ets_class clazz, \
664   InteropTypeConverter<P0>::InteropType _p0) { \
665     KOALA_MAYBE_LOG(name)              \
666     P0 p0 = getArgument<P0>(env, _p0); \
667     impl_##name(p0); \
668     releaseArgument(env, _p0, p0); \
669   } \
670 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, "void|" #P0, 0)
671 
672 #define KOALA_INTEROP_V2(name, P0, P1) \
673   void Ark_##name(EtsEnv *env, ets_class clazz, \
674     InteropTypeConverter<P0>::InteropType _p0, \
675     InteropTypeConverter<P1>::InteropType _p1) { \
676       KOALA_MAYBE_LOG(name) \
677       P0 p0 = getArgument<P0>(env, _p0); \
678       P1 p1 = getArgument<P1>(env, _p1); \
679       impl_##name(p0, p1); \
680       releaseArgument(env, _p0, p0); \
681       releaseArgument(env, _p1, p1); \
682    } \
683 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, "void|" #P0 "|" #P1, 0)
684 
685 #define KOALA_INTEROP_V3(name, P0, P1, P2) \
686   void Ark_##name(EtsEnv *env, ets_class clazz, \
687     InteropTypeConverter<P0>::InteropType _p0, \
688     InteropTypeConverter<P1>::InteropType _p1, \
689     InteropTypeConverter<P2>::InteropType _p2) { \
690       KOALA_MAYBE_LOG(name) \
691       P0 p0 = getArgument<P0>(env, _p0); \
692       P1 p1 = getArgument<P1>(env, _p1); \
693       P2 p2 = getArgument<P2>(env, _p2); \
694       impl_##name(p0, p1, p2); \
695       releaseArgument(env, _p0, p0); \
696       releaseArgument(env, _p1, p1); \
697       releaseArgument(env, _p2, p2); \
698   } \
699 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, "void|" #P0 "|" #P1 "|" #P2, 0)
700 
701 #define KOALA_INTEROP_V4(name, P0, P1, P2, P3) \
702   void Ark_##name(EtsEnv *env, ets_class clazz, \
703     InteropTypeConverter<P0>::InteropType _p0, \
704     InteropTypeConverter<P1>::InteropType _p1, \
705     InteropTypeConverter<P2>::InteropType _p2, \
706     InteropTypeConverter<P3>::InteropType _p3) { \
707       KOALA_MAYBE_LOG(name) \
708       P0 p0 = getArgument<P0>(env, _p0); \
709       P1 p1 = getArgument<P1>(env, _p1); \
710       P2 p2 = getArgument<P2>(env, _p2); \
711       P3 p3 = getArgument<P3>(env, _p3); \
712       impl_##name(p0, p1, p2, p3); \
713       releaseArgument(env, _p0, p0); \
714       releaseArgument(env, _p1, p1); \
715       releaseArgument(env, _p2, p2); \
716       releaseArgument(env, _p3, p3); \
717 } \
718 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, "void|" #P0 "|" #P1 "|" #P2 "|" #P3, 0)
719 
720 #define KOALA_INTEROP_V5(name, P0, P1, P2, P3, P4) \
721   void Ark_##name(EtsEnv *env, ets_class clazz, \
722     InteropTypeConverter<P0>::InteropType _p0, \
723     InteropTypeConverter<P1>::InteropType _p1, \
724     InteropTypeConverter<P2>::InteropType _p2, \
725     InteropTypeConverter<P3>::InteropType _p3, \
726     InteropTypeConverter<P4>::InteropType _p4) { \
727       KOALA_MAYBE_LOG(name) \
728       P0 p0 = getArgument<P0>(env, _p0); \
729       P1 p1 = getArgument<P1>(env, _p1); \
730       P2 p2 = getArgument<P2>(env, _p2); \
731       P3 p3 = getArgument<P3>(env, _p3); \
732       P4 p4 = getArgument<P4>(env, _p4); \
733       impl_##name(p0, p1, p2, p3, p4); \
734       releaseArgument(env, _p0, p0); \
735       releaseArgument(env, _p1, p1); \
736       releaseArgument(env, _p2, p2); \
737       releaseArgument(env, _p3, p3); \
738       releaseArgument(env, _p4, p4); \
739 } \
740 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, "void|" #P0 "|" #P1 "|" #P2 "|" #P3 "|" #P4, 0)
741 
742 #define KOALA_INTEROP_V6(name, P0, P1, P2, P3, P4, P5) \
743   void Ark_##name(EtsEnv *env, ets_class clazz, \
744     InteropTypeConverter<P0>::InteropType _p0, \
745     InteropTypeConverter<P1>::InteropType _p1, \
746     InteropTypeConverter<P2>::InteropType _p2, \
747     InteropTypeConverter<P3>::InteropType _p3, \
748     InteropTypeConverter<P4>::InteropType _p4, \
749     InteropTypeConverter<P5>::InteropType _p5) { \
750       KOALA_MAYBE_LOG(name) \
751       P0 p0 = getArgument<P0>(env, _p0); \
752       P1 p1 = getArgument<P1>(env, _p1); \
753       P2 p2 = getArgument<P2>(env, _p2); \
754       P3 p3 = getArgument<P3>(env, _p3); \
755       P4 p4 = getArgument<P4>(env, _p4); \
756       P5 p5 = getArgument<P5>(env, _p5); \
757       impl_##name(p0, p1, p2, p3, p4, p5); \
758       releaseArgument(env, _p0, p0); \
759       releaseArgument(env, _p1, p1); \
760       releaseArgument(env, _p2, p2); \
761       releaseArgument(env, _p3, p3); \
762       releaseArgument(env, _p4, p4); \
763       releaseArgument(env, _p5, p5); \
764   } \
765 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, "void|" #P0 "|" #P1 "|" #P2 "|" #P3 "|" #P4 "|" #P5, 0)
766 
767 #define KOALA_INTEROP_V7(name, P0, P1, P2, P3, P4, P5, P6) \
768   void Ark_##name(EtsEnv *env, ets_class clazz, \
769     InteropTypeConverter<P0>::InteropType _p0, \
770     InteropTypeConverter<P1>::InteropType _p1, \
771     InteropTypeConverter<P2>::InteropType _p2, \
772     InteropTypeConverter<P3>::InteropType _p3, \
773     InteropTypeConverter<P4>::InteropType _p4, \
774     InteropTypeConverter<P5>::InteropType _p5, \
775     InteropTypeConverter<P6>::InteropType _p6) { \
776       KOALA_MAYBE_LOG(name) \
777       P0 p0 = getArgument<P0>(env, _p0); \
778       P1 p1 = getArgument<P1>(env, _p1); \
779       P2 p2 = getArgument<P2>(env, _p2); \
780       P3 p3 = getArgument<P3>(env, _p3); \
781       P4 p4 = getArgument<P4>(env, _p4); \
782       P5 p5 = getArgument<P5>(env, _p5); \
783       P6 p6 = getArgument<P6>(env, _p6); \
784       impl_##name(p0, p1, p2, p3, p4, p5, p6); \
785       releaseArgument(env, _p0, p0); \
786       releaseArgument(env, _p1, p1); \
787       releaseArgument(env, _p2, p2); \
788       releaseArgument(env, _p3, p3); \
789       releaseArgument(env, _p4, p4); \
790       releaseArgument(env, _p5, p5); \
791       releaseArgument(env, _p6, p6); \
792   } \
793 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, "void|" #P0 "|" #P1 "|" #P2 "|" #P3 "|" #P4 "|" #P5 "|" #P6, 0)
794 
795 #define KOALA_INTEROP_V8(name, P0, P1, P2, P3, P4, P5, P6, P7) \
796   void Ark_##name(EtsEnv *env, ets_class clazz, \
797     InteropTypeConverter<P0>::InteropType _p0, \
798     InteropTypeConverter<P1>::InteropType _p1, \
799     InteropTypeConverter<P2>::InteropType _p2, \
800     InteropTypeConverter<P3>::InteropType _p3, \
801     InteropTypeConverter<P4>::InteropType _p4, \
802     InteropTypeConverter<P5>::InteropType _p5, \
803     InteropTypeConverter<P6>::InteropType _p6, \
804     InteropTypeConverter<P7>::InteropType _p7) { \
805       KOALA_MAYBE_LOG(name) \
806       P0 p0 = getArgument<P0>(env, _p0); \
807       P1 p1 = getArgument<P1>(env, _p1); \
808       P2 p2 = getArgument<P2>(env, _p2); \
809       P3 p3 = getArgument<P3>(env, _p3); \
810       P4 p4 = getArgument<P4>(env, _p4); \
811       P5 p5 = getArgument<P5>(env, _p5); \
812       P6 p6 = getArgument<P6>(env, _p6); \
813       P7 p7 = getArgument<P7>(env, _p7); \
814       impl_##name(p0, p1, p2, p3, p4, p5, p6, p7); \
815       releaseArgument(env, _p0, p0); \
816       releaseArgument(env, _p1, p1); \
817       releaseArgument(env, _p2, p2); \
818       releaseArgument(env, _p3, p3); \
819       releaseArgument(env, _p4, p4); \
820       releaseArgument(env, _p5, p5); \
821       releaseArgument(env, _p6, p6); \
822       releaseArgument(env, _p7, p7); \
823   } \
824 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, "void|" #P0 "|" #P1 "|" #P2 "|" #P3 "|" #P4 "|" #P5 "|" #P6 "|" #P7, 0)
825 
826 #define KOALA_INTEROP_V9(name, P0, P1, P2, P3, P4, P5, P6, P7, P8) \
827   void Ark_##name(EtsEnv *env, ets_class clazz, \
828     InteropTypeConverter<P0>::InteropType _p0, \
829     InteropTypeConverter<P1>::InteropType _p1, \
830     InteropTypeConverter<P2>::InteropType _p2, \
831     InteropTypeConverter<P3>::InteropType _p3, \
832     InteropTypeConverter<P4>::InteropType _p4, \
833     InteropTypeConverter<P5>::InteropType _p5, \
834     InteropTypeConverter<P6>::InteropType _p6, \
835     InteropTypeConverter<P7>::InteropType _p7, \
836     InteropTypeConverter<P8>::InteropType _p8) { \
837       KOALA_MAYBE_LOG(name) \
838       P0 p0 = getArgument<P0>(env, _p0); \
839       P1 p1 = getArgument<P1>(env, _p1); \
840       P2 p2 = getArgument<P2>(env, _p2); \
841       P3 p3 = getArgument<P3>(env, _p3); \
842       P4 p4 = getArgument<P4>(env, _p4); \
843       P5 p5 = getArgument<P5>(env, _p5); \
844       P6 p6 = getArgument<P6>(env, _p6); \
845       P7 p7 = getArgument<P7>(env, _p7); \
846       P8 p8 = getArgument<P8>(env, _p8); \
847       impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8); \
848       releaseArgument(env, _p0, p0); \
849       releaseArgument(env, _p1, p1); \
850       releaseArgument(env, _p2, p2); \
851       releaseArgument(env, _p3, p3); \
852       releaseArgument(env, _p4, p4); \
853       releaseArgument(env, _p5, p5); \
854       releaseArgument(env, _p6, p6); \
855       releaseArgument(env, _p7, p7); \
856       releaseArgument(env, _p8, p8); \
857   } \
858 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, "void|" #P0 "|" #P1 "|" #P2 "|" #P3 "|" #P4 "|" #P5 "|" #P6 "|" #P7 "|" #P8, 0)
859 
860 #define KOALA_INTEROP_V10(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9) \
861   void Ark_##name(EtsEnv *env, ets_class clazz, \
862     InteropTypeConverter<P0>::InteropType _p0, \
863     InteropTypeConverter<P1>::InteropType _p1, \
864     InteropTypeConverter<P2>::InteropType _p2, \
865     InteropTypeConverter<P3>::InteropType _p3, \
866     InteropTypeConverter<P4>::InteropType _p4, \
867     InteropTypeConverter<P5>::InteropType _p5, \
868     InteropTypeConverter<P6>::InteropType _p6, \
869     InteropTypeConverter<P7>::InteropType _p7, \
870     InteropTypeConverter<P8>::InteropType _p8, \
871     InteropTypeConverter<P9>::InteropType _p9) { \
872       KOALA_MAYBE_LOG(name) \
873       P0 p0 = getArgument<P0>(env, _p0); \
874       P1 p1 = getArgument<P1>(env, _p1); \
875       P2 p2 = getArgument<P2>(env, _p2); \
876       P3 p3 = getArgument<P3>(env, _p3); \
877       P4 p4 = getArgument<P4>(env, _p4); \
878       P5 p5 = getArgument<P5>(env, _p5); \
879       P6 p6 = getArgument<P6>(env, _p6); \
880       P7 p7 = getArgument<P7>(env, _p7); \
881       P8 p8 = getArgument<P8>(env, _p8); \
882       P9 p9 = getArgument<P9>(env, _p9); \
883       impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9); \
884       releaseArgument(env, _p0, p0); \
885       releaseArgument(env, _p1, p1); \
886       releaseArgument(env, _p2, p2); \
887       releaseArgument(env, _p3, p3); \
888       releaseArgument(env, _p4, p4); \
889       releaseArgument(env, _p5, p5); \
890       releaseArgument(env, _p6, p6); \
891       releaseArgument(env, _p7, p7); \
892       releaseArgument(env, _p8, p8); \
893       releaseArgument(env, _p9, p9); \
894 } \
895 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, "void|" #P0 "|" #P1 "|" #P2 "|" #P3 "|" #P4 "|" #P5 "|" #P6 "|" #P7 "|" #P8 "|" #P9, 0)
896 
897 #define KOALA_INTEROP_V11(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) \
898   void Ark_##name(EtsEnv *env, ets_class clazz, \
899     InteropTypeConverter<P0>::InteropType _p0, \
900     InteropTypeConverter<P1>::InteropType _p1, \
901     InteropTypeConverter<P2>::InteropType _p2, \
902     InteropTypeConverter<P3>::InteropType _p3, \
903     InteropTypeConverter<P4>::InteropType _p4, \
904     InteropTypeConverter<P5>::InteropType _p5, \
905     InteropTypeConverter<P6>::InteropType _p6, \
906     InteropTypeConverter<P7>::InteropType _p7, \
907     InteropTypeConverter<P8>::InteropType _p8, \
908     InteropTypeConverter<P9>::InteropType _p9, \
909     InteropTypeConverter<P10>::InteropType _p10) { \
910       KOALA_MAYBE_LOG(name) \
911       P0 p0 = getArgument<P0>(env, _p0); \
912       P1 p1 = getArgument<P1>(env, _p1); \
913       P2 p2 = getArgument<P2>(env, _p2); \
914       P3 p3 = getArgument<P3>(env, _p3); \
915       P4 p4 = getArgument<P4>(env, _p4); \
916       P5 p5 = getArgument<P5>(env, _p5); \
917       P6 p6 = getArgument<P6>(env, _p6); \
918       P7 p7 = getArgument<P7>(env, _p7); \
919       P8 p8 = getArgument<P8>(env, _p8); \
920       P9 p9 = getArgument<P9>(env, _p9); \
921       P10 p10 = getArgument<P10>(env, _p10); \
922       impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); \
923       releaseArgument(env, _p0, p0); \
924       releaseArgument(env, _p1, p1); \
925       releaseArgument(env, _p2, p2); \
926       releaseArgument(env, _p3, p3); \
927       releaseArgument(env, _p4, p4); \
928       releaseArgument(env, _p5, p5); \
929       releaseArgument(env, _p6, p6); \
930       releaseArgument(env, _p7, p7); \
931       releaseArgument(env, _p8, p8); \
932       releaseArgument(env, _p9, p9); \
933       releaseArgument(env, _p10, p10); \
934   } \
935 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, "void|" #P0 "|" #P1 "|" #P2 "|" #P3 "|" #P4 "|" #P5 "|" #P6 "|" #P7 "|" #P8 "|" #P9 "|" #P10, 0)
936 
937 #define KOALA_INTEROP_V12(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11) \
938   void Ark_##name(EtsEnv *env, ets_class clazz, \
939     InteropTypeConverter<P0>::InteropType _p0, \
940     InteropTypeConverter<P1>::InteropType _p1, \
941     InteropTypeConverter<P2>::InteropType _p2, \
942     InteropTypeConverter<P3>::InteropType _p3, \
943     InteropTypeConverter<P4>::InteropType _p4, \
944     InteropTypeConverter<P5>::InteropType _p5, \
945     InteropTypeConverter<P6>::InteropType _p6, \
946     InteropTypeConverter<P7>::InteropType _p7, \
947     InteropTypeConverter<P8>::InteropType _p8, \
948     InteropTypeConverter<P9>::InteropType _p9, \
949     InteropTypeConverter<P10>::InteropType _p10, \
950     InteropTypeConverter<P11>::InteropType _p11) { \
951       KOALA_MAYBE_LOG(name) \
952       P0 p0 = getArgument<P0>(env, _p0); \
953       P1 p1 = getArgument<P1>(env, _p1); \
954       P2 p2 = getArgument<P2>(env, _p2); \
955       P3 p3 = getArgument<P3>(env, _p3); \
956       P4 p4 = getArgument<P4>(env, _p4); \
957       P5 p5 = getArgument<P5>(env, _p5); \
958       P6 p6 = getArgument<P6>(env, _p6); \
959       P7 p7 = getArgument<P7>(env, _p7); \
960       P8 p8 = getArgument<P8>(env, _p8); \
961       P9 p9 = getArgument<P9>(env, _p9); \
962       P10 p10 = getArgument<P10>(env, _p10); \
963       P11 p11 = getArgument<P11>(env, _p11); \
964       impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); \
965       releaseArgument(env, _p0, p0); \
966       releaseArgument(env, _p1, p1); \
967       releaseArgument(env, _p2, p2); \
968       releaseArgument(env, _p3, p3); \
969       releaseArgument(env, _p4, p4); \
970       releaseArgument(env, _p5, p5); \
971       releaseArgument(env, _p6, p6); \
972       releaseArgument(env, _p7, p7); \
973       releaseArgument(env, _p8, p8); \
974       releaseArgument(env, _p9, p9); \
975       releaseArgument(env, _p10, p10); \
976       releaseArgument(env, _p11, p11); \
977 } \
978 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, "void|" #P0 "|" #P1 "|" #P2 "|" #P3 "|" #P4 "|" #P5 "|" #P6 "|" #P7 "|" #P8 "|" #P9 "|" #P10 "|" #P11, 0)
979 
980 #define KOALA_INTEROP_V13(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) \
981   void Ark_##name(EtsEnv *env, ets_class clazz, \
982     InteropTypeConverter<P0>::InteropType _p0, \
983     InteropTypeConverter<P1>::InteropType _p1, \
984     InteropTypeConverter<P2>::InteropType _p2, \
985     InteropTypeConverter<P3>::InteropType _p3, \
986     InteropTypeConverter<P4>::InteropType _p4, \
987     InteropTypeConverter<P5>::InteropType _p5, \
988     InteropTypeConverter<P6>::InteropType _p6, \
989     InteropTypeConverter<P7>::InteropType _p7, \
990     InteropTypeConverter<P8>::InteropType _p8, \
991     InteropTypeConverter<P9>::InteropType _p9, \
992     InteropTypeConverter<P10>::InteropType _p10, \
993     InteropTypeConverter<P11>::InteropType _p11, \
994     InteropTypeConverter<P12>::InteropType _p12) { \
995       KOALA_MAYBE_LOG(name) \
996       P0 p0 = getArgument<P0>(env, _p0); \
997       P1 p1 = getArgument<P1>(env, _p1); \
998       P2 p2 = getArgument<P2>(env, _p2); \
999       P3 p3 = getArgument<P3>(env, _p3); \
1000       P4 p4 = getArgument<P4>(env, _p4); \
1001       P5 p5 = getArgument<P5>(env, _p5); \
1002       P6 p6 = getArgument<P6>(env, _p6); \
1003       P7 p7 = getArgument<P7>(env, _p7); \
1004       P8 p8 = getArgument<P8>(env, _p8); \
1005       P9 p9 = getArgument<P9>(env, _p9); \
1006       P10 p10 = getArgument<P10>(env, _p10); \
1007       P11 p11 = getArgument<P11>(env, _p11); \
1008       P12 p12 = getArgument<P12>(env, _p12); \
1009       impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); \
1010       releaseArgument(env, _p0, p0); \
1011       releaseArgument(env, _p1, p1); \
1012       releaseArgument(env, _p2, p2); \
1013       releaseArgument(env, _p3, p3); \
1014       releaseArgument(env, _p4, p4); \
1015       releaseArgument(env, _p5, p5); \
1016       releaseArgument(env, _p6, p6); \
1017       releaseArgument(env, _p7, p7); \
1018       releaseArgument(env, _p8, p8); \
1019       releaseArgument(env, _p9, p9); \
1020       releaseArgument(env, _p10, p10); \
1021       releaseArgument(env, _p11, p11); \
1022       releaseArgument(env, _p12, p12); \
1023 } \
1024 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, "void|" #P0 "|" #P1 "|" #P2 "|" #P3 "|" #P4 "|" #P5 "|" #P6 "|" #P7 "|" #P8 "|" #P9 "|" #P10 "|" #P11 "|" #P12, 0)
1025 
1026 #define KOALA_INTEROP_V14(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13) \
1027   void Ark_##name(EtsEnv *env, ets_class clazz, \
1028   InteropTypeConverter<P0>::InteropType _p0, \
1029   InteropTypeConverter<P1>::InteropType _p1, \
1030   InteropTypeConverter<P2>::InteropType _p2, \
1031   InteropTypeConverter<P3>::InteropType _p3, \
1032   InteropTypeConverter<P4>::InteropType _p4, \
1033   InteropTypeConverter<P5>::InteropType _p5, \
1034   InteropTypeConverter<P6>::InteropType _p6, \
1035   InteropTypeConverter<P7>::InteropType _p7, \
1036   InteropTypeConverter<P8>::InteropType _p8, \
1037   InteropTypeConverter<P9>::InteropType _p9, \
1038   InteropTypeConverter<P10>::InteropType _p10, \
1039   InteropTypeConverter<P11>::InteropType _p11, \
1040   InteropTypeConverter<P12>::InteropType _p12, \
1041   InteropTypeConverter<P13>::InteropType _p13) { \
1042       KOALA_MAYBE_LOG(name) \
1043       P0 p0 = getArgument<P0>(env, _p0); \
1044       P1 p1 = getArgument<P1>(env, _p1); \
1045       P2 p2 = getArgument<P2>(env, _p2); \
1046       P3 p3 = getArgument<P3>(env, _p3); \
1047       P4 p4 = getArgument<P4>(env, _p4); \
1048       P5 p5 = getArgument<P5>(env, _p5); \
1049       P6 p6 = getArgument<P6>(env, _p6); \
1050       P7 p7 = getArgument<P7>(env, _p7); \
1051       P8 p8 = getArgument<P8>(env, _p8); \
1052       P9 p9 = getArgument<P9>(env, _p9); \
1053       P10 p10 = getArgument<P10>(env, _p10); \
1054       P11 p11 = getArgument<P11>(env, _p11); \
1055       P12 p12 = getArgument<P12>(env, _p12); \
1056       P13 p13 = getArgument<P13>(env, _p13); \
1057       impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); \
1058       releaseArgument(env, _p0, p0); \
1059       releaseArgument(env, _p1, p1); \
1060       releaseArgument(env, _p2, p2); \
1061       releaseArgument(env, _p3, p3); \
1062       releaseArgument(env, _p4, p4); \
1063       releaseArgument(env, _p5, p5); \
1064       releaseArgument(env, _p6, p6); \
1065       releaseArgument(env, _p7, p7); \
1066       releaseArgument(env, _p8, p8); \
1067       releaseArgument(env, _p9, p9); \
1068       releaseArgument(env, _p10, p10); \
1069       releaseArgument(env, _p11, p11); \
1070       releaseArgument(env, _p12, p12); \
1071       releaseArgument(env, _p13, p13); \
1072 } \
1073 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, "void|" #P0 "|" #P1 "|" #P2 "|" #P3 "|" #P4 "|" #P5 "|" #P6 "|" #P7 "|" #P8 "|" #P9 "|" #P10 "|" #P11 "|" #P12 "|" #P13, 0)
1074 
1075 #define KOALA_INTEROP_V15(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14) \
1076   void Ark_##name(EtsEnv *env, ets_class clazz, \
1077   InteropTypeConverter<P0>::InteropType _p0, \
1078   InteropTypeConverter<P1>::InteropType _p1, \
1079   InteropTypeConverter<P2>::InteropType _p2, \
1080   InteropTypeConverter<P3>::InteropType _p3, \
1081   InteropTypeConverter<P4>::InteropType _p4, \
1082   InteropTypeConverter<P5>::InteropType _p5, \
1083   InteropTypeConverter<P6>::InteropType _p6, \
1084   InteropTypeConverter<P7>::InteropType _p7, \
1085   InteropTypeConverter<P8>::InteropType _p8, \
1086   InteropTypeConverter<P9>::InteropType _p9, \
1087   InteropTypeConverter<P10>::InteropType _p10, \
1088   InteropTypeConverter<P11>::InteropType _p11, \
1089   InteropTypeConverter<P12>::InteropType _p12, \
1090   InteropTypeConverter<P13>::InteropType _p13, \
1091   InteropTypeConverter<P14>::InteropType _p14) { \
1092       KOALA_MAYBE_LOG(name) \
1093       P0 p0 = getArgument<P0>(env, _p0); \
1094       P1 p1 = getArgument<P1>(env, _p1); \
1095       P2 p2 = getArgument<P2>(env, _p2); \
1096       P3 p3 = getArgument<P3>(env, _p3); \
1097       P4 p4 = getArgument<P4>(env, _p4); \
1098       P5 p5 = getArgument<P5>(env, _p5); \
1099       P6 p6 = getArgument<P6>(env, _p6); \
1100       P7 p7 = getArgument<P7>(env, _p7); \
1101       P8 p8 = getArgument<P8>(env, _p8); \
1102       P9 p9 = getArgument<P9>(env, _p9); \
1103       P10 p10 = getArgument<P10>(env, _p10); \
1104       P11 p11 = getArgument<P11>(env, _p11); \
1105       P12 p12 = getArgument<P12>(env, _p12); \
1106       P13 p13 = getArgument<P13>(env, _p13); \
1107       P14 p14 = getArgument<P14>(env, _p14); \
1108       impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14); \
1109       releaseArgument(env, _p0, p0); \
1110       releaseArgument(env, _p1, p1); \
1111       releaseArgument(env, _p2, p2); \
1112       releaseArgument(env, _p3, p3); \
1113       releaseArgument(env, _p4, p4); \
1114       releaseArgument(env, _p5, p5); \
1115       releaseArgument(env, _p6, p6); \
1116       releaseArgument(env, _p7, p7); \
1117       releaseArgument(env, _p8, p8); \
1118       releaseArgument(env, _p9, p9); \
1119       releaseArgument(env, _p10, p10); \
1120       releaseArgument(env, _p11, p11); \
1121       releaseArgument(env, _p12, p12); \
1122       releaseArgument(env, _p13, p13); \
1123       releaseArgument(env, _p14, p14); \
1124 } \
1125 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, "void|" #P0 "|" #P1 "|" #P2 "|" #P3 "|" #P4 "|" #P5 "|" #P6 "|" #P7 "|" #P8 "|" #P9 "|" #P10 "|" #P11 "|" #P12 "|" #P13 "|" #P14, 0)
1126 
1127 #define KOALA_INTEROP_CTX_0(name, Ret) \
1128   InteropTypeConverter<Ret>::InteropType Ark_##name(EtsEnv *env, ets_class clazz) { \
1129       KOALA_MAYBE_LOG(name)                   \
1130       KVMContext ctx = (KVMContext)env; \
1131       auto rv = makeResult<Ret>(env, impl_##name(ctx)); \
1132       return rv; \
1133   } \
1134 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, #Ret, ETS_SLOW_NATIVE_FLAG)
1135 
1136 #define KOALA_INTEROP_CTX_1(name, Ret, P0) \
1137   InteropTypeConverter<Ret>::InteropType Ark_##name(EtsEnv *env, ets_class clazz, \
1138    InteropTypeConverter<P0>::InteropType _p0) { \
1139       KOALA_MAYBE_LOG(name)                   \
1140       P0 p0 = getArgument<P0>(env, _p0); \
1141       KVMContext ctx = (KVMContext)env; \
1142       auto rv = makeResult<Ret>(env, impl_##name(ctx, p0)); \
1143       releaseArgument(env, _p0, p0); \
1144       return rv; \
1145   } \
1146 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, #Ret "|" #P0, ETS_SLOW_NATIVE_FLAG)
1147 
1148 #define KOALA_INTEROP_CTX_2(name, Ret, P0, P1) \
1149   InteropTypeConverter<Ret>::InteropType Ark_##name(EtsEnv *env, ets_class clazz, \
1150     InteropTypeConverter<P0>::InteropType _p0, \
1151     InteropTypeConverter<P1>::InteropType _p1) { \
1152       KOALA_MAYBE_LOG(name)                   \
1153       P0 p0 = getArgument<P0>(env, _p0); \
1154       P1 p1 = getArgument<P1>(env, _p1); \
1155       KVMContext ctx = (KVMContext)env; \
1156       auto rv = makeResult<Ret>(env, impl_##name(ctx, p0, p1)); \
1157       releaseArgument(env, _p0, p0); \
1158       releaseArgument(env, _p1, p1); \
1159       return rv; \
1160   } \
1161 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, #Ret "|" #P0 "|" #P1, ETS_SLOW_NATIVE_FLAG)
1162 
1163 #define KOALA_INTEROP_CTX_3(name, Ret, P0, P1, P2) \
1164   InteropTypeConverter<Ret>::InteropType Ark_##name(EtsEnv *env, ets_class clazz, \
1165     InteropTypeConverter<P0>::InteropType _p0, \
1166     InteropTypeConverter<P1>::InteropType _p1, \
1167     InteropTypeConverter<P2>::InteropType _p2) { \
1168       KOALA_MAYBE_LOG(name)                   \
1169       P0 p0 = getArgument<P0>(env, _p0); \
1170       P1 p1 = getArgument<P1>(env, _p1); \
1171       P2 p2 = getArgument<P2>(env, _p2); \
1172       KVMContext ctx = (KVMContext)env; \
1173       auto rv = makeResult<Ret>(env, impl_##name(ctx, p0, p1, p2)); \
1174       releaseArgument(env, _p0, p0); \
1175       releaseArgument(env, _p1, p1); \
1176       releaseArgument(env, _p2, p2); \
1177       return rv; \
1178   } \
1179 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, #Ret "|" #P0 "|" #P1 "|" #P2, ETS_SLOW_NATIVE_FLAG)
1180 
1181 #define KOALA_INTEROP_CTX_4(name, Ret, P0, P1, P2, P3) \
1182   InteropTypeConverter<Ret>::InteropType Ark_##name(EtsEnv *env, ets_class clazz, \
1183     InteropTypeConverter<P0>::InteropType _p0, \
1184     InteropTypeConverter<P1>::InteropType _p1, \
1185     InteropTypeConverter<P2>::InteropType _p2, \
1186     InteropTypeConverter<P3>::InteropType _p3) { \
1187       KOALA_MAYBE_LOG(name)                   \
1188       P0 p0 = getArgument<P0>(env, _p0); \
1189       P1 p1 = getArgument<P1>(env, _p1); \
1190       P2 p2 = getArgument<P2>(env, _p2); \
1191       P3 p3 = getArgument<P3>(env, _p3); \
1192       KVMContext ctx = (KVMContext)env; \
1193       auto rv = makeResult<Ret>(env, impl_##name(ctx, p0, p1, p2, p3)); \
1194       releaseArgument(env, _p0, p0); \
1195       releaseArgument(env, _p1, p1); \
1196       releaseArgument(env, _p2, p2); \
1197       releaseArgument(env, _p3, p3); \
1198       return rv; \
1199   } \
1200 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, #Ret "|" #P0 "|" #P1 "|" #P2 "|" #P3, ETS_SLOW_NATIVE_FLAG)
1201 
1202 #define KOALA_INTEROP_CTX_V0(name)  \
1203   void Ark_##name(EtsEnv *env, ets_class clazz) { \
1204       KOALA_MAYBE_LOG(name)                   \
1205       KVMContext ctx = (KVMContext)env; \
1206       impl_##name(ctx); \
1207   } \
1208 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, "void", ETS_SLOW_NATIVE_FLAG)
1209 
1210 #define KOALA_INTEROP_CTX_V1(name, P0)  \
1211   void Ark_##name(EtsEnv *env, ets_class clazz, \
1212     InteropTypeConverter<P0>::InteropType _p0) { \
1213       KOALA_MAYBE_LOG(name)                   \
1214       P0 p0 = getArgument<P0>(env, _p0); \
1215       KVMContext ctx = (KVMContext)env; \
1216       impl_##name(ctx, p0); \
1217       releaseArgument(env, _p0, p0); \
1218   } \
1219 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, "void|" #P0, ETS_SLOW_NATIVE_FLAG)
1220 
1221 #define KOALA_INTEROP_CTX_V2(name, P0, P1)  \
1222   void Ark_##name(EtsEnv *env, ets_class clazz, \
1223     InteropTypeConverter<P0>::InteropType _p0, \
1224     InteropTypeConverter<P1>::InteropType _p1) { \
1225       KOALA_MAYBE_LOG(name)                   \
1226       P0 p0 = getArgument<P0>(env, _p0); \
1227       P1 p1 = getArgument<P1>(env, _p1); \
1228       KVMContext ctx = (KVMContext)env; \
1229       impl_##name(ctx, p0, p1); \
1230       releaseArgument(env, _p0, p0); \
1231       releaseArgument(env, _p1, p1); \
1232   } \
1233 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, "void|" #P0 "|" #P1, ETS_SLOW_NATIVE_FLAG)
1234 
1235 #define KOALA_INTEROP_CTX_V3(name, P0, P1, P2)  \
1236   void Ark_##name(EtsEnv *env, ets_class clazz, \
1237     InteropTypeConverter<P0>::InteropType _p0, \
1238     InteropTypeConverter<P1>::InteropType _p1, \
1239     InteropTypeConverter<P2>::InteropType _p2) { \
1240       KOALA_MAYBE_LOG(name)                   \
1241       P0 p0 = getArgument<P0>(env, _p0); \
1242       P1 p1 = getArgument<P1>(env, _p1); \
1243       P2 p2 = getArgument<P2>(env, _p2); \
1244       KVMContext ctx = (KVMContext)env; \
1245       impl_##name(ctx, p0, p1, p2); \
1246       releaseArgument(env, _p0, p0); \
1247       releaseArgument(env, _p1, p1); \
1248       releaseArgument(env, _p2, p2); \
1249   } \
1250 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, "void|" #P0 "|" #P1 "|" #P2, ETS_SLOW_NATIVE_FLAG)
1251 
1252 #define KOALA_INTEROP_CTX_V4(name, P0, P1, P2, P3)  \
1253   void Ark_##name(EtsEnv *env, ets_class clazz, \
1254     InteropTypeConverter<P0>::InteropType _p0, \
1255     InteropTypeConverter<P1>::InteropType _p1, \
1256     InteropTypeConverter<P2>::InteropType _p2, \
1257     InteropTypeConverter<P3>::InteropType _p3) { \
1258       KOALA_MAYBE_LOG(name)                   \
1259       P0 p0 = getArgument<P0>(env, _p0); \
1260       P1 p1 = getArgument<P1>(env, _p1); \
1261       P2 p2 = getArgument<P2>(env, _p2); \
1262       P3 p3 = getArgument<P3>(env, _p3); \
1263       KVMContext ctx = (KVMContext)env; \
1264       impl_##name(ctx, p0, p1, p2, p3); \
1265       releaseArgument(env, _p0, p0); \
1266       releaseArgument(env, _p1, p1); \
1267       releaseArgument(env, _p2, p2); \
1268       releaseArgument(env, _p3, p3); \
1269   } \
1270 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, "void|" #P0 "|" #P1 "|" #P2 "|" #P3, ETS_SLOW_NATIVE_FLAG)
1271 
1272 #define KOALA_INTEROP_CTX_V5(name, P0, P1, P2, P3, P4)  \
1273   void Ark_##name(EtsEnv *env, ets_class clazz, \
1274     InteropTypeConverter<P0>::InteropType _p0, \
1275     InteropTypeConverter<P1>::InteropType _p1, \
1276     InteropTypeConverter<P2>::InteropType _p2, \
1277     InteropTypeConverter<P3>::InteropType _p3, \
1278     InteropTypeConverter<P4>::InteropType _p4) { \
1279       KOALA_MAYBE_LOG(name)                   \
1280       P0 p0 = getArgument<P0>(env, _p0); \
1281       P1 p1 = getArgument<P1>(env, _p1); \
1282       P2 p2 = getArgument<P2>(env, _p2); \
1283       P3 p3 = getArgument<P3>(env, _p3); \
1284       P4 p4 = getArgument<P4>(env, _p4); \
1285       KVMContext ctx = (KVMContext)env; \
1286       impl_##name(ctx, p0, p1, p2, p3, p4); \
1287       releaseArgument(env, _p0, p0); \
1288       releaseArgument(env, _p1, p1); \
1289       releaseArgument(env, _p2, p2); \
1290       releaseArgument(env, _p3, p3); \
1291       releaseArgument(env, _p4, p4); \
1292   } \
1293 MAKE_ETS_EXPORT(KOALA_INTEROP_MODULE, name, "void|" #P0 "|" #P1 "|" #P2 "|" #P3 "|" #P4, ETS_SLOW_NATIVE_FLAG)
1294 
1295 bool setKoalaEtsNapiCallbackDispatcher(
1296     EtsEnv* etsEnv,
1297     ets_class clazz,
1298     const char* dispatcherMethodName,
1299     const char* dispactherMethodSig
1300 );
1301 void getKoalaEtsNapiCallbackDispatcher(ets_class* clazz, ets_method* method);
1302 
1303 #define KOALA_INTEROP_CALL_VOID(venv, id, length, args)                               \
1304 {                                                                                     \
1305   ets_class clazz = nullptr;                                                          \
1306   ets_method method = nullptr;                                                        \
1307   getKoalaEtsNapiCallbackDispatcher(&clazz, &method);                                 \
1308   EtsEnv* etsEnv = reinterpret_cast<EtsEnv*>(vmContext);                              \
1309   etsEnv->PushLocalFrame(1);                                                          \
1310   ets_byteArray args_ets = etsEnv->NewByteArray(length);                              \
1311   etsEnv->SetByteArrayRegion(args_ets, 0, length, reinterpret_cast<ets_byte*>(args)); \
1312   etsEnv->CallStaticIntMethod(clazz, method, id, args_ets, length);                   \
1313   etsEnv->GetByteArrayRegion(args_ets, 0, length, reinterpret_cast<ets_byte*>(args)); \
1314   etsEnv->PopLocalFrame(nullptr);                                                     \
1315 }
1316 
1317 #define KOALA_INTEROP_CALL_INT(venv, id, length, args)                                \
1318 {                                                                                     \
1319   ets_class clazz = nullptr;                                                          \
1320   ets_method method = nullptr;                                                        \
1321   getKoalaEtsNapiCallbackDispatcher(&clazz, &method);                                 \
1322   EtsEnv* etsEnv = reinterpret_cast<EtsEnv*>(venv);                              \
1323   etsEnv->PushLocalFrame(1);                                                          \
1324   ets_byteArray args_ets = etsEnv->NewByteArray(length);                              \
1325   etsEnv->SetByteArrayRegion(args_ets, 0, length, reinterpret_cast<ets_byte*>(args)); \
1326   int32_t rv = etsEnv->CallStaticIntMethod(clazz, method, id, args_ets, length);      \
1327   etsEnv->GetByteArrayRegion(args_ets, 0, length, reinterpret_cast<ets_byte*>(args)); \
1328   etsEnv->PopLocalFrame(nullptr);                                                     \
1329   return rv;                                                                          \
1330 }
1331 
1332 #define KOALA_INTEROP_CALL_VOID_INTS32(venv, id, argc, args) KOALA_INTEROP_CALL_VOID(venv, id, (argc) * sizeof(int32_t), args)
1333 #define KOALA_INTEROP_CALL_INT_INTS32(venv, id, argc, args) KOALA_INTEROP_CALL_INT(venv, id, (argc) * sizeof(int32_t), args)
1334 
1335 #define KOALA_INTEROP_THROW(vmContext, object, ...) \
1336    do { \
1337      EtsEnv* env = reinterpret_cast<EtsEnv*>(vmContext); \
1338      env->ThrowError(object); \
1339      return __VA_ARGS__;  \
1340    } while (0)
1341 
1342 #define KOALA_INTEROP_THROW_STRING(vmContext, message, ...) \
1343   do { \
1344     EtsEnv* env = reinterpret_cast<EtsEnv*>(vmContext); \
1345     const static ets_class errorClass = env->FindClass("std/core/Error"); \
1346     env->ThrowErrorNew(errorClass, message); \
1347   } while (0)
1348 
1349 #endif // KOALA_ETS_NAPI
1350 
1351 #endif // CONVERTORS_ETS_H