如果你想在 C 代码中使用由 C++ 编写的 DLL,你就应该将这些函数声明为 C 的链接(linkage)而不是 C++ 的。如果没有指定的话,C++ 编译器会使用 C++ 的类型安全命名(也叫做名字修饰)和 C++ 的调用约定,这使得 C 很难对其进行调用。
要指定 C 链接,在函数声明中使用
extern "C"
,例如:
如果你想要在 C 或 C++ 中调用由 C 编写的 DLL,你需要使用
__cpluscplus
预处理宏来确定在使用哪种语言。如果正在使用 C++ 语言,应该将这些函数声明为 C 链接。如果你这样做了并为你的 DLL 提供了客户程序使用的头文件,这些函数可以不加改变地在 C 和 C++ 中使用。
//MyFunc.h
#ifdef __cplusplus
extern"C" { //only need to export C interface if
// used by C++ source code
#endif__declspec(dllimport) voidMyCFunc();
__declspec(dllimport) voidAnotherCFunc();
#ifdef __cplusplus
#endif
(dllimport 的使用对于函数声明不是必要的,但是这样做可以让编译器生成更好的代码)
(此处的头文件仅作为头文件提供给其它模块使用,不参与编译,函数定义处应使用 dllexport)
如果你需要将 C 函数供 C++ 程序使用,而函数声明头文件又没有向上面那么做,那么可以这样做来避免 C++ 编译器对 C 函数名进行装饰:
extern"C" {
#include"MyCHeader.h" #defineCLASS_DECLSPEC__declspec(dllexport)
#else #defineCLASS_DECLSPEC__declspec(dllimport)
#endif
class CLASS_DECLSPEC CExampleA : public CObject
{ ... class definition ...};
//project.h
#ifdef _DLL //if accessing the data from inside the DLL
ULONGulDataInDll;
#else//if accessing the data from outside the DLL
ULONG *ulDataInDll;
当你使用 __declspec(dllimport) 来标出数据时,编译器会自动为你生成间接代码。你不必担心是否需要解引用,可以直接使用变量而不是指针。
不要在构建 DLL 时使用 __declspec(dllimport) ,在 DLL 内的函数不需要使用导入地址表来访问数据对象。
#ifdef DLL_BUILD //use macro to detect dll or client program
#defineDECL__declspec(dllexport)
#else#defineDECL__declspec(dllimport)
#endif
DECL intyyzero;
DECL intadd(int, int);
DECL intmulti(int, int);
#ifdef __cplusplus
#endif#endif//correspond to YYDLL_INCLUDE
编写源文件时,可以使用 DEF 文件。下面的源文件是不使用 DEF 文件的情况。
//yydll.c
#include"yydll.h"// inner data and function
intzero_in = 0;
intadd_in(inta, intb)
return a + b;
//exprot data and functions
DECL intyyzero = 0;
DECL intadd(inta, intb)
return a + b;
DECL intmulti(inta, intb)
if (a == zero_in)
return 0;
return add_in(b, multi(a - 1, b));
将 yydll.c 和 yydll.h 放在同一目录下,就可以开始编译了。
如果使用 MSVC 编译器,首先运行 vsdevcmd.bat 并 cd 到源代码目录,再使用如下命令: