Как настроить динамическое связывание VC ++ через командную строку?

Хотя у меня нет проблем с настройкой загрузки DLL во время выполнения через Visual Studio, у меня возникают некоторые проблемы при выполнении этого вручную с помощью инструментов Visual Studio CLI.

Скажем, у нас есть следующие 2 простых исходных файла C ++, которые мы хотим скомпилировать: один для двоичного исполняемого файла и один для DLL:

main.cpp

void say_hello();

int main()
{
say_hello();
return 0;
}

say_hello.cpp

#include <stdio.h>

void say_hello()
{
printf("Hello DLL World!");
}

Какие шаги для компиляции say_hello.cpp файл как DLL, а затем динамически связать его с вызовом из main.cpp?

Основываясь на моем прочтении документации MSDN, я смог успешно скомпилировать say_hello.dll и приложение затем запускает его и использует следующие команды:

cl say_hello.cpp /LD
lib say_hello.obj
cl say_hello.lib main.cpp

К сожалению, это, кажется, позволяет только статически связать приложение через say_hello.lib файл (который можно подтвердить, удалив файлы .lib и .dll, что позволяет бинарному файлу работать успешно).

Какие команды / параметры мне нужно передать на этап компиляции / компоновки, чтобы main.exe использовать DLL вместо статической библиотеки?

1

Решение

Вот пример. Не каждая вещь абсолютно необходима (например, DLLMain), но я думаю, что это те вещи, которые вы должны искать 😉

SayHello.cpp

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>

// see https://msdn.microsoft.com/en-us/library/56h2zst2.aspx : Decorated Names
extern "C" {  // somehow making it superfluous to put the code in SayHello.cPP ...but anyway ;-)
// see https://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx : dllexport, dllimport
__declspec(dllexport) void say_hello()
{
printf("Hello DLL World!");
}

// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms682583%28v=vs.85%29.aspx : (optional) DllMain entry point
BOOL WINAPI DllMain(HMODULE hModule,
DWORD  ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
}

main.cpp

extern "C" { __declspec(dllimport) void say_hello(); }  // we did this in SayHello.cpp, so we have to do it here too.
// otherwise the name wouldn't match

int main() {
say_hello();
return 0;
}

а затем компиляция / связывание

cl /D_USRDLL /D_WINDLL SayHello.cpp /LD /link /OUT:SayHello.dll

/ LD говорит компоновщику построить DLL а также использовать / MT, см. / MD, / MT, / LD (использовать библиотеку времени выполнения). (через OUT: параметр, который вы мог изменить имя .dll; здесь это по умолчанию, только для демонстрационных целей. Если вы пропустите это, вы также можете пропустить параметр / link, так как больше не будет параметров компоновщика.)

cl.exe /MT main.cpp /link /SUBSYSTEM:CONSOLE "SayHello.lib"

сопоставляя параметры библиотеки времени выполнения для DLL, создавая консольное приложение (main.cpp имеет int main()) и связывание заглушки SayHello (вместо использования LoadLibrary ( «SayHello.dll»)/GetProcAddress (…))

2

Другие решения

Я пометил ответ VolkerK как правильный, поскольку он включает в себя некоторые другие важные детали API Windows DLL, которые определенно стоит прочитать, но я хотел бы подвести итог минимум изменения, которые можно сделать, чтобы получить динамическое связывание, работающее в самом простом примере, основанном на комментариях Игоря Тандетника и VolkerK.

  • Добавление макроса __declspec(dllexport) прежде чем по крайней мере одна функция, подлежащая экспорту в DLL, является необходимой, в противном случае команда компиляции библиотеки не создаст библиотеку импорта, чтобы указать, какие функции доступны для динамического связывания.

  • Второй «lib say_hello.obj» был полностью неверным, так как команда компиляции DLL правильно создаст say_hello.lib (тогда как эта команда lib будет генерировать только статическую библиотеку и перезаписывать первую команду).

Вот полный самый основной рабочий пример:

main.cpp

void say_hello();

int main()
{
say_hello();
return 0;
}

say_hello.cpp

#include <stdio.h>

__declspec(dllexport) void say_hello()
{
printf("Hello DLL World!");
}

Команды компиляции:

cl say_hello.cpp /LD
cl main.cpp say_hello.lib
0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector