关于DLL的函数:
动态链接库中定义有两种函数:导出函数(export function)和内部函数(internal function)。
导出函数可以被其它模块调用,内部函数在定义它们的DLL程序内部使用。
输出函数的方法有以下几种:
1、传统的方法
在模块定义文件的EXPORT部分指定要输入的函数或者变量。语法格式如下:
entryname[=internalname] [@ordinal[NONAME]] [DATA] [PRIVATE]
其中:
entryname是输出的函数或者数据被引用的名称;
internalname同entryname;
@ordinal表示在输出表中的顺序号(index);
NONAME仅仅在按顺序号输出时被使用(不使用entryname);
DATA表示输出的是数据项,使用DLL输出数据的程序必须声明该数据项为_declspec(dllimport)。
上述各项中,只有entryname项是必须的,其他可以省略。
对于“C”函数来说,entryname可以等同于函数名;但是对“C++”函数(成员函数、非成员函数) 来说,entryname是修饰名。可以从.map映像文件中得到要输出函数的修饰
名,或者使用 DUMPBIN /SYMBOLS得到,然后把它们写在.def文件的输出模块。DUMPBIN是VC提供的一个工具。
如果要输出一个“C++”类,则把要输出的数据和成员的修饰名都写入.def模块定义文件。
2、在命令行输出
对链接程序LINK指定/EXPORT命令行参数,输出有关函数。
3、使用MFC提供的修饰符号_declspec(dllexport)
在要输出的函数、类、数据的声明前加上_declspec(dllexport)的修饰符,表示输出。__declspec (dllexport)在C调用约定、C编译情况下可以去掉输出函数名的下划线前缀。
extern "C "使得在C++中 使用C编译方式成为可能。在“C++”下定义“C”函数,需要加extern “C”关键词。用extern "C "来 指明该函数使用C编译方式。输出的“C”函数可
以从“C”代码里调用。
例如,BaseFunce 工程中 的一个C++文件有如下类:
#ifdef _BASEFUNC_EXPORT_
#define BASE_API __declspec(dllexport)
#else
#define BASE_API __declspec(dllimport)
#endif
class BASE_API CJCJMsgCmd_PrintRoadMap : public CJCJMsgCmd
{
public:
CJCJMsgCmd_PrintRoadMap();
virtual ~CJCJMsgCmd_PrintRoadMap();
virtual void Execute();
}
在另外工程中 CDlgJCJModule类中 需要将 CJCJMsgCmd_PrintRoadMap类中的 函数链接到 CDlgJCJModule 的C++ 可执行文件中,在CDlgJCJModule的CPP文件头部加上“#include "..\BaseFunc\JCJMsgCmd_QueryXQ.h"”
导出 C 函数以用于 C 或 C++ 语言可执行文件
可由 C 和 C++ 客户端应用程序使用的头文件:
// MyCFuncs.h #ifdef __cplusplus extern "C" { // only need to export C interface if // used by C++ source code #endif __declspec( dllimport ) void MyCFunc(); __declspec( dllimport ) void AnotherCFunc(); #ifdef __cplusplus } #endif
如果需要将 C 函数链接到 C++ 可执行文件,并且函数声明头文件没有使用上面的技术,则在 C++ 源文件中添加下列内容以防止编译器修饰 C 函数名:
extern "C" { #include "MyCHeader.h" }
导出 C++ 函数以用于 C 语言可执行文件
如果在用 C++ 编写的 DLL 中有希望从 C 语言模块访问的函数,应使用 C 链接而不是 C++ 链接来声明这些函数。除非另外指定,C++ 编译器使用 C++ 类型安全命名约定(也称作名称修饰)和 C++ 调用约定(使用此调用约定从 C 调用会很困难)。
若要指定 C 链接,请为函数声明指定 extern "C"。例如:
extern "C" __declspec( dllexport ) int MyFunc(long parm1);