自己编写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
以上三个文件拷贝到项目目录下
在编译器中也要添加库文件
至于函数的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;
}