MonoMac/Xamarin.Mac绑定简单的dylib无法正常工作

The*_*man 1 mono monomac xamarin.mac

我正在尝试绑定一些本机代码以用于MonoMac/Xamarin.Mac,但我不确定我哪里出错了.我创建了一个简单的dylib来测试:

nativelibrary.h:

- (NSString *)echo:(NSString *)message;
Run Code Online (Sandbox Code Playgroud)

我知道我的库很好,因为我引用它并在Objective-C/Cocoa应用程序中使用它.

接下来,我尝试使用parse.exe生成初始绑定文件:

mono parse.exe [path...]/nativelibrary.h 
Run Code Online (Sandbox Code Playgroud)

问题#1 根据Miguel的指南,没有生成'gen.cs'文件

问题#2 Parse.exe确实输出了一些东西到控制台,虽然它缺少我唯一的方法?

[BaseType (typeof (NSObject))]
interface nativelibrary {
}
Run Code Online (Sandbox Code Playgroud)

无论如何,我继续创建自己的gen.cs文件,手动填写缺少的方法:

gen.cs:

using MonoMac.Foundation;

namespace ManagedConsumer
{
    [BaseType (typeof (NSObject))]
    interface Binding 
    {
        [Export ("echo:")]
        string Echo(string message);

        // I also tried like this:
        // NSString Echo(NSString message);
    }
}
Run Code Online (Sandbox Code Playgroud)

接下来,我尝试使用bmac.exe创建我的绑定DLL:

mono bmac.exe -o="dynamiclibrary.dll" -d="MONOMAC" -r="System.Drawing" -v [path].../gen.cs 
Run Code Online (Sandbox Code Playgroud)

这会吐出我在MonoMac项目中引用的.dll.

最后,我将.dylib本身添加到我的MonoMac项目中,并指定'content'构建操作.我验证.dylib被复制到我的bundle的'Resources'目录.

我可以实例化我的绑定对象的实例没问题:

Binding b = new Binding();
Console.WriteLine(b.ToString());
Run Code Online (Sandbox Code Playgroud)

问题3但是,尝试调用我的方法:

Binding b = new Binding();
var result = b.Echo((NSString)"Hello, world");
Run Code Online (Sandbox Code Playgroud)

导致无法管理的崩溃:

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_PROTECTION_FAILURE at 0x00000000bf74bffc
Run Code Online (Sandbox Code Playgroud)

我在另一个问题中看到,我们需要强制加载.dylib.因此,在调用Application.Init()之前,我尝试将此行插入到main.cs中:

Dlfcn.dlopen ("nativelibrary.dylib", 0);
Run Code Online (Sandbox Code Playgroud)

但是我遇到了同样的崩溃.由于对dlopen的调用返回0而不是有效指针,我认为问题在于加载我的动态库.我也尝试使用该属性:

[assembly:MonoMac.RequiredFramework("nativelibrary.dylib")]
Run Code Online (Sandbox Code Playgroud)

但这只会让我:

System.Exception: Unable to load required framework: 'nativelibrary.dylib'
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

The*_*man 5

经过大量的反复试验,我才能完成这项工作.两个变化:

在我的自制gen.cs文件中,接口名称需要匹配我的本机类的名称,即

nativelibrary.h

@interface nativelibrary : NSObject

- (NSString *)echo:(NSString *)message;
Run Code Online (Sandbox Code Playgroud)

gen.cs

使用MonoMac.Foundation;

namespace ManagedConsumer
{
    [BaseType (typeof (NSObject))]
    interface nativelibrary 
    {
        [Export ("echo:")]
        string Echo(string message);
    }
}
Run Code Online (Sandbox Code Playgroud)

其次,我的本地库本身似乎有些东西意味着无法使用dlopen打开它.我认为问题是XCode'library'项目默认为x64,并且只显示x86才有效.

我从命令行编译它,就像这样:

gcc -arch i386 -framework Cocoa -o nativelibrary.o  -c [path...]/nativelibrary.m 
Run Code Online (Sandbox Code Playgroud)

然后建立我的库:

libtool -dynamic -flat_namespace -lSystem -undefined suppress -macosx_version_min 10.6 -install_name $CURRENT_DIR/nativelibrary.dylib -o nativelibrary.dylib nativelibrary.o 
Run Code Online (Sandbox Code Playgroud)

它现在有效.