Skip to content

Commit

Permalink
[unity]用p-api实现c#引用js object/function
Browse files Browse the repository at this point in the history
  • Loading branch information
chexiongsheng committed Oct 11, 2024
1 parent d4971f7 commit 1abaf53
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 164 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ static ${il2cpp_snippets.SToCPPType(bridgeInfo.ReturnSignature)} b_${bridgeInfo.
PObjectRefInfo* delegateInfo = GetPObjectRefInfo(target);
AutoValueScope valueScope(delegateInfo->EnvRef);
auto env = pesapi_get_env_from_ref(delegateInfo->EnvRef);
pesapi_env_ref envRef = pesapi_get_ref_associated_env(delegateInfo->ValueRef);
AutoValueScope valueScope(envRef);
auto env = pesapi_get_env_from_ref(envRef);
if (!env)
{
il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetInvalidOperationException("JsEnv had been destroy"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -484,11 +484,10 @@ static void* CtorCallback(pesapi_callback_info info)
return nullptr;
}

static void SetPObjectRefInfoValue(pesapi_env env, PObjectRefInfo* objectInfo, pesapi_value jsval)
static void SetPObjectRefInfoValue(pesapi_env env, PObjectRefInfo* objectInfo, pesapi_value_ref value_ref)
{
objectInfo->EnvRef = pesapi_create_env_ref(env);
objectInfo->ValueRef = pesapi_create_value_ref(env, jsval, 0);
g_unityExports.SetExtraData(env, objectInfo);
objectInfo->ValueRef = value_ref;
objectInfo->EnvPrivate = (void*)pesapi_get_env_private(env);
}


Expand All @@ -497,21 +496,57 @@ static pesapi_value GetPObjectRefInfoValue(pesapi_env env, const PObjectRefInfo*
return pesapi_get_value_from_ref(env, objectInfo->ValueRef);
}

static pesapi_value GetPObjectRefInfoValue(const PObjectRefInfo* objectInfo)
{
auto env = pesapi_get_env_from_ref(objectInfo->EnvRef);
return GetPObjectRefInfoValue(env, objectInfo);
static std::atomic<RuntimeObject*>* FindOrCreateAtomicOfValue(pesapi_env env, pesapi_value value, pesapi_value_ref* out_value_ref)
{
void* out_ptr;
if(!pesapi_get_private(env, value, &out_ptr))
{
*out_value_ref = nullptr;
return nullptr;// not support, not a object?
}

pesapi_value_ref value_ref = static_cast<pesapi_value_ref>(out_ptr);
std::atomic<RuntimeObject*>* atomic_store = nullptr;
uint32_t field_count;
if (value_ref)
{
atomic_store = (std::atomic<RuntimeObject*>*)pesapi_get_ref_internal_fields(value_ref, &field_count);
if(field_count * sizeof(void*) < sizeof(std::atomic<RuntimeObject*>))
{
PLog("size of internal_fields not enough : %u", field_count);
pesapi_release_value_ref(value_ref);
atomic_store = nullptr;
value_ref = nullptr;
}
}

if (!atomic_store)
{
value_ref = pesapi_create_value_ref(env, value, (sizeof(std::atomic<RuntimeObject*>) + sizeof(void*) - 1) / sizeof(void*));

atomic_store = new (pesapi_get_ref_internal_fields(value_ref, &field_count)) std::atomic<RuntimeObject*>();
pesapi_set_private(env, value, value_ref);
}

//atomic_store->load(std::memory_order_acquire);
//atomic_store->store(obj, std::memory_order_release);
*out_value_ref = value_ref;
return atomic_store;
}

static RuntimeObject* FunctionToDelegate(pesapi_env env, pesapi_value jsval, JsClassInfoHeader* classInfo)
{
RuntimeObject* ret = (RuntimeObject*)g_unityExports.GetRuntimeObjectFromPersistentObject(env, jsval);
pesapi_value_ref value_ref;
auto atomic_store = FindOrCreateAtomicOfValue(env, jsval, &value_ref);
if (!atomic_store) return nullptr;

RuntimeObject* ret = atomic_store->load(std::memory_order_acquire);
if (ret == nullptr)
{
PObjectRefInfo* delegateInfo;
ret = (RuntimeObject *)DelegateAllocate(classInfo->Class, classInfo->DelegateBridge, &delegateInfo);
SetPObjectRefInfoValue(env, delegateInfo, jsval);
g_unityExports.SetRuntimeObjectToPersistentObject(env, jsval, ret);
atomic_store->store(ret, std::memory_order_release);
SetPObjectRefInfoValue(env, delegateInfo, value_ref);
}
return ret;
}
Expand All @@ -530,14 +565,6 @@ static void* DelegateCtorCallback(pesapi_callback_info info)
return FunctionToDelegate(env, jsval, classInfo);
}

void ReleaseScriptObject(RuntimeObject* obj)
{
//TODO: 优化性能 ///
PObjectRefInfo* objectInfo = GetPObjectRefInfo(obj);
// PLog(">>>>>> ReleaseScriptObject: %p, %p, %p, %p", obj, objectInfo, objectInfo->EnvRef, objectInfo->ValueRef);
g_unityExports.UnrefJsObject(objectInfo);
}

bool IsDelegate(Il2CppClass *klass)
{
return Class::IsAssignableFrom(il2cpp_defaults.delegate_class, klass) && klass != il2cpp_defaults.delegate_class && klass != il2cpp_defaults.multicastdelegate_class;
Expand Down Expand Up @@ -853,7 +880,11 @@ handle_underlying:
{
Il2CppClass* persistentObjectInfoClass = g_typeofPersistentObjectInfo;

RuntimeObject* ret = (RuntimeObject*)g_unityExports.GetRuntimeObjectFromPersistentObject(env, jsval);
pesapi_value_ref value_ref;
auto atomic_store = FindOrCreateAtomicOfValue(env, jsval, &value_ref);
if (!atomic_store) return nullptr;

RuntimeObject* ret = atomic_store->load(std::memory_order_acquire);
if (ret == nullptr)
{
ret = il2cpp::vm::Object::New(persistentObjectInfoClass);
Expand All @@ -864,8 +895,8 @@ handle_underlying:
((NativeCtorPtr)ctor->methodPointer)(ret, ctor);

PObjectRefInfo* objectInfo = GetPObjectRefInfo(ret);
SetPObjectRefInfoValue(env, objectInfo, jsval);
g_unityExports.SetRuntimeObjectToPersistentObject(env, jsval, ret);
atomic_store->store(ret, std::memory_order_release);
SetPObjectRefInfoValue(env, objectInfo, value_ref);
}
return ret;
}
Expand Down Expand Up @@ -1699,8 +1730,9 @@ Il2CppObject* GetJSObjectValue(Il2CppObject* jsObject, Il2CppString* key, Il2Cpp

auto type = il2cpp_codegen_class_from_type(rtype->type);

AutoValueScope ValueScope(objectInfo->EnvRef);
auto env = pesapi_get_env_from_ref(objectInfo->EnvRef);
pesapi_env_ref envRef = pesapi_get_ref_associated_env(objectInfo->ValueRef);
AutoValueScope ValueScope(envRef);
auto env = pesapi_get_env_from_ref(envRef);
auto obj = pesapi_get_value_from_ref(env, objectInfo->ValueRef);
auto val = pesapi_get_property(env, obj, key_std.c_str());
if (!val)
Expand Down Expand Up @@ -1790,7 +1822,6 @@ void InitialPuerts(pesapi_func_ptr* func_array)
InternalCalls::Add("PuertsIl2cpp.NativeAPI::EvalInternal(System.IntPtr,System.Byte[],System.String,System.Type)", (Il2CppMethodPointer)puerts::EvalInternal);
InternalCalls::Add("PuertsIl2cpp.NativeAPI::TypeIdToType(System.IntPtr)", (Il2CppMethodPointer)puerts::TypeIdToType);
InternalCalls::Add("PuertsIl2cpp.NativeAPI::GetModuleExecutor(System.IntPtr,System.Type)", (Il2CppMethodPointer)puerts::GetModuleExecutor);
InternalCalls::Add("Puerts.JSObject::releaseScriptObject()", (Il2CppMethodPointer)puerts::ReleaseScriptObject);
InternalCalls::Add("Puerts.JSObject::GetJSObjectValue(System.String,System.Type)", (Il2CppMethodPointer)puerts::GetJSObjectValue);
pesapi_init(func_array);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,14 @@ namespace puerts
{
struct PObjectRefInfo
{
pesapi_env_ref EnvRef;
pesapi_value_ref ValueRef;
void* ExtraData;
std::weak_ptr<int> EnvLifeCycleTracker; // TODO: 增加pesapi_env_ref有效性判断后去掉
void* EnvPrivate;
};

#if defined(USE_OUTSIZE_UNITY)

typedef void* (*GetJsClassInfoFunc)(const void* TypeId, bool TryLazyLoad);

typedef void (*UnrefJsObjectFunc)(struct PObjectRefInfo* objectInfo);

typedef const void* (*CSharpTypeToTypeIdFunc)(const void *type);

typedef v8::Value* (*GetModuleExecutorFunc)(v8::Context* env);
Expand All @@ -31,38 +27,23 @@ typedef v8::Value* (*GetModuleExecutorFunc)(v8::Context* env);

typedef struct JsClassInfoHeader* (*GetJsClassInfoFunc)(const void* TypeId, bool TryLazyLoad);

typedef void (*UnrefJsObjectFunc)(struct PObjectRefInfo* delegateInfo);

typedef const void* (*CSharpTypeToTypeIdFunc)(Il2CppObject *type);

typedef pesapi_value (*GetModuleExecutorFunc)(pesapi_env env);

#endif


typedef void* (*GetRuntimeObjectFromPersistentObjectFunc)(pesapi_env env, pesapi_value pvalue);

typedef void (*SetRuntimeObjectToPersistentObjectFunc)(pesapi_env env, pesapi_value pvalue, void* runtimeObject);

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

typedef void (*SetExtraDataFunc)(pesapi_env env, struct PObjectRefInfo* objectInfo);

struct UnityExports
{
//.cpp api
CSharpTypeToTypeIdFunc CSharpTypeToTypeId = nullptr;

//plugin api
UnrefJsObjectFunc UnrefJsObject = nullptr;
GetJsClassInfoFunc GetJsClassInfo = nullptr;

GetModuleExecutorFunc GetModuleExecutor = nullptr;

GetRuntimeObjectFromPersistentObjectFunc GetRuntimeObjectFromPersistentObject = nullptr;
SetRuntimeObjectToPersistentObjectFunc SetRuntimeObjectToPersistentObject = nullptr;

SetExtraDataFunc SetExtraData = nullptr;

LogCallbackFunc LogCallback = nullptr;
};
Expand Down
18 changes: 3 additions & 15 deletions unity/Assets/core/upm/Runtime/Src/IL2Cpp/JSType/JSObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,8 @@ namespace Puerts
[UnityEngine.Scripting.Preserve]
public class JSObject
{
IntPtr placeHold0; // PObjectRefInfo first ptr
IntPtr placeHold1;
IntPtr placeHold2;
IntPtr placeHold3;
IntPtr placeHold4;
IntPtr placeHold5;
IntPtr placeHold6;
IntPtr placeHold7;

[MethodImpl(MethodImplOptions.InternalCall)]
void releaseScriptObject()
{
throw new NotImplementedException();
}
IntPtr valueRef; // PObjectRefInfo first ptr
IntPtr nativeJsEnv;

[MethodImpl(MethodImplOptions.InternalCall)]
object GetJSObjectValue(string key, Type resultType)
Expand All @@ -44,7 +32,7 @@ public T Get<T>(string key)

~JSObject()
{
releaseScriptObject();
PuertsIl2cpp.NativeAPI.AddPendingKillScriptObjects(nativeJsEnv, valueRef);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion unity/Assets/core/upm/Runtime/Src/IL2Cpp/JsEnv.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ public JSObject ExecuteModule(string specifier)
public Action TickHandler;
public void Tick()
{
PuertsIl2cpp.NativeAPI.ReleasePendingJsObjects(nativeJsEnv);
PuertsIl2cpp.NativeAPI.CleanupPendingKillScriptObjects(nativeJsEnv);
PuertsIl2cpp.NativeAPI.InspectorTick(nativeJsEnv);
PuertsIl2cpp.NativeAPI.LogicTick(nativeJsEnv);
if (TickHandler != null) TickHandler();
Expand Down
5 changes: 4 additions & 1 deletion unity/Assets/core/upm/Runtime/Src/IL2Cpp/Native/NativeAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,10 @@ public class NativeAPI
public static extern void SetObjectToGlobal(IntPtr jsEnv, string key, IntPtr objPtr);

[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern void ReleasePendingJsObjects(IntPtr jsEnv);
public static extern void AddPendingKillScriptObjects(IntPtr jsEnv, IntPtr valueRef);

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

[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern void CreateInspector(IntPtr jsEnv, int port);
Expand Down
3 changes: 3 additions & 0 deletions unity/native_src_il2cpp/Inc/DataTransfer.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
#if !defined(BACKENDENV_DATA_POS)
#define BACKENDENV_DATA_POS 1
#endif
#if !defined(PESAPI_PRIVATE_DATA_POS_IN_ISOLATE)
#define PESAPI_PRIVATE_DATA_POS_IN_ISOLATE 2
#endif

#define RELEASED_UOBJECT ((UObject*) 12)
#define RELEASED_UOBJECT_MEMBER ((void*) 12)
Expand Down
Loading

0 comments on commit 1abaf53

Please sign in to comment.