4

У меня есть приложение C#, которое использует SQLite и отлично работает в Windows.Моно на Mac: DllNotFoundException, несмотря на то, что SQLite.Interop.dll находится в dllmap

Тот же проект Visual Studio отлично компилируется в Xamarin Studio, но при запуске я получаю:

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' не использует переменную' $ PATH', которую выполняет 'Windows', а динамические библиотеки -' dylibs', а не 'dlls'. Для того, чтобы 'dll' корректно работал с mono и' OS X', его нужно сопоставить с помощью 'Dllmap'. –

+0

@ l'L'l: [Это программное обеспечение] (https://github.com/aegif/CmisSync) использует SQLite на Mac с Mono и не содержит никаких «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 ищет эту родную библиотеку, установив MONO_LOG_LEVEL для отладки и фильтрации MONO_LOG_MASK только для сообщений, связанных с DLL.

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

или как один лайнер, так что вы не должны быть сброшен окр вары:

MONO_LOG_LEVEL=debug MONO_LOG_MASK=dll mono yourprogram.exe 

Mono и редактор OS-X динамической ссылки («человек dyld» для подробностей) не требуют DYLD_LIBRARY_PATH для установки в текущий каталог ('.'). Примечание. Linux требует, чтобы LD_LIBRARY_PATH включал текущий каталог, если это ваше намерение.

  • Переместите эти файлы карт dll с пути, чтобы удалить их из уравнения.
  • Unset DYLD_LIBRARY_PATH
  • кд в каталоге, который содержит ех вашего CIL на основе, динамические библиотеки и родной dylib (ы)
  • MONO_LOG_LEVEL = отлаживать MONO_LOG_MASK = дллы моно yourprogram.exe

Использования DLL нативный/вы можете отслеживать, какая библиотека не найдена (или одна из ее зависимостей), или если это неправильная ARCH для вашей моно версии.

Если у вас по-прежнему возникают проблемы, нам нужно знать, в какой библиотеке SQLite вы используете параметры, которые вы используете для его компиляции (или версии с аркой, если вы получаете его через Nuget). Публикация вывода вашей DLL-трассировки также быстро решила бы проблему.

Примечания:

Я предполагаю, что вы используете библиотеку System.Data.SQLite и компиляции опции «/ р: UseInteropDll = истина/р: UseSqliteStandard = ложь».

Mono включает в себя SQLite в нем по умолчанию установки, это 32-разрядный на OS-X:

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 пакета из Mono, таким образом, получают 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». Если есть стандартный простой способ использовать SQLite на Mono/Mac, я все его использую :-) –

+0

«Файл, который mono» говорит '/ usr/bin/mono: Mach-O исполняемый i386' действительно. –

+0

«файл /usr/lib/libsqlite3.0.dylib» также выводит то же, что и ваш. –

2

Вам необходимо построить и поставить SQLite.Interop.dll (точнее, libSQLite.Interop.dylib). Пакеты дистрибутива Mono не включают его, вероятно, потому, что это собственный код и действительно необходимо создать на целевой платформе.

System.Data.SQLite в Windows использует смешанный режим (управляемый адаптер данных + собственный код sqlite в одной сборке). Однако Mono действительно не поддерживает сборки смешанного режима.

Так на MacOS есть две альтернативы, когда речь идет о строительстве System.Data.SQLite на Windows:

  1. Использование DLL Interop.
  2. Использование libsqlite.x.x.dylib.

Оба эти кода являются собственными и должны быть построены на Mac.

Interop - это Windows com, так что это немного смущает, что он используется в контексте MacOS. Какова эта родная dll - это исходный код sqlite, скомпилированный с некоторым дополнительным собственным кодом, который может быть P \ Invoked by System.Data.SQLite. Есть benefits для использования interop dll в отличие от sqlite dylib.

System.Data.SQLite поставляется с копией соответствующего исходного кода SQLite в формате ./SQLite.Interop/src.core. Вы можете создать библиотеку interop, запустив compile-interop-assembly-release.sh на Mac. Это построит 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и др все годны к употреблению.

Я предпочитаю этот подход, поскольку он входит в репо, и дает некоторое представление о том, что происходит, когда происходит загрязнение.