Including custom dll and dylib in MonoMac app

℡╲_俬逩灬. 提交于 2019-12-05 05:51:27
Martin Baulig

Have a look at my answer to this question: Setting path of the Native Library for DllImport on 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 any path names in your [DllImport] but instead add the <dllmap> using @executable_path to your app.config like I explained in that other answer.

There's a also a link to a test app on github in there.

Detailed Instructions

  1. Pick a path inside the MyApp.app to install your native dll, for instance Contents/SharedSupport/sqlite3.0.8.6.dylib.

  2. Compute the relative path from the directory where the managed assembly is located to the native .dll and prepend @executable_path to it.

    For instance, if your managed assembly is in Contents/MonoBundle/MyApp.exe and the native dll in Contents/SharedSupport/sqlite3.0.8.6.dylib, then it's @executable_path/../SharedSupport/sqlite3.0.8.6.dylib.

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

  4. Add a new MyApp.exe.config file to your project, containing

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

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

  5. Use [DllImport ("sqlite")] to reference this in your code.

When another library references it

When another library, for instance Mono.Data.Sqlite.dll references it, it get a little bit more complicated.

Use the same steps as above, but you need to figure out which name that other library is using in its [DllImport] to reference the native library and put that into the <dllimport dll="..." />. You can either look for the [DllImport] statements in the source code or run monodis on the assembly and search for pinvokeimpl, for instance:

// 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 is using "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>

Be careful if you're using mono. @executable_path will return the path to the mono binary, instead of the actual .EXE executable. This should work correctly with Xamarin though.

TrustMe

You can try manually loading the 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 correctly resolving the path to your dylib.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!