C++编程笔记:dll的生成与调用

1. dll的创建

1.1 使用 __declspec(dllexport) 创建dll

首先在VS中的Visual C++中创建一个Win32 Project,取名为Dll1。在Application Type中选择DLL,在Additional options中选择Empty project,即创建一个空的动态链接库工程。 

然后为工程添加一个C++源文件:Dll1.cpp,假设我要实现的是加法和减法运算,则代码如下
 

extern "C"  __declspec(dllexport) int add(int a, int b){ 

return a + b; 

} 

extern "C"  __declspec(dllexport) int subtract(int a, int b){

return a - b;

}

1.2 使用模块定义(.def)文件创建dll

使用def文件创建dll的话就不再需要__declspec(dllexport),因此将代码写成最原始的样子:

int add(int a, int b){
    return a + b;
}

int subtract(int a, int b){
    return a - b;
}

同时为工程创建一个后缀名为.def的文件,并添加进工程,编辑其内容为:

LIBRARY Dll1

EXPORTS
add
subtract

其中LIBRARY语句用于指定动态链接库的名称,该名称与生成的动态链接库名称一定要匹配。EXPORTS语句用于表明dll将要导出的函数,以及为这些导出函数指定的符号名。 
将该模块定义文件链接到工程中,方法为工程属性页面>链接器>输入>模块定义文件中写入“Dll1.def”。 

2. dll的使用

2.1 隐式链接方式加载dll

将生成好的Dll1.dll和Dll1.lib复制到对话框程序所在的文件夹,然后在CXXXDlg.h中注册动态链接库的引入库文件。因为.lib文件包含了Dll1.dll中导出函数的符号名,相当于告诉对话框程序相关函数应该去dll中调用。然后在CXXXDlg.cpp中声明外部函数:

#pragma comment(lib,"Dll1.lib")

然后在CXXXDlg.cpp中声明外部函数:

_declspec(dllimport) int add(int a, int b);
_declspec(dllimport) int subtract(int a, int b);
//另一种常用方法



//===============================================================
//要导出静态库时,导出库的工程要加预编译宏STATIC_LIBRARY,使用库的工程什么也要加STATIC_LIBRARY宏
//要导出动态库时,导出库的工程要加预编译宏EXPORT,使用库的工程什么也不用加
//===============================================================
#ifdef EXPORT   //导出库
#define _API_  __declspec(dllexport)
#else           //导入库
#define _API_  __declspec(dllimport)
#endif  //EXPORT


#ifdef STATIC_LIBRARY   //导出静态库
#define EBAPI int
#else                   //导出动态库
#define EBAPI extern "C" _API_ int
#endif  //STATIC_LIBRARY

 这样我们就可以使用这两个函数了。为两个按钮添加事件响应程序,并添加如下代码:

void CXXXDlg::OnBtnAdd()
{
    // TODO: Add your control notification handler code here
    CString str;
    str.Format(_T("5 + 3 = %d"), add(5, 3));
    MessageBox(str);
}

2.2 显示加载方式加载dll

另一种是通过LoadLiabrary函数显示加载dll。代码如下。需要注意的是这时候我们不再需要注册.lib文件,也不需要声明外部函数。只要在需要使用的地方调用dll文件即可。

void CXXXDlg::OnBtnSubtract()
{
    // TODO: Add your control notification handler code here
    HINSTANCE hInst;
    hInst = LoadLibrary(L"Dll1.dll");
    typedef int(*SUBPROC)(int a, int b);
    SUBPROC Sub = (SUBPROC)GetProcAddress(hInst, "subtract");
    CString str;
    str.Format(_T("5-3=%d"), Sub(5, 3));
    FreeLibrary(hInst);       //LoadLibrary后要记得FreeLibrary
    MessageBox(str);
}
2.3 两种加载方式对比

通过以上的例子,可以看到隐式链接和动态加载两种加载dll的方式各有优点。

隐式链接方式实现简单,一开始就把dll加载进来,在需要调用的时候直接调用即可。但是如果程序要访问十多个dll,如果都采用隐式链接方式加载他们的话,在该程序启动时,这些dll都需要被加载到内存中,并映射到调用进程的地址空间,这样将加大程序的启动时间。而且一般来说,在程序运行过程中只是在某个条件满足的情况下才需要访问某个dll中的函数,如在上述例子中,我只有在点击按钮时才需要访问dll,其他情况下并不需要访问。这样如果所有dll都被加载到内存中,资源浪费是比较严重的。
显示加载的方法则可以解决上述问题,dll只有在需要用到的时候才会被加载到内存中。另外,其实采用隐式链接方式访问dll时,在程序启动时也是通过调用LoadLibrary函数加载该进程需要的动态链接库的。
 

原文:https://blog.csdn.net/elaine_bao/article/details/51784864 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值