dll的创建和使用

风流意气都作罢 提交于 2020-03-18 19:50:32

前几天有个朋友问道这个问题,结果因为以前从没搞过这个,对vs2005也不熟悉,竟花了2个小时才搞定, 。

特地拿来与大家分享,希望能给像我这样的菜鸟们一些帮助,O(∩_∩)O

【第一步】创建自己的dll

1.打开vs2005,选择菜单【File-New-Project】,在弹出对话框中选择[Visual C++]下的[Win32]-[Win32 Console Application],输入工程名后确认。

2.在弹出的对话框中选择[next],在Application Settiongs中选择Application type为Dll,Additional options选择Empty project,然后点Finish。

这时就创建了一个空的可以生成dll文件的工程。

3.在工程中添加一个头文件(这里为dll_test.h),在头文件中写入如下内容:

 1 #ifndef _DLL_TUTORIAL_H
 2 #define _DLL-TUTORIAL_H
 3 
 4 #include<iostream>
 5 
 6 #if defined DLL_EXPORT
 7   #define DECLDIR _declspec(dllexport)
 8 #else
 9   #define DECLDIR _declspec(dllimport)
10 #endif
11 
12 extern "C"
13 {
14   DECLDIR int Add(int a, int b);
15   DECLDIR void Function(void);
16 }
17
18 #endif

 

这里要说明的是:

在VC中有两个方法来导出dll中定义的函数:

  (1) 使用__declspec,这是一个Microsoft定义的关键字。

  (2) 创建一个模板定义文件(Module-Definition File,即.DEF)。

  第一种方法稍稍比第二种方法简单,在这里我们使用的是第一种方法。

    __declspec(dllexport)函数的作用是导出函数符号到在你的Dll中的一个存储类里去。

当下面一行被定义时我定义DECLDIR宏来运行这个函数。

    #define DLL_EXPORT

在此情况下你将导出函数Add(int a,int b)和Function().

4.创建一个源文件(名字为dll_test.cpp),内容如下:

 

 1 #include <iostream>
 2 #define DLL_EXPORT
 3 #include "dll_test.h"
 4 
 5 extern "C"
 6 {
 7         // 定义了(DLL中的)所有函数
 8     DECLDIR int Add( int a, int b )
 9     {
10         return( a + b );
11     }
12     
13     DECLDIR void Function( void )
14     {
15         std::cout << "DLL Called!" << std::endl;
16     }
17 }
18 

 

【第二步】使用创建好的DLL

现在已经创建了DLL,那么如何在一个应用程序中使用它呢?

当DLL被生成后,它创建了一个.dll文件和一个.lib,这两个都是使用dll时需要用到的。

在具体介绍之前先看一下dll的链接方式。

(1)隐式连接

这里有两个方法来载入一个DLL,一个方法是只链接到.lib文件,并将.dll文件放到要使用这个DLL的项目路径中。

因此,创建一个新的空的Win32控制台项目并添加一个源文件。将我们创建好的DLL放入与新项目相同的目录下。同时我们还必须链接到dll_test.lib文件。

可以在项目属性中设置,也可以在源程序中用下面的语句来链接:

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

最后,我们还要在新的win32控制台项目中包含前面的dll_test.h头文件。可以把这个头文件放到新建win32控制台项目的目录中然后在程序中加入语句:

#include "dll_test.h"

新项目代码如下:

#include<iostream>

#include "DLLTutorial.h"

int main()

{

  Function();

  std::cout<< Add(32, 56)<< endl;

  return 0;

}

(2)显示链接

稍微复杂一点的加载DLL的方法需要用到函数指针和一些Windows函数。但是,通过这种载入DLL的方法,不需要DLL的.lib文件或头文件,而只需要DLL即可。

下面列出一些代码:

/****************************************************************/

#include <iostream>

#include <windows.h>

typedef int (*AddFunc)(int,int);

typedef void (*FunctionFunc)();

int main()

{

AddFunc _AddFunc;

   FunctionFunc _FunctionFunc;

   HINSTANCE hInstLibrary = LoadLibrary("DLL_Tutorial.dll");

   if (hInstLibrary == NULL)

{

FreeLibrary(hInstLibrary);

}

   _AddFunc = (AddFunc)GetProcAddress(hInstLibrary, "Add");

   _FunctionFunc = (FunctionFunc)GetProcAddress(hInstLibrary, "Function");

   if ((_AddFunc == NULL) || (_FunctionFunc == NULL))

{

FreeLibrary(hInstLibrary);

}

   std::cout << _AddFunc(23, 43) << std::endl;

   _FunctionFunc();

   std::cin.get();

   FreeLibrary(hInstLibrary);

   return(1);

}

/*******************************************************************/

首先可以看到,这里包括进了windows.h头文件,同时去掉了对dll_test.h头文件的包含。原因很简单:因为windows.h包含了一些Windows函数,

它也包含了一些将会用到的Windows特定变量。可以去掉DLL的头文件,因为当使用这个方法载入DLL时并不需要其头文件。

下面你会看到:以下面形式的一小块古灵精怪的代码:

    typedef int (*AddFunc)(int,int);

typedef void (*FunctionFunc)();

    这是函数指针。因为这是一个关于DLL的自学指南,深入探究函数指针超出了本指南的范围;因此,现在我们只把它们当作DLL包含的函数的别名。

    我喜欢在尾部用“Func”命名之。(int,int)部分是这个函数的参数部分,比如,Add函数要获得两个整数;因此,你需要它们

(译注:指(int,int)部分)作为函数指针的参数。Function函数没有参数,因此你让它为空。main()部分中的前面两行是声明函数指针以使得你可

以认为它们等同于DLL内部的函数。我只是喜欢预先定义它们。

      一个HINSTANCE是一个Windows数据类型:是一个实例的句柄;在此情况下,这个实例将是这个DLL。你可以通过使用函数LoadLibrary()获得DLL的

实例,它获得一个名称作为参数。

     在调用LoadLibrary函数后,你必需查看一下函数返回是否成功。你可以通过检查HINSTANCE是否等于NULL(在Windows.h中定义为0或Windows.h包

含的一个头文件)来查看其是否成功。如果其等于NULL,该句柄将是无效的,并且你必需释放这个库。换句话说,你必需释放DLL获得的内存。

      如果函数返回成功,你的HINSTANCE就包含了指向DLL的句柄。一旦你获得了指向DLL的句柄,你现在可以从DLL中重新获得函数。

     为了这样作,你必须使用函数GetProcAddress(),它将DLL的句柄(你可以使用HINSTANCE)和函数的名称作为参数。你可以让函数指针获得由

GetProcAddress()返回的值,同时你必需将GetProcAddress()转换为那个函数定义的函数指针。举个例子,对于Add()函数,你必需将GetProcAddress()

转换为AddFunc;这就是它知道参数及返回值的原因。现在,最好先确定函数指针是否等于NULL以及它们拥有DLL的函数。

     这只是一个简单的if语句;如果其中一个等于NULL,你必需如前所述释放库。一旦函数指针拥有DLL的函数,你现在就可以使用它们了,但是这里有一个

需要注意的地方:你不能使用函数的实际名称;你必需使用函数指针来调用它们。在那以后,所有你需要做的是释放库如此而已。

     现在你知道了DLL的一些基本知识。你知道如何创建它们,你也知道如何用两种不同的方法链接它们。这里仍然有更多的东西需要我们学习,但我把它们留给你们自己探索了和更棒的作者来写了。

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!