问题
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?
回答1:
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.
来源:https://stackoverflow.com/questions/15073178/monomac-xamarin-mac-binding-simple-dylib-not-working