DLL编程基础

来源:互联网 发布:软件注册码怎么破 编辑:程序博客网 时间:2024/06/04 19:28

DLL是组成windows系统的基石,在很多情况下的编程是离不开它的,今天说一下关于DLL编程的一些基础,也是必须要了解的。

主要分为两大类:(1)DLL的编写 (2)DLL的使用

1.DLL的编写

DLL编写需要一个头文件和一个源文件,头文件用于声明,源文件用于实现:

下面是我编写的一个例子程序的头文件中的内容:

// The following ifdef block is the standard way of creating macros which make exporting // from a DLL simpler. All files within this DLL are compiled with the TESTDLL_EXPORTS// symbol defined on the command line. this symbol should not be defined on any project// that uses this DLL. This way any other project whose source files include this file see // TESTDLL_API functions as being imported from a DLL, wheras this DLL sees symbols// defined with this macro as being exported.#ifdef TESTDLL_EXPORTS#define TESTDLL_API __declspec(dllexport)#else#define TESTDLL_API __declspec(dllimport)#endif// This class is exported from the TestDll.dllclass TESTDLL_API CTestDll {public:CTestDll(void);// TODO: add your methods here.};extern TESTDLL_API int nTestDll;TESTDLL_API int fnTestDll(void);extern "C" __declspec(dllexport) int add( int a  , int b ) ;

下面是对应的源文件的内容:

// TestDll.cpp : Defines the entry point for the DLL application.//#include "stdafx.h"#include "TestDll.h"BOOL APIENTRY DllMain( HANDLE hModule,                        DWORD  ul_reason_for_call,                        LPVOID lpReserved ){    switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:MessageBox( NULL , "Message" , "Inject OK!" , NULL ) ;break ;case DLL_THREAD_ATTACH:MessageBox( NULL , "Message" , "Inject Ok!" , NULL ) ;break ;case DLL_THREAD_DETACH:MessageBox( NULL , "Message" , "UnInject Ok!" , NULL ) ;break ;case DLL_PROCESS_DETACH:MessageBox( NULL , "Message" , "UnInject Ok!" , NULL ) ;break ;    }    return TRUE;}// This is an example of an exported variableTESTDLL_API int nTestDll=0;// This is an example of an exported function.TESTDLL_API int fnTestDll(void){return 42;} __declspec(dllexport) int add( int a , int b ){return a + b ;}// This is the constructor of a class that has been exported.// see TestDll.h for the class definitionCTestDll::CTestDll(){ return; }

DLL的编写过程中最主要的区别是如何导出函数/变量/C++类,有两种方法:

(1)使用.def文件

这种方法用的不多,我们主要说第二种

(2)使用extern "C" _declspec(dllexport)

在函数的前面加上以上代码(因为DLL主要用于导出函数所以导出变量与C++类就不说了)即可。

有一点要注意的是,一定要要加上extern ”C",这样编译器就会按照C语言的编译方式来处理符号(函数),那么就不会使用C++的编译方法把我们的函数改的面目全非了。假如不加上,那么在使用GetProcAddress函数寻找函数的地址的时候是找不到的。


二.DLL的使用

在我们的exe程序中,我们需要调用DLL的时候我们有两种使用方法:

(1)隐式调用

这种方法我们需要在生成dll的过程中的dll文件和lib文件,在很多时候我们都是使用的这种方法,例如在socket编程中我们使用#pragama comment ( lib , "ws2_32.lib" ) 来导入winsock支持网络编程的dll,这样我们就能使用它其中的函数了。

同样的道理,在隐式编写程序的时候我们一样使用#pragma comment 宏来导入我们需要的模块。

#pragma comment ( lib , "TestDll.lib") _declspec(dllimport) int add( int a , int b ) ;

如上,我们隐私调用只要在文件头加上上面两行即可。

(2)显式调用

显式调用相对于隐私调用更急灵活,使用的API是LoadLibrary(实际上是一个宏)。

#include "stdio.h"#include "windows.h"// #pragma comment ( lib , "TestDll.lib") // // _declspec(dllimport) int add( int a , int b ) ;// ////////////////////////////////////////////////////////////////////////////// 在显式加载的的情况下要注意,在DLL中声明导出函数的时候一定要在其// 声明的位置加上 extern "C" // 否则,早动态导入函数的时候GetProAddress是找不到相应的函数的//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////typedef int ( * ADD_FUNC) ( int , int ) ;int main(){HMODULE hMod = LoadLibrary( "TestDll.dll") ;if( hMod ){ADD_FUNC add_funcPointer = ( ADD_FUNC )GetProcAddress( hMod , "add" ) ;if( add_funcPointer ){printf( "%d\n" , add_funcPointer( 7 , 8 ) ) ;}FreeLibrary( hMod ) ;}// printf( "%d\n" , add( 7 , 8 ) ) ;return 0 ;}



0 0
原创粉丝点击