diff --git a/arkoala/framework/native/src/callbacks.cc b/arkoala/framework/native/src/callbacks.cc index 9dcd6167fe812cb4f64210313f12c502ef2fa882..b0f23c9c976d7beb1ce577d4d483def10231947d 100644 --- a/arkoala/framework/native/src/callbacks.cc +++ b/arkoala/framework/native/src/callbacks.cc @@ -53,9 +53,9 @@ KInt impl_CheckArkoalaCallbackEvent(KByte* result, KInt size) { return 0; } const CallbackEventKind frontEventKind = callbackEventsQueue.front(); - Serializer serializer(result); + Serializer serializer(result, size); serializer.writeInt32(frontEventKind); - switch (frontEventKind) + switch (frontEventKind) { case Event_CallCallback: memcpy(result + serializer.length(), callbackCallSubqueue.front().buffer, sizeof(CallbackBuffer::buffer)); diff --git a/interop/src/cpp/SerializerBase.h b/interop/src/cpp/SerializerBase.h index 0cd090e2dea50a09a246ed8a3788eb7b04fde3ca..5cd41d1e61adac74b8fc55f3f3340f2728debcad 100644 --- a/interop/src/cpp/SerializerBase.h +++ b/interop/src/cpp/SerializerBase.h @@ -66,21 +66,60 @@ T* allocArray(const std::array& ref) { class SerializerBase { private: uint8_t* data; - int position; + uint32_t dataLength; + uint32_t position; + bool ownData; CallbackResourceHolder* resourceHolder; + void resize(uint32_t newLength) { + assert(ownData); + assert(newLength > dataLength); + auto* newData = reinterpret_cast(malloc(newLength)); + memcpy(newData, data, position); + free(data); + data = newData; + } public: - SerializerBase(uint8_t* data, CallbackResourceHolder* resourceHolder = nullptr): data(data), position(0), resourceHolder(resourceHolder) {} + SerializerBase(uint8_t* data = nullptr, uint32_t dataLength = 0, CallbackResourceHolder* resourceHolder = nullptr): + data(data), dataLength(dataLength), position(0), ownData(data == nullptr), resourceHolder(resourceHolder) { + if (data == nullptr) { + this->dataLength = 256; + this->data = reinterpret_cast(malloc(dataLength)); + } + } + + ~SerializerBase() { + if (ownData) { + free(data); + } + } + void* release() { + ownData = false; + return data; + } int length() { return position; } + inline void check(int more) { + if (position + more > dataLength) { + if (ownData) { + resize(dataLength * 3 / 2 + 2); + } else { + fprintf(stderr, "Buffer overrun: %d > %d\n", position + more, dataLength); + assert(false); + } + } + } + void writeInt8(InteropInt8 value) { + check(1); *((InteropInt8*)(data + position)) = value; position += 1; } void writeInt32(InteropInt32 value) { + check(4); #ifdef KOALA_NO_UNALIGNED_ACCESS memcpy(data + position, &value, 4); #else @@ -90,6 +129,7 @@ public: } void writeInt64(InteropInt64 value) { + check(8); #ifdef KOALA_NO_UNALIGNED_ACCESS memcpy(data + position, &value, 8); #else @@ -99,6 +139,7 @@ public: } void writeFloat32(InteropFloat32 value) { + check(8); #ifdef KOALA_NO_UNALIGNED_ACCESS memcpy(data + position, &value, 4); #else @@ -108,6 +149,7 @@ public: } void writePointer(InteropNativePointer value) { + check(8); #ifdef KOALA_NO_UNALIGNED_ACCESS memcpy(data + position, &value, 8); #else @@ -135,6 +177,7 @@ public: void writeString(InteropString value) { writeInt32(value.length + 1); + check(value.length + 1); strcpy((char*)(data + position), value.chars); position += value.length + 1; } diff --git a/interop/src/cpp/common-interop.cc b/interop/src/cpp/common-interop.cc index 8014dc988bbb681d8486812c03fe34fa6c4a75e4..d497181c3fd46e5a46309ac49c58d2537abb0e29 100644 --- a/interop/src/cpp/common-interop.cc +++ b/interop/src/cpp/common-interop.cc @@ -429,3 +429,12 @@ KStringPtr impl_StdStringToString(KVMContext vmContext, KNativePointer stringPtr KOALA_INTEROP_CTX_1(StdStringToString, KStringPtr, KNativePointer) #endif +#if defined(KOALA_JNI) || defined(KOALA_NAPI) +KInteropReturnBuffer impl_RawReturnData(KVMContext vmContext, KInt v1, KInt v2) { + void* data = new int8_t[v1]; + memset(data, v2, v1); + KInteropReturnBuffer buffer = { v1, data, [](KNativePointer ptr, KInt) { delete[] (int8_t*)ptr; }}; + return buffer; +} +KOALA_INTEROP_CTX_2(RawReturnData, KInteropReturnBuffer, KInt, KInt) +#endif diff --git a/interop/src/cpp/jni/convertors-jni.h b/interop/src/cpp/jni/convertors-jni.h index 0be8b95f2c5a2be3aa85b1a92d44c08b98b4201a..469fb9686c200eb985bee207cb573aa3a006141b 100644 --- a/interop/src/cpp/jni/convertors-jni.h +++ b/interop/src/cpp/jni/convertors-jni.h @@ -156,6 +156,21 @@ struct SlowInteropTypeConverter { } }; +template<> +struct SlowInteropTypeConverter { + using InteropType = jarray; + static inline KInteropReturnBuffer convertFrom(JNIEnv* env, InteropType value) = delete; + static InteropType convertTo(JNIEnv* env, KInteropReturnBuffer value) { + jarray result = env->NewByteArray(value.length); + void* data = env->GetPrimitiveArrayCritical(result, nullptr); + memcpy(data, value.data, value.length); + env->ReleasePrimitiveArrayCritical(result, data, 0); + value.dispose(value.data, value.length); + return result; + } + static inline void release(JNIEnv* env, InteropType value, const KInteropReturnBuffer& converted) = delete; +}; + template<> struct InteropTypeConverter { using InteropType = jbyteArray; diff --git a/interop/src/cpp/napi/convertors-napi.h b/interop/src/cpp/napi/convertors-napi.h index 17dc6c02268ec6162010648268a9b7b56d695b3c..d55dd6f584e0e03bc6fda330895545a70a8446eb 100644 --- a/interop/src/cpp/napi/convertors-napi.h +++ b/interop/src/cpp/napi/convertors-napi.h @@ -145,6 +145,28 @@ struct InteropTypeConverter { } }; +template<> +struct InteropTypeConverter { + using InteropType = napi_value; + static inline KInteropReturnBuffer convertFrom(napi_env env, InteropType value) = delete; + static void disposer(napi_env env, void* data, void* hint) { + KInteropReturnBuffer* bufferCopy = (KInteropReturnBuffer*)hint; + bufferCopy->dispose(bufferCopy->data, bufferCopy->length); + delete bufferCopy; + } + static InteropType convertTo(napi_env env, KInteropReturnBuffer value) { + napi_value result = nullptr; + napi_value arrayBuffer = nullptr; + auto clone = new KInteropReturnBuffer(); + *clone = value; + napi_create_external_arraybuffer(env, value.data, value.length, disposer, clone, &arrayBuffer); + napi_create_typedarray(env, napi_uint8_array, value.length, arrayBuffer, 0, &result); + return result; + } + static inline void release(napi_env env, InteropType value, const KInteropReturnBuffer& converted) = delete; +}; + + #define KOALA_INTEROP_THROW(vmcontext, object, ...) \ do { \ napi_env env = (napi_env)vmcontext; \ @@ -605,6 +627,11 @@ inline napi_value makeResult(const CallbackInfo& info, KInteropB return InteropTypeConverter::convertTo(info.Env(), value); } +template <> +inline napi_value makeResult(const CallbackInfo& info, KInteropReturnBuffer value) { + return InteropTypeConverter::convertTo(info.Env(), value); +} + template <> inline napi_value makeResult(const CallbackInfo& info, KInteropNumber value) { return InteropTypeConverter::convertTo(info.Env(), value); @@ -624,8 +651,6 @@ public: const std::vector>& getMethods(const std::string& module); }; -// Napi::ModuleRegisterCallback ProvideModuleRegisterCallback(Napi::ModuleRegisterCallback value); - #define __QUOTE(x) #x #define QUOTE(x) __QUOTE(x) diff --git a/interop/src/cpp/types/koala-types.h b/interop/src/cpp/types/koala-types.h index 04639170f946a4fad1e672c949291c4706cbdc29..8b0e86f8a91e0a0c17266633ca3a200810f497df 100644 --- a/interop/src/cpp/types/koala-types.h +++ b/interop/src/cpp/types/koala-types.h @@ -139,6 +139,12 @@ struct KInteropBuffer { void (*dispose)(KInt /* resourceId for now */); }; +struct KInteropReturnBuffer { + KInt length; + KNativePointer data; + void (*dispose)(KNativePointer data, KInt length); +}; + struct KLength { KByte type; KFloat value; diff --git a/interop/src/cpp/types/signatures.cc b/interop/src/cpp/types/signatures.cc index 833149e54552c2c0cb4f88966a437a25d747ac54..3d035719f51673ed3183d266358fa9bc4b0fe31a 100644 --- a/interop/src/cpp/types/signatures.cc +++ b/interop/src/cpp/types/signatures.cc @@ -63,6 +63,7 @@ KOALA_INTEROP_TYPEDEF(func, lang, "int32_t*", "[I", "int[]") \ KOALA_INTEROP_TYPEDEF(func, lang, "KInt*", "[I", "int[]") \ KOALA_INTEROP_TYPEDEF(func, lang, "KNativePointerArray", "[J", "long[]") \ + KOALA_INTEROP_TYPEDEF(func, lang, "KInteropReturnBuffer", "[B", "byte[]") \ KOALA_INTEROP_TYPEDEF(func, lang, "float*", "[F", "float[]") \ KOALA_INTEROP_TYPEDEF(func, lang, "KFloatArray", "[F", "float[]") \ KOALA_INTEROP_TYPEDEF(func, lang, "KFloat*", "[F", "float[]") \