C++动态链接库
1、动态链接库概述:
- 动态链接库通常都不能直接运行,也不能接受消息;只有在其他模块调用动态链接库中的函数时,它才发挥作用。
- Windows API中所有的函数都包含在动态链接库中。
- 动态链接库分静态库和动态库。
2、导出函数的声明方式
1)强制用C语言方式进行修饰,且用C的默认调用约定,即__cdecl方式。这种方式编译产生的DLL中有一个导出函数:add,不加任何修饰。(这种方式最好)
extern "C" int __declspec(dllexport) add();
2)强制用C语言方式进行修饰,且用__stdcall约定。这种方式编译产生的DLL中有一个导出函数:_add@0,即前面有“_”,后面加了参数长。
extern "C" int __declspec(dllexport) __stdcall add();
3)不强制用C语言方式进行修饰,但是用__stdcall约定。这种方式编译产生的DLL中有一个导出函数:?add@@YGHXZ。这个名字很怪,后面的不好理解。
int __declspec(dllexport) __stdcall add();
4)不强制用C语言方式进行修饰,并且用 __cdecl 约定。这种方式编译产生的DLL中有一个导出函数:?add@@YAHXZ。注意看,和第三种方有一点不同。
int __declspec(dllexport) __cdecl add();
对于DLL导出函数声明的四种写法,在动态调用时, 声明成第一种方式是最好的。但是,C/C++缺省的调用约定为__cdecl约定,如果想别的语言能用DLL的话,最好是将调用约定写成__stdcall方式(不能动态调用),然后静态(隐式)调用。
在隐式调用时,四种声明方式都是可以的,只要调用者的声明方式和DLL声明时的方式一致即可。
3、动态链接库的创建:
我们以第一种声明方式对函数进行声明,要导出的函数的形式为:
extern "C" int _declspec(dllexport) add()
{
return 5;
}
为解决名字改编问题,可为工程添加一个模块定义文件.def
LIBRARY
MFC-Add EXPORTS
add@0 ;函数名@参数长
要导出的类的形式为:
class __declspec(dllexport) Point
{
public:
void OutPut(int x, int y);
};
编译之后会生成:一个DLL(.dll)文件、一个引入库(.lib)文件等
注:若在声明类时,指定了导出标志,那么该类中的所有函数均被导出;否则只导出那些声明时指定了导出标志的类成员函数
4、动态链接库的加载:
(1) 隐式加载
利用 extern 或 __declspec(dllimport) 声明外部函数(最好将此声明写在一个头文件*.h中)
extern "C" int _declspec(dllimport) add();
导入对应的引入库(.lib)文件:在项目“设置”中链接lib库 或 在源文件中使用代码链接lib库:
#pragma comment(lib, "*.lib")
将动态链接库文件所在目录添加到系统的环境变量path中。
附:Qt中库的隐式加载:
VC的引用库文件为xxx.lib, GCC的为xxx.a,通过比较两种库文件的格式,发现很相似,于是把xxx.dll,xxx.lib和xxx.h复制到Qt的project下,直接把xxx.lib改为xxx.a, 根据Qt的库名字的格式, 在xxx.a的前面加上lib, 即为libxxx.a。再在Qt的.pro文件中最后面加上
LIBS += -L. –lxxx //增加当前目录下的libxxx.a
先在pro文件中加入一行,LIBS += -L ./ -lPlotDll,然后将PlotDll.dll和PlotDll.lib拷贝到工程build目录下(就是含有Makefile的目录),再重新编译一次即可。
(2) 显式加载
将指定的可执行模块映射到调用进程的地址空间
#include <Windows.h>
HINSTANCE handlerDLL = NULL;
handlerDLL = LoadLibrary(_T("..\\..\\MFC-Add\\Debug\\MFC-Add.dll"));
获取该动态链接库中导出函数的地址
typedef int(__stdcall *ADDPROC)(int a,int b);//声明ADDPROC为指向函数的指针类型,函数返回值类型为int; _stdcall即标准调用约定
ADDPROC AddProc = NULL;
AddProc = (ADDPROC)GetProcAddress(handlerDLL,_T("add"));
调用导出函数
AddProc(5,6);
当不需要访问dll时,释放对dll的引用
FreeLibrary("..\\..\\MFC-Add\\Debug\\MFC-Add.dll");
Qt中的动态调用方式,代码:
//动态加载
QLibrary hDll(".\\Libs\\GHC02DLL.dll");
if(hDll.load())
{
typedef int (__stdcall *ADDFunc)();
ADDFunc Add=(ADDFunc)hDll.resolve("fnGHC02DLL"); QMessageBox::about(this,"about",QString::number(Add(),)); hDll.unload();
}
注:
- Dumpbin 和 Depends 工具
- 调用约定:__stdcall:标准调用约定即WINAPI调用约定,也就是pascal调用约定,非C调用约定
- 名字改编:C++编译器在生成DLL时,会对导出函数进行名字改编,且不同的编译器使用的改编规则不同
相关链接:http://www.cnblogs.com/DxSoft/archive/2011/04/22/2024686.html
C++动态链接库的更多相关文章
- 【腾讯Bugly干货分享】动态链接库加载原理及HotFix方案介绍
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57bec216d81f2415515d3e9c 作者:陈昱全 引言 随着项目中动 ...
- MacOS平台下@rpath在动态链接库中的应用
一.背景介绍 公司开发的一个底层库被用在了Mac平台的多个产品中.在开发这个底层库的初期,对于Mac OSX下的Install name 并没有过多的了解.对于XCode中的install name项 ...
- 关于 .NET Core 动态链接库的开发
上个月月底,VS2017RC版发布了,一个很大的特点就是将原来的xProj文件又改回了csproj了. 这样一改,其实很多新的问题也暴露出来了,最严重的问题就是Net版本兼容性. 原来的Net体系大致 ...
- vc下的静态链接库与动态链接库(一)
一.静态库与动态库的区别 目前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Lib ...
- 编译可供C#调用的C/C++动态链接库dll文件
编译可供C#调用的C/C++动态链接库dll文件,C语言控制台应用程序,探索生成dll过程 由于项目需求,需要公司另一个团队提供相关算法支持,是用C语言编译好的dll库提供给我们进行调用. 但是拿到d ...
- C/C++ 静态链接库(.a) 与 动态链接库(.so)
平时我们写程序都必须 include 很多头文件,因为可以避免重复造轮子,软件大厦可不是单靠一个人就能完成的.但是你是否知道引用的那些头文件中的函数是怎么被执行的呢?这就要牵扯到链接库了! 库有两种, ...
- linux下动态链接库解决方案(二)
以前写过一个关于linux下用c++写动态链接库无法通过的解决方案,今天看到<linux C程序设计-王者归来>这本书,书中有个更容易的解决方案,特此记录下来 书中使用的是c语言,我改用c ...
- Linux 动态链接库
如何使用动态链接库 Linux下打开使用动态链接库需要三步(实际上和windows下基本一样):1.加载动态链接库,通过调用库函数dlopen()获得链接库的句柄,对应于windows下的 AfxLo ...
- VC++动态链接库(DLL)编程深入浅出(zz)
VC++动态链接库(DLL)编程深入浅出(zz) 1.概论 先来阐述一下DLL(Dynamic Linkable Library)的概念,你可以简单的把DLL看成一种仓库,它提供给你一些可以直接拿来用 ...
- [转载:]C#与Fortran混合编程之本地调用Fortran动态链接库
前言 C#发展到现在,已是一门相当完善的语言,他基于C语言风格,演化于C++.并依靠强大的.NET底层框架.C#可以用来快速构建桌面及Web应用.然而在我们的实际工作中,尽管C#已经非常完善,但还是不 ...
随机推荐
- js jq 实现鼠标经过div背景以进度条方式 变宽,鼠标离开变小,同时文字颜色和原来不一样
<!DOCTYPE html> <html> <head> <title></title> <script typet="t ...
- mongodb副本集的从库永久性设置setSlaveOk
今天在生产环境下面搭了一个mongo的副本集,但开发那边要求副本集读写分离. 坑爹的是每次上副本集的时候都要设置db.getMongo().setSlaveOk()才能访问数据.感觉很是苦逼. 后来开 ...
- 提升系统的QPS和吞吐量
简单而言通过增加集群来提升qps和吞吐量 实际上要比这个要复杂 首先我们需要知道系统的瓶颈 我们所知道的系统拓扑架构 对于rest接口而言 系统设施依次是: dns nginx tomcat db/s ...
- 【C++】operator new/new operator/placement new之间的区别
new operator new operator即是c++中的关键字new.比如A* = new A; 中的new就是new operator. 它执行了三个步骤: 1. 分配内存空间 事实上,分配 ...
- 无法加载DLL"***.dll":找不到指定的模块
加载dll的路径不对. 绝对路径不合适,可以换成相对路径. 比如: 把dll放入bin目录下的debug或者release下,然后就可以直接“test.dll”了.不用加路径了. 注意:路径必须与发布 ...
- matomo 开源网站分析平台
1.安装PHP https://www.jianshu.com/p/8d54a401ec06 yum remove php* yum -y install epel-release rpm -Uvh ...
- Oracle 11g 静默安装-db_install.rsp详解
转自--------------https://blog.csdn.net/jameshadoop/article/details/48086933 :db_install.rsp详解 ####### ...
- 取得<asp:TextBox中的值:
取得<asp:TextBox中的值: var a= document.getElementById("<%= (ID名).ClientID %>").valu ...
- 《学习OpenCV(中文版)》
<模式识别中文版(希)西奥多里蒂斯> <学习OpenCV(中文版)> 矩阵计算 英文版 第四版 Matrix Computations OpenCV 3.x with Pyth ...
- YYKit @autoreleasepool 使用,优化内存
写在前面 最近再看YY大神的YYKit工具,发现在代码中经常使用@autoreleasepool,特别是在与for循环搭配使用的时候.刚开始很不能理解. 先有个概念: 自己创建的对象:使用 alloc ...