48.编写DLL动态链接库__declspec(dllexport)、DllMain生成xxx.dll、xxx.lib和xxx.h、LoadLibrary、GetProcessAddress、Free

自己编写DLL动态链接库文件
入加函数和出口函数
int WINAPI DllMain(HINSTANCE hInstance,DWORD fdwReason,PVOID pReason)
fdwReason的几个case的情况:

#define DLL_PROCESS_ATTACH 1     //调用进程时
#define DLL_THREAD_ATTACH  2     //调用线程时
#define DLL_THREAD_DETACH  3    //释放线程时
#define DLL_PROCESS_DETACH 0   //释放进程时

需要把调用方式要说明,是用C调用方式还是CPP调用方式
#ifdef __cplusplus //C++方式调用,需要用C的方式
#define EXPORT extern “C” __declspec(dllexport)
#else
#define EXPORT __declspec(dllexport)
#endif
其中extern "C"是C调用函数的方式,保证这个函数使用C方法进行调用
__declspec(dllexport) 的解释
在 32 位编译器版本中,可以使用 __declspec(dllexport) 关键字从 DLL 导出数据、函数、类或类成员函数。
__declspec(dllexport) 将导出指令添加到对象文件

若要导出函数,__declspec(dllexport) 关键字必须出现在调用约定关键字的左边(如果指定了关键字)。例如:

__declspec(dllexport) void __cdecl Function1(void);
若要导出类中的所有公共数据成员和成员函数,关键字必须出现在类名的左边,如下所示:

class __declspec(dllexport) CExampleExport : public CObject
{ … class definition … };
生成 DLL 时,通常创建一个包含正在导出的函数原型和/或类的头文件,并将 __declspec(dllexport) 添加到头文件中的声明。若要提高代码的可读性,请为 __declspec(dllexport) 定义一个宏并对正在导出的每个符号使用该宏:

#define EXORT __declspec( dllexport )
__declspec(dllexport) 将函数名存储在 DLL 的导出表中。

如何调用DLL文件,如果其他程序调用DLL文件时需要准备
xxx.lib
xxx.h
xxx.dll
以上三个文件拷贝到项目目录下
48.编写DLL动态链接库__declspec(dllexport)、DllMain生成xxx.dll、xxx.lib和xxx.h、LoadLibrary、GetProcessAddress、Free_第1张图片
在编译器中也要添加库文件
48.编写DLL动态链接库__declspec(dllexport)、DllMain生成xxx.dll、xxx.lib和xxx.h、LoadLibrary、GetProcessAddress、Free_第2张图片
至于函数的A版(UNICODE)和W版(!UNICODE),这个就不细说了。

以上是静态的方法,动态方法是:
Loadlibrary 加载动太链接库

WINBASEAPI
__out_opt
HMODULE
WINAPI
LoadLibraryW(
    __in LPCWSTR lpLibFileName //加载文件路径
    );
#ifdef UNICODE
#define LoadLibrary  LoadLibraryW
#else
#define LoadLibrary  LoadLibraryA
#endif // !UNICODE

GetProcAddress 取得函数入口地址
返回参数 Module 指定的模块中,由参数 ProcName 指定的过程或函数的入口地址。

WINBASEAPI
FARPROC
WINAPI
GetProcAddress (
    __in HMODULE hModule, //由LoadLibrary函数产生的句柄
    __in LPCSTR lpProcName //函数名
    );

FreeLibrary 卸载加载的dll动态链接库

WINBASEAPI
BOOL
WINAPI
FreeLibrary (
    __in HMODULE hLibModule
    );

创建ADDPlus.h文件

//ADDPlus.h
#ifndef _ADDPLUS_H_
#define _ADDPLUS_H_

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

	EXPORT DWORD CALLBACK add_zcm(DWORD dwa,DWORD dwb);
	EXPORT LPWSTR CALLBACK pt_zcmW(DWORD dwa,DWORD dwb,LPWSTR szStr,DWORD dwSize);
	EXPORT LPSTR CALLBACK pt_zcmA(DWORD dwa,DWORD dwb,LPSTR szStr,DWORD dwSize);
	EXPORT VOID CALLBACK showmsgA(LPSTR szmsg);
	EXPORT VOID CALLBACK showmsgW(LPWSTR szmsg);

	#ifdef UNICODE
		#define pt_zcm	pt_zcmW
		#define showmsg showmsgW
	#else
		#define pt_zcm	pt_zcmA
		#define showmsg showmsgW
	#endif

#endif



创建ADDPlus.cpp文件

// ADDPlus.cpp
#include 
#include "ADDPlus.h"

int WINAPI DllMain(HINSTANCE hInstance,DWORD fdwReason,PVOID pvReason)
{
	BOOL bRet = true;
	switch(fdwReason)
	{
	case DLL_PROCESS_ATTACH:
		MessageBox(NULL,TEXT("DLL_PROCESS_ATTACH"),TEXT("process start"),MB_OK);
		break;
	case DLL_THREAD_ATTACH:
		MessageBox(NULL,TEXT("DLL_THREAD_ATTACH"),TEXT("thread start"),MB_OK);
		break;

	case DLL_THREAD_DETACH:
		MessageBox(NULL,TEXT("DLL_PROCESS_DETACH"),TEXT("thread start"),MB_OK);
		break;
	case DLL_PROCESS_DETACH:
		MessageBox(NULL,TEXT("DLL_PROCESS_DETACH"),TEXT("thread start"),MB_OK);
		break;
	default:
		bRet = false;
		break;
	}
	return bRet;
}

EXPORT DWORD CALLBACK add_zcm(DWORD dwa,DWORD dwb)
{
	return dwa+dwb;
}

EXPORT LPWSTR CALLBACK pt_zcmW(DWORD dwa,DWORD dwb,LPWSTR szStr,DWORD dwSize)
{
	wsprintfW(szStr,TEXT("CALLBACK DLL:%d + %d = %d\n"),dwa,dwb,add_zcm(dwa,dwb));
	return szStr;
}

EXPORT LPSTR CALLBACK pt_zcmA(DWORD dwa,DWORD dwb,LPSTR szStr,DWORD dwSize)
{
	wsprintfA(szStr,"CALLBACK DLL:%d + %d = %d\n",dwa,dwb,add_zcm(dwa,dwb));
	return szStr;
}

EXPORT VOID CALLBACK showmsgA(LPSTR szmsg)
{
	MessageBoxA(NULL,szmsg,"test",MB_OK);
	return ;
}

EXPORT VOID CALLBACK showmsgW(LPWSTR szmsg)
{
	MessageBoxW(NULL,szmsg,L"test",MB_OK);
	return ;
}

以下是动态使用加载的DLL

#include 
#include "resource.h"
HINSTANCE hLibrary;
typedef VOID(*SHOWMSG)(LPWSTR szStr);


INT_PTR CALLBACK DlgMainProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
	BOOL bRet = true;
	DWORD wmId = LOWORD(wParam);
	DWORD wmEvent = HIWORD(wParam);
	SHOWMSG showmsgW;
	


	switch(uMsg)
	{
	case WM_COMMAND:
		switch(wmId)
		{
		case IDC_BUTTON1:
			hLibrary = LoadLibrary(TEXT("ADDPlus.dll"));
			break;
		case IDC_BUTTON2:
			showmsgW = (SHOWMSG)GetProcAddress((HMODULE)hLibrary,("showmsgW"));
			if(!showmsgW)
			{
				MessageBox(hWnd,TEXT("GetProcAddress Error"),TEXT("Error"),MB_OK);
			}
			else
			{
				showmsgW(L"你好,单于先生!");
			}
			
			break;
		case IDC_BUTTON3:
			FreeLibrary(hLibrary);
			break;
		case IDC_BUTTON4:
			EndDialog(hWnd,0);
			break;
		default:
			return DefWindowProc(hWnd,uMsg,wParam,lParam);
			break;
		}
		break;
	case WM_CLOSE:
		EndDialog(hWnd,0);
		break;

	default:
		bRet = false;
		break;
	}
	

	return bRet;
}

int APIENTRY WinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR szCmdLine,
	int nCmdShow)
{
	DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),NULL,(DLGPROC)DlgMainProc);
	return 0;
}

你可能感兴趣的:(win32,API)