【转】extern “C“以及__declspec(dllexport) 讲解和def文件dll导出方法

转自:https://blog.csdn.net/qing666888/article/details/41135245

一,__ 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(dllimport)或__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 ++中,我们可以通过  __declspec(DLLEXPORT)  将函数导出为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文件中即可。

    

DEF文件的简单示例如下:

    LIBRARY
    EXPORTS
        添加

最后记得在链接器选项中选中使用的DEF文件(默认情况下,添加DEF文件时会自动加上该选项,无需手动更改)。

    

这样,我们的函数无需加那一堆前缀,仍然可以使用默认的INT 添加(诠释一个,INT B);形式,导出但后的方式然的英文Ç形式的函数定义。

    

最后指得一提的是,一般的C / C ++默认的调用方式是__cdecl,这种方式下需要调用方对函数清栈。如果对外提供API共其它非C ++程序使用时,调用方会无法清栈而出错(C#会直接报函数声明不匹配的错误)。因此,对外提供api时还应该将接口声明为__stdcall,让api函数自己清栈。这也是Windows API前面都加上了一个WINAPI的宏的原因。

def文件还有许多其它的高级用法,要进一步了解的话,可以参看一下MS的官方文档:http://msdn.microsoft.com/zh-cn/library/28d6s79h( v = vs.80).aspx

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/436178.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【转】DICOM医学图像处理:浅析SWF、MWL、SPS、MPPS

转自:https://blog.csdn.net/zssureqh/article/details/40151107 背景: 最近重新花时间阅读了DICOM标准,顺带着看了一下HL7标准和IHE,对标题中提到的SWF、MWL、SPS和MPPS有了更进一步的认识,现将自己的理解整理出来&a…

Php点击更换封面,JavaScript_js实现点击图片改变页面背景图的方法,本文实例讲述了js实现点击图 - phpStudy...

js实现点击图片改变页面背景图的方法本文实例讲述了js实现点击图片改变页面背景图的方法。分享给大家供大家参考。具体实现方法如下:点击图片即改变页面的背景图片希望本文所述对大家的javascript程序设计有所帮助。相关阅读:C语言编程中统计输入的行数以及单词个数…

串口通讯基础及S3C2410 UART控制器

数据通信的基本方式可分为并行通信与串行通信两种: 并行通信:是指利用多条数据传输线将一个资料的各位同时传送。它的特点是传输速度快,适用于短距离通信,但要求通讯速率较高的应用场合。 串行通信:是指利用一条传输线…

几个实用的Servlet应用例子-入门、cookie、session及上传文件

1Servlet可以被认为是服务端的applet,它被WEB服务器加载和执行,前端可以显示页面和获得页面数据,后台可以操纵数据库,能完成JavaBean的很多功能。在这里我较为详细的说说Servlet在Cookie,Session和上传文件上的应用&am…

【转】DICOM医学图像处理:DIMSE消息发送与接收“大同小异”之DCMTK fo-dicom mDCM

转自:https://my.oschina.net/zssure/blog/354816 背景: 从DICOM网络传输一文开始,相继介绍了C-ECHO、C-FIND、C-STORE、C-MOVE等DIMSE-C服务的简单实现,博文中的代码给出的实例都是基于fo-dicom库来实现的,原因只有一…

公司间交易学习笔记---概述

本系列笔记是我在学习公司间交易的过程中的随笔,有些是我自己的想法,内容可能跟教程有所出入,由于对AX的应用部分理解得很浅,所以如果错误还请多多指教。 为了处理集团公司中各个分公司之间的交易,AX采用了InterCompan…

用VS2005开发WinCE程序调试图文教程

一、WinCE 模拟器通过ActiveSync 6.1(即Windows Mobile设备中心)连接PC ActiveSync 6.1:http://www.cr173.com/soft/26994.html 1.启动WinCE模拟器 命令行: start .\DeviceEmulator.exe WINCE镜像\Wince5.bin /memsize 256 /video 480x272x16 /sharedf…

【转】 ADO.NET最佳实践

本文转自:http://blog.csdn.net/spidertan/archive/2003/12/13/17110.aspx 概述: 本文在微软站点资源的基础上加工整理而成,意在介绍在你的ADO.NET应用程序中执行和完成性能优化、稳定性和功能性方面提供最佳的解决方案;同…

php 变量文件间传递,同一文件的两个JS函数之间如何传变量?

满意答案ed_ch2013.11.06采纳率:44% 等级:12已帮助:8801人定义成全局变量就可以了var style_key;function change_mystyle(my){style_keymy.options[my.selectedIndex].value;if(style_key 114la){document.getElementById(shoostyleicon…

获取 Web 设计的免费资源

Web 开发人员可以找到很多免费资源,尽管其中一些资源会比另外一些资源更加自由。如果您正在设计网站或 Web 应用程序,那么不管是静态的还是所有可以想到的动态 Ajax 内容,都能找到减轻您的劳动强度并为网站增色的资源。本文从免费图标到 Web …

设计模式C++实现(1)——工厂模式

软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径。设计模式中运用了面向对象编程语言的重要特性:封装、继承、多态,真正领悟设计模式的精髓是可能一个漫长的过程,需要大量实践经验的积累。最近看设计模式的书&#xff0…

java对象间的转型,详细讲述Java中的对象转型

向上转型:子类对象转为父类,父类可以是接口。公式:Father f new Son();Father是父类或接口,son是子类。向下转型:父类对象转为子类。公式:Son s (Son)f;我们将形参设为父类Animal类型,当执行t…

C++设计模式之一 工厂模式(简单工厂、工厂和抽象工厂)

今天开始这个系列之前,心里有些恐慌,毕竟园子里的高手关于设计模式的经典文章很多很多,特别是大侠李会军、吕震宇 老师的文章更是堪称经典。他们的文笔如行云流水,例子活泼生动,讲解深入浅出。好在他们都是用C#描述&am…

【转】Windows消息传递机制详解

林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka Windows是一个消息(Message)驱动系统。Windows的消息提供了应用程序之间、应用程序与Windows系统之间进行通信的手段。应用程序想要实现的功能由消息来触发,并且靠对消…

设计模式C++实现(2)——单例模式

软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径。设计模式中运用了面向对象编程语言的重要特性:封装、继承、多态,真正领悟设计模式的精髓是可能一个漫长的过程,需要大量实践经验的积累。最近看设计模式的书&#xff0…

设计模式C++实现(3)——建造者模式

软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径。设计模式中运用了面向对象编程语言的重要特性:封装、继承、多态,真正领悟设计模式的精髓是可能一个漫长的过程,需要大量实践经验的积累。最近看设计模式的书&#xff0…

宽字符串忽略大小写比较的实现(原)

宽字符串忽略大小写比较的实现(原) 孙文涛 2008-07-24 在Mac机器平台上没有wcsicmp 或 wcscasecmp之类的函数实现对宽字符忽略大小写的比较,所以实现了好几种方法。 一个自然的思路是: (1) wcscpy 原字符串到tmp字符串; (2) tolower tmp字符串; (3) 然后调用仅存的w…

有关JAVA考试中数据库的题,javaee期末考试题库,用javaEE编写一个题库系统,要怎么做...

javaEE数据库简单问题。你插入2113数据库的时候是把5261它封装为一4102个对象插入的吗?1653如果封装为一个User对象版的权话(User对象有ID和LEVEL两个属性)ResultSet rs ps.executeQuery();User user new User();if(rs.hasNext()){user rs.next();}关于javaee 中j…

oracle 12c sql图形化,Oracle 12c PL/SQL程序设计终极指南

Oracle 12c PL/SQL程序设计终极指南作者:孙风栋;王澜;郭晓惠出版日期:2015年06月文件大小:11.73M支持设备:¥60.00在线试读适用客户端:言商书局iPad/iPhone客户端:下载 Android客户端&#xff1a…

oracle 存储同步,Oracle数据库知识——存储过程篇

在线QQ客服:1922638专业的SQL Server、MySQL数据库同步软件存储过程是一组用于完成特定功能的SQL语句,该语句已编译并存储在数据库中。用户通过指定存储过程的名称并提供参数(如果存储过程具有参数)来执行它。存储过程是数据库中的重要对象。任何设计良好…