Enabling custom dll and dylib in MonoMac app

Reference Information. My MonoMac application uses custom assembly sqlite3.0.8.6.dylib.

I need the exact steps for MyApp.app to use this dylib.

Here are some steps I took:

  • Copied dylib to MyApp.app/Contents/SharedSupport. (Related question: is this the preferred place for third-party dylib or is it preferable MyApp.app/Contents/Frameworks?)

  • The installed library name has been changed to match its new location.

    MyApp.app/Contents/SharedSupport> otool -L libsqlite3.0.8.6.dylib libsqlite3.0.8.6.dylib: @executable_path/../SharedSupport/libsqlite3.0.8.6.dylib (compatibility version 9.0.0, current version 9.6.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0) 

Problems

  • MyApp.app/Contents/MacOS/MyApp does not directly reference dylib, so I cannot use install_name_tool to point to the new library location. I believe the System.Data.Sqlite.dll is referencing the library.
  • I was thinking of overriding DYLD_FALLBACK_LIBRARY_PATH in the script launch bar, but MonoMac now uses the binary launcher (MyApp.app/Contents/MacOS/MyApp) and not the script, so I was out of luck there.

Can the MonoMac gods help with what should be a simple solution? I spent a couple of months turning it on and off trying to get this to work.

And please provide accurate steps - this problem is related to the details.

+7
source share
3 answers

Take a look at my answer to this question: Setting up the path for the Native Library for DllImport for Mono for Mac

The binary launcher comes from monodevelop / main / build / MacOSX / monostub.m .

You can use either MyApp.app/Contents/Frameworks , or some other path, the important part is not to use the path names in your [DllImport] , but instead add <dllmap> with @executable_path to your app.config , as I explained a different answer to this.

There is also a link to a test application on github.

Detailed instructions

  • Choose the path inside MyApp.app to install your native DLL, for example Contents/SharedSupport/sqlite3.0.8.6.dylib .

  • Compute the relative path from the directory where the managed assembly is located on the native .dll and prepend @executable_path .

    For example, if your managed assembly is located in Contents/MonoBundle/MyApp.exe , and the native dll is in Contents/SharedSupport/sqlite3.0.8.6.dylib , then this is @executable_path/../SharedSupport/sqlite3.0.8.6.dylib .

  • Change the installed library name to this relative path using install_name_tool .

  • Add a new MyApp.exe.config file to the project containing

     <configuration> <dllmap dll="sqlite" target="@executable_path/../SharedSupport/sqlite3.0.8.6.dylib" /> </configuration> 

    Use the path that you calculated in step 2. for the target field. Right-click the file in MonoDevelop, select "Quick Properties" in the context menu and enable "Copy to Output Directory". This will copy the file to the Contents/MonoBundle , so it will be next to your MyApp.exe .

  • Use [DllImport ("sqlite")] to refer to this in your code.

When another library references it

When another library, such as Mono.Data.Sqlite.dll refers to it, it becomes a little more complicated.

Use the same steps as above, but you need to find out what name the other library in [DllImport] to refer to its own library and put it in <dllimport dll="..." /> . You can search for [DllImport] operators in the source code or run monodis in the assembly and search for pinvokeimpl , for example:

 // method line 679 .method assembly static hidebysig pinvokeimpl ("sqlite3" as "sqlite3_create_function" cdecl ) default int32 sqlite3_create_function (native int db, unsigned int8[] strName, int32 nArgs, int32 nType, native int pvUser, class Mono.Data.Sqlite.SQLiteCallback func, class Mono.Data.Sqlite.SQLiteCallback fstep, class Mono.Data.Sqlite.SQLiteFinalCallback ffinal) cil managed preservesig { // Method begins at RVA 0x0 } // end of method UnsafeNativeMethods::sqlite3_create_function 

So, Mono.Data.Sqlite.dll uses "sqlite3" to reference the native dll, so your MyApp.exe.config file will look like this:

  <configuration> <dllmap dll="sqlite3" target="@executable_path/../SharedSupport/sqlite3.0.8.6.dylib" /> </configuration> 
+4
source

Be careful if you use mono. @executable_path will return the path to the monobyte, not the executable .EXE file. This should work correctly with Xamarin.

+2
source

You can manually load sqlite dylib .

 [DllImport ("/usr/lib/libSystem.dylib")] public static extern IntPtr dlopen (string path, int mode); IntPtr p = dlopen("libsqlite3.0.8.6.dylib", 0); 

Of course, we resolve the path to your dylib .

+1
source

All Articles