externC以及__declspec(dllexport)讲解和def⽂件dll导出⽅
法
⼀,__ declspec(dllexport):
将⼀个函数声名为导出函数,就是说这个函数要被其他程序调⽤,即作为DLL的⼀个对外函数接⼝。通常它和extern“C”合⽤,形式如下:
extern "C"
{
__declspec(dllexport) void FUNCTION()
{
}
}
这是由于在制作DLL导出函数时由于C 法式浓汤
++存在函数重载,因此__declspec(dllexport)FUNCTION(int,int)在DLL会被装饰,例如被装饰成为function为梦而战
_int_int,⽽且不同的编译器decorate的⽅法不同,造成了在⽤GetProcAddress的的取得FUNCTION地址时的不便,使⽤外部的“C”时,上述的装饰不会发⽣,因为没有函数重载,如此⼀来被外部的“C”修饰的函数,就不具备重载能⼒。
⼆,MSDN:
“在32位编译器版本中,可以使⽤__declspec(dllexport)关键字从DLL导出数据,函数,类或类成员函数.__ declspec(dllexport)将导出指令添加到对象⽂件(即obj⽂件旧成语
) ,若要导出函数,__ declspec(dllexport)关键字必须出现在调⽤约定关键字的左边(如果指定了关键字)。例如:__ declspec
(dllexport)void __cdecl Function1(void);
若要导出类中的所有公共数据成员和成员函数,关键字必须出现在类名的左边,如下所⽰:
class __declspec(dllexport)CExampleExport:public CObject
{... class definition ...};
⽣成DLL时,通常创建⼀个包含正在导出的函数原型和/或类的头⽂件,并将__declspec(dllexport)的添加到头⽂件中的声明。
若要提⾼代码的可读性,请为__declspec(DLLEXPORT )定义⼀个宏并对正在导出的每个符号使⽤该宏:
#define DllExport __declspec(dllexport)“
三,__ declspec(dllexport)与.def
模块定义(.def)⽂件是包含⼀个或多个描述各种DLL属性的模块语句的⽂本⽂件
.1,⼆者的⽬外企面试问题
的都是将公共符号导⼊到应⽤程序中或从DLL导出函数
.2,添加__declspec(dllexport)是为了提供不使⽤.def⽂件从.EXE或.DLL导出函数的简单⽅法
.3,如果不使⽤__declspec(dlli六年级上册数学练习与测试答案
mport)或__declspec(dllexport)导出DLL函数,则DLL需要.def⽂件
.4,并不是任何时候选择添加__declspec(dllexport)⽽放弃.def的⽅式都是好的。如果DLL是提供给
VC ++⽤户使⽤的,只需要把编译DLL时产⽣的。 lib提供给⽤户,它可以很轻松地调⽤你的DLL。但是如果DLL是供VB,PB,Delphi⽤户使⽤的,那么会产⽣⼀个⼩⿇烦。因为VC ++对于__declspec(dllexport)声明的函数会进⾏名称转换,如下⾯的函数:__ declspec
(dllexport)int __stdcall IsWinNT()
会转换为IsWinNT @ 0,这样你在VB中必须这样声明:
声明函数IsWinNT Lib“my.dll”别名“IsWinNT @ 0”()As Long
@的后⾯的数由于参数类型不同⽽可能不同。这显然不太⽅便。所以如果要想避免这种转换,就要使⽤.DEF⽂件⽅式。
在C ++中,我们可以通过 将函数导出为DLL的中供其它程序使⽤,例如:
_declspec (dllexport )int add(int a,int b);
在这种⽅式下,如果调⽤该DLL的是⼀个C ++程序(同⼀个编译器的版本)是没有问题的。但是,如果调⽤该DLL是⼀个其它语⾔的程序(如C#,VB),则会出错。究其原因,是因为在C ++中存在函数的重载,允许函数重名,因此在编译器⽣成的DLL的时候,为了区别重名的程序,其会将进⾏⼀定算法进⾏。例如,对于前⾯的添加函数,实际的函数名称是如下形式。
因此,我们直接通过函数名add是⽆法找到该函数的,从⽽导致调⽤失败。为了解决这⼀问题,我们往往在函数前⾯再加⼀个extern “C”,使⽤C⽅式的函数命名规则。
extern “C” _declspec (dllexport )int add(int a,int b);
这茄子秧
样函数的名称就成加了。
这样,我们就需要在每⼀个函数签名加上“ extern ”C“ _declspec (dllexport ) ”这⼀长串声明。如果需要导出的函数较多则显得⾮常繁琐,也⾮常难看。为了简化这⼀过程, MS引⼊了⽹求⽅便我们操作。
使⽤默认值⽂件⽐较简单,只需要在项⽬中添加⼀个DEF⽂件,然后把我们要导出的函数放在DEF⽂件中即可。
DE单身证明怎么开
F⽂件的简单⽰例如下:
LIBRARY
EXPORTS
添加
最后记得在链接器选项中选中使⽤的DEF⽂件(默认情况下,添加DEF⽂件时会⾃动加上该选侧方位停车技巧图解
项,⽆需⼿动更改)。
这样,我们的函数⽆需加那⼀堆前缀,仍然可以使⽤默认的INT 添加(诠释⼀个,INT B);形式,导出但后的⽅式依然的英⽂形式的函数定义。
最后西安建筑科技大学分数线
指得⼀提的是,⼀般的C / C ++默认的调⽤⽅式是__cdecl,这种⽅式下需要调⽤⽅对函数清栈。如果对外提供API共其它⾮C ++程序使⽤时,调⽤⽅会⽆法清栈⽽出错(C#会直班级自我介绍
接报函数声明不匹配的错误)。因此,对外提供api时还应该将接⼝声明为__stdcall,让api函数⾃⼰清栈。这也是Windows API前⾯都加上了⼀个WINAPI的宏的原因。
def⽂件还有许多其它的⾼级⽤法,要进⼀步了解的话,可以参看⼀下MS的官⽅⽂档:: v = vs.80)