Dynamic-link library

动态链接库基本概念

Dynamic-link library (or DLL) is Microsoft’s implementation of the shared library concept in the Microsoft Windows and OS/2 operating systems. These libraries usually have the file extension DLL, OCX (for libraries containing ActiveX controls), or DRV (for legacy system drivers). The file formats for DLLs are the same as for Windows EXE files – that is, Portable Executable (PE) for 32-bit and 64-bit Windows, and New Executable (NE) for 16-bit Windows. As with EXEs, DLLs can contain code, data, and resources, in any combination.

所谓动态链接,就是把一些经常会共用的代码(静态链接的OBJ程序库)制作成DLL档,当可执行文件调用到DLL档内的函数时,windows操作系统才会把DLL档加载存储器内,DLL档本身的结构就是可执行文件,当程序需求函数才进行链接.通过动态链接方式,存储器浪费的情形将可大幅降低.

DLL的文档格式与视窗EXE文档一样——也就是说,等同于32位视窗的可移植执行文档(PE)和16位视窗的New Executable(NE).作为EXE格式,DLL可以包括源代码、数据和资源的多种组合.

在使用动态库的时候,往往提供两个文件:一个引入库(LIB)和一个动态链接库(DLL).引入库(LIB)包含被动态连接库(DLL)所导出的函数和变量的符号名,动态连接库(DLL)包含实际的函数和数据.

在编译链接可执行文件时,只需要链接引入库(LIB),动态连接库(DLL)中的函数代码和数据并不复制到可执行文件中。
在运行的时候,再去加载DLL,访问动态链接库(DLL)中导出的函数.

动态链接库(DLL)通常都不能直接运行,也不能接收消息.它们是一些独立的文件,其中包含能被可执行程序或其它动态连接库(DLL)调用来完成某项工作的函数.只有在其它模块调用动态链接库(DLL)中的函数时,它才发挥作用.但是动态连接库(DLL)被多进程调用时候,动态链接库(DLL)中进程访问到动态链接库(DLL)的成员时,系统会为它开辟一个新的数据成员页面给访问进程提供单独的动态连接库(DLL)数据区.
这里写图片描述

Windows 下 3 个重要的 DLL

Windows API中的所有函数都包含在DLL中。其中有3个最重要的DLL

  • Kernel32.dll,它包含用于管理内存、进程和线程的各个函数
  • User32.dll,它包含用于执行用户界面任务(如窗口的创建和消息的传送)的各个函数
  • GDI32.dll,它包含用于画图和显示文本的各个函数

动态库加载方式及对比

  • 显式加载动态库
  • 隐式加载动态库

动态加载隐式链接这两种加载DLL的方式各有优点.
如果采用动态加载的方式,那么可以在需要加载时才加载DLL.而隐式链接方式实现起来比较简单,在编写客户端代码时就可以把链接工作做好,在程序中可以随时调用DLL导出的函数。

但是访问十多个DLL,如果都采用隐式链接的方式链接加载他们的话,那么在启动程序时候,这些DLL都需要加载到内存中,并映射到调用进程的地址空间,这样将加大启动程序的时间,而且,一般来说,在程序运行过程中只是在某个条件满足时候,这时才会访问某个DLL中的某个函数,其他情况下都不需要访问这些DLL,但是,这时所有的DLL都被已经加载到内存中,资源浪费会比较严重,这种情况下,就可以采用动态加载DLL技术。

也就是说,在需要时,DLL才会被加载到内存中,并被映射到进程的地址空间中,有一点需要说明的是,实际上,采用隐式链接的方式访问DLL时,在启动时也是通过调用LoadLibrary函数加载到该进程需要的动态链接库的。

// test.h 头文件 -------------------------------------------
#ifndef DLL_API
#define DLL_API _declspec(dllimport)
#endif

DLL_API int max_dll(int a,int b);
DLL_API double max_dll(double a,double b);

class DLL_API testClass{
public:
    testClass();
    int getValue();
private:
    int value;
};
// test.cpp 源程序 -----------------------------------------
#define DLL_API _declspec(dllexport)
#include "test.h"

int max_dll(int a,int b){
    return a>b?a:b;
}
double max_dll(double a,double b){
    return a>b?a:b;
}

testClass::testClass():value(100)
{}

int testClass::getValue()
{
    return value;
}

隐式调用动态链接

#include<iostream>
#include<cstdlib>
//加载动态连接库头文件
#include"../dll/test.h"
//加载动态连接库的引入库(LIB)
#pragma comment(lib, "../release/dll.lib")
using namespace std;

void main(){
    int a=6,b=10;
    double a1=11.1,b1=32.22;

    //调用动态连接库中的类
    testClass c;

    //调用动态链接库函数
    cout<<"the max:"<<max_dll(a,b)<<endl;
    cout<<"the max:"<<max_dll(a1,b1)<<endl;
    //调用动态链接库成员函数
    cout<<"the c.value is "<<c.getValue()<<endl;

    system("pause");
}

显示调用动态链接库

#include"windows.h"
#include<iostream>
#include<cstdlib>
//加载动态连接库头文件
#include"../dll/test.h"
using namespace std;
//声明函数指针类型
typedef int (/*_stdcall*/ *MAXINT)(int a,int b);
typedef double (/*_stdcall*/ *MAXDOUBLE)(double a,double b);

void main(){
    int a=6,b=10;
    double a1=11.1,b1=32.22;
    HINSTANCE hInst;

    hInst=LoadLibrary("../release/dll.dll");

    //动态加载动态链接库中的函数 int max_dll(int a,int b)
    //MAXINT max_int=(MAXINT)GetProcAddress(hInst,"?max_dll@@YAHHHH@Z");//用函数名调用
    //获取函数指针
    MAXINT max_int=(MAXINT)GetProcAddress(hInst,MAKEINTRESOURCE(4));//用函数序号调用
    if(!max_int)
    {
        cout<<"获取max_int函数地址失败!"<<endl;
        system("pause");
        return;
    }

    //动态加载动态链接库中的函数 double max_dll(double a,double b)
    //获取函数指针
    MAXDOUBLE max_double=(MAXDOUBLE)GetProcAddress(hInst,"?max_dll@@YANNN@Z");//用函数名调用
    //MAXDOUBLE max_double=(MAXDOUBLE)GetProcAddress(hInst,MAKEINTRESOURCE(5));//用函数序号调用

    if(!max_double)
    {
        cout<<"获取max_double函数地址失败!"<<endl;
        system("pause");
        return;
    }

    //调用动态链接库函数
    cout<<"the max:"<<max_int(a,b)<<endl;
    cout<<"the max:"<<max_double(a1,b1)<<endl;

    //释放动态连接库链接
    FreeLibrary(hInst);

    system("pause");
}

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>

void*  new_thread(){
        int i=0;
        for(i=0;i<10;i++){
                printf("current %d thread are running....\n",i);
                sleep(2);
        }
        pthread_exit(0);
}

int main(int argc, char* argv[],char* env[]){

        int i=0;
        pthread_t tid[4];
        printf("start runing main thread\n");
        for(i=0;i<4;i++){
                pthread_create(&tid[i],NULL,(void*)new_thread,NULL);
        }
        for(i=0;i<4;i++){
                pthread_join(tid[i],NULL);
        }
        printf("end  running main thread\n");
        return 0;
}

$ ls
test_mthread.c
$ gcc -E test_mthread.c -o test_mthread.i
$ gcc -S test_mthread.i -o test_mthread.s
$ gcc -c test_mthread.s -o test_mthread.o
$ gcc test_mthread.o -o test_mthread
test_mthread.o: In function `main':
test_mthread.c:(.text+0xa0): undefined reference to `pthread_create'
test_mthread.c:(.text+0xca): undefined reference to `pthread_join'
collect2: error: ld returned 1 exit status
$ gcc test_mthread.o -o test_mthread -lpthread
$ ls
test_mthread  test_mthread.c  test_mthread.i  test_mthread.o  test_mthread.s

Reference
1. 动态链接库(VC_Win32)
2. Dynamic-link library

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值