这是我的库Lib.c
文件:
#include <stdio.h> int helloworld(){ printf("Hello World DLL"); }
这是我的exe Main.c
文件:
int helloworld(); int main(int argc, char** argv){ helloworld(); }
我想创buildLib.dll
和Main.exe
,其中Lib.dll
来自Lib.c
和Main.exe
链接。
具体步骤是什么?
请参阅有关如何构建DLL的相关问题。
您的库代码不会导出任何符号,而且您的可执行文件不会从库中导入符号。 下面显示了两种典型的模式,但您可能需要先阅读这些模式。
第一种方法使用__declspec()
在代码中声明哪些函数(或其他项)从DLL中导出并由其他可执行文件导入。 您使用头文件来声明导出的项目,并有一个预处理器标志用于控制符号是导出还是导入:
mylib.h:
#ifndef MYLIB_H #define MYLIB_H #if defined(BUILDING_MYLIB) #define MYLIB_API __declspec(dllexport) __stdcall #else #define MYLIB_API __declspec(dllimport) __stdcall #endif #ifdef __cplusplus extern "C" { #endif int MYLIB_API helloworld(void); #ifdef __cplusplus } #endif #endif
我也特别将调用约定设置为__stdcall
就像大多数DLL函数一样(如果我包含了windows.h,我可以使用WINAPI
而不是__stdcall
),并且声明了函数作为extern "C"
这样当它们的名字不会在编译为C ++。 在这里没有这样的问题,因为它全是C,但是如果你要从C源代码构建DLL,然后尝试从C ++可执行文件中使用它,那么导入的名称将是不正确的。
代码可能看起来像这样:
mylib.c
#include "mylib.h" #include <stdio.h> int MYLIB_API helloworld(void) { printf("Hello World DLL"); return 42; }
您将使用以下命令行来构建您的DLL。 除了创建DLL之外,它还将创建从另一个可执行文件(以及导出文件,但只在某些情况下才需要)使用您的DLL所需的导入库(.lib):
cl /DBUILDING_MYLIB mylib.c /LD
/DBUILDING_MYLIB
参数定义用于控制DLL中的函数是导出(如果已定义)还是导入(未定义)的预处理器符号。 所以你应该在构建DLL时定义它,而不是在构建应用程序时定义它。
/LD
参数告诉cl产生一个DLL。
第二种方法是使用注释中提到的模块定义文件 。 您可以使用已有的代码,但也需要创建模块定义文件。 最简单的是这样的:
LIBRARY mylib EXPORTS helloworld
在这种情况下建立DLL需要下面的命令行:
cl /LD mylib.c /link /DEF:mylib.def
然后,您可以编写您的应用程序,以便使用您的库头与您的DLL函数的导入版本:
main.c中
/* No need to include this if you went the module definition * route, but you will need to add the function prototype. */ #include "mylib.h" int main(void) { helloworld(); return (0); }
然后你可以使用下面的命令行进行编译(假设DLL创建的导入库与main.c位于同一目录中)。 无论您使用declspec还是模块定义文件,此步骤都是相同的:
cl main.c /link mylib.lib
在/link
参数之后传递的参数在链接器命令行上传递,因此只是一个文件名,它被用作额外的输入来链接到可执行文件。 在这种情况下,我们指定生成DLL时生成的导入库。
我在这里显示的命令行几乎是绝对最小的,但它可以让你创建一个DLL并将应用程序链接到它。
以上所有的调用惯例都是正确的,而且我也没有做过多的尝试,看看我是否在任何时候都搞错了。