我有一个使用SQLite的C#应用程序,可以在Windows上正常运行。
相同的Visual Studio项目在Xamarin Studio中编译得很好,但在运行时我得到:
DllNotFoundException: SQLite.Interop.dll
尽管:
libsqlite3.0.dylib
位于/usr/lib
中,并且与可执行文件和其他DLL位于同一文件夹中.
是$DYLD_LIBRARY_PATH
<the_exe_or_dll_including_filename_extension>.config
文件,其中包含: <configuration>
<dllmap dll="sqlite" target="libsqlite.0.dylib" os="osx"/>
<dllmap dll="sqlite3" target="libsqlite3.0.dylib" os="osx"/>
</configuration>
我也尝试添加<dllmap dll="SQLite.Interop.dll" target="libsqlite3.0.dylib" os="osx"/>
,而不是更好。
有什么问题?
答案 0 :(得分:5)
通过将MONO_LOG_LEVEL设置为debug并将MONO_LOG_MASK过滤设置为仅与DLL相关的消息,您可以轻松找到mono寻找该本机库的位置。
export MONO_LOG_LEVEL=debug
export MONO_LOG_MASK=dll
mono yourprogram.exe
或作为一个班轮,所以你不必取消设置env vars:
MONO_LOG_LEVEL=debug MONO_LOG_MASK=dll mono yourprogram.exe
Mono和OS-X动态链接编辑器(有关详细信息的“man dyld”)不需要将DYLD_LIBRARY_PATH设置为当前目录('。')。注意:如果您愿意,Linux确实需要LD_LIBRARY_PATH来包含当前目录。
使用本机dll /共享库跟踪输出,您可以跟踪找不到哪个库(或其中一个依赖项),或者它是否是单声道版本的错误ARCH。
如果您仍然遇到问题,我们需要知道您正在使用哪个SQLite库来编译它(或者如果通过Nuget获取它,则使用arch版本)。发布你的dll跟踪输出也可以快速解决问题。
注意:
我假设您正在使用System.Data.SQLite库并正在编译选项“/ p:UseInteropDll = true / p:UseSqliteStandard = false”。
Mono在其默认安装中包含一个SQLite,它在OS-X上是32位:
file /Library/Frameworks/Mono.framework/Versions/4.0.2/lib/libsqlite3.dylib
/Library/Frameworks/Mono.framework/Versions/4.0.2/lib/libsqlite3.dylib: Mach-O dynamically linked shared library i386
假设您正在使用Mono的OS-X软件包安装程序,因此获得了32位版本的Mono,因此需要32位版本的本机库。
>>file `which mono`
/usr/bin/mono: Mach-O executable i386
/usr/lib/libsqlite3.0.dylib是一个多ARCH胖二进制文件,因此库不是问题,但是你的调试输出可能会显示另一个问题,
>>file /usr/lib/libsqlite3.0.dylib
libsqlite3.0.dylib: Mach-O universal binary with 3 architectures
libsqlite3.0.dylib (for architecture x86_64): Mach-O 64-bit dynamically linked shared library x86_64
libsqlite3.0.dylib (for architecture i386): Mach-O dynamically linked shared library i386
libsqlite3.0.dylib (for architecture x86_64h): Mach-O 64-bit dynamically linked shared library x86_64
答案 1 :(得分:3)
您需要构建并提供SQLite.Interop.dll
(或更准确地说libSQLite.Interop.dylib
)。 Mono发行包不包含它,可能是因为它是本机代码,并且确实需要在目标平台上构建。
Windows上的System.Data.SQLite使用混合模式方法(一个程序集中的托管数据适配器+ sqlite本机代码)。但Mono并不真正支持混合模式组件。
因此,在MacOS上,在Windows上构建System.Data.SQLite时有两种选择:
这两个都是本机代码,需要在Mac上构建。
Interop是Windows com,所以看到它在MacOS上下文中使用有点令人不安。这个原生的dll是使用一些额外的本机代码编译的sqlite源代码,可以由System.Data.SQLite进行P \ Invoked。使用benefits而不是sqlite dylib有一些interop dll。
System.Data.SQLite附带了./SQLite.Interop/src.core
中相关SQLite本机源代码的副本。您可以通过在Mac上运行compile-interop-assembly-release.sh
来构建互操作库。这将构建libSQLite.Interop.dylib
。放在System.Data.SQLite旁边,你应该好好去。
如果打开Mono dll跟踪,您可以观察加载程序(请参阅mono 4.8.0 loader.c)在各个位置搜索dll并使用各种名称替换。最终它找到了我们的dylib。也可以在dllmap
文件中使用System.Data.SQLite.dll.config
条目将运行时定向到dll。在我的情况下Mono在我的应用程序包上,所以我有:
<dllmap dll="SQLite.Interop.dll" target="@executable_path/../Mono/libSQLite.Interop.dylib" os="!windows"/>
dllmap
目标参数传递给dlopen()
,因此@executable_path
等都可以使用。
我喜欢这种方法,因为它进入了回购,并提供了一些洞察当发生犯规时发生的事情。