Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何设置VC++;通过命令行动态链接?_C++_Visual C++_Dll_Dynamic Linking_Cl - Fatal编程技术网

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

C++ 如何设置VC++;通过命令行动态链接?,c++,visual-c++,dll,dynamic-linking,cl,C++,Visual C++,Dll,Dynamic Linking,Cl,虽然通过VisualStudio设置运行时DLL加载没有问题,但在通过VisualStudioCLI工具手动执行时遇到了一些问题 我们说下面有2个简单的C++源文件我们要编译,一个是二进制可执行文件,一个是DLL:< /P> main.cpp void say_hello(); int main() { say_hello(); return 0; } #include <stdio.h> void say_hello() { printf("Hello

虽然通过VisualStudio设置运行时DLL加载没有问题,但在通过VisualStudioCLI工具手动执行时遇到了一些问题

我们说下面有2个简单的C++源文件我们要编译,一个是二进制可执行文件,一个是DLL:< /P> main.cpp

void say_hello();

int main()
{
    say_hello();
    return 0;
}
#include <stdio.h>

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

int main()
{
    say_hello();
    return 0;
}
#include <stdio.h>

__declspec(dllexport) void say_hello()
{
    printf("Hello DLL World!");
}
打招呼。cpp

void say_hello();

int main()
{
    say_hello();
    return 0;
}
#include <stdio.h>

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

int main()
{
    say_hello();
    return 0;
}
#include <stdio.h>

__declspec(dllexport) void say_hello()
{
    printf("Hello DLL World!");
}
不幸的是,这似乎只允许通过
say_hello.lib
文件静态链接应用程序(可以通过删除.lib和.dll文件来确认,这仍然允许二进制文件成功运行)


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

下面是一个示例。并非每件事都是完全必要的(例如,德尔曼),但我认为这些是你应该查阅的;-)

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;
    }
}
然后编译/链接

cl /D_USRDLL /D_WINDLL SayHello.cpp /LD /link /OUT:SayHello.dll
/LD告诉链接器构建DLL并使用/MT,请参阅。(通过OUT:parameter,您可以更改.dll的名称;这里是默认名称,仅用于演示。如果不使用它,您还可以跳过/link参数,因为不再有链接器参数。)


匹配dll的运行时库设置,创建一个(main.cpp有一个
int main()
)并链接SayHello的存根库(而不是使用/)

我将VolkerK的答案标记为正确,因为它包含了一些非常值得一读的其他重要Windows dll API详细信息,但我想总结一下,根据Igor Tandetnik和VolkerK的评论,在最简单的示例中,动态链接可以实现的最小变化

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

  • 第二个“lib say_hello.obj”是完全错误的,因为DLL编译命令将正确地生成say_hello.lib(而该lib命令只会生成一个静态库并最终覆盖第一个命令)

以下是最基本的完整工作示例:

main.cpp

void say_hello();

int main()
{
    say_hello();
    return 0;
}
#include <stdio.h>

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

int main()
{
    say_hello();
    return 0;
}
#include <stdio.h>

__declspec(dllexport) void say_hello()
{
    printf("Hello DLL World!");
}
打招呼。cpp

void say_hello();

int main()
{
    say_hello();
    return 0;
}
#include <stdio.h>

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

int main()
{
    say_hello();
    return 0;
}
#include <stdio.h>

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

cl say_hello.cpp/LD
应在.lib文件中生成DLL和导入库。随后的
lib
命令将用静态库覆盖前面提到的导入库。别那么做。另一个问题是名称需要通过DEF文件或
\uuu declspec(dllexport)
从DLL显式导出。如前所述,您没有导出任何内容,因此没有实际链接的内容。啊,是的。。。第一步
cl say_hello.cpp/LD
的控制台输出似乎表明创建了“/implib:say_hello.lib”,但我只看到目录中生成的
say_hello.obj
say_hello.dll
。是否需要传递一些其他标志来告诉它不要清理导入库?啊,我明白了,为要导出的函数添加前缀的
\u declspec(dllexport)
宏是至关重要的,因为如果没有它,cl.exe会在完成后立即删除导入库文件
say_hello.lib
。是的,因为没有什么可导入的;-)Doh,混淆了第二个cl.exe命令的编译器/链接器参数。自我提示:先测试,然后发布。