diff --git a/unity/Assets/core/upm/Editor/Resources/puerts/xil2cpp/Puerts_il2cpp.cpp.txt b/unity/Assets/core/upm/Editor/Resources/puerts/xil2cpp/Puerts_il2cpp.cpp.txt index 1216fd2a3b..cf0c137abb 100644 --- a/unity/Assets/core/upm/Editor/Resources/puerts/xil2cpp/Puerts_il2cpp.cpp.txt +++ b/unity/Assets/core/upm/Editor/Resources/puerts/xil2cpp/Puerts_il2cpp.cpp.txt @@ -34,6 +34,7 @@ #include #include #include +#include // Because we need to hold the C# object pointer, we must ensure that GC does not do memory reorganization. static_assert(IL2CPP_GC_BOEHM, "Only BOEHM GC supported!"); @@ -42,6 +43,39 @@ using namespace il2cpp::vm; namespace puerts { + +struct CSharpMethodInfo +{ + std::string Name; + bool IsStatic; + bool IsGetter; + bool IsSetter; + std::vector OverloadDatas; +}; + +struct FieldWrapData +{ + FieldWrapFuncPtr Getter; + FieldWrapFuncPtr Setter; + FieldInfo *FieldInfo; + size_t Offset; + Il2CppClass* TypeInfo; +}; + +struct CSharpFieldInfo +{ + std::string Name; + bool IsStatic; + FieldWrapData *Data; +}; + +struct JsClassInfo : public JsClassInfoHeader +{ + std::string Name; + std::vector Ctors; + std::vector Methods; + std::vector Fields; +}; intptr_t GetMethodPointer(Il2CppReflectionMethod* method) { @@ -266,6 +300,18 @@ static void MethodCallback(pesapi_callback_info info) } } +static void GetterCallback(pesapi_callback_info info) +{ + FieldWrapData* wrapData = static_cast(pesapi_get_userdata(info)); + wrapData->Getter(info, wrapData->FieldInfo, wrapData->Offset, wrapData->TypeInfo); +} + +static void SetterCallback(pesapi_callback_info info) +{ + FieldWrapData* wrapData = static_cast(pesapi_get_userdata(info)); + wrapData->Setter(info, wrapData->FieldInfo, wrapData->Offset, wrapData->TypeInfo); +} + void GetFieldValue(void *ptr, FieldInfo *field, size_t offset, void *value) { void *src; @@ -781,7 +827,7 @@ handle_underlying: { if (IsDelegate(klass)) { - JsClassInfoHeader* jsClassInfo = g_unityExports.GetJsClassInfo(klass); + JsClassInfoHeader* jsClassInfo = g_unityExports.GetJsClassInfo(klass, true); if (!jsClassInfo) { Exception::Raise(Exception::GetInvalidOperationException("call not load type of delegate")); @@ -1699,12 +1745,7 @@ MethodPointer FindBridgeFunc(const char* signature); puerts::UnityExports* GetUnityExports() { - g_unityExports.ValueTypeDeallocate = &ValueTypeFree; - g_unityExports.MethodCallback = &MethodCallback; - g_unityExports.ConstructorCallback = &CtorCallback; - g_unityExports.DelegateConstructorCallback = &DelegateCtorCallback; g_unityExports.CSharpTypeToTypeId = &CSharpTypeToTypeId; - g_unityExports.FindBridgeFunc = FindBridgeFunc; return &g_unityExports; } @@ -1840,6 +1881,203 @@ void FindFieldWrap(const char* signature, puerts::FieldWrapFuncPtr *getter, puer } } +puerts::JsClassInfo* CreateCSharpTypeInfo(const char* name, const void* type_id, const void* super_type_id, Il2CppClass* klass, bool isValueType, bool isDelegate, const char* delegateSignature) +{ + Il2CppMethodPointer delegateBridge = nullptr; + if (isDelegate) + { + delegateBridge = puerts::FindBridgeFunc(delegateSignature); + if (!delegateBridge) return nullptr; + } + puerts::JsClassInfo* ret = new puerts::JsClassInfo(); + ret->Name = name; + ret->TypeId = type_id; + ret->SuperTypeId = super_type_id; + ret->Class = klass; + ret->IsValueType = isValueType; + ret->DelegateBridge = delegateBridge; + + return ret; +} + +void ReleaseCSharpTypeInfo(puerts::JsClassInfo* classInfo) +{ + //TODO: 有内存泄漏,需要释放里面的内容 + delete classInfo; +} + +static void SetParamArrayFlagAndOptionalNum(puerts::WrapData* data, const char* signature) +{ + data->HasParamArray = false; + data->OptionalNum = 0; + + const char* p = signature; + while(*p) + { + if (*p == 'V') + { + data->HasParamArray = true; + } + if (*p == 'D') + { + ++data->OptionalNum; + } + ++p; + } +} + +puerts::WrapData* AddConstructor(puerts::JsClassInfo* classInfo, const char* signature, puerts::WrapFuncPtr WrapFunc, MethodInfo* method, Il2CppMethodPointer methodPointer, int typeInfoNum) +{ + // puerts::PLog(puerts::LogLevel::Log, "ctor %s -> %s", classInfo->Name.c_str(), signature); + if (!WrapFunc) return nullptr; + int allocSize = sizeof(puerts::WrapData) + sizeof(void*) * typeInfoNum; + puerts::WrapData* data = (puerts::WrapData*)malloc(allocSize); + memset(data, 0, allocSize); + data->Method = method; + data->MethodPointer = methodPointer; + data->Wrap = WrapFunc; + data->IsStatic = false; + data->IsExtensionMethod = false; + SetParamArrayFlagAndOptionalNum(data, signature); + + classInfo->Ctors.push_back(data); + return data; +} + +puerts::WrapData* AddMethod(puerts::JsClassInfo* classInfo, const char* signature, puerts::WrapFuncPtr WrapFunc, const char* name, bool isStatic, bool isExtensionMethod, bool isGetter, bool isSetter, MethodInfo* method, Il2CppMethodPointer methodPointer, int typeInfoNum) +{ + if (!WrapFunc) return nullptr; + int allocSize = sizeof(puerts::WrapData) + sizeof(void*) * typeInfoNum; + puerts::WrapData* data = (puerts::WrapData*)malloc(allocSize); + memset(data, 0, allocSize); + data->Method = method; + data->MethodPointer = methodPointer; + data->Wrap = WrapFunc; + data->IsStatic = isStatic; + data->IsExtensionMethod = isExtensionMethod; + SetParamArrayFlagAndOptionalNum(data, signature); + + for(int i = 0; i < classInfo->Methods.size(); ++i) + { + if (classInfo->Methods[i].IsStatic == isStatic && classInfo->Methods[i].IsGetter == isGetter && classInfo->Methods[i].IsGetter == isGetter && classInfo->Methods[i].Name == name) + { + if (isGetter || isSetter) // no overload for getter or setter + { + free(data); + return nullptr; + } + //puerts::PLog("add overload for %s, %s", name, signature); + classInfo->Methods[i].OverloadDatas.push_back(data); + return data; + } + } + + //puerts::PLog("%s %d %d %d %p", name, typeInfoNum, allocSize, sizeof(puerts::WrapData), data); + std::vector OverloadDatas; + OverloadDatas.push_back(data); + classInfo->Methods.push_back({std::string(name), isStatic, isGetter, isSetter, std::move(OverloadDatas)}); + return data; +} + +bool AddField(puerts::JsClassInfo* classInfo, puerts::FieldWrapFuncPtr getter, puerts::FieldWrapFuncPtr setter, const char* name, bool is_static, FieldInfo* fieldInfo, int offset, Il2CppClass* fieldTypeInfo) +{ + if (!getter && !setter) + { + return false; + } + puerts::FieldWrapData* data = new puerts::FieldWrapData(); + data->Getter = getter; + data->Setter = setter; + data->FieldInfo = fieldInfo; + data->Offset = offset; + data->TypeInfo = fieldTypeInfo; + + classInfo->Fields.push_back({std::string(name), is_static, data}); + return true; +} + +void SetTypeInfo(puerts::WrapData* data, int index, Il2CppClass* typeInfo) +{ + data->TypeInfos[index] = typeInfo; +} + +bool RegisterCSharpType(puerts::JsClassInfo* classInfo) +{ + if (puerts::g_unityExports.GetJsClassInfo(classInfo->TypeId, false)) + { + ReleaseCSharpTypeInfo(classInfo); + return true; + } + + classInfo->Ctors.push_back(nullptr); + classInfo->CtorWrapDatas = classInfo->Ctors.data(); + + std::map> gseters; + std::vector methods; + + for (auto & method : classInfo->Methods) + { + method.OverloadDatas.push_back(nullptr); + + if (method.IsGetter || method.IsSetter) + { + auto iter = gseters.find(method.Name); + if (iter == gseters.end()) + { + gseters[method.Name] = std::make_pair(method.IsGetter ? &method : nullptr, method.IsSetter ? &method : nullptr); + } + else + { + if (method.IsGetter) + { + iter->second.first = &method; + } + else + { + iter->second.second = &method; + } + } + } + else + { + methods.push_back(&method); + } + //puerts::WrapData** wrapDatas = reinterpret_cast(method.OverloadDatas.data()); + } + + size_t propertiesCount = gseters.size() + methods.size() + classInfo->Fields.size(); + auto properties = pesapi_alloc_property_descriptors(propertiesCount); + size_t pos = 0; + + for (auto const& method: methods) + { + pesapi_set_method_info( + properties, pos++, method->Name.c_str(), method->IsStatic, &puerts::MethodCallback, method->OverloadDatas.data(), nullptr); + } + + for (auto const& kv: gseters) + { + auto geter_or_setter = kv.second.first ? kv.second.first : kv.second.second; + pesapi_set_property_info(properties, pos++, geter_or_setter->Name.c_str(), geter_or_setter->IsStatic, + kv.second.first ? &puerts::MethodCallback : nullptr, + kv.second.second ? &puerts::MethodCallback : nullptr, + kv.second.first ? kv.second.first->OverloadDatas.data() : nullptr, + kv.second.second ? kv.second.second->OverloadDatas.data() : nullptr, + nullptr); + } + + for (auto & field : classInfo->Fields) + { + pesapi_set_property_info(properties, pos++, field.Name.c_str(), field.IsStatic, + puerts::GetterCallback, puerts::SetterCallback, field.Data, field.Data, nullptr); + } + + pesapi_define_class(classInfo->TypeId, classInfo->SuperTypeId, classInfo->Name.c_str(), + classInfo->DelegateBridge ? &puerts::DelegateCtorCallback : &puerts::CtorCallback, classInfo->IsValueType ? &puerts::ValueTypeFree : (pesapi_finalize)nullptr, propertiesCount, properties, classInfo); + + return true; +} + #ifdef __cplusplus } #endif diff --git a/unity/Assets/core/upm/Editor/Resources/puerts/xil2cpp/UnityExports4Puerts.h.txt b/unity/Assets/core/upm/Editor/Resources/puerts/xil2cpp/UnityExports4Puerts.h.txt index 0d80fac3ab..a90fd92dd1 100644 --- a/unity/Assets/core/upm/Editor/Resources/puerts/xil2cpp/UnityExports4Puerts.h.txt +++ b/unity/Assets/core/upm/Editor/Resources/puerts/xil2cpp/UnityExports4Puerts.h.txt @@ -20,10 +20,8 @@ struct PObjectRefInfo #if defined(USE_OUTSIZE_UNITY) typedef void (*MethodPointer)(); -typedef void (*ValueTypeDeallocateFunc)(void* ptr); typedef void MethodType; typedef bool (*WrapFuncPtr)(MethodType* method, MethodPointer methodPointer, const v8::FunctionCallbackInfo& info, bool checkArgument, struct WrapData* wrapData); -typedef v8::FunctionCallback FunctionCallbackFunc; typedef void (*FieldWrapFuncPtr)(const v8::FunctionCallbackInfo& info, void* fieldInfo, size_t offset, void* typeInfo); @@ -41,11 +39,8 @@ typedef v8::Value* (*GetModuleExecutorFunc)(v8::Context* env); #define MethodPointer Il2CppMethodPointer -typedef void (*ValueTypeDeallocateFunc)(void* ptr); typedef MethodInfo MethodType; typedef bool (*WrapFuncPtr)(MethodType* method, Il2CppMethodPointer methodPointer, pesapi_callback_info info, bool checkArgument, struct WrapData* wrapData); -typedef pesapi_callback FunctionCallbackFunc; -typedef pesapi_constructor InitializeFunc; typedef void (*FieldWrapFuncPtr)(pesapi_callback_info info, FieldInfo* field, size_t offset, Il2CppClass* fieldType); typedef Il2CppClass TypeIdType; @@ -60,18 +55,12 @@ typedef pesapi_value (*GetModuleExecutorFunc)(pesapi_env env); #endif -typedef struct JsClassInfoHeader* (*GetJsClassInfoFunc)(const void* TypeId); +typedef struct JsClassInfoHeader* (*GetJsClassInfoFunc)(const void* TypeId, bool TryLazyLoad); typedef void* (*GetRuntimeObjectFromPersistentObjectFunc)(pesapi_env env, pesapi_value pvalue); typedef void (*SetRuntimeObjectToPersistentObjectFunc)(pesapi_env env, pesapi_value pvalue, void* runtimeObject); -typedef WrapFuncPtr (*FindWrapFuncFunc)(const char* signature); - -typedef struct FieldWrapFuncInfo * (*FindFieldWrapFuncInfoFunc)(const char* signature); - -typedef MethodPointer (*FindBridgeFuncFunc)(const char* signature); - typedef void(*LogCallbackFunc)(const char* value); typedef void (*SetExtraDataFunc)(pesapi_env env, struct PObjectRefInfo* objectInfo); @@ -101,12 +90,7 @@ struct JsClassInfoHeader struct UnityExports { //.cpp api - ValueTypeDeallocateFunc ValueTypeDeallocate = nullptr; - FunctionCallbackFunc MethodCallback = nullptr; - InitializeFunc ConstructorCallback = nullptr; - InitializeFunc DelegateConstructorCallback = nullptr; CSharpTypeToTypeIdFunc CSharpTypeToTypeId = nullptr; - FindBridgeFuncFunc FindBridgeFunc = nullptr; //plugin api diff --git a/unity/Assets/core/upm/Runtime/Src/IL2Cpp/Native/NativeAPI.cs b/unity/Assets/core/upm/Runtime/Src/IL2Cpp/Native/NativeAPI.cs index 1815041695..8e5229ccbf 100644 --- a/unity/Assets/core/upm/Runtime/Src/IL2Cpp/Native/NativeAPI.cs +++ b/unity/Assets/core/upm/Runtime/Src/IL2Cpp/Native/NativeAPI.cs @@ -56,10 +56,10 @@ public class NativeAPI [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr GetIsolate(IntPtr jsEnv); - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] + [DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr CreateCSharpTypeInfo(string name, IntPtr type_id, IntPtr super_type_id, IntPtr klass, bool isValueType, bool isDelegate, string delegateSignature); - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] + [DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)] public static extern void ReleaseCSharpTypeInfo(IntPtr classInfo); [DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)] @@ -68,24 +68,24 @@ public class NativeAPI [DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)] public static extern void FindFieldWrap(string signature, out IntPtr getter, out IntPtr setter); - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] + [DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr AddConstructor(IntPtr classInfo, string signature, IntPtr WrapFunc, IntPtr method, IntPtr methodPointer, int typeInfoNum); - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] + [DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr AddMethod(IntPtr classInfo, string signature, IntPtr WrapFunc, string name, bool isStatic, bool isExtensionethod, bool isGetter, bool isSetter, IntPtr method, IntPtr methodPointer, int typeInfoNum); - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] + [DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)] public static extern bool AddField(IntPtr classInfo, IntPtr getter, IntPtr setter, string name, bool isStatic, IntPtr fieldInfo, int offset, IntPtr fieldTypeInfo); - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] + [DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)] public static extern void SetTypeInfo(IntPtr wrapData, int index, IntPtr typeId); + [DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)] + public static extern bool RegisterCSharpType(IntPtr classInfo); + [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] public static extern void ExchangeAPI(IntPtr exports); - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern bool RegisterCSharpType(IntPtr classInfo); - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] public static extern void SetObjectPool(IntPtr jsEnv, IntPtr objectPoolAddMethodInfo, IntPtr objectPoolAdd, IntPtr objectPoolRemoveMethodInfo, IntPtr objectPoolRemove, IntPtr objectPoolInstance); diff --git a/unity/cli/UnityExports4Puerts.h b/unity/cli/UnityExports4Puerts.h index 22df51d5df..fcdfce9d80 100644 --- a/unity/cli/UnityExports4Puerts.h +++ b/unity/cli/UnityExports4Puerts.h @@ -20,10 +20,8 @@ struct PObjectRefInfo #if defined(USE_OUTSIZE_UNITY) typedef void (*MethodPointer)(); -typedef void (*ValueTypeDeallocateFunc)(void* ptr); typedef void MethodType; typedef bool (*WrapFuncPtr)(MethodType* method, MethodPointer methodPointer, const v8::FunctionCallbackInfo& info, bool checkArgument, struct WrapData* wrapData); -typedef v8::FunctionCallback FunctionCallbackFunc; typedef void (*FieldWrapFuncPtr)(const v8::FunctionCallbackInfo& info, void* fieldInfo, size_t offset, void* typeInfo); @@ -41,11 +39,8 @@ typedef v8::Value* (*GetModuleExecutorFunc)(v8::Context* env); #define MethodPointer Il2CppMethodPointer -typedef void (*ValueTypeDeallocateFunc)(void* ptr); typedef MethodInfo MethodType; typedef bool (*WrapFuncPtr)(MethodType* method, Il2CppMethodPointer methodPointer, pesapi_callback_info info, bool checkArgument, struct WrapData* wrapData); -typedef pesapi_callback FunctionCallbackFunc; -typedef pesapi_constructor InitializeFunc; typedef void (*FieldWrapFuncPtr)(pesapi_callback_info info, FieldInfo* field, size_t offset, Il2CppClass* fieldType); typedef Il2CppClass TypeIdType; @@ -60,18 +55,12 @@ typedef pesapi_value (*GetModuleExecutorFunc)(pesapi_env env); #endif -typedef struct JsClassInfoHeader* (*GetJsClassInfoFunc)(const void* TypeId); +typedef struct JsClassInfoHeader* (*GetJsClassInfoFunc)(const void* TypeId, bool TryLazyLoad); typedef void* (*GetRuntimeObjectFromPersistentObjectFunc)(pesapi_env env, pesapi_value pvalue); typedef void (*SetRuntimeObjectToPersistentObjectFunc)(pesapi_env env, pesapi_value pvalue, void* runtimeObject); -typedef WrapFuncPtr (*FindWrapFuncFunc)(const char* signature); - -typedef struct FieldWrapFuncInfo * (*FindFieldWrapFuncInfoFunc)(const char* signature); - -typedef MethodPointer (*FindBridgeFuncFunc)(const char* signature); - typedef void(*LogCallbackFunc)(const char* value); typedef void (*SetExtraDataFunc)(pesapi_env env, struct PObjectRefInfo* objectInfo); @@ -101,12 +90,7 @@ struct JsClassInfoHeader struct UnityExports { //.cpp api - ValueTypeDeallocateFunc ValueTypeDeallocate = nullptr; - FunctionCallbackFunc MethodCallback = nullptr; - InitializeFunc ConstructorCallback = nullptr; - InitializeFunc DelegateConstructorCallback = nullptr; CSharpTypeToTypeIdFunc CSharpTypeToTypeId = nullptr; - FindBridgeFuncFunc FindBridgeFunc = nullptr; //plugin api diff --git a/unity/native_src_il2cpp/Src/Puerts.cpp b/unity/native_src_il2cpp/Src/Puerts.cpp index ca5044cab9..c8f2d66d93 100644 --- a/unity/native_src_il2cpp/Src/Puerts.cpp +++ b/unity/native_src_il2cpp/Src/Puerts.cpp @@ -172,9 +172,9 @@ static void SetRuntimeObjectToPersistentObject(pesapi_env env, pesapi_value pval } -static JsClassInfoHeader* GetJsClassInfo(const void* TypeId) +static JsClassInfoHeader* GetJsClassInfo(const void* TypeId, bool TryLazyLoad) { - auto ClassDefinition = FindClassByID(TypeId, true); + auto ClassDefinition = FindClassByID(TypeId, TryLazyLoad); if (!ClassDefinition) { return nullptr; @@ -387,252 +387,6 @@ V8_EXPORT pesapi_env_ref GetPesapiEnvHolder(puerts::JSEnv* jsEnv) return pesapi_create_env_ref(env); } -V8_EXPORT puerts::JsClassInfo* CreateCSharpTypeInfo(const char* name, const void* type_id, const void* super_type_id, void* klass, bool isValueType, bool isDelegate, const char* delegateSignature) -{ - puerts::MethodPointer delegateBridge = nullptr; - if (isDelegate) - { - delegateBridge = puerts::GUnityExports.FindBridgeFunc(delegateSignature); - if (!delegateBridge) return nullptr; - } - puerts::JsClassInfo* ret = new puerts::JsClassInfo(); - ret->Name = name; - ret->TypeId = type_id; - ret->SuperTypeId = super_type_id; - ret->Class = klass; - ret->IsValueType = isValueType; - ret->DelegateBridge = delegateBridge; - - return ret; -} - -V8_EXPORT void ReleaseCSharpTypeInfo(puerts::JsClassInfo* classInfo) -{ - //TODO: 有内存泄漏,需要释放里面的内容 - delete classInfo; -} - -static void SetParamArrayFlagAndOptionalNum(puerts::WrapData* data, const char* signature) -{ - data->HasParamArray = false; - data->OptionalNum = 0; - - const char* p = signature; - while(*p) - { - if (*p == 'V') - { - data->HasParamArray = true; - } - if (*p == 'D') - { - ++data->OptionalNum; - } - ++p; - } -} - -V8_EXPORT puerts::WrapData* AddConstructor(puerts::JsClassInfo* classInfo, const char* signature, puerts::WrapFuncPtr WrapFunc, void* method, puerts::MethodPointer methodPointer, int typeInfoNum) -{ - // puerts::PLog(puerts::LogLevel::Log, "ctor %s -> %s", classInfo->Name.c_str(), signature); - if (!WrapFunc) return nullptr; - int allocSize = sizeof(puerts::WrapData) + sizeof(void*) * typeInfoNum; - puerts::WrapData* data = (puerts::WrapData*)malloc(allocSize); - memset(data, 0, allocSize); - data->Method = method; - data->MethodPointer = methodPointer; - data->Wrap = WrapFunc; - data->IsStatic = false; - data->IsExtensionMethod = false; - SetParamArrayFlagAndOptionalNum(data, signature); - - classInfo->Ctors.push_back(data); - return data; -} - -V8_EXPORT puerts::WrapData* AddMethod(puerts::JsClassInfo* classInfo, const char* signature, puerts::WrapFuncPtr WrapFunc, const char* name, bool isStatic, bool isExtensionMethod, bool isGetter, bool isSetter, void* method, puerts::MethodPointer methodPointer, int typeInfoNum) -{ - if (!WrapFunc) return nullptr; - int allocSize = sizeof(puerts::WrapData) + sizeof(void*) * typeInfoNum; - puerts::WrapData* data = (puerts::WrapData*)malloc(allocSize); - memset(data, 0, allocSize); - data->Method = method; - data->MethodPointer = methodPointer; - data->Wrap = WrapFunc; - data->IsStatic = isStatic; - data->IsExtensionMethod = isExtensionMethod; - SetParamArrayFlagAndOptionalNum(data, signature); - - for(int i = 0; i < classInfo->Methods.size(); ++i) - { - if (classInfo->Methods[i].IsStatic == isStatic && classInfo->Methods[i].IsGetter == isGetter && classInfo->Methods[i].IsGetter == isGetter && classInfo->Methods[i].Name == name) - { - if (isGetter || isSetter) // no overload for getter or setter - { - free(data); - return nullptr; - } - //puerts::PLog("add overload for %s, %s", name, signature); - classInfo->Methods[i].OverloadDatas.push_back(data); - return data; - } - } - - //puerts::PLog("%s %d %d %d %p", name, typeInfoNum, allocSize, sizeof(puerts::WrapData), data); - std::vector OverloadDatas; - OverloadDatas.push_back(data); - classInfo->Methods.push_back({std::string(name), isStatic, isGetter, isSetter, std::move(OverloadDatas)}); - return data; -} - -V8_EXPORT bool AddField(puerts::JsClassInfo* classInfo, puerts::FieldWrapFuncPtr getter, puerts::FieldWrapFuncPtr setter, const char* name, bool is_static, void* fieldInfo, int offset, void* fieldTypeInfo) -{ - if (!getter && !setter) - { - return false; - } - puerts::FieldWrapData* data = new puerts::FieldWrapData(); - data->Getter = getter; - data->Setter = setter; - data->FieldInfo = fieldInfo; - data->Offset = offset; - data->TypeInfo = fieldTypeInfo; - - classInfo->Fields.push_back({std::string(name), is_static, data}); - return true; -} - -V8_EXPORT void SetTypeInfo(puerts::WrapData* data, int index, void* typeInfo) -{ - data->TypeInfos[index] = typeInfo; -} - -V8_EXPORT bool RegisterCSharpType(puerts::JsClassInfo* classInfo) -{ - std::lock_guard guard(puerts::RegisterMutex()); - if (puerts::FindClassByID(classInfo->TypeId)) - { - ReleaseCSharpTypeInfo(classInfo); - return true; - } - - puerts::JSClassDefinition ClassDef = JSClassEmptyDefinition; - ClassDef.ScriptName = classInfo->Name.c_str(); - ClassDef.TypeId = classInfo->TypeId; - ClassDef.SuperTypeId = classInfo->SuperTypeId; - - ClassDef.Initialize = classInfo->DelegateBridge ? puerts::GUnityExports.DelegateConstructorCallback : puerts::GUnityExports.ConstructorCallback; - ClassDef.Finalize = classInfo->IsValueType ? puerts::GUnityExports.ValueTypeDeallocate : (puerts::FinalizeFunc)nullptr; - ClassDef.Data = classInfo; - - classInfo->Ctors.push_back(nullptr); - classInfo->CtorWrapDatas = classInfo->Ctors.data(); - - std::vector functions{}; - - std::vector methods{}; - - std::vector properties{}; - - std::vector variables{}; - - std::map> gseters; - - for (auto & method : classInfo->Methods) - { - method.OverloadDatas.push_back(nullptr); - - if (method.IsGetter || method.IsSetter) - { - auto iter = gseters.find(method.Name); - if (iter == gseters.end()) - { - gseters[method.Name] = std::make_pair(method.IsGetter ? &method : nullptr, method.IsSetter ? &method : nullptr); - } - else - { - if (method.IsGetter) - { - iter->second.first = &method; - } - else - { - iter->second.second = &method; - } - } - } - else - { - if (method.IsStatic) - { - //puerts::PLog("add static method [%s]", method.Name.c_str()); - functions.push_back(puerts::JSFunctionInfo{method.Name.c_str(), puerts::GUnityExports.MethodCallback, method.OverloadDatas.data()}); - } - else - { - //puerts::PLog("add instance method [%s]", method.Name.c_str()); - methods.push_back(puerts::JSFunctionInfo{method.Name.c_str(), puerts::GUnityExports.MethodCallback, method.OverloadDatas.data()}); - } - } - //puerts::WrapData** wrapDatas = reinterpret_cast(method.OverloadDatas.data()); - } - - for (auto const& kv: gseters) - { - auto geter_or_setter = kv.second.first ? kv.second.first : kv.second.second; - if (geter_or_setter->IsStatic) - { - variables.push_back(puerts::JSPropertyInfo{ - geter_or_setter->Name.c_str(), - kv.second.first ? puerts::GUnityExports.MethodCallback : nullptr, - kv.second.second ? puerts::GUnityExports.MethodCallback: nullptr, - kv.second.first ? kv.second.first->OverloadDatas.data() : nullptr, - kv.second.second ? kv.second.second->OverloadDatas.data() : nullptr - }); - } - else - { - properties.push_back(puerts::JSPropertyInfo{ - geter_or_setter->Name.c_str(), - kv.second.first ? puerts::GUnityExports.MethodCallback : nullptr, - kv.second.second ? puerts::GUnityExports.MethodCallback: nullptr, - kv.second.first ? kv.second.first->OverloadDatas.data() : nullptr, - kv.second.second ? kv.second.second->OverloadDatas.data() : nullptr - }); - } - } - - for (auto & field : classInfo->Fields) - { - if (field.IsStatic) - { - variables.push_back(puerts::JSPropertyInfo{field.Name.c_str(), puerts::GetterCallback, puerts::SetterCallback, field.Data, field.Data}); - } - else - { - properties.push_back(puerts::JSPropertyInfo{field.Name.c_str(), puerts::GetterCallback, puerts::SetterCallback, field.Data, field.Data}); - } - } - - functions.push_back({nullptr, nullptr, nullptr}); - ClassDef.Functions = functions.data(); - //puerts::PLog("static size %d", (int)functions.size()); - - methods.push_back({nullptr, nullptr, nullptr}); - ClassDef.Methods = methods.data(); - //puerts::PLog("instance size %d", (int)methods.size()); - - properties.push_back({nullptr, nullptr, nullptr, nullptr}); - ClassDef.Properties = properties.data(); - - variables.push_back({nullptr, nullptr, nullptr, nullptr}); - ClassDef.Variables = variables.data(); - - puerts::RegisterJSClass(ClassDef); - - return true; -} - V8_EXPORT void ExchangeAPI(puerts::UnityExports * exports) { exports->SetNativePtr = &puerts::SetNativePtr;