原文连接地址:http://www.cnblogs.com/findumars/p/8660427.htmlhtml
DLL中导出函数的声明有两种方式:ios
一种方式是:在函数声明中加上__declspec(dllexport);
另一种方式是:采用模块定义(.def)文件声明,(.def)文件为连接器提供了有关被连接程序的导出、属性及其余方面的信息。windows
方式一:在函数声明中加上__declspec(dllexport)
函数
/// 在动态连接库程序中 /// 声明动态连接库(**.dll)的对外接口函数TestFuction extern "C" __declspec(dllexport) int TestFuction(int nType,char *strPath,std::vector<string> &vecData) { ////do anything here//// return 0; } /// 在外部但愿调用动态连接库的程序中 /// 加载动态连接库(**.dll)并调用其对外接口TestFuction void func() { //typedef与函数TestFuction类型相同的函数指针为TESTDLL typedef int (_cdecl * TESTDLL)(int nType,char *strPath,std::vector<string> &vecData); HINSTANCE hmod; //加载动态连接库**.dll hmod =::LoadLibrary(_TEXT("dll相对路径\\**.dll")); if(NULL == hmod) { TRACE("加载**.dll失败"); } //定义一个与函数TestFuction类型相同的函数指针lpproc TESTDLL lpproc; //搜索**.dll中函数名为TestFuction的对外接口 lpproc = (TESTDLL)GetProcAddress (hmod,"TestFuction"); //若是搜索成功 if(NULL != lpproc) { int nType = 0; char* strPath = "Data"; std::vector<string> vecData; //经过函数指针lpproc调用**.dll的接口函数TestFuction int nResult = (*lpproc)(nType,strPath,vecData); } //... //在恰当的时候释放动态连接库**.dll FreeLibrary(hmod); }
方式二:采用模块定义(.def)文件声明
首先建立 一个DLL程序(DllTestDef)
在*.cpp中
测试
int __stdcall Add(int numa, int numb) { return (numa + numb); } int __stdcall Sub(int numa, int numb) { return (numa - numb); }
而后建立一个.def的文件,在里面加上this
;DllTestDef.lib : 导出DLL函数 ;做者:---- LIBRARY DllTestDef EXPORTS Add @ 1 Sub @ 2
最后建立一个测试程序:.cpp文件以下:
spa
#include <iostream> #include <windows.h> using namespace std; typedef int (__stdcall *FUN)(int, int); HINSTANCE hInstance; FUN fun; int main() { hInstance = LoadLibrary("DLLTestDef.dll"); if(!hInstance) cout << "Not Find this Dll" << endl; fun = (FUN)GetProcAddress(hInstance, MAKEINTRESOURCE(1)); if (!fun) { cout << "not find this fun" << endl; } cout << fun(1, 2) << endl; FreeLibrary(hInstance); return 0; }
说明:
.def文件的规则为:指针
(1)LIBRARY语句说明.def文件相应的DLL;code
(2)EXPORTS语句后列出要导出函数的名称。能够在.def文件中的导出函数名后加@n,表示要导出函数的序号为n(在进行函数调用时,这个序号将发挥其做用);htm
(3).def 文件中的注释由每一个注释行开始处的分号 (;) 指定,且注释不能与语句共享一行。
(4)使用__declspec(dllexport)和使用.def文件是有区别的。
若是你的DLL是提供给VC用户使用的,你只须要把编译DLL时产生的.lib提供给用户,
它能够很轻松地调用你的DLL。可是若是你的DLL是供VB、PB、Delphi用户使用的,那么会产生一个小麻烦。
由于VC++编译器对于__declspec(dllexport)声明的函数会进行名称转换,以下面的函数:
__declspec(dllexport) int __stdcall Add()
会转换为Add@0,这样你在VB中必须这样声明:
Declare Function Add Lib "DLLTestDef.dll" Alias "Add@0" () As Long
http://www.cnblogs.com/enterBeijingThreetimes/archive/2010/08/04/1792099.html
1.VS2012建立.def文件 右键工程名->add->New Item->Visual C++->Code->Module-Define File(.def) 2.def文件的编写 一个def文件必须有两个部分:LIBRARY和EXPORTS 让咱们先看一个基本的.def文件稍后我将解析第一行,''LIBRARY''是一个必需的部分。它告诉连接器(linker)如何命名你的DLL。下面被标识为''DESCRIPTION''的部分并非必需的,可是我喜欢把它放进去。该语句将字符串写入 .rdata 节[据 MSDN],它告诉人们谁可能使用这个DLL,这个DLL作什么或它为了什么(存在)。再下面的部分标识为''EXPORTS''是另外一个必需的部分;这个部分使得该函数能够被其它应用程序访问到而且它建立一个导入库。当你生成这个项目时,不只是一个.dll文件被建立,并且一个文件扩展名为.lib的导出库也被建立了。除了前面的部分之外,这里还有其它四个部分标识为:NAME, STACKSIZE, SECTIONS, 和 VERSION。我将再也不在本文中涉及这些内容,可是若是你在Internet上搜索,我想你将找到一些东西(译注: MSDN2003上对模板定义文件各部份内容有详尽解释,请参阅)。另外,一个分号(;)开始一个注解 3.def文件路径的设置 Lingker->Input->Module Definition File 4.def文件的做用 通俗解释: 在VC++中,生成DLL能够不使用.def文件。只须要在VC++的函数定义前要加 __declspec(dllexport)修饰就能够了。可是使用__declspec(dllexport)和使用.def文件是有区别的。若是 DLL是提供给VC++用户使用的,你只须要把编译DLL时产生的.lib提供给用户,它能够很轻松地调用你的DLL。可是若是你的DLL是供其余程序如 VB、delphi,以及.NET 用户使用的,那么会产生一个小麻烦。由于VC++对于 __declspec(dllexport)声明的函数会进行名称转换,以下面的函数: __declspec(dllexport) int __stdcall IsWinNT() 会转换为IsWinNT@0,这样你在VB中必须这样声明: Declare Function IsWinNT Lib "my.dll" Alias "IsWinNT@0" () As Long @的后面的数因为参数类型不一样而可能不一样。这显然不太方便。因此若是要想避免这种转换,就要使用.def文件方式。 EXPORTS后面的数能够不给,系统会自动分配一个数。对于VB、PB、 Delphi用户,一般使用按名称进行调用的方式,这个数关系不大,可是对于使用.lib连接的VC程序来讲,不是按名称进行调用,而是按照这个数进行调用的,因此最好给出。 例子:咱们用VC6.0制做一个dll,不使用.def文件,在头文件中这样写 #ifndef LIB_H #define LIB_H extern "C" int _declspec(dllexport)add(int x,int y); #endifLIBRARY dll_tutorial DESCRIPTION "our simple DLL" EXPORTS Add @1 Function @2
http://blog.sina.com.cn/s/blog_78fd98af0101ghno.htmlhttp://www.cnblogs.com/leijiangtao/p/4805940.html