windows下编译和使用动态库dll

实验环境 VC 2010 ,全程使用的是交叉命令行。

准备

先准备两个文件:

main.c

#include <stdio.h>

extern int add(int a, int b);

int main()
{
    printf("%d", add(1, 2));
    return 0;
}

add.c

_declspec(dllexport) int add(int a, int b)
{
    return a + b;
}

_declspec(dllexport)

Microsoft 在 Visual C++ 的 16 位编译器版本中引入了 __export,使编译器得以自动生成导出名并将它们放到一个 .lib 文件中。 然后,此 .lib 文件就可以像静态 .lib 那样用于与 DLL 链接。

在更新的编译器版本中,可以使用 declspec(dllexport) 关键字从 DLL 导出数据、函数、类或类成员函数。 declspec(dllexport) 会将导出指令添加到对象文件中,因此您不需要使用 .def 文件。

当尝试导出 C++ 修饰函数名时,这种便利最明显。 由于对名称修饰没有标准规范,因此导出函数的名称在不同的编译器版本中可能有所变化。 如果使用 __declspec(dllexport),仅当解决任何命名约定更改时才必须重新编译 DLL 和依赖 .exe 文件。

许多导出指令(如序号、NONAME 和 PRIVATE)只能在 .def 文件中创建,并且必须使用 .def 文件来指定这些特性。 不过,在 .def 文件的基础上另外使用 __declspec(dllexport) 不会导致生成错误。

编译

cl /LD add.c

/LD 参数是告诉编译器要创建 .DLL文件。

运行完之后便可生产对应的dll文件lib文件。lib文件里面并没有可执行函数,函数全部在dll文件中,lib文件相当于一个索引,我们在链接的时候将会用到,而程序运行的时候才会用到dll文件。

链接

cl main.c add.lib

这样一个依赖于add.dll的二进制可执行文件便编译好了,当你删除掉add.dll后再运行该文件,程序便会抛出找不到add.dll的错误。

当然也可以用下面的方法来事先告诉编译器要链接add.lib文件。

#include<stdio.h>
#pragma comment(lib, "add.lib")

extern int add(int a, int b);

int main()
{
    printf("%d", add(1, 2));
    return 0;
}

总结

多记多写,总会有收获。