dll 使用方法

extern "C"int add(int x,int y);

extern "C"int _declspec(dllimport) add(int x,int y);

使用DLL导出函数的声明有两种方式:

1在函数声明中加上__declspec(dllexport),这里不再举例说明;

2采用模块定义(.def) 文件声明,.def文件为链接器提供了有关被链接程序的导出、属性及其他方面的信息。.def文件的基本语法为:

① LIBRARY语句说明.def文件相应的DLL

EXPORTS语句后列出要导出函数的名称。可以在.def文件中的导出函数名后加@n,表示要导出函数的序号为n(在进行函数调用时,这个序号将发挥其作用);

.def 文件中的注释由每个注释行开始处的分号 (;) 指定,且注释不能与语句共享一行。例如:

;DllTestDef.lib : 导出DLL函数

;作者:----

LIBRARY DllTestDef

EXPORTS 

ADD @ 1

有两种方式可以导出 C++ 文件中的函数:使用.def文件和使用extern "C"

将修饰名放到 .def 文件中,可以通过使用 DUMPBIN 工具或 /MAP 链接器选项来获取修饰名。请注意,编译器产生的修饰名是编译器特定的。如果将 Visual C++ 编译器产生的修饰名放到 .def 文件中,则链接到 DLL 的应用程序必须也是用相同版本的 Visual C++ 生成的,这样调用应用程序中的修饰名才能与 DLL .def 文件中的导出名相匹配。

另外还需要将下列代码放在包含导出类的头文件的开头和结尾:

#undefAFX_DATA

#define AFX_DATA  AFX_EXT_DATA

 <bodyof your header file>

#undefAFX_DATA[1]

#defineAFX_DATA

这些代码行确保内部使用的 MFC 变量或添加到类的变量是从扩展 DLL 导出(或导入)的。例如,当使用 DECLARE_DYNAMIC 派生类时,该宏扩展以将 CRuntimeClass 成员变量添加到类。省去这四行代码可能会导致不能正确编译或链接 DLL,或在客户端应用程序链接到 DLL 时导致错误。

生成 DLL ,链接器首先使用 .def 文件创建导出 (.exp) 文件导入库 (.lib) 文件,然后使用导出文件生成 DLL 文件隐式链接到 DLL 的可执行文件在生成时链接到导入库。请注意,MFC 本身使用 .def 文件从 MFCx0.dll 导出函数和类。

使用extern “C”定义具有标准 C 链接的导出函数具有以下使用要点:

可以是单一语句也可以是复合语句

extern"C" double sqrt(double);

extern"C"

{

   double sqrt(double);

   int min(int, int);

}

可以包含头文件

  extern "C"

  {

   #include <cmath>

  }

如果函数有多个声明,可以都加extern "C", 也可以只出现在第一次声明中,后面的声明会接受第一个链接指示符的规则。

不能将extern "C"放到函数内部

extern"C"外还有extern "FORTRAN"

 

外部调用dll内函数的机制:

通过调用 GetProcAddress,可以获取 DLL 导出函数的地址,返回值是一个指向DLL中函数的函数指针函数。

GetProcAddress的参数由两部分组成:

DLL 模块句柄,由 LoadLibraryAfxLoadLibrary GetModuleHandle 返回;

要调用的函数名或函数的导出序号。

使用导出序号方式调用 GetProcAddress 中指定的函数时,需要满足下列条件:

1要链接到的 DLL 是用模块定义 (.def) 文件生成;

2序号在 DLL .def 文件的 EXPORTS 部分中与函数一起列出;

3有权控制 .def 文件中导出函数的序号分配,否则外部改变序号分配会导致不可预料错误。

使用导出序号方式调用的优势:GetProcAddress 可直接定位函数,而不是将指定名称与 DLL 导出表中的函数名进行比较。如果 DLL 具有许多导出函数,则相对于使用函数名,使用导出序号调用 GetProcAddress 的速度稍快一些,因为导出序号是 DLL 导出表的索引。

注意事项:

需确保函数的参数的正确性,避免超出在堆栈上分配的内存和导致访问冲突,原因是DLL 函数在外部被以函数指针的形式调用,编译时没有类型检查。帮助提供类型安全的一种方法是查看导出函数的函数原型,并创建函数指针的匹配 typedef



[1] #undef的作用是取消一个宏的定义,在其之后该宏的定义无效;但是可以重新使用#define 进行定义,恢复宏的作用


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值