如何通过命令行设置VC ++动态链接?

时间:2016-04-13 22:37:14

标签: c++ visual-c++ dll dynamic-linking cl

虽然通过Visual Studio设置运行时DLL加载没有问题,但是在通过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文件来确认,它仍然允许二进制文件成功运行)。 p>

我必须将哪些命令/参数传递给编译/链接阶段以使main.exe使用DLL而不是静态库?

2 个答案:

答案 0 :(得分:2)

这是一个例子。并非所有事情都是完全必要的(例如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 (Use Run-Time Library)。 (通过OUT:参数你可以更改.dll的名称;这里它是默认值,仅用于演示目的。如果你把它遗漏,你也可以跳过/链接参数,因为不再有链接器参数。)

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

匹配dll的运行时lib设置,创建console application(main.cpp有一个int main())并链接SayHello的stub lib(而不是使用LoadLibrary("SayHello.dll") / GetProcAddress(...)

答案 1 :(得分:0)

我将VolkerK的答案标记为正确,因为它包含一些其他重要的Windows DLL API详细信息,绝对值得一读,但我想总结最低更改,可以让它获得基于Igor Tandetnik和VolkerK的评论,动态链接工作在最简单的例子中。

  • 在DLL中导出至少一个函数之前添加宏__declspec(dllexport)是必不可少的,否则库编译命令将不会创建导入库来指示哪些函数可用于动态链接。

  • 第二个“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