Frage

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?

War es hilfreich?

Lösung

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top