Having trouble making a native OS X plugin

I have ten or so 32-bit dylibs that I’d like to put into a plug-in, for use by a 32-bit OS X Unity player. There ARE no 64-bit versions of these dylibs, and so I am content for the moment to not support 64 bit mode.

I am having trouble getting calls into even one of these dylibs to work, and so I have some questions.

  1. The docs ambiguously state that for OS X “you should build your plugin as a universal binary that contains both 32-bit and 64-bit architectures” (I added the bold). Do they mean I must, or just that this is a good practice?

  2. In my C# code for MyPlugin.bundle containing libMyLib.dylib, should the string constant in the DllImport() attribute be “MyPlugIn” or “MyLib” for a function that resides within the libMyLib.dylib library? I suspect the former, based on my results, even though this seems a poor design choice, as a Windows version of this plugin will require different attributes to work.

Though I have my dylibs ready to go, I’m trying an incremental approach to learn the ropes. If I strip my bundle down to the simplest case where there is just one 32-bit dylib within it, which has no external dependencies, I find I am still not succeeding.

If I run “otool -L libMyLib.dylib”, I get

libMyLib.dylib:
    @loader_path//libMyLib.dylib (compatibility version 0.0.0, current version 0.0.0)
    /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 104.1.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)

However, if I call a single function within the dylib which has the attribute [DllImport(“MyPlugin”, CallingConvention = CallingConvention.Cdecl)], I get

Couldn't open MyApp.app/Contents/Plugins/MyPlugin.bundle/Contents/MacOS/MyPlugin, error: dlopen(MyApp.app/Contents/Plugins/MyPlugin.bundle/Contents/MacOS/MyPlugin, 2): library not loaded: @rpath/libMyLib.dylib 
referenced from: MyApp.app/Contents/Plugins/MyPlugin.bundle/Contents/MacOS/MyPlugin
reason: image not found
Couldn't open MyApp.app/Contents/Plugins/MyPlugin.bundle/Contents/MacOS/MyPlugin, error: dlopen(MyApp.app/Contents/Plugins/MyPlugin.bundle/Contents/MacOS/MyPlugin, 2): library not loaded: @rpath/libMyLib.dylib 
referenced from: MyApp.app/Contents/Plugins/MyPlugin.bundle/Contents/MacOS/MyPlugin
reason: image not found
DllNotFoundException: MyApp.app/Contents/Plugins/MyPlugin.bundle/Contents/MacOS/MyPlugin

I would really love to hear from anyone with some experience in this.

Thanks in advance!

tone

  1. While it’s a good idea to build fat binaries with x86 and x86_64 if you are worried about maximum compatibility, most Applications on OS X these days only support x86_64. So I would actually recommend only building for x86_64 if you can track down 64-bit versions of the dynamic libraries you are using.

  2. The DllImport attribute is meant to specify the DLL containing the extern, see DllImportAttribute Class (System.Runtime.InteropServices) | Microsoft Learn

For cross-platform development, it’s actually suggested to omit the .dll extension as it will automatically try to resolve using platform dependent extensions in Mono in addition to .dll (.a for iOS/Mac, .so for Android, etc…). Just make sure you are specifying the file on disk that contains the extern symbol. In your case you are having to specify MyPlugin because that is the built assembly that references “MyLib”.

@Tony-Lovell I think you’d better manually hook up your dynamic libraries.
I made an exhaustive writeup on my findings here, see Override app delegate in Unity for iOS and OSX (4/4) Inject code to Mach-O binary for more.

1 Like