MonoMac/Xamarin.Mac绑定简单的dylib无法正常工作 [英] MonoMac / Xamarin.Mac binding simple dylib not working
问题描述
我正在尝试绑定一些本机代码以在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屋!