Задержка загрузки DLL в режиме релиза

В проекте C, который я создаю в Visual Studio (C++ 2010 Express), я использую движок MatLab, чтобы позволить пользователю предоставлять пользовательскую функцию для использования в проекте. Проблема заключается в том, что этот код также должен быть в состоянии запускаться на компьютерах без установленного MatLab, а это означает, что в этом случае требуемые библиотеки DLL не будут доступны на компьютере. Конечно, это должно работать только тогда, когда пользователь не пытается получить доступ к фрагменту кода, который вызывает механизм Matlab (я предоставил для этого флаг).

У меня есть 3 DLL, которые необходимы для этого сценария.

  • libmx.dll
  • libmex.dll
  • libeng.dll

До сих пор я был в состоянии загрузить libeng.dll во время выполнения, используя LoadLibrary и GetProcAddress. Две другие библиотеки DLL немного сложнее, хотя, помимо C-кода, вызывающего движок MatLab, код также часто компилируется как mex-файл (исполняемый файл MatLab), чтобы позволить пользователям вызывать его из MatLab. При компиляции в качестве mex-файла и libmx.dll, и libmex.dll динамически связываются компилятором mex. Это означает, что использование LoadLibrary и GetProcAddress не работает для этих DLL.

Прямо сейчас я просто добавляю библиотеки libmx и libmex в свойства компоновщика в Visual Studio, и это работает нормально, но не будет возможно для тех, у кого не установлен MatLab.

Я попытался использовать delayLoad, и это работает, если я компилирую в режиме отладки, но выдает эту ошибку сборки, когда я компилирую в режиме выпуска.

1>C:\Program Files (x86)\MATLAB\R2012a\bin\win32\libmx.dll : fatal error LNK1107: invalid or corrupt file: cannot read at 0x2B8

Есть ли способ просто полностью пропустить поиск / загрузку этих DLL, если к части кода, которая их использует, нет доступа?

Это командная строка для компоновщика:

/OUT:"C:\Users\A.Vandenber\documents\visual studio 2010\Projects\Flash\Release\Flash.exe" /NOLOGO "C:\Program Files (x86)\MATLAB\R2012a\bin\win32\libmx.lib" "C:\Program Files (x86)\MATLAB\R2012a\bin\win32\libmex.lib" "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /DELAYLOAD:"libmex.dll" /DELAYLOAD:"libmx.dll" /MANIFEST /ManifestFile:"Release\Flash.exe.intermediate.manifest" /ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"C:\Users\A.Vandenber\documents\visual studio 2010\Projects\Flash\Release\Flash.pdb" /OPT:REF /OPT:ICF /PGD:"C:\Users\A.Vandenber\documents\visual studio 2010\Projects\Flash\Release\Flash.pgd" /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 /ERRORREPORT:QUEUE 

2 ответа

Решение

Чем больше я об этом думаю, тем больше это похоже на проблему [Wikipedia]: XY.

1. X (запуск файла MEX на компьютере без библиотек MATLAB)

Согласно [MathWorks]: Запустите MEX-файл, который вы получили от кого-то другого (акценты мои):

На платформах Windows® установите библиотеки времени выполнения компилятора C++, используемые для создания файла MEX.

...

MEX-файл - это динамически связанная подпрограмма, которую интерпретатор MATLAB загружает и выполняет при вызове функции. Динамическое связывание означает, что когда вы вызываете функцию, программа ищет зависимые библиотеки. В файлах MEX используются библиотеки времени выполнения MATLAB и языковые библиотеки. MEX-файл может также использовать специализированные библиотеки времени выполнения. Код для этих библиотек не включен в файл MEX; библиотеки должны присутствовать на вашем компьютере при запуске файла MEX.

[MathWorks]: MATLAB Runtime содержит ссылки для загрузки многих версий (ваша - по вашим путям - будет http://ssd.mathworks.com/supportfiles/MCR_Runtime/R2012a/MCR_R2012a_win32_installer.exe), которые являются бесплатными (я установил 3 из этих версий для тестирования этого сценария), а также заявляет:

Запускать скомпилированные приложения или компоненты MATLAB без установки MATLAB

Таким образом, для меня совершенно очевидно, что тот, кто хотел бы использовать этот файл, должен установить MCR.

2. Y (с использованием Delay Loaded DLL s)

VStudio уже давно поддерживает эту функцию ( [MS.Docs]: поддержка компоновщика DLL-библиотек с задержкой).

Никогда не работал с файлами MEX, и при этом у меня нет полной спецификации проблемы, но разрешение запуска одного такого файла при отсутствии MATLAB .dll не выглядит для меня хорошим дизайном (это означает, что он также содержит другие вещи - который на мой взгляд должен быть размещен отдельно). Единственный сценарий, который имеет смысл, состоит в том, что MEX- файл будет .exe (не знаю, возможно ли это, или это просто глупость), и он будет иметь некоторые --help эквивалентный (что было бы неплохо (но не обязательно) для запуска в средах без .dll).
Но это также может быть решено с помощью других способов (например, README, как файл)

3. Конечная проблема

Учитывая, что в вопросе было / есть несколько (логических) ошибок:

  • .Dll переданы компоновщику
  • Файлы .lib, расположенные в каталоге bin
  • Последний путь (extern / lib / win64 / microsoft) содержит 64-битные .lib s, а компоновщик настроен на 32-битный вывод
  • [MS.Docs]: Ошибка инструментов компоновщика LNK1107, которая довольно ясна (как сообщение об ошибке в вопросе)

Я могу только заключить, что для выпуска " C: \ Program Files (x86) \ MATLAB \ R2012a \ bin \ win32 \ libmx. Dll " был неправильно передан компоновщику (вместо соответствующего .lib).

Я немного поиграл с MEX:

code.c:

#include <stdio.h>
#include <conio.h>
#include <mex.h>


int main(int argc, char **argv) {
    if (argc > 1) {
        fprintf(stdout, "Argument passed: mexEvalString() returns\n", mexEvalString("n = 1;"));
    } else {
        fprintf(stdout, "Argument NOT passed: pass...\n");
    }
    fprintf(stdout, "Press a key to exit...\n");
    _getch();
    return 0;
}

Примечания:

  • Я использовал fprintf, потому что в mex.h есть строка:

    #define printf mexPrintf
    
  • Не знал, какую функцию использовать из libmx.dll, чтобы принудительно добавить ее (а не просто зависимость для libmex.dll)
  • Мне удалось протестировать функцию DLL с задержкой в приложении Debug и Release (при отсутствии аргумента программа запускалась без добавления MEX .dll в % PATH%).
    Это правда, что во время выполнения я получил Access Violation, но это совершенно другая проблема
  • Само собой разумеется, что добавление любой из .dll к " Linker -> Input -> Additional Dependencies ", вызвало точно такую ​​же ошибку

В заключение я хотел бы отметить, что MCR R2012a (и некоторые другие, выпущенные после него), собраны с VStudio 9.0 (2008), а сборка вашей программы с VStudio 10.0 (2010) даст оба CRT Lib. в загруженном процессе, а в некоторых случаях это может вызвать некоторые ошибки (особенно если VStudio 9.0 поставляется в виде сборки). Это относится к libmx.dll и libmex.dll, но не к libeng.dll.

Во-первых, переместите свой код в каталог, который имеет access privileges и не read-only, Также проверьте этот ответ здесь: Задержка загрузки DLL

Чтобы добавить dll файлы в Visual Studio, вы можете следовать этой ссылки DLL в Visual Studio

Другое предложение состоит в том, чтобы поставить dll в c:\windows\system32, Когда программа запускается, она будет искать этот файл в c:\windows\system32 каталог. Перед этим он будет искать каталог, из которого была запущена программа. Visual Studio запускает программы из каталога своего проекта (куда должен быть помещен упомянутый файл.dll, если он не помещен в windows\system32 каталог). Аналогичным образом, если исполняемый файл программы запускается вручную из своего каталога, указанный файл.dll должен находиться в same folder where the program's executable файл находится. Вам понадобятся права администратора, чтобы сделать это.

Другие вопросы по тегам