Windows下动态链接库与静态链接库的构建


构建DLL入口函数

BOOL WINAPI DllMain(HANDLE hDllHandle,DWORD dwReason,  )
{
   HMODULE hModule=(HMODULE)hDllHandle;//本模块加载到内存中时的基址
   switch(dwReason)
   {
        case DLL_PROCESSS_ATTACH;//进程加载
            //初始化
        case DLL_PROCESSS_DETACH;//进程卸载
            //资源释放
        case DLL_THREAD_ATTACH;

        case DLL_THREAD_DETACH;
   }
}

当一个程序试图加载卸载dll时,系统会调用dll库中的DllMain函数
然后编写实际功能函数

导出函数

使用def文件

  • VS设置

    属性-链接器-输入-模块定义文件-输入def文件

  • def文件语法

LIBIARY WIN32_DLL <-模块名称
EXPORTS <-下面的函数才能在DLL外使用
    FUN1
    FUN2
    ... 

使用函数标识符

在函数前一句话,如下,表示该函数导出
__declspec(dllexport) int fun1()
这样导出的函数名会被VS修饰,非MS的编译器无法正确识别函数
添加extern “C”可以使得函数名就是自己输入的名字
extern "C" __declspec(dllexport) int fun1()

使用DLL

生成动态链接库时会生成两个文件
dll文件:
1. 保存代码与资源
lib文件:(不是静态链接库)
1. 使用的动态链接库的文件名是什么(此处为WIN32_DLL)
2. 保存指定函数在dll文件中的偏移地址

隐式加载

  1. 导入并申明函数
#include 
extern "C" __declspec(dllimport) int fun1()
#pragma comment(lib,"WIN32_DLL.lib") 
  1. 使用头文件
    写一个头文件,方便调用
    WIN32_DLL.h
#include 
#ifdef _MYWIN32DLLTEST
extern "C" __declspec(dllexport) int fun1();
#else
extern "C" __declspec(dllimport) int fun1();
#pragma comment(lib,"WIN32_DLL.lib") ;
#endif
#undef _MYWIN32DLLTEST

然后在WIN32_DLL.cpp引用并定义指定的宏,在调用文件中引用即可

显式调用,动态加载

当只有dll时,可以这样,但时需要通过某种方法获得dll中的函数信息,如反汇编等

#incluce 
typedef int(*lpFUN1)(int,int);//定义一个函数指针

int main()
{
    lpFUN1 fun1;
    HMODULE hDll;
    hDll=LoadLibrary(L"WIN32_DLL.dll");//加载dll,返回dll的内存地址
    if(hDll)
    {
        fun1=(lpFUN!)GetProcAddress(hDll,"FUN1");//获取函数指针,然后就可以用了
    }

    FreeLiberary(hDll);//最后释放掉这个动态链接库
}

类的导出与使用

与导出函数类似,在类的名称前加上__declspec(dllexport)即可
class __declspec(dllexport) MyClass

为方便调用,类的头文件可以这么写

#include 
#ifdef _MYWIN32DLLTEST
#define MY_DLL_API __declspec(dllexport)
extern "C" __declspec(dllexport) int fun1();
#else
#define MY_DLL_API __declspec(dllexport)
extern "C" __declspec(dllimport) int fun1();
#pragma comment(lib,"WIN32_DLL.lib") ;
#endif
#undef _MYWIN32DLLTEST

class MY_DLL_API MyClass
{
    //书写相应代码
};

资源的导出与使用

我们可以把资源放在DLL之中,通过调用DLL中的某个函数获得指定资源

hBitmap=(HBITMAP)LoadImage(MyModule(),MAKEINTRESOURCE(103),IMAGE_BITMAP,0,0,LR_COPYFROMRESOURCR);

HRSRC hsrc;
HGLOBAL hExe;
LPVOID lpBuf;
DWORD dwSize;
DWORD dwWritten;

//找到一个资源句柄
hsrc=FindResourse(MyModule(),MAKEINTRESOURCE(104),L”EXE”);
//加载资源,获得资源地址
hExe=LaodResourse(MyModule(),hsrc);
//hExe与lpBuf值相同,此句用来检测该资源是否能被正常锁定。
lpBuf=LoakResource(hExe);
//获取资源大小
dwSize=SizeofResource(MyModule(),hsec);
//然后就可以对资源进行操作了

hFile=CreateFile(L”./a.exe”,FENERIC_ALL,FILE_SHARE_READ|FILE_SHARE_WRITE,0,CREATE_ALWAYS,0,0);
SetFilePointer(hFile,0,0,FILE_BEGIN);
WriteFile(hFile,lpBuf,dwSize,&dwWritten,0);
CloseHandle(hFile);

静态链接库的构造与使用

与动态链接库几乎完全一样,但没有DllMain函数

你可能感兴趣的:(Windows)