3

我正在尝试在 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)

当我尝试连接 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 设备上运行时崩溃。

4

3 回答 3

0

原来 Matrix 不支持 iOS :(

于 2012-08-28T12:49:37.163 回答
0

在尝试在统一项目中使用之前,您需要删除 agsXMPP 库中的所有事件使用。我确实使用了 agsXMPP 并进行了一些修改,似乎它工作正常。

以下是补丁的一些见解(这不是很好的方法):

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

xmppClient.OnBeforeSasl += this.xmppClient_OnBeforeSasl;

由 ( = )

xmppClient.OnBeforeSasl = this.xmppClient_OnBeforeSasl;

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

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

我确实这样做了,它的工作,所以试试吧!

于 2013-04-19T09:34:53.127 回答
0

以下堆栈帧导致此错误:

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 重建包含事件注册的二进制文件来解决问题。

于 2014-04-21T10:26:35.120 回答