Я не вижу недостатков в этом решении.
Я не являюсь большим пользователем Windows, но должен признать, что решение неявного поиска динамических библиотек там, где стоит исполняемый файл, очень помогает.
Вы размещаете весь контент вашего приложения (исполняемых файлов и динамических библиотек/плагинов) в любом месте, и как только вам удастся запустить исполняемый файл, все остальное будет найдено.
Конечно, если вы планируете поставлять много разных приложений с общим подмножеством динамических библиотек, было бы лучше поместить все эти библиотеки в общее место и соответствующим образом настроить переменную среды PATH.
Но это не стоит усилий. для одного приложения.
В приложении на основе mingw-w64 (не совсем Msys64 и MingW, но очень похожем) (с плагинами), которое я поставил несколько месяцев назад, я только что предоставил libgcc_s_seh-1.dll, libstdc++-6.dll и libwinpthread-1.dll. как дополнение к моим собственным двоичным файлам, и это работало без каких-либо проблем.
Использование objdump.exe -p my_program.exe
(затем рекурсивно на отображаемом результате) помогает найти необходимые динамические библиотеки (например, ldd
в Linux или otool -L
в Macosx).
Это то, что мне нравится в решении, похожем на mingw: оно создает собственное приложение Windows, которое не зависит от многих других необычных компонентов (которые пользователю пришлось бы сначала извлекать).
Нет необходимости иметь дело с некоторыми .lib
файлами; достаточно создать файл .dll
и связать его (см. пример ниже).
Он работает точно так же, как мы в UNIX (с файлами .so
).
Я действительно не знаю, почему Visual-C++ полагается на файл so сложная комбинация файлов .lib
и .dll
...
Я только что перепроверил этот простой пример.
файл prog.cpp
#include <windows.h>
#include <iostream>
__declspec(dllimport)
int
my_library_function(int arg);
int
main()
{
std::cout << "~~~~ entering " << __func__ << " ~~~~\n";
int result=my_library_function(123);
std::cout << "result=" << result << '\n';
std::cout << "~~~~ still in " << __func__ << " ~~~~\n";
HINSTANCE lib=LoadLibrary("my_plugin.dll");
if(lib)
{
FARPROC symbol=GetProcAddress(lib, "my_plugin_function");
if(symbol)
{
int (*fnct)(int)=NULL;
memcpy(&fnct, &symbol, sizeof(fnct));
int result=fnct(123);
std::cout << "result=" << result << '\n';
}
FreeLibrary(lib);
}
std::cout << "~~~~ leaving " << __func__ << " ~~~~\n";
return 0;
}
файл my_library.cpp
#include <iostream>
__declspec(dllexport)
int
my_library_function(int arg)
{
std::cout << "~~~~ entering " << __func__ << " ~~~~\n";
std::cout << "arg=" << arg << '\n';
std::cout << "~~~~ leaving " << __func__ << " ~~~~\n";
return 2*arg;
}
файл my_plugin.cpp
#include <iostream>
extern "C" __declspec(dllexport)
int
my_plugin_function(int arg)
{
std::cout << "~~~~ entering " << __func__ << " ~~~~\n";
std::cout << "arg=" << arg << '\n';
std::cout << "~~~~ leaving " << __func__ << " ~~~~\n";
return 2*arg;
}
процесс сборки
==== compiling [opt=0] my_plugin.cpp ====
g++ -o my_plugin.o my_plugin.cpp -c -g -O0 -MMD -pedantic -Wall -Wextra -Wconversion -Wno-unused -Wno-unused-parameter -Werror -Wfatal-errors -UNDEBUG -std=c++17 -Wno-missing-braces -Wno-sign-conversion
==== linking [opt=0] my_plugin.dll ====
g++ -shared -o my_plugin.dll my_plugin.o -g -O0
==== compiling [opt=0] my_library.cpp ====
g++ -o my_library.o my_library.cpp -c -g -O0 -MMD -pedantic -Wall -Wextra -Wconversion -Wno-unused -Wno-unused-parameter -Werror -Wfatal-errors -UNDEBUG -std=c++17 -Wno-missing-braces -Wno-sign-conversion
==== linking [opt=0] my_library.dll ====
g++ -shared -o my_library.dll my_library.o -g -O0
==== compiling [opt=0] prog.cpp ====
g++ -o prog.o prog.cpp -c -g -O0 -MMD -pedantic -Wall -Wextra -Wconversion -Wno-unused -Wno-unused-parameter -Werror -Wfatal-errors -UNDEBUG -std=c++17 -Wno-missing-braces -Wno-sign-conversion
==== linking [opt=0] prog.exe ====
g++ -o prog.exe prog.o -g -O0 -lmy_library
исполнение
C:\Work\PluginTest>prog.exe
~~~~ entering main ~~~~
~~~~ entering my_library_function ~~~~
arg=123
~~~~ leaving my_library_function ~~~~
result=246
~~~~ still in main ~~~~
~~~~ entering my_plugin_function ~~~~
arg=123
~~~~ leaving my_plugin_function ~~~~
result=246
~~~~ leaving main ~~~~
C:\Work\PluginTest>
Это все еще работает, когда каталог mingw64 (содержащий набор инструментов) переименовывается, как только файлы libgcc_s_seh-1.dll
, libstdc++-6.dll
и libwinpthread-1.dll
помещаются в тот же каталог, что и prog.exe
.
Это даже работает, когда prog.exe
запускается щелчком (а не из командная строка); чтобы увидеть это, мне пришлось добавить бесконечный цикл в конце программы, чтобы окно оставалось открытым достаточно долго, чтобы увидеть отображаемые сообщения.
person
prog-fh
schedule
28.03.2020