I have a C# application that uses SQLite and works fine on Windows.
The same Visual Studio project compiles fine in Xamarin Studio, but when running I get:
DllNotFoundException: SQLite.Interop.dll
Despite:
libsqlite3.0.dylib
is in/usr/lib
and also in the same folder as the executable and other DLLs.
is part of the$DYLD_LIBRARY_PATH
- The executable and all SQLite-using DLLs have a matching
<the_exe_or_dll_including_filename_extension>.config
file containing:
<configuration>
<dllmap dll="sqlite" target="libsqlite.0.dylib" os="osx"/>
<dllmap dll="sqlite3" target="libsqlite3.0.dylib" os="osx"/>
</configuration>
I also tried adding <dllmap dll="SQLite.Interop.dll" target="libsqlite3.0.dylib" os="osx"/>
, not better.
What is the problem?
You need to build and supply
SQLite.Interop.dll
(or more preciselylibSQLite.Interop.dylib
). The Mono distribution packages don't include it, probably because it's native code and really needs to be built on the target platform.System.Data.SQLite on Windows uses a mixed mode approach (Managed data adapter + sqlite native code in one assembly). Mono however doesn't really support mixed mode assemblies.
So on MacOS there are two alternatives when it comes to building System.Data.SQLite on Windows:
Both of these are native code and need to be built on the Mac.
Interop is Windows com speak so it's a bit disconcerting to see it used in a MacOS context. What this native dll is is the sqlite source code compiled up with some additional native code that can be P\Invoked by System.Data.SQLite. There are some benefits to using the interop dll as opposed to the sqlite dylib.
System.Data.SQLite ships with a copy of the relevant SQLite native source code in
./SQLite.Interop/src.core
. You can build the interop library by runningcompile-interop-assembly-release.sh
on the Mac. This will buildlibSQLite.Interop.dylib
. Drop that in beside System.Data.SQLite and you should be good to go.If you turn on Mono dll tracing you can watch the loader (see mono 4.8.0 loader.c) searching for the dll in various locations and with various name substitutions. Eventually it finds our dylib. It is also possible to use a
dllmap
entry in theSystem.Data.SQLite.dll.config
file to direct the runtime to the dll. In my case Mono is on my app bundle so I have:The
dllmap
target argument is passed todlopen()
so@executable_path
et al are all usable.I prefer this approach as it goes into the repo and provides some insight into what is going on when there's a foul up.
You can easily find where mono is looking for that native library by setting the MONO_LOG_LEVEL to debug and MONO_LOG_MASK filtering to only DLL related messages.
or as a one liner so you do not have to unset env vars:
Mono and the OS-X dynamic link editor ('man dyld' for details) does not require DYLD_LIBRARY_PATH to be set to the current directory ('.'). Note: Linux does require LD_LIBRARY_PATH to include the current directory, if that is your intention.
Using the native dll/shared library trace output you can track which library is not being found (or one of its dependancies) or if it is the wrong ARCH for your mono version.
If you are still having problems, we would need to know which SQLite library you are using the options that you are using to compile it (or the arch version if getting it via a Nuget). A posting your dll trace output would quickly solve things also.
Notes:
I am assuming you are using the System.Data.SQLite library and are compiling the the options "/p:UseInteropDll=true /p:UseSqliteStandard=false".
Mono includes a SQLite in it's default install, it is 32-bit on OS-X:
Assuming you are using the OS-X package installer from Mono, thus are getting the 32-bit version of Mono and thus need 32-bit versions of the native libraries.
The /usr/lib/libsqlite3.0.dylib is a multi ARCH fat binary, so that library is not a problem, but your debug output might show another one that is a problem,