简体   繁体   English

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

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

I am trying to create a chatclient for facebook for iOS in Unity/Monotouch/C#. 我正在尝试在Unity / Monotouch / C#中为iOS for facebook创建一个chatclient。 I get the following error 我收到以下错误

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)

when I try to connect one of the delegates in the XMPP framework. 当我尝试连接XMPP框架中的一个委托时。 This is the code that probably causes it: 这是可能导致它的代码:

xmppClient.OnBeforeSasl += this.xmppClient_OnBeforeSasl;

The delegate method: 委托方法:

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

Have also tried to change API comparability level top .NET 2.0 without any result. 还试图在没有任何结果的情况下更改API可比性级别顶级.NET 2.0。 Setting the xmppClient_OnBeforeSasl method as static does not help either. 将xmppClient_OnBeforeSasl方法设置为静态也无济于事。 It works fine in Unity but crashes when running on an iOS device. 它在Unity中运行良好,但在iOS设备上运行时崩溃。

原来Matrix不支持iOS :(

You will need to remove all event usage in agsXMPP library before trying to use it in your unity project. 在尝试在Unity项目中使用它之前,您需要删除agsXMPP库中的所有事件使用。 I did use agsXMPP with some modifications and seems that it's working right. 我确实使用了agsXMPP进行了一些修改,似乎它正常工作。

Here are some insights for the patch (It's not really good way to go) : 以下是补丁的一些见解(这不是一个很好的方法):

Find and delete all event keywords in the library project (leave the Event class untouch, it's a different thing) then replace ( += ) 查找并删除库项目中的所有事件关键字(将Event类取消,这是另一回事)然后替换(+ =)

xmppClient.OnBeforeSasl += this.xmppClient_OnBeforeSasl;

by ( = ) 通过(=)

xmppClient.OnBeforeSasl = this.xmppClient_OnBeforeSasl;

as OnBeforeSasl is now a delegate, not an event and you can not register multiple handlers with this. 因为OnBeforeSasl现在是一个委托,而不是一个事件,你不能用这个注册多个处理程序。

But anyway, it's kind of work and you can always extending it by adding addEventListener / removeEventListeners and use an array of delegate instead of only one. 但无论如何,这是一种工作,您可以通过添加addEventListener / removeEventListeners来扩展它,并使用委托数组而不是仅使用一个委托数组。

I did doing that way and it's work so just try it out ! 我这样做了,它的工作就这样试试吧!

The following stack frame caused this error: 以下堆栈帧导致此错误:

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

The add_OnConnect method was a compiler generated method used to register an event. add_OnConnect方法是用于注册事件的编译器生成方法。 The way that this method is generated has been changed in newer version of Microsoft's C# compiler, which uses the generic version of Interlocked.CompareExchange for better performance and thread safety. 在较新版本的Microsoft C#编译器中更改了生成此方法的方式,该编译器使用Interlocked.CompareExchange的通用版本以获得更好的性能和线程安全性。

So check if the XMPP binaries you've got was built by some recent Visual Studio releases. 因此,请检查您获得的XMPP二进制文件是否是由最近的一些Visual Studio版本构建的。

And the problem of Interlocked.CompareExchange is that the generic version of this method cannot be implemented in pure C# with acceptable performance. Interlocked.CompareExchange的问题在于此方法的通用版本无法在具有可接受性能的纯C#中实现。 So the JIT has been hacked. 因此JIT遭到黑客攻击。 When it reads the body of Interlocked.CompareExchange<T> , it just triggers a JIT process and generates the following IL: 当它读取Interlocked.CompareExchange <T>的主体时,它只是触发一个JIT进程并生成以下IL:

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

So this method will never get AOT compiled and always trigger a JIT process which will fail because iOS does not allow code generation. 因此,此方法永远不会被AOT编译并始终触发JIT进程,因为iOS不允许代码生成,因此将失败。

Try solve the problem by rebuilding binaries which contain event registrations with MonoDevelop if the source codes are available. 如果源代码可用,请尝试通过使用MonoDevelop重建包含事件注册的二进制文件来解决问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM