Задержка загрузки DLL в режиме релиза - PullRequest
0 голосов
/ 21 января 2019

В проекте на 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 ]

0 голосов
/ 29 января 2019

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

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

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

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

...

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

[MathWorks]: MATLAB Runtime содержит ссылки для загрузки многих версий ( ваша - в соответствии с вашими путями - будет [MathWorks]: MCR Runtime - 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 s переданы компоновщику
  • Файлы .lib , расположенные в bin dir
  • Последний путь ( extern / lib / win64 / microsoft ) содержит 64 бит .lib с, в то время как компоновщик установлен на 32 бит выход
  • [MS.Docs]: Ошибка инструментов компоновщика LNK1107 , что довольно ясно (как сообщение об ошибке в вопросе)

Я могу только заключить, что для Release , " 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 с задержкой в Отладка и Release (при отсутствии аргумента программа работала без добавление MEX .dll s к % PATH% ).
    Это правда, что во время выполнения я получил Нарушение доступа , но это совсем другая проблема
  • Нет необходимости говорить, что добавление любого из .dll s к " 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 .

0 голосов
/ 28 января 2019

Сначала переместите свой код в каталог с 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.Для этого вам потребуются права администратора.

...