动态链接库的创建

来源:互联网 发布:微分怎么编程 编辑:程序博客网 时间:2024/05/21 17:58

 

动态链接库的创建:

1. 需要在要导出的函数前加上关键字 _declspec(dllexport) 例如:

_declspec(dllexport) int add(int a,int b)

{

    return a+b;

}

class _declspec(dllexport) ClassName     //将_declspec(dllexport)放在类名前,将导出类的所有成

{                                        //员函数。如果放在成员函数前则只导出该成员函数。

public:

    void add(int a,int b);

};

//以上方式导出时编译器将自动将函数名改编以支持函数重载,这样导出的DLL在C程序无法使用,

//为了解决这个问题必须再加上 extern "C" 关键字,以使导出时不变更函数名。例如:

extern "C" _declspec(dllexport) int add(int a,int b)

{

    return a+b;

}

//如果增加函数调用约定的关键字 _stdcall,则不论是否声明过 extern "C" 都将进行函数名改编。

//例如:

extern "C" _declspec(dllexport) _stdcall int add(int a,int b)

{

    return a+b;

}

//使用模块定义文件导出函数时不需要关键字 _declspec(dllexport),函数名也可以自行定义,

//推荐使用这个方法。例如:

<dll1.def>

LIBRARY dll1            //dll1是动态链接库的内部名,必须与导出的dll文件名相同

EXPORTS                 //导出标记

add                     //导出的函数名

sub=subtract            //导出后的函数名=被导出的函数名

2. 编译后会生成*.lib 和*.dll 文件。

其中*.lib 文件为导出库文件,他包含了动态链接库中的函数名和变量名等信息;*.dll文件为动态链接库文件,他包含了函数的实现和变量等数据。

动态链接库的静态加载:

1. 在使用动态链接库的代码前,需要先声明函数或变量来自外部,例如:

extern int add(int ,int);                    //第一种方式

或者:

_declspec(dllimport) int add(int ,int);      //第二种方式(推荐)

class _declspec(dllimport) ClassName

{

public:

    void add(int a,int b);

};

//推荐使用第2种方式,因为他可以告诉编译器该函数来自一个dll,据说可以生成效率更高的代码。

2. 在工程中添加创建时产生的*.lib。

动态链接库的动态加载:

HINSTANCE hInst;

hInst=LoadLibrary("Dll1.dll");                                   //API函数加载DLL

typedef int (*ADDPROC)(int a,int b);                             //定义函数指针类型

ADDPROC Add=(ADDPROC)GetProcAddress(hInst,"add");                //API函数获取函数地址

/*ADDPROC Add=(ADDPROC)GetProcAddress(hInst,MAKEINTRESOURCE(1));

*使用函数序号的方式获取函数地址*/

if(!Add)

{

MessageBox("获取函数地址失败!");

return;

}

Add(5,3);

FreeLibrary(hInst);                                             //API函数释放DLL

//动态加载时不需要在工程中添加*.lib,并且使用dumpbin工具也无法看到需要的外部函数名

动态链接库的入口函数

BOOL WINAPI DllMain(

  HINSTANCE hinstDLL,  // handle to the DLL module

  DWORD fdwReason,     // reason for calling function

  LPVOID lpvReserved   // reserved

);

小技巧:

1. 可以使用dumpbin或者depends工具来查看dll导出的函数,也可以用他来查exe文件需要的外部函数。

2. 在编译dll文件时,通常提供一个头文件,例如:

<dll1.h>

#ifdef DLL1_API

#else

#define DLL1_API _declspec(dllimport)

#endif

DLL1_API int add(int a,int b);

这样在创建dll文件时做如下修改:

#define DLL1_API _declspec(dllexport)

#include "dll1.h"

int add(int a,int b) //此处不再需要_declspec(dllexport),因为已经在头文件中声明过了。

{

    return a+b;

}

在使用dll文件时做如下修改:

#include "dll1.h" //添加头文件

int add(int ,int); //此处不再需要_declspec(dllimport),因为已经在头文件中声明过了