Background: My MonoMac app uses a custom build of sqlite3.0.8.6.dylib.
I need the exact steps to have MyApp.app use this dylib.
Here are some steps I took:
Copied the dylib to MyApp.app/Contents/SharedSupport. (Related question: is this the preferred location for 3rd party dylibs or is MyApp.app/Contents/Frameworks preferred?)
Changed the installed name for the library so that it matches 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
Would the MonoMac gods please help with what must be a simple solution? I've spent a couple of months, on and off, trying to get this to work.
And please provide exact steps - this problem is all about the details.
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
Pick a path inside the MyApp.app
to install your native dll, for instance Contents/SharedSupport/sqlite3.0.8.6.dylib
.
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
.
Change the installed name of the library to this relative path using install_name_tool
.
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
.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With