2015-07-01 47 views
4

是我有一個使用SQLite和Windows上工作得很好C#應用程序。單在Mac上:DllNotFoundException儘管SQLite.Interop.dll在dllmap

相同的Visual Studio項目在Xamarin工作室編譯罰款,但在運行時,我得到:

DllNotFoundException: SQLite.Interop.dll 

儘管:

  • libsqlite3.0.dylib/usr/lib,並在同一文件夾中的可執行文件和其他DLL
  • .$DYLD_LIBRARY_PATH的一部分
  • 可執行文件和所有使用SQLite的dll有一個包含匹配<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"/>,而不是更好。

什麼問題?

+1

有兩件事:'OS X'不使用'Windows'的'$ PATH'變量,動態庫是'dylibs',而不是'dlls'。爲了使'dll'在單聲道和'OS X'上正常工作,它需要使用'Dllmap'進行映射。 –

+0

@ l'L'l:[這個軟件](https://github.com/aegif/CmisSync)在Mono上使用Mac上的SQLite,不包含任何'Dllmap' ...仍然試圖找到它如何管理。 –

+0

看起來像* * dllmaps](https://github.com/aegif/CmisSync/search?utf8=%E2%9C%93&q=dllmap),所以我會想象[interop.dll](https ://github.com/aegif/CmisSync/search?utf8 =%E2%9C%93&q = Interop.dll)也可能需要它。 –

回答

5

你可以很容易找到,其中單是由MONO_LOG_LEVEL調試和MONO_LOG_MASK過濾設置爲僅DLL有關的消息尋找一個機庫。

export MONO_LOG_LEVEL=debug 
export MONO_LOG_MASK=dll 
mono yourprogram.exe 

或作爲一個襯墊,所以你不必取消設置ENV瓦爾:

MONO_LOG_LEVEL=debug MONO_LOG_MASK=dll mono yourprogram.exe 

單聲道和OS-X動態鏈接編輯器(「人dyld的」瞭解詳細信息)不需要DYLD_LIBRARY_PATH設置爲當前目錄('。')。注意:如果您的意圖是Linux,則需要LD_LIBRARY_PATH包含當前目錄。

  • 移動這些dll映射文件,將其從等式中移除。
  • 取消設置DYLD_LIBRARY_PATH
  • CD中包含根據您的CIL EXE,DLL和本地dylib(S)
  • MONO_LOG_LEVEL =調試MONO_LOG_MASK = DLL單yourprogram.exe

使用本地的dll目錄/共享庫跟蹤輸出,你可以跟蹤不被發現的庫(或其依賴關係之一),或者如果它是你的單聲道版本錯誤的ARCH。

如果您仍然有問題,我們就需要知道你正在使用您正在使用的選項編譯它(或拱形的版本,如果通過的NuGet得到它),這SQLite庫。張貼您的DLL跟蹤輸出將迅速解決事情。

注:

我假設你使用的是System.Data.SQLite庫,並編譯選項 「/ P:UseInteropDll = TRUE/P:UseSqliteStandard =假」。

單聲道包括一個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 

假設你正在使用從單聲道的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

我不編譯「/ p:UseInteropDll = true/p:UseSqliteStandard = false」。如果在Mono/Mac上有使用SQLite的標準簡單方法,我可以使用它:-) –

+0

「單聲道」文件說/ usr/bin/mono:Mach-O可執行文件i386'確實如此。 –

+0

「file /usr/lib/libsqlite3.0.dylib」也會輸出與你的一樣的文件。 –

2

您需要構建並提供SQLite.Interop.dll(或更準確地說libSQLite.Interop.dylib)。 Mono發行包不包含它,可能是因爲它是本地代碼,並且確實需要在目標平臺上構建。

Windows上的System.Data.SQLite使用混合模式方法(在一個程序集中管理數據適配器+ sqlite本機代碼)。但單聲道並不真正支持混合模式程序集。

所以在MacOS上有兩種選擇,當談到在Windows上建立System.Data.SQLite:

  1. 使用互操作的dll。
  2. 使用libsqlite.x.x.dylib。

這兩個都是本機代碼,需要在Mac上構建。

Interop是Windows的COM說話,所以看到它在MacOS環境中使用有點令人不安。這個本地DLL是什麼編譯了一些額外的本地代碼,可以由System.Data.SQLite調用SQLite源代碼。有一些benefits使用interop dll而不是sqlite dylib。

System.Data.SQLite附帶了./SQLite.Interop/src.core中的相關SQLite本機源代碼的副本。您可以通過在Mac上運行compile-interop-assembly-release.sh來構建互操作庫。這將建立libSQLite.Interop.dylib。把它放在System.Data.SQLite旁邊,你應該很好。

如果您打開單聲道dll跟蹤,您可以觀察加載器(請參閱mono 4.8.0 loader.c)在各個位置搜索dll並使用各種名稱替換。最終它找到我們的dylib。也可以使用System.Data.SQLite.dll.config文件中的dllmap條目將運行時指向dll。在我的情況Mono是我的應用程序包,所以我必須:

<dllmap dll="SQLite.Interop.dll" target="@executable_path/../Mono/libSQLite.Interop.dylib" os="!windows"/> 

dllmap目標參數傳遞給dlopen()所以@executable_path都可以使用。

我更喜歡這種方法,因爲它進入回購,並提供了一些有關發生什麼事情時,有一個犯規。