簡體   English   中英

第三方庫的Unity / Monotouch / C#設置委托中的JIT編譯方法錯誤

[英]JIT compile method error in Unity/Monotouch/C# setting delegate for 3rd party library

我正在嘗試在Unity / Monotouch / C#中為iOS for facebook創建一個chatclient。 我收到以下錯誤

ExecutionEngineException: Attempting to JIT compile method '(wrapper managed-to-native) 
System.Threading.Interlocked:CompareExchange  
(System.EventHandler`1<Matrix.EventArgs>&,System.EventHandler`1<Matrix.EventArgs>,
System.Eve ntHandler`1<Matrix.EventArgs>)' while running with --aot-only.

  at Matrix.Net.BaseSocket.add_OnConnect (System.EventHandler`1 value) [0x00000]
in <filename unknown>:0 
  at Matrix.XmppStream..ctor (StreamType type) [0x00000] in <filename unknown>:0 
  at Matrix.Xmpp.Client.XmppClient..ctor () [0x00000] in <filename unknown>:0 
  at TestFacebook.setup () [0x00000] in <filename unknown>:0 
  at TestFacebook.Start () [0x00000] in <filename unknown>:0 

(Filename:  Line: -1)

當我嘗試連接XMPP框架中的一個委托時。 這是可能導致它的代碼:

xmppClient.OnBeforeSasl += this.xmppClient_OnBeforeSasl;

委托方法:

public void xmppClient_OnBeforeSasl(object sender, Matrix.Xmpp.Sasl.SaslEventArgs e)
    { ... }

還試圖在沒有任何結果的情況下更改API可比性級別頂級.NET 2.0。 將xmppClient_OnBeforeSasl方法設置為靜態也無濟於事。 它在Unity中運行良好,但在iOS設備上運行時崩潰。

原來Matrix不支持iOS :(

在嘗試在Unity項目中使用它之前,您需要刪除agsXMPP庫中的所有事件使用。 我確實使用了agsXMPP進行了一些修改,似乎它正常工作。

以下是補丁的一些見解(這不是一個很好的方法):

查找並刪除庫項目中的所有事件關鍵字(將Event類取消,這是另一回事)然后替換(+ =)

xmppClient.OnBeforeSasl += this.xmppClient_OnBeforeSasl;

通過(=)

xmppClient.OnBeforeSasl = this.xmppClient_OnBeforeSasl;

因為OnBeforeSasl現在是一個委托,而不是一個事件,你不能用這個注冊多個處理程序。

但無論如何,這是一種工作,您可以通過添加addEventListener / removeEventListeners來擴展它,並使用委托數組而不是僅使用一個委托數組。

我這樣做了,它的工作就這樣試試吧!

以下堆棧幀導致此錯誤:

at Matrix.Net.BaseSocket.add_OnConnect (System.EventHandler`1 value) [0x00000]

add_OnConnect方法是用於注冊事件的編譯器生成方法。 在較新版本的Microsoft C#編譯器中更改了生成此方法的方式,該編譯器使用Interlocked.CompareExchange的通用版本以獲得更好的性能和線程安全性。

因此,請檢查您獲得的XMPP二進制文件是否是由最近的一些Visual Studio版本構建的。

Interlocked.CompareExchange的問題在於此方法的通用版本無法在具有可接受性能的純C#中實現。 因此JIT遭到黑客攻擊。 當它讀取Interlocked.CompareExchange <T>的主體時,它只是觸發一個JIT進程並生成以下IL:

ldarg.0 
ldarg.1
ldarg.2
call System.Threading.Interlocked::CompareExchange(ref Object, Object, Object)
ret

因此,此方法永遠不會被AOT編譯並始終觸發JIT進程,因為iOS不允許代碼生成,因此將失敗。

如果源代碼可用,請嘗試通過使用MonoDevelop重建包含事件注冊的二進制文件來解決問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM