Skip to content

Commit

Permalink
[unity]p-api全部代码切换成和标准的一样,不再把objectPool传入原生plugin持有,对象引用和释放改为通过pesapi…
Browse files Browse the repository at this point in the history
…_trace_native_object_lifecycle在Puerts_il2cpp里实现
  • Loading branch information
chexiongsheng committed Oct 23, 2024
1 parent c2a476f commit 6d5a0b7
Show file tree
Hide file tree
Showing 14 changed files with 353 additions and 213 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,10 @@ void* GetDefaultValuePtr(const MethodInfo* method, uint32_t index)
return (defaultValue && Class::IsValuetype(Class::FromIl2CppType(Method::GetParam(method, index), false))) ? Object::Unbox(defaultValue) : defaultValue;
}

typedef void(*LogCallbackFunc)(const char* value);

static LogCallbackFunc GLogCallback = nullptr;

void PLog(const char* Fmt, ...)
{
static char SLogBuffer[1024];
Expand All @@ -433,10 +437,10 @@ void PLog(const char* Fmt, ...)
vsnprintf(SLogBuffer, sizeof(SLogBuffer), Fmt, list);
va_end(list);

//if (g_unityExports.LogCallback)
//{
// g_unityExports.LogCallback(SLogBuffer);
//}
if (GLogCallback)
{
GLogCallback(SLogBuffer);
}
}

static void* CtorCallback(pesapi_callback_info info)
Expand Down Expand Up @@ -1842,15 +1846,18 @@ Il2CppObject* GetModuleExecutor(intptr_t ptr, Il2CppReflectionType* rtype)
return JsValueToCSRef(type, env, func);
}

struct ScriptObjectsRefsMgr
struct JsEnvPrivate
{
pesapi_env_ref envRef;
std::mutex pendingKillRefsMutex;
std::unordered_set<pesapi_value_ref> pendingKillRefs;
MethodInfoHelper<int32_t(Il2CppObject* obj)> objPoolAdd;
MethodInfoHelper<Il2CppObject*(int32_t index)> objPoolRemove;

ScriptObjectsRefsMgr(pesapi_env_ref inEnvRef)
JsEnvPrivate(pesapi_env_ref inEnvRef, Il2CppObject *objPool, Il2CppReflectionMethod* objPoolAddMethodInfo, Il2CppReflectionMethod* objPoolRemoveMethodInfo)
: envRef(inEnvRef), objPoolAdd(objPoolAddMethodInfo, objPool), objPoolRemove(objPoolRemoveMethodInfo, objPool)

{
envRef = inEnvRef;
}

void AddPendingKillScriptObjects(pesapi_value_ref valueRef)
Expand Down Expand Up @@ -1899,8 +1906,29 @@ struct ScriptObjectsRefsMgr

pendingKillRefs.clear();
}

int32_t RefCSObject(Il2CppObject* obj)
{
return objPoolAdd.CallWithInstance(obj);
}

void UnRefCSObject(int32_t idx)
{
objPoolRemove.CallWithInstance(idx);
}
};

static void* OnCsObjectEnter(Il2CppObject* obj, const void* type_id, JsEnvPrivate* jsEnvPrivate)
{
return reinterpret_cast<void*>(jsEnvPrivate->RefCSObject(obj));
}

static void OnCsObjectExit(void* ptr, const void* type_id, JsEnvPrivate* jsEnvPrivate, void* userdata)
{
intptr_t idx = reinterpret_cast<intptr_t>(userdata);
jsEnvPrivate->UnRefCSObject(idx);
}

static void LoadTypeWrapper(pesapi_callback_info info)
{
pesapi_env env = pesapi_get_env(info);
Expand All @@ -1910,20 +1938,20 @@ static void LoadTypeWrapper(pesapi_callback_info info)
pesapi_add_return(info, ret);
}

puerts::ScriptObjectsRefsMgr* InitialPapiEnvRef(pesapi_env_ref envRef)
puerts::JsEnvPrivate* InitialPapiEnvRef(pesapi_env_ref envRef, Il2CppObject *objPool, Il2CppReflectionMethod* objPoolAddMethodInfo, Il2CppReflectionMethod* objPoolRemoveMethodInfo)
{
puerts::AutoValueScope ValueScope(envRef);
auto env = pesapi_get_env_from_ref(envRef);
auto mgr = new puerts::ScriptObjectsRefsMgr(envRef);
pesapi_set_env_private(env, mgr);
auto jsEnvPrivate = new puerts::JsEnvPrivate(envRef, objPool, objPoolAddMethodInfo, objPoolRemoveMethodInfo);
pesapi_set_env_private(env, jsEnvPrivate);
auto func = pesapi_create_function(env, LoadTypeWrapper, nullptr);
if (func)
{
pesapi_value global = pesapi_global(env);
if (global)
{
pesapi_set_property(env, global, "loadType", func);
return mgr;
return jsEnvPrivate;
}
}
Exception::Raise(Exception::GetInvalidOperationException("can not init global.loadType"));
Expand All @@ -1934,9 +1962,9 @@ void CleanupPapiEnvRef(pesapi_env_ref envRef)
{
puerts::AutoValueScope ValueScope(envRef);
auto env = pesapi_get_env_from_ref(envRef);
auto scriptObjectsRefsMgr = (puerts::ScriptObjectsRefsMgr*)pesapi_get_env_private(env);
scriptObjectsRefsMgr->CleanupPendingKillScriptObjects();
delete scriptObjectsRefsMgr;
auto jsEnvPrivate = (puerts::JsEnvPrivate*)pesapi_get_env_private(env);
jsEnvPrivate->CleanupPendingKillScriptObjects();
delete jsEnvPrivate;
pesapi_release_env_ref(envRef);
}

Expand All @@ -1963,27 +1991,27 @@ void InitialPuerts(pesapi_func_ptr* func_array)
InternalCalls::Add("PuertsIl2cpp.NativeAPI::SetObjectToGlobal(System.IntPtr,System.String,System.Object)", (Il2CppMethodPointer)puerts::SetObjectToGlobal);
InternalCalls::Add("PuertsIl2cpp.NativeAPI::TypeIdToType(System.IntPtr)", (Il2CppMethodPointer)puerts::TypeIdToType);
InternalCalls::Add("PuertsIl2cpp.NativeAPI::GetModuleExecutor(System.IntPtr,System.Type)", (Il2CppMethodPointer)puerts::GetModuleExecutor);
InternalCalls::Add("PuertsIl2cpp.NativeAPI::InitialPapiEnvRef(System.IntPtr)", (Il2CppMethodPointer)puerts::InitialPapiEnvRef);
InternalCalls::Add("PuertsIl2cpp.NativeAPI::InitialPapiEnvRef(System.IntPtr,System.Object,System.Reflection.MethodBase,System.Reflection.MethodBase)", (Il2CppMethodPointer)puerts::InitialPapiEnvRef);
InternalCalls::Add("PuertsIl2cpp.NativeAPI::CleanupPapiEnvRef(System.IntPtr)", (Il2CppMethodPointer)puerts::CleanupPapiEnvRef);
InternalCalls::Add("Puerts.JSObject::GetJSObjectValue(System.String,System.Type)", (Il2CppMethodPointer)puerts::GetJSObjectValue);
InternalCalls::Add("PuertsIl2cpp.NativeAPI::SetRegisterNoThrow(System.Reflection.MethodBase)", (Il2CppMethodPointer)puerts::SetRegisterNoThrow);
pesapi_init(func_array);
}

void AddPendingKillScriptObjects(puerts::ScriptObjectsRefsMgr* mgr, pesapi_value_ref valueRef)
void AddPendingKillScriptObjects(puerts::JsEnvPrivate* jsEnvPrivate, pesapi_value_ref valueRef)
{
pesapi_env_ref envRef = pesapi_get_ref_associated_env(valueRef);
if (!pesapi_env_ref_is_valid(envRef)) // jsEnv已经释放
{
pesapi_release_value_ref(valueRef);
return;
}
mgr->AddPendingKillScriptObjects(valueRef);
jsEnvPrivate->AddPendingKillScriptObjects(valueRef);
}

void CleanupPendingKillScriptObjects(puerts::ScriptObjectsRefsMgr* mgr)
void CleanupPendingKillScriptObjects(puerts::JsEnvPrivate* jsEnvPrivate)
{
mgr->CleanupPendingKillScriptObjects();
jsEnvPrivate->CleanupPendingKillScriptObjects();
}

puerts::WrapFuncPtr FindWrapFunc(const char* signature)
Expand Down Expand Up @@ -2218,11 +2246,21 @@ bool RegisterCSharpType(puerts::JsClassInfo* classInfo)
}

pesapi_define_class(classInfo->TypeId, classInfo->SuperTypeId, classInfo->Name.c_str(),
classInfo->DelegateBridge ? &puerts::DelegateCtorCallback : &puerts::CtorCallback, classInfo->IsValueType ? &puerts::PApiFree : (pesapi_finalize)nullptr, propertiesCount, properties, classInfo);
classInfo->DelegateBridge ? &puerts::DelegateCtorCallback : &puerts::CtorCallback, classInfo->IsValueType ? (pesapi_finalize)&puerts::PApiFree : (pesapi_finalize)nullptr, propertiesCount, properties, classInfo);

if (!classInfo->IsValueType)
{
pesapi_trace_native_object_lifecycle(classInfo->TypeId, (pesapi_on_native_object_enter)&puerts::OnCsObjectEnter, (pesapi_on_native_object_exit)&puerts::OnCsObjectExit);
}

return true;
}

void SetLogCallbackInternal(puerts::LogCallbackFunc Log)
{
puerts::GLogCallback = Log;
}

#ifdef __cplusplus
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,10 @@ typedef struct pesapi_property_descriptor__* pesapi_property_descriptor;

typedef void (*pesapi_callback)(pesapi_callback_info info);
typedef void* (*pesapi_constructor)(pesapi_callback_info info);
typedef void (*pesapi_finalize)(void* ptr, void* class_data, void* env_private);
typedef void (*pesapi_finalize)(void* ptr, const void* type_id, void* env_private);
typedef void* (*pesapi_on_native_object_enter)(void* ptr, const void* type_id, void* env_private);
// userdata: return of pesapi_on_native_object_enter
typedef void (*pesapi_on_native_object_exit)(void* ptr, const void* type_id, void* env_private, void* userdata);
typedef bool (*pesapi_class_not_found_callback)(const void* type_id);
typedef void (*pesapi_func_ptr)(void);

Expand Down Expand Up @@ -260,6 +263,9 @@ PESAPI_EXTERN void pesapi_define_class(const void* type_id, const void* super_ty

PESAPI_EXTERN void* pesapi_get_class_data(const void* type_id, bool force_load);

PESAPI_EXTERN bool pesapi_trace_native_object_lifecycle(
const void* type_id, pesapi_on_native_object_enter on_enter, pesapi_on_native_object_exit on_exit);

PESAPI_EXTERN void pesapi_on_class_not_found(pesapi_class_not_found_callback callback);

PESAPI_EXTERN void pesapi_class_type_info(const char* proto_magic_id, const void* type_id, const void* constructor_info,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,12 @@ void* pesapi_get_class_data (const void* type_id, bool force_load) {
return pesapi_get_class_data_ptr(type_id, force_load);
}

typedef bool (*pesapi_trace_native_object_lifecycleType)(const void* type_id, pesapi_on_native_object_enter on_enter, pesapi_on_native_object_exit on_exit);
static pesapi_trace_native_object_lifecycleType pesapi_trace_native_object_lifecycle_ptr;
bool pesapi_trace_native_object_lifecycle (const void* type_id, pesapi_on_native_object_enter on_enter, pesapi_on_native_object_exit on_exit) {
return pesapi_trace_native_object_lifecycle_ptr(type_id, on_enter, on_exit);
}

typedef void (*pesapi_on_class_not_foundType)(pesapi_class_not_found_callback callback);
static pesapi_on_class_not_foundType pesapi_on_class_not_found_ptr;
void pesapi_on_class_not_found (pesapi_class_not_found_callback callback) {
Expand Down Expand Up @@ -676,9 +682,10 @@ void pesapi_init(pesapi_func_ptr* func_array){
pesapi_set_property_info_ptr = (pesapi_set_property_infoType)func_array[88];
pesapi_define_class_ptr = (pesapi_define_classType)func_array[89];
pesapi_get_class_data_ptr = (pesapi_get_class_dataType)func_array[90];
pesapi_on_class_not_found_ptr = (pesapi_on_class_not_foundType)func_array[91];
pesapi_class_type_info_ptr = (pesapi_class_type_infoType)func_array[92];
pesapi_find_type_id_ptr = (pesapi_find_type_idType)func_array[93];
pesapi_trace_native_object_lifecycle_ptr = (pesapi_trace_native_object_lifecycleType)func_array[91];
pesapi_on_class_not_found_ptr = (pesapi_on_class_not_foundType)func_array[92];
pesapi_class_type_info_ptr = (pesapi_class_type_infoType)func_array[93];
pesapi_find_type_id_ptr = (pesapi_find_type_idType)func_array[94];

#endif
}
Expand Down
10 changes: 2 additions & 8 deletions unity/Assets/core/upm/Runtime/Src/IL2Cpp/JsEnv.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,8 @@ public JsEnv(ILoader loader, int debugPort = -1)

nativeJsEnv = PuertsIl2cpp.NativeAPI.CreateNativeJSEnv();
nativePesapiEnv = PuertsIl2cpp.NativeAPI.GetPapiEnvRef(nativeJsEnv);
nativeScriptObjectsRefsMgr = PuertsIl2cpp.NativeAPI.InitialPapiEnvRef(nativePesapiEnv);

//PuertsIl2cpp.NativeAPI.SetObjectPool(objectPool, typeof(PuertsIl2cpp.ObjectPool).GetMethod("Add")); //TODO: remove....
objectPoolAddMethodInfo = typeof(PuertsIl2cpp.ObjectPool).GetMethod("Add");
objectPoolRemoveMethodInfo = typeof(PuertsIl2cpp.ObjectPool).GetMethod("Remove");
PuertsIl2cpp.NativeAPI.SetObjectPool(nativeJsEnv, PuertsIl2cpp.NativeAPI.GetMethodInfoPointer(objectPoolAddMethodInfo), PuertsIl2cpp.NativeAPI.GetMethodPointer(objectPoolAddMethodInfo),
PuertsIl2cpp.NativeAPI.GetMethodInfoPointer(objectPoolRemoveMethodInfo), PuertsIl2cpp.NativeAPI.GetMethodPointer(objectPoolRemoveMethodInfo),
PuertsIl2cpp.NativeAPI.GetObjectPointer(objectPool));
var objectPoolType = typeof(PuertsIl2cpp.ObjectPool);
nativeScriptObjectsRefsMgr = PuertsIl2cpp.NativeAPI.InitialPapiEnvRef(nativePesapiEnv, objectPool, objectPoolType.GetMethod("Add"), objectPoolType.GetMethod("Remove"));

PuertsIl2cpp.NativeAPI.SetObjectToGlobal(nativePesapiEnv, "jsEnv", this);

Expand Down
12 changes: 8 additions & 4 deletions unity/Assets/core/upm/Runtime/Src/IL2Cpp/Native/NativeAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public class NativeAPI
public static extern IntPtr GetPapiEnvRef(IntPtr jsEnv);

[MethodImpl(MethodImplOptions.InternalCall)]
public static IntPtr InitialPapiEnvRef(IntPtr envRef)
public static IntPtr InitialPapiEnvRef(IntPtr envRef, Object obj, MethodBase addMethodBase, MethodBase removeMethodBase)
{
throw new NotImplementedException();
}
Expand Down Expand Up @@ -92,8 +92,8 @@ public static void CleanupPapiEnvRef(IntPtr envRef)
[DllImport("__Internal", 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);
//[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
//public static extern void SetObjectPool(IntPtr jsEnv, IntPtr objectPoolAddMethodInfo, IntPtr objectPoolAdd, IntPtr objectPoolRemoveMethodInfo, IntPtr objectPoolRemove, IntPtr objectPoolInstance);

[MethodImpl(MethodImplOptions.InternalCall)]
public static void SetRegisterNoThrow(MethodBase methodInfo)
Expand Down Expand Up @@ -217,6 +217,9 @@ public static void LogImpl(string msg)

[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern void SetLogCallback(IntPtr log);

[DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)]
public static extern void SetLogCallbackInternal(IntPtr log);

//[UnityEngine.Scripting.RequiredByNativeCodeAttribute()]
public static void SetLogCallback(LogCallback log)
Expand All @@ -228,7 +231,8 @@ public static void SetLogCallback(LogCallback log)

try
{
SetLogCallback(fn1);
SetLogCallback(fn1);
SetLogCallbackInternal(fn1);
}
catch(DllNotFoundException)
{
Expand Down
67 changes: 34 additions & 33 deletions unity/native_src_il2cpp/Inc/CppObjectMapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,41 @@

#pragma once

#include "NamespaceDef.h"

PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
#pragma warning(push, 0)
#include "v8.h"
#pragma warning(pop)
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS

#include <map>
#include <unordered_map>
#include "JSClassRegister.h"
#include "ObjectCacheNode.h"
#include "ObjectMapper.h"

namespace puerts
namespace PUERTS_NAMESPACE
{
struct PointerHash
{
typedef int32_t (*ObjectPoolAddFunc) (void * objectPool, void * obj, void* method);
typedef void* (*ObjectPoolRemoveFunc) (void * objectPool, int32_t index, void* method);
std::size_t operator()(const void* ptr) const
{
return reinterpret_cast<std::size_t>(ptr);
}
};

struct PointerEqual
{
bool operator()(const void* lhs, const void* rhs) const
{
return lhs == rhs;
}
};
class FCppObjectMapper final : public ICppObjectMapper
{
public:
void Initialize(v8::Isolate* InIsolate, v8::Local<v8::Context> InContext);

v8::Local<v8::Function> LoadTypeByString(v8::Isolate* Isolate, v8::Local<v8::Context> Context, std::string TypeName);

virtual v8::MaybeLocal<v8::Function> LoadTypeById(v8::Local<v8::Context> Context, const void* TypeId) override;


void LoadCppType(const v8::FunctionCallbackInfo<v8::Value>& Info);

virtual bool IsInstanceOfCppObject(v8::Isolate* Isolate, const void* TypeId, v8::Local<v8::Object> JsObject) override;
Expand All @@ -45,42 +56,32 @@ class FCppObjectMapper final : public ICppObjectMapper

virtual void BindCppObject(v8::Isolate* Isolate, JSClassDefinition* ClassDefinition, void* Ptr, v8::Local<v8::Object> JSObject,
bool PassByPointer) override;

virtual void* GetPrivateData(v8::Local<v8::Context> Context, v8::Local<v8::Object> JSObject) override;

virtual void SetPrivateData(v8::Local<v8::Context> Context, v8::Local<v8::Object> JSObject, void* Ptr) override;

virtual v8::MaybeLocal<v8::Function> LoadTypeById(v8::Local<v8::Context> Context, const void* TypeId) override;

void UnInitialize(v8::Isolate* InIsolate);

v8::Local<v8::FunctionTemplate> GetTemplateOfClass(v8::Isolate* Isolate, const void* TypeId);

void* ObjectPoolAddMethodInfo = nullptr;

ObjectPoolAddFunc ObjectPoolAdd = nullptr;

void* ObjectPoolRemoveMethodInfo = nullptr;

ObjectPoolRemoveFunc ObjectPoolRemove = nullptr;

void* ObjectPoolInstance = nullptr;
v8::Local<v8::FunctionTemplate> GetTemplateOfClass(v8::Isolate* Isolate, const JSClassDefinition* ClassDefinition);

private:
std::unordered_map<void*, FObjectCacheNode> CDataCache;
// TODO: pass by UnBindCppObject parameter
v8::Isolate* Isolate;

std::unordered_map<const void*, v8::UniquePersistent<v8::FunctionTemplate>> TypeIdToTemplateMap;
std::unordered_map<void*, FObjectCacheNode, PointerHash, PointerEqual> CDataCache;

v8::UniquePersistent<v8::FunctionTemplate> PointerTemplate;

v8::Global<v8::Symbol> PrivateKey;
std::unordered_map<const void*, v8::UniquePersistent<v8::FunctionTemplate>, PointerHash, PointerEqual> CDataNameToTemplateMap;

struct FinalizeInfo
{
void* ClassData;
FinalizeFunc Finalize;
};
std::unordered_map<void*, FinalizeInfo> CDataFinalizeMap;
v8::UniquePersistent<v8::Function> PointerConstructor;

#ifndef WITH_QUICKJS
v8::Global<v8::Symbol> PrivateKey;
#endif

std::shared_ptr<int> Ref = std::make_shared<int>(0);
};

} // namespace puerts
} // namespace PUERTS_NAMESPACE
Loading

0 comments on commit 6d5a0b7

Please sign in to comment.