2014-03-30工作日志:我对如何创建和调用dll的总结

来源:互联网 发布:js函数递归调用 编辑:程序博客网 时间:2024/05/29 19:30

1、新建Project->Win32Dynamic-Link Library。然后像以往一样编程。选择这样的工程和win32 console application工程的区别就是

project->settings->link->project options->在category是general的条件下,将其中的subsystem:console改为dll,out:"Release/DLL_CheckMd5.exe"改为out:"Release/DLL_CheckMd5.dll",并在out:"Release/DLL_CheckMd5.dll"后添加/implib:"Release/Md5_Test.lib" 。


project->settings->link->output file name->在category是general的条件下,将Release/DLL_CheckMd5.exe改为Release/DLL_CheckMd5.dll


project->settings->c++->Preprocessor definitions->将WIN32,NDEBUG,_CONSOLE,_MBCS改为:NDEBUG,WIN32,_WINDOWS,_UNICODE,UNICODE,_USRDLL,DLL_REGSRVPRINT_EXPORTS


即可将win32 console application工程变化为Win32Dynamic-Link Library工程。


2、在Dll_Main.cpp文件中(这个文件的名字随意,只要在该文件中包含三个内容即可:1、DllMain函数。2、被调用的函数的定义。3、#include“包含被调函数声明的头文件”)写出固定格式的DLL_Main()函数和其他函数。

BOOL APIENTRY DllMain(HINSTANCE hInstance,DWORD fdwReason,PVOID pvReserved){switch( fdwReason )     { case DLL_PROCESS_ATTACH:_tsetlocale(LC_CTYPE,TEXT(""));break;case DLL_PROCESS_DETACH:break;case DLL_THREAD_ATTACH:break;case DLL_THREAD_DETACH:break;    }return TRUE; }


该文件要包含#include <LOCALE.H>文件和#include <TCHAR.H>,因为其中的_tsetlocale函数的声明在这个头文件中,目的是防止程序产生中文乱码。该文件还要包含头文件Dll_Md5_Test.h(头文件名随意定义都行),内容如下:


#ifndef DLLAPI#ifdef _USRDLL#ifdef __cplusplus#define DLLEXPORT extern "C" __declspec(dllexport)#else#define DLLEXPORT __declspec(dllexport) #endif#define DLLAPI DLLEXPORT#else /* Not BUILDING_DLL */#ifdef __cplusplus#define DLLIMPORT extern "C" __declspec(dllimport)#else#define DLLIMPORT __declspec(dllimport)#endif#define DLLAPI DLLIMPORT#endif /* Not BUILDING_DLL */#endifDLLAPI BOOL DLL_Test(IN LPTSTR lpFilePath,IN LPTSTR lpMd5Content);


以上语句中

DLLAPI BOOL DLL_Test(IN LPTSTR lpFilePath,IN LPTSTR lpMd5Content);

确定要输出的函数。Dll_Main.cpp中可以写其他函数,其他函数和平时一样,没有要求,但是必须有被调用的函数的定义。


系统在调用dll工程时,会默认产生_USRDLL,调用dll时,却不会产生_USRDLL



3、在Dll_Main.h中声明

BOOL APIENTRY DllMain(HINSTANCE hInstance,DWORD fdwReason,PVOID pvReserved);


4、写Dll_Md5_Test.h头文件,并在DllMain.cpp文件中包含(上面已经提到过)。


5、build->set Active Configuration->双击包含release的那一项。


7、点击编译按钮,进行创建,在Release文件夹里面可以找到。


注意:如果被掉函数调用了其他函数,则头文件的顺序应该是Dll_Md5_Test.h文件在其他头文件的最上方,如:

#include <Windows.h>#include <LOCALE.H>#include <STDIO.H>#include <IOSTREAM.H>#include <TCHAR.H>#include "InitialDisk_DLL.h"#include "FormatDrive.h"#include "SetPartitionName.h"#include "InitialDisk.h"
一定要注意这一点,写成
#include "FormatDrive.h"#include "SetPartitionName.h"#include "InitialDisk.h"#include "InitialDisk_DLL.h"
的话就不能产生lib文件。


8、调用时,将调用的工程的project->settings->link->project options->在category是general的条件下,将其中的

out:"/Debug/EXE_RegSrvPrint.exe" 改为out:"../Release/EXE_RegSrvPrint.exe" 和lib、dll放在同一个文件夹下面。


可以设置Project->Dependencies来确定依赖,如果没有找到lib文件,系统会先编译dll工程,后执行调用dll的文件,以免产生错误。


9、调用刚刚那个头文件Dll_Md5_Test.h

#ifndef DLLAPI#ifdef _USRDLL#ifdef __cplusplus#define DLLEXPORT extern "C" __declspec(dllexport)#else#define DLLEXPORT __declspec(dllexport) #endif#define DLLAPI DLLEXPORT#else /* Not BUILDING_DLL */#ifdef __cplusplus#define DLLIMPORT extern "C" __declspec(dllimport)#else#define DLLIMPORT __declspec(dllimport)#endif#define DLLAPI DLLIMPORT#endif /* Not BUILDING_DLL */#endifDLLAPI BOOL DLL_Test(IN LPTSTR lpFilePath,IN LPTSTR lpMd5Content);

10、在调用包含主函数的文件中引用这个头文件,并在调用它之前函数之外写上这句话

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

注意千万不要带分号。


11、直接调用这个函数即可。如下

#include<stdio.h>#include <windows.h>#include <locale.h>#include<tchar.h>#include"Common/HelperFunc.h"#include "Common/LogInfo.h"#include "call_Md5_Test.h"#pragma comment(lib,"lib/Md5_Test.lib")bool _tmain(int argc,LPTSTR argv[]){_tsetlocale(LC_CTYPE,TEXT(""));if(argc==1){LI_INFOPRINT(TEXT("对不起,请输入正确的文件路径%s",argv[2]));return FALSE;}else {bool bResult=DLL_Test(argv[1],argv[2]);return bResult;}} 

直接运行即可。

另:请注意:创建dll和调用dll没有想象中的那么难,只是某些细节需要注意一下,其他地方和平时做项目一样。


(1)lib是编译时需要的,dll是运行时需要的。
如果要完成源代码的编译,有lib就够了。
如果也使动态连接的程序运行起来,有dll就够了。

在开发和调试阶段,当然最好都有。



(2)一般的动态库程序有lib文件和dll文件。lib文件是必须在编译期就连接到应用程序中的,而dll文件是运行期才会被调用的。如果有dll文件,那么对应的lib文件一般是一些索引信息,具体的实现在dll文件中。如果只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。静态编译的lib文件有好处:给用户安装时就不需要再挂动态库了。但也有缺点,就是导致应用程序比较大,而且失去了动态库的灵活性,在版本升级时,同时要发布新的应用程序才行。



(3)在动态库的情况下,有两个文件,一个是引入库(.LIB)文件,一个是DLL文件,引入库文件包含被DLL导出的函数的名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到所需要使用的DLL文件,库中的函数和数据并不复制到可执行文件中,因此在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中所要调用的函数的内存地址,这样当一个或多个应用程序运行是再把程序代码和被调用的函数代码链接起来,从而节省了内存资源。从上面的说明可以看出,DLL和.LIB文件必须随应用程序一起发行,否则应用程序将会产生错误。


0 0
原创粉丝点击