【问题标题】:JIT compile method error in Unity/Monotouch/C# setting delegate for 3rd party libraryUnity/Monotouch/C# 为 3rd 方库设置委托中的 JIT 编译方法错误
【发布时间】:2012-08-15 21:51:55
【问题描述】:

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

【问题讨论】:

  • 找到了解决方法:forum.unity3d.com/threads/… 但在将其转化为我的情况时遇到了麻烦
  • 但是不确定是否可以在不更改我无法做到的库代码的情况下应用解决方法。

标签: c# ios mono xmpp unity3d


【解决方案1】:

以下堆栈帧导致此错误:

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 的主体时,它只是触发一个 JIT 进程并生成以下 IL:

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

所以这个方法永远不会编译 AOT 并且总是触发一个 JIT 进程,该进程将失败,因为 iOS 不允许代码生成。

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

【讨论】:

    【解决方案2】:

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

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

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

    xmppClient.OnBeforeSasl += this.xmppClient_OnBeforeSasl;
    

    按(=)

    xmppClient.OnBeforeSasl = this.xmppClient_OnBeforeSasl;
    

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

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

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

    【讨论】:

      【解决方案3】:

      原来 Matrix 不支持 iOS :(

      【讨论】:

        猜你喜欢
        • 2016-07-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-01
        • 1970-01-01
        • 2016-11-10
        相关资源
        最近更新 更多