2017-08-03 46 views
1

我正在開發一個Unity項目,並處理WebGL插件,它被Unity稱爲「jslib」。從直接c#和jslib回調調用事件時會調用不同的函數簽名c#

雖然統一推薦使用UnitySendMessage當jslib與c#交互時,我更喜歡使用委託作爲回調。在一個小測試代碼中,它工作。但是當它運行到觸發事件代碼時,會發生奇怪的錯誤。

C#:

public class Test : MonoBehaviour { 

    public void Start() 
    { 
     UserLoginDispatcher.GetInstance().onLoginOver += onLoginOver; 
    } 

    public void OnDestroy() 
    { 
     UserLoginDispatcher.GetInstance().onLoginOver -= onLoginOver; 
    } 

    //[MonoPInvokeCallback(typeof(System.Action<string, string, SDKError>))] 
    public static void onLoginOver(string context, string pluginId, SDKError err) 
    { 
     string errmsg = err == null ? "" : err.errmsg; 
     LogFormat ("Login Over with context " + context + ", pluginId " + pluginId + ", errmsg:" + errmsg); 
    } 

    static void LogFormat(string format, params object[] param) 
    { 
     string log = string.Format (format, param); 
     Debug.Log (log); 
    } 
} 

public class UserLoginDispatcher { 
    private static UserLoginDispatcher s_Instance = new UserLoginDispatcher(); 
    public static UserLoginDispatcher GetInstance() 
    { 
     return s_Instance; 
    } 

    public delegate void UserLoginCallback(string context, string pluginId, SDKError error); 

    public event UserLoginCallback onLoginOver; 

    public void ProcessLoginOver(string context, string pluginId, SDKError error) 
    { 
     onLoginOver (context, pluginId, error); 
    } 
} 

public class WebGLPluginManager 
{ 
    [DllImport("__Internal")] 
    private static extern int Plugin_addLoginOverCB (LoginCBDelegate nativeCb); 
    private delegate void LoginCBDelegate(string context, string pluginId, int errno, int channelerrno, string errmsg); 

    [MonoPInvokeCallback(typeof(LoginCBDelegate))] 
    private static void OnLoginOver(string context, string pluginId, int errno, int channelerrno, string errmsg) 
    { 
     SDK.GetInstance().loginDispatcher.ProcessLoginOver (context, pluginId, new SDKError (errno, channelerrno, errmsg)); 
    } 

    public void Init() 
    { 
     Plugin_addLoginOverCB(OnLoginOver); 
    } 
} 

在jslib:

...//login succeed: 
Runtime.dynCall("viiiii", .....); 

雖然ProcessLoginOver在UserLoginDispatcher被調用時,onLoginOver在測試拋出一個錯誤:

無效的函數指針調用署名「VIIII 」。也許這是一個無效的值(例如通過在NULL指針上調用虛擬方法造成的)?或者調用一個錯誤類型的函數,這會失敗? (這是值得建立你的源文件與-Werror(警告是錯誤),因爲警告可能表明未定義的行爲,可能會導致此)

但如果我嘗試直接在C#代碼中調用此事件,它可以被成功觸發。

錯誤調用堆棧:

Uncaught abort(68) at Error 
at jsStackTrace (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23794:12) 
at stackTrace (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23808:11) 
at abort (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:464638:43) 
at nullFunc_viiii (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:50912:2) 
at Array.b68 (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:455121:2) 
at ftCall_viiii (eval at loadDynamicLibrary (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23235:19), <anonymous>:6602:49) 
at mftCall_viiii (eval at loadDynamicLibrary (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23235:19), <anonymous>:732323:2) 
at _UserLoginCallback_Invoke_m2599958513 (eval at loadDynamicLibrary (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23235:19), <anonymous>:533179:4) 
at _UserLoginCallback_Invoke_m2599958513 (eval at loadDynamicLibrary (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23235:19), <anonymous>:533170:14) 
at _UserLoginDispatcher_ProcessLoginOver_m2254139378 (eval at loadDynamicLibrary (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23235:19), <anonymous>:562185:2) 
at _WebGLPluginManager_OnLoginOver_m1528063286 (eval at loadDynamicLibrary (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23235:19), <anonymous>:548824:2) 
at Array.asm._WebGLPluginManager_OnLoginOver_m1528063286 (eval at loadDynamicLibrary (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23235:19), <anonymous>:921460:59) 
.... 

直接C#調用

Login Over with context a test session 12:13:28, pluginId DefaultUserLogin, errmsg: 
at __Z13GetStacktracei [GetStacktrace(int)] (blob:http://localhost:60912/6467252d-2f87-4a2c-9967-31868825bff3:2275897:2) 
at __Z17DebugStringToFileRK21DebugStringToFileData [DebugStringToFile(DebugStringToFileData const&)] (blob:http://localhost:60912/6467252d-2f87-4a2c-9967-31868825bff3:1247009:5) 
at __Z17DebugStringToFilePKciS0_i15LogMessageFlagsiiPFvRK11CppLogEntryE [DebugStringToFile(char const*, int, char const*, int, LogMessageFlags, int, int, void (*)(CppLogEntry const&))] (blob:http://localhost:60912/6467252d-2f87-4a2c-9967-31868825bff3:2562904:2) 
at __Z35DebugLogHandler_CUSTOM_Internal_Log7LogTypeP12Il2CppStringP12Il2CppObject [DebugLogHandler_CUSTOM_Internal_Log(LogType, Il2CppString*, Il2CppObject*)] (blob:http://localhost:60912/6467252d-2f87-4a2c-9967-31868825bff3:2126846:2) 
at Array.UnityLoader.d9fd6255ccad354c9cc5ad72abf13dcc.asm.__Z35DebugLogHandler_CUSTOM_Internal_Log7LogTypeP12Il2CppStringP12Il2CppObject [DebugLogHandler_CUSTOM_Internal_Log(LogType, Il2CppString*, Il2CppObject*)] (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:145057:93) 
at ftCall_viii (eval at loadDynamicLibrary (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23235:19), <anonymous>:7197:48) 
at mftCall_viii (eval at loadDynamicLibrary (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23235:19), <anonymous>:747533:2) 
at _DebugLogHandler_Internal_Log_m1116757358 (eval at loadDynamicLibrary (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23235:19), <anonymous>:719622:2) 
at Array._DebugLogHandler_LogFormat_m2613962716 (eval at loadDynamicLibrary (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23235:19), <anonymous>:620933:2) 
at mftCall_viiiiii (eval at loadDynamicLibrary (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23235:19), <anonymous>:708880:40) 
at __ZN23InterfaceActionInvoker4IiP18Object_t3753624189P8String_tP24ObjectU5BU5D_t2405707486E6InvokeEjP11Il2CppClassP12Il2CppObjectiS1_S3_S5_ [InterfaceActionInvoker4<int, Object_t3753624189*, String_t*, ObjectU5BU5D_t2405707486*>::Invoke(unsigned int, Il2CppClass*, Il2CppObject*, int, Object_t3753624189*, String_t*, ObjectU5BU5D_t2405707486*)] (eval at loadDynamicLibrary (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23235:19), <anonymous>:394923:2) 
at Array._Logger_Log_m314997607 (eval at loadDynamicLibrary (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23235:19), <anonymous>:564686:3) 
at mftCall_viiii (eval at loadDynamicLibrary (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23235:19), <anonymous>:732320:39) 
at __ZN23InterfaceActionInvoker2IiP12Il2CppObjectE6InvokeEjP11Il2CppClassS1_iS1_ [InterfaceActionInvoker2<int, Il2CppObject*>::Invoke(unsigned int, Il2CppClass*, Il2CppObject*, int, Il2CppObject*)] (eval at loadDynamicLibrary (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23235:19), <anonymous>:412747:2) 
at _Debug_Log_m2324883804 (eval at loadDynamicLibrary (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23235:19), <anonymous>:619913:2) 
at _Test_LogFormat_m983122927 (eval at loadDynamicLibrary (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23235:19), <anonymous>:579589:2) 
at Array._Test_onLoginOver_m2512123873 (eval at loadDynamicLibrary (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23235:19), <anonymous>:383768:2) 
at mftCall_viiiii (eval at loadDynamicLibrary (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23235:19), <anonymous>:720078:40) 
at _UserLoginCallback_Invoke_m2599958513 (eval at loadDynamicLibrary (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23235:19), <anonymous>:533182:4) 
at _UserLoginDispatcher_ProcessLoginOver_m2254139378 (eval at loadDynamicLibrary (blob:http://localhost:60912/134eecaa-92a2-4615-b5b2-0a2ab6d2ed73:23235:19), <anonymous>:562185:2) 
.... 

我注意到,在直接C#調用,dynCall在jslib通話使用mftCall_viiiii,同時,該堆棧dynCall使用mftCall_viiii,可能這就是爲什麼函數調用失敗。這很奇怪,爲什麼會發生這種情況?

回答

0

自己修復!

事實上,這是我的一個小錯誤:我只是忘記初始化loginDispatcher,所以當輸入loginDispatcher時這個ptr是0,那麼這個行爲很混亂。

當「this」是0時,代碼沒有拋出任何異常,因爲它是從c代碼翻譯的。它繼續運行,直到事件調用函數,最後函數表沒有這個函數並且抱怨,所以我看到了非常混亂的錯誤報告!

ps:在asm.js中的c#委託的行爲如下:如果此ptr爲0,則委託被視爲靜態函數,如果此ptr不爲0,則委託被視爲成員函數。這就是爲什麼當這個ptr爲0時,調用mftCall_viiii而不是mftCall_viiiii