【转】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,一经查实,立即删除!

相关文章

php源码查找替换,php 替换模板中的 PHP源码标签字符方法

//替换php代码function RepPhpAspJspcode($string){global $public_r;if(!$public_r[candocode]){//$stringstr_replace("<?xml ","[!--ecms.xml--]",$string);$stringstr_replace("$stringstr_replace("\\>","\\>",$s…

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

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

Parallel Extensions CTP第二版发布

Parallel Extensions CTP第二版发布 LazyBee 2008年6月微软Parallel Extensions项目组发布了Parallel Extendsions CTP的第二个版本。这个版本主要包含以下组件&#xff1a; 1 任务并行库TPL(Task Parallel Library): 提供命令的方式将面向数据的操作以及轻量级的任务自动的运行…

wince中的背光灯控制

要控制背光灯就必须知道相关设置&#xff0c;以下是wince中背光灯的设置。在BL_ReadRegistry函数中被读取。 [HKEY_CURRENT_USER/ControlPanel/BackLight] "ACTimeout"dword:0000012c "UseExt"dword:00000001 "UseBattery"dword:00000001 …

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

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

VistaDB 数据库,.NET的新选择

VistaDB 3.3 fully managed embedded database engine runs Nothing but .Net! Designed and built as a 100% managed code database engine. Now with TSQL Procs! 商业版&#xff0c;提供ADO.NET 2.0 的Provider。商业版。但是有 Express 版&#xff0c;可应用于非商业环境。…

wince中重启网卡

WCHAR Name[]_T("CS89001/0"); HANDLE m_hFileHandle CreateFile(_T("NDS0:"), 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE) INVALID_HANDLE_VALUE); if( m_hFileHandle INVALID_HANDLE_VALUE ) { //获得网卡名时打开设备错误 …

【转】DICOM的常用Tag分类和说明

转自&#xff1a;https://blog.csdn.net/inter_peng/article/details/46513847 1. 前言&#xff1a; 基于DICOM3.0标准的医学图像中&#xff0c;每一张图像中都携带着许多的信息&#xff0c;这些信息主要可以分为Patient, Study, Series和Image四类。每一个DICOM Tag都…

matlab电压稳定极限,电力系统电压稳定性的Matlab建模分析

Matlab软件作为一个编程效率高、程序设计灵活、图形功能强的工程实用的分析软件,在电力系统的仿真分析及相关计算中得以广泛应用,特别是其中的Simulink工具箱可以实现电力系统的模型建立及动态仿真[1].但是在实际应用中,特别是针对电力系统的动态过程分析,Simulink存在以下2个问…

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

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

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

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

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

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

php记录登录时间,php记录 用户当前页面停留时间

onunload JS定时器 ajax 实现每秒写一次数据库肯定是不行的资源释放都来不及&#xff0c;使用js计时器&#xff0c;在离开页面时&#xff0c;调用ajax异步插入数据库&#xff0c;即不延迟跳转&#xff0c;也不会占用资源&#xff0c;插入完就释放了HTML onunload 事件属性定义…

WinCE驱动开发问题精华集锦

如何让系统加载自己写的驱动程序&#xff1f;两种办法&#xff1a; 1、在[HKEY_LOCAL_MACHINE/Drivers/BuiltIn]下添加注册键。 2、在应用程序中调用ActivateDeviceEx。 在一些文件中用分号来表示注释&#xff0c;例如下面的内容 ; CESYSGEN IF SERVERS_MODULES_HTTPD …

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

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

【转】走进windows编程的世界-----对话框、文本框、按钮

一、对话框 1 对话框的分类 2 对话框的基本使用方式 3 对话框资源 4 有模式对话框的使用 int DialogBox( HINSTANCE hInstance, LPCTSTR lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc ); 5 无模式对话框的使用 5.1 添加对话框资源 5.2 定义窗口处理函数 …

php接口datatype= text,关于php:dataType:“json”不起作用

我正在尝试使用数组中的json将多个变量从php文件发送回ajax。 php文件中的代码完美运行&#xff0c;并且应该像我的数据库一样完成所有操作。 但是当我在ajax中添加dataType&#xff1a;"json"时&#xff0c;php文件中就没有任何事情发生了。 我google了一下&#xf…

做饭记

小时候,听奶奶讲:最没出息的男人才要做饭,有出息的男人是应该赚钱养家的,而女人则是要做饭的. 于是一直对做饭没什么兴趣, 现在的生活每天都在代码,突然想学做饭,真的学了,才发现做饭可不是一件容易的事儿. 做饭的时候,发现自己可以全身心的投入到做饭的"艺术&quo…

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

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

【转】win32 的DLL中创建windows窗口

转自&#xff1a;https://blog.51cto.com/wangyw/1071967 因工作需求&#xff0c;需要写一个DLL&#xff0c;并在其中创建windows窗口&#xff0c;网上有很多关于DLL创建窗口的文章&#xff0c;不过都是基于MFC的&#xff0c; 却鲜见直接用win32的DLL创建的。经过研究调试&…