2、类库的依赖解决:通过otool-L命令来确认相应的plugin依赖的类库位置都正确(文件路径下文件确实存在),如果相应文件不存在要手工拷贝文件到指定目录:而新的macOS安全架构限制了往系统目录下(如/usr/lib)进行任何改动,一个临时的解决方法是通过install_name_tool工具主动修改类库依赖路径到另一个可以放置新文件的位置(如home目录)。
坑二:Delegate的正确使用姿势
如果Managed侧的编程语言是C#,则Delegate是实现回调的重要手段。在Unmanaged侧完成期望工作时回调一个FunctionPtr即可实现通用的回调模式,而此FunctionPtr正是对应到Managed侧的Delegate。当你的Delegate绑定到一个类对象上时,你有两种选择:
namespace ChatSDK { //delegate definition public void delegate OnMessageReceived(EMMessage message); public class MyDelegate { //Option 1: field public OnMessageReceived MyMessageReceived; //Option 2: instance method public void OnMessageReceived(EMMessage message) { ... } } //send delegate method to unmanaged side MyDelegate md = new(); NativeMethods.SetOnMessageReceivedCallback(md.MyMessageReceived); //option 1 NativeMethods.SetOnMessageReceivedCallback(md.OnMessageReceived); //option 2 }
看起来两个方式都没有问题,并且第二个方式看起来更顺眼。但是这里隐藏着一个很深的坑,就是你选择第二个方式的时候,如果你在回调方法实现中采用this.xxx方式引用时,你会发现this=null!这是因为当你使用这种方式传递一个对象的方法作为回调方法指针时,其实已经丢失了Delegate.Target(也就是this)属性。而通过第一种方式传递的是一个对象的属性/字段,它和对象本身的绑定是不会在传递过程中丢失的。
至于该Delegate字段的定义可以在此类的构造函数中通过以下方式实现:
...public MyDelegate() { MyMessageReceived = (EMMessage message) => { ... }}...