C# Unity/Monotouch/C设置第三方库委托时JIT编译方法错误

C# Unity/Monotouch/C设置第三方库委托时JIT编译方法错误,c#,ios,mono,xmpp,unity3d,C#,Ios,Mono,Xmpp,Unity3d,我正在尝试在Unity/Monotouch/C#中为iOS的facebook创建聊天客户端。我得到以下错误 ExecutionEngineException: Attempting to JIT compile method '(wrapper managed-to-native) System.Threading.Interlocked:CompareExchange (System.EventHandler`1<Matrix.EventArgs>&,System.E

我正在尝试在Unity/Monotouch/C#中为iOS的facebook创建聊天客户端。我得到以下错误

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)
委托方法:

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

他们还试图改变API可比性级别top.NET2.0,但没有任何结果。将xmppClient_OnBeforeSasl方法设置为static也没有帮助。它在Unity中工作正常,但在iOS设备上运行时崩溃。

结果表明Matrix不支持iOS:(

在尝试在Unity项目中使用agsXMPP库之前,您需要删除agsXMPP库中的所有事件用法。我确实使用了agsXMPP,但做了一些修改,看起来它工作正常

以下是补丁的一些见解(这并不是一个好办法):

查找并删除库项目中的所有事件关键字(保持事件类不变,这是另一回事),然后替换(+=)

由(=)

因为OnBeforeSasl现在是一个委托,而不是一个事件,并且您不能向它注册多个处理程序

但无论如何,这是一种工作,您可以通过添加addEventListener/removeEventListeners来扩展它,并使用一个委托数组,而不仅仅是一个委托数组


我这样做是可行的,所以请尝试一下!

以下堆栈帧导致了此错误:

at Matrix.Net.BaseSocket.add_OnConnect (System.EventHandler`1 value) [0x00000]
add#u OnConnect方法是编译器生成的用于注册事件的方法。此方法的生成方式已在较新版本的Microsoft C#编译器中更改,该编译器使用通用版本的Interlocked.compareeexchange,以提高性能和线程安全性

因此,请检查您得到的XMPP二进制文件是否是由最近的Visual Studio版本构建的

联锁的问题。CompareExchange的问题是,该方法的通用版本无法在性能可接受的纯C#中实现。因此JIT已被黑客攻击。当它读取联锁的.CompareExchange的主体时,它只会触发JIT进程并生成以下IL:

ldarg.0 
ldarg.1
ldarg.2
call System.Threading.Interlocked::CompareExchange(ref Object, Object, Object)
ret
因此,这个方法永远不会编译AOT,并且总是触发JIT进程,因为iOS不允许代码生成,所以JIT进程将失败


如果源代码可用,请尝试通过使用MonoDevelop重新生成包含事件注册的二进制文件来解决问题。

找到了一个解决方法:但在将其转换到我的案例时遇到问题。但是,不确定您是否可以在不更改库代码的情况下应用该解决方法,我无法更改库代码。
xmppClient.OnBeforeSasl = this.xmppClient_OnBeforeSasl;
at Matrix.Net.BaseSocket.add_OnConnect (System.EventHandler`1 value) [0x00000]
ldarg.0 
ldarg.1
ldarg.2
call System.Threading.Interlocked::CompareExchange(ref Object, Object, Object)
ret