MonoMac/Xamarin.Mac绑定简单的dylib无法正常工作 [英] MonoMac / Xamarin.Mac binding simple dylib not working

查看:103
本文介绍了MonoMac/Xamarin.Mac绑定简单的dylib无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试绑定一些本机代码以在MonoMac/Xamarin.Mac中使用,但是我不确定哪里出了问题.我创建了一个简单的dylib进行测试:

nativelibrary.h :

- (NSString *)echo:(NSString *)message;

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

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

mono parse.exe [path...]/nativelibrary.h 

问题1 根据Miguel的指南 <,不会生成"gen.cs"文件/p>

问题2 实际上,Parse.exe确实向控制台输出了一些内容,尽管它缺少我唯一的方法?

[BaseType (typeof (NSObject))]
interface nativelibrary {
}

无论如何,我继续制作自己的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);
    }
}

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

mono bmac.exe -o="dynamiclibrary.dll" -d="MONOMAC" -r="System.Drawing" -v [path].../gen.cs 

这会吐出一个.dll,我在我的MonoMac项目中引用了该文件.

最后,我将.dylib自身添加到我的MonoMac项目中,并指定"content"构建动作.我确认.dylib已复制到我包的'Resources'目录中.

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

Binding b = new Binding();
Console.WriteLine(b.ToString());

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

Binding b = new Binding();
var result = b.Echo((NSString)"Hello, world");

导致非托管崩溃:

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_PROTECTION_FAILURE at 0x00000000bf74bffc

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

Dlfcn.dlopen ("nativelibrary.dylib", 0);

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

[assembly:MonoMac.RequiredFramework("nativelibrary.dylib")]

但这只会让我:

System.Exception: Unable to load required framework: 'nativelibrary.dylib'

我在做什么错了?

解决方案

经过反复的 的尝试,我能够完成这项工作.两项更改:

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

nativelibrary.h

@interface nativelibrary : NSObject

- (NSString *)echo:(NSString *)message;

gen.cs

使用MonoMac.Foundation;

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

第二,似乎我的本机库本身存在某些问题,这意味着无法使用 dlopen 打开它.我认为问题在于XCode库"项目默认为x64,并且似乎只有x86可以工作.

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

gcc -arch i386 -framework Cocoa -o nativelibrary.o  -c [path...]/nativelibrary.m 

然后建立了我的图书馆:

libtool -dynamic -flat_namespace -lSystem -undefined suppress -macosx_version_min 10.6 -install_name $CURRENT_DIR/nativelibrary.dylib -o nativelibrary.dylib nativelibrary.o 

现在可以使用了.

I'm trying to bind some native code for use in MonoMac / Xamarin.Mac, but I'm not sure where I'm going wrong. I create a simple dylib to test with:

nativelibrary.h:

- (NSString *)echo:(NSString *)message;

I know that my library is fine, because I reference it and use it in an Objective-C / Cocoa application.

Next, I try to generate the initial binding file using parse.exe:

mono parse.exe [path...]/nativelibrary.h 

Problem #1 No 'gen.cs' file is generated as per Miguel's guide

Problem #2 Parse.exe does actually output something to the console, although it's missing my only method?

[BaseType (typeof (NSObject))]
interface nativelibrary {
}

Regardless, I go ahead and make my own gen.cs file, filling in the missing method manually:

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);
    }
}

Next, I try to create my binding DLL using bmac.exe:

mono bmac.exe -o="dynamiclibrary.dll" -d="MONOMAC" -r="System.Drawing" -v [path].../gen.cs 

This spits out a .dll which I reference in my MonoMac project.

Finally, I add the .dylib itself to my MonoMac project, and specify the 'content' build action. I verify that the .dylib is copied to the 'Resources' directory of my bundle.

I can instantiate an instance of my binding object no problem:

Binding b = new Binding();
Console.WriteLine(b.ToString());

Problem 3 However, trying to call my method:

Binding b = new Binding();
var result = b.Echo((NSString)"Hello, world");

results in an unmanaged crash:

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_PROTECTION_FAILURE at 0x00000000bf74bffc

I have seen in another question, that we need to force the .dylib to load. So I try to insert this line into my main.cs, before Application.Init() is called:

Dlfcn.dlopen ("nativelibrary.dylib", 0);

But I get the same crash. Since the call to dlopen returns 0 rather than a valid pointer, I assume that the issue is in loading my dynamic library. I also tried to use the attribute:

[assembly:MonoMac.RequiredFramework("nativelibrary.dylib")]

But that only gets me:

System.Exception: Unable to load required framework: 'nativelibrary.dylib'

What am I doing wrong?

解决方案

After a lot of trial and error, I was able to make this work. Two changes:

In my homebrew gen.cs file, the interface name needed to match the name of my native class, i.e.

nativelibrary.h

@interface nativelibrary : NSObject

- (NSString *)echo:(NSString *)message;

gen.cs

using MonoMac.Foundation;

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

Secondly, it seems there was something about my native library itself that means it couldn't be opened with dlopen. I think the problem is that the XCode 'library' project defaults to x64, and it appears only x86 will work.

I compiled it from the command line instead, like so:

gcc -arch i386 -framework Cocoa -o nativelibrary.o  -c [path...]/nativelibrary.m 

Then built my library:

libtool -dynamic -flat_namespace -lSystem -undefined suppress -macosx_version_min 10.6 -install_name $CURRENT_DIR/nativelibrary.dylib -o nativelibrary.dylib nativelibrary.o 

And it now works.

这篇关于MonoMac/Xamarin.Mac绑定简单的dylib无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆