天末凉风

有梦最美,希望相随!

导航

win32 dll 的编写

  一般来说,DLL是一种磁盘文件(通常带有DLL扩展名),它由全局数据、服务函数和资源组成,在运行时被系统加载到进程的虚拟空间中,成为调用进程的一 部分。如果与其它DLL之间没有冲突,该文件通常映射到进程虚拟空间的同一地址上。DLL模块中包含各种导出函数,用于向外界提供服务。Windows在 加载DLL模块时将进程函数调用与DLL文件的导出函数相匹配。 
在Win32环境中,每个进程都复制了自己的读/写全局变量。如果想要与其它进程共享内存,必须使用内存映射文件或者声明一个共享数据段。DLL模块需要的堆栈内存都是从运行进程的堆栈中分配出来的。

//----testdll.h

#ifdef  __cplusplus
#define EXPORT extern "C" __declspec(dllexport)
#else
#define EXPORT __declspec(dllexport)
#endif


//----testdll.cpp
#include "test.h"
#include <Windows.h>

int WINAPI DllMain(HINSTANCE hin,DWORD fdwReason,PVOID pvReserved)
{
return TRUE;
}

//用到头文件里的宏定义 EXPORT
EXPORT int _stdcall add(int i,int j)
{
return i+j;
}

/*此函数通过DEF文件导出,不会发生名字改编*/
int add1(int a,int b) 
{
return a+b;
}

/*此函数通过DEF文件导出,不会发生名字改编
此函数的调用方式为_stdcall
*/
int __stdcall add2(int a,int b)
{
return a+b;
}
/*此函数通过关键字__declspec(dllexport)导出,会发生函数名的变化*/
__declspec(dllexport)  int add3(int a,int b)
{
return a+b;
}
/*此函数通过关键字__declspec(dllexport)导出,但由于使用了
extern "C",所以不会发生函数名的变化*/
extern "C" __declspec(dllexport)  int add4(int a,int b)
{
return a+b;
}

/*此函数通过关键字__declspec(dllexport)导出,尽管使用了extern "C",
但是函数的调用方式改为了__stdcall,所以还是会发生函数名改编*/
extern "C" __declspec(dllexport)  int __stdcall add5(int a,int b)
{
return a+b;
}


testdll.def文件:

LIBRARY testdll

EXPORTS
add1
add2

可以只有testdll.cpp文件,也可以添加上testdll.h或者testdll.def文件,视不同需要而定。

 

调用方法:

void CDllTestDlg::OnAdd1()
{
/*----------------动态加载动态连接库----------------------*/

 HINSTANCE hInst=::LoadLibrary("Dll2.dll");
if(hInst)
{
typedef int (*ADD)(int,int); //定义一个函数指针类型
ADD pAdd=(ADD)::GetProcAddress(hInst,"add1");
if(pAdd)
{
CString str;
str.Format("5+3=%d",pAdd(5,3));
MessageBox(str);
}

       ::FreeLibrary(hInst);
}
}

第2个导出函数的调用:
typedef int (__stdcall *ADD)(int,int); //定义一个函数指针类型
ADD pAdd=(ADD)::GetProcAddress(hInst,"add2");

第3个导出函数的调用:
typedef int (*ADD)(int,int); //定义一个函数指针类型
ADD pAdd=(ADD)::GetProcAddress(hInst,"?add3@@YAHHH@Z");
//或者:ADD pAdd=(ADD)::GetProcAddress(hInst,MAKEINTRESOURCE(3));

第4个导出函数的调用:
typedef int (*ADD)(int,int); //定义一个函数指针类型
ADD pAdd=(ADD)::GetProcAddress(hInst,"add4");

第5个导出函数的调用:
typedef int (__stdcall *ADD)(int,int); //定义一个函数指针类型
ADD pAdd=(ADD)::GetProcAddress(hInst,"_add5@8");

 

以上是动态加载dll. 以下是静态加载的方法:

/*------------------声明导入函数的方法----------------*/
#pragma comment(lib,"Dll1.lib")

/*
方法一:直接写出dll中函数的声明
int add(int a,int b); 
int sub(int a,int b);

方法二:通过关键字__declspec(dllimport)这种方法能够编译出效率更高的代码
__declspec(dllimport)  int add(int a,int b);
__declspec(dllimport)  int sub(int a,int b);

方法三:直接包含dll的头文件 */
#include "Dll1.h"
/*---------------------------------------------------------*/

然后直接调用dll中的函数:
void CDllTestDlg::OnAdd()
{
CString str;
str.Format("1+2=%d",add(1,2));
MessageBox(str); 
}

posted on 2009-08-13 00:31  天末凉风  阅读(578)  评论(0)    收藏  举报