Я не вижу никаких недостатков в этом решении.
Я не большой пользователь Windows, но я должен признать, что решение неявного поиска динамических c библиотек, где стоит исполняемый файл, очень помогает.
Вы помещаете весь контент вашего приложения (исполняемые файлы и динамические c библиотеки / плагины) куда угодно, и как только вам удастся запустить исполняемый файл, все остальное будет найдено.
Конечно, если вы планируете поставлять много разных приложений с общим подмножеством динамических c библиотек, может быть лучше разместить все эти библиотеки в одном месте и соответствующим образом изменить переменную среды PATH.
Но это не стоит усилий для одного приложения.
В приложении на основе mingw-w64 (не совсем Msys64 и MingW, но очень близко) (с плагинами), которое я поставил несколько месяцев за go, я просто предоставил libgcc_s_seh-1 .dll, libstdc ++ - 6.dll и libwinpthread-1.dll в качестве дополнения к моим собственным двоичным файлам, и это работало без каких-либо пр oblem.
Использование objdump.exe -p my_program.exe
(затем рекурсивно для отображаемого результата) помогает найти необходимые динамические библиотеки (например, ldd
в Linux или otool -L
в Macosx).
Это то, что мне нравится в mingw-подобном решении: оно создает собственное приложение Windows, которое не зависит от многих других необычных компонентов (которые пользователь должен был бы получить первым).
Нет необходимости иметь дело с некоторыми .lib
файлами; достаточно создать .dll
и связать его (см. пример ниже).
Он работает точно так же, как мы делаем на UNIX (с .so
файлами).
Я действительно не знаю, почему Visual -C ++ использует очень сложную комбинацию файлов .lib
и .dll
...
Я только что протестировал этот простой пример.
file 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
запускается нажатием (не из командной строки); чтобы увидеть это, мне пришлось добавить бесконечный цикл в конце программы, чтобы окно оставалось открытым достаточно долго, чтобы видеть отображаемые сообщения.