C++中模块(Dll)对外暴露接口的方式
总结下C++中模块(Dll)对外暴露接口的方式:
(1)导出API函数的方式
这种方式是Windows中调用DLL接口的最基本方式,GDI32.dll, User32.dll都是用这种方式对外暴露系统API的。
这种方式的优点是导出函数没有语言限制,什么语言都能调用;
缺点是这种方式是面向过程的,外部如果要支持多实例等不是很方便,另外它要求的回调函数(callback)只能是普通C函数,C++中我们通常用类静态成员函数,很不方便。
当然,我们通过封装其实也可以让这种方式支持多实例,通过一个抽象句柄HComponent, 比如支持导出函数HComponent CreateInstance(); VOID DeleteInstance(HComponent h);然后内部的其他导出函数的第一个参数都是实例句柄,类似INT SendMessage(HComponent h, ...), 用这种方式可以模拟出面向对象的效果。
另外如果用动态加载(LoadLibrary, GetProcAddress)的方式调用它的导出函数,即使导出函数内部实现修改了,外部程序也不用重新编译,仍然可用。
导出函数方式一个比较优秀的例子是GDI+的实现,整个GdiPlus.dll对外提供的都是普通导出函数,但是它却可以方便的给面向对象的语言使用,因为一方面它用Handle的方式在DLL内部封装了对象,另一方面它在DLL外围又用C++类的方式封装了头文件直接提供给用户, 所以C++程序可以直接以面向对象的方式调用。
(2)导出类方式
导出类的方式就是把整个C++类对外导出, MFC42.dll就是这种方式。
这种方式的优点是直接面向对象。
缺点是只能给C++用,而且最好编译器都要一致,另外DLL一变动, 外部程序需要重新编译, 而且外部程序可以通过头文件看到你类的内部实现,
所以这种方式是最不建议使用的方式。
(3)COM方式
COM方式实际上导出了几个固定函数(DllGetClassObject, DllCanUnloadNow, DllRegisterServer, DllUnregisterServer), 然后以这几个函数为入口,调用组件内部‘实现的接口。
COM方式综合了上面2种方法的所有优点,没有语言限制,面向对象,多实例,只能看到接口,动态升级等。
当然COM因为其复杂性和对注册表的依赖,很多时候我们在封装模块时不愿意严格按照COM标准来实现,但是我们可以按照COM思想来提供接口。
比如我们可以让我们模块只提供一个导出函数CreateFactory, 然后外部可以调用该接口来创建工厂,最后通过工厂创建出各种类型的对象,这些对象实现了某些接口,外部只需要这些接口的头文件即可调用对象的方法。
现在越来越多的组件以这种方式对外提供接口,比如D2D对外的导出接口就是D2D1CreateFactory, 然后就可以通过该工厂来创建其他的对象,比如pD2DFactory->CreateHwndRenderTarget(...),最后可以直接调用对象实现的接口:pRenderTarget->DrawRectangle(D2D1::RectF(100.f, 100.f, 500.f, 500.f), pBlackBrush);
当然,上面几种DLL对外暴露接口的方式本质上没有区别,都是利用PE文件的导出节来导出数据和函数,但是根据它们使用方式的不同,对外部模块来说还是有很大的区别,我们的推荐次序依次是:COM方式->导出API函数方式->导出类方式。
C++中模块(Dll)对外暴露接口的方式的更多相关文章
- sdk开发时,对外暴露的接口封装
思考,用同步还是异步? 实质就是屏蔽一些东西,让使用者直接传参数 拿结果 而不用关心具体实现 eg.登陆接口 1.定义接口LoginCallBack,两个函数 请求成功和失败 public inter ...
- php在apache中一共有三种工作方式:CGI模式、FastCGI模式、Apache 模块DLL
php在apache中一共有三种工作方式:CGI模式.FastCGI .FastCGI是什么? FastCGI是语言无关的.可伸缩架构的CGI开放扩展,其主要行 为是将CGI解释器进程保持在内存中并因 ...
- WPF内嵌WCF服务对外提供接口
要测试本帖子代码请记得管理员权限运行vs. 我写这个帖子的初衷是在我做surface小车的时候有类似的需求,感觉这个功能还挺有意思的,所以就分享给大家,网上有很多关于wcf的文章 我就不一一列举了.公 ...
- 在C++中调用DLL中的函数 (3)
1.dll的优点 代码复用是提高软件开发效率的重要途径.一般而言,只要某部分代码具有通用性,就可将它构造成相对独立的功能模块并在之后的项目中重复使用.比较常见的例子是各种应用程序框架,ATL.MFC等 ...
- Delphi 中的DLL 封装和调用对象技术(刘艺,有截图)
Delphi 中的DLL 封装和调用对象技术本文刊登2003 年10 月份出版的Dr.Dobb's 软件研发第3 期刘 艺摘 要DLL 是一种应用最为广泛的动态链接技术但是由于在DLL 中封装和调用对 ...
- JavaScript中模块“写法”
在JavaScript模块到底是什么 event = function() { // do more return { bind: function() {}, unbind: function() ...
- [转载]解析WINDOWS中的DLL文件---经典DLL解读
[转载]解析WINDOWS中的DLL文件---经典DLL解读 在Windows世界中,有无数块活动的大陆,它们都有一个共同的名字——动态链接库.现在就走进这些神奇的活动大陆,找出它们隐藏已久的秘密吧! ...
- springboot+CXF开发webservice对外提供接口(转)
文章来源:http://www.leftso.com/blog/144.html 1.项目要对外提供接口,用webservcie的方式实现 2.添加的jar包 maven: <dependenc ...
- 在后台业务管理系统中使用Autofac实现微信接口的处理
在后台业务管理系统中使用Autofac实现微信接口的处理,我们只需要把相关使用到的DLL放到BIN目录里面即可,通过IOC控制反转方式实现对接口的调用.在实现在业务系统里面,我们本身程序可能已经依赖了 ...
随机推荐
- mysql-备份及关联python
阅读目录 IDE工具介绍 MySQL数据库备份 mysqldump实现逻辑备份 回复逻辑备份 备份/恢复案例 自动化备份 表的导出和导入 数据库迁移 pymysql模块 一 链接.执行sql.关闭(游 ...
- redis之(三)redis的数据类型
[一]字符串类型(基本数据类型) --->字符串类型是redis的最基本的数据类型 --->能存储任何形式的字符串,(用户邮箱,json化的对象,一张图片) --->一个字符串类型的 ...
- Thinking in java基础之集合框架(转载)
集合简介(容器)把具有相同性质的一类东西,汇聚成一个整体,就可以称为集合,例如这里有20个苹果,我们把每一个苹果当成一个东西(一个对象),然后我们借用袋子把这20个苹果装起来,而这个袋子就是集合(也叫 ...
- 【JBPM4】流程分支fork - join
流程分支.聚合.流程每个分支节点都全部处理完成后,聚合到下一个节点. JPDL <?xml version="1.0" encoding="UTF-8"? ...
- hdu5798
官方题解: 考虑去掉abs符号,发现只有相邻两个数的最高位被影响了才会影响abs的符号,所以可以按照最高位不一样的位置分类,之后考虑朴素枚举x从0到2^20,每次的复杂度是O(400),无法通过,考虑 ...
- Pycharm中的Django项目连接mysql数据库
一.安装Pycharm和Django就不详细说了,自行百度 二.新建Django项目也不说了 三.配置Django连接到mysql 1.models.py写一个类,继承models.Model cla ...
- Laravel5中的Session
有关Session的配置文件是aonfig/session.PHP文件. 如果不使用基于数据库.cookie或者Redis缓存类的Session的话,不需要改配置文件就可以使用了. 下面一个简单的使用 ...
- 开源游戏地图编辑器MarbleMap
开源游戏地图编辑器MarbleMap MIT协议,MarbleMap是一款as3开发的游戏地图编辑器,他免费开源,同时支持Cocos2d-x坐标系和AS3坐标系,功能丰富,不过是一款新推出的开源项目, ...
- Qt精简编译方法总结
原文请看:http://blog.csdn.net/loaden/article/details/6061702 Qt如果采取默认编译安装,一般都要占用上G的空间.当初自己不想涉及Qt的一个原因,就是 ...
- 洛谷P2713 罗马游戏
题目传送门 分析: 好吧,其实没什么好分析的,左偏树裸题. Code: #include<cstdio> #include<cstring> #include<cstdl ...