Win32 下动态链接库 (DLL) 机制笔记
来自Jack's Lab
目录 |
1 准备
使用 VC++ 带的命令行编译器 cl 前,需用 "C:\Program Files\Microsoft Visual Studio 8\VC\vcvarsall.bat" 设置环境变量:
C:\> cd workspace\dll C:\workspace\dll> "C:\Program Files\Microsoft Visual Studio 8\VC\vcvarsall.bat"
2 DLL 导出简单 C 函数
simple.cc:
#include <stdio.h>
#ifdef __cplusplus // If used by C++ code,
extern "C" { // we need to export the C interface
#endif
__declspec(dllexport) int myPuts(char *lpszMsg)
{
printf("%s\n", lpszMsg);
return 1;
}
#ifdef __cplusplus
}
#endif
编译生成 DLL:
cl /LD /Fesimple.dll simple.cc
选项 /LD 告诉编译器创建 DLL
完了会生成 simple.dll simple.lib
3 加载时动态链接测试
#include <windows.h>
int myPuts(char *str); // a function from a DLL
int main(VOID)
{
int Ret = 1;
Ret = myPuts("Using the DLL function, HaHaHaHa, Tutututu\n");
return Ret;
}
以上保存为 load.time.link.c
编译之:
cl /Feload.time.link.exe load.time.link.c simple.lib
simple.lib 为 simple.dll 对应的 import library,链接时为链接器 link.exe 所需要
4 运行时动态加载测试
#include <stdio.h>
#include <windows.h>
typedef int (*MYFUNC)(char *);
VOID main(VOID)
{
HINSTANCE hinstLib;
MYFUNC ProcAdd;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;
//用 LoadLibrary() 加载 simple.dll
hinstLib = LoadLibrary(TEXT("simple"));
// If the handle is valid, try to get the function address.
if (hinstLib != NULL)
{
//用 GetProcAddress() 获取 DLL 中函数地址
ProcAdd = (MYPROC) GetProcAddress(hinstLib, TEXT("myPuts"));
// If the function address is valid, call the function.
if (NULL != ProcAdd)
{
fRunTimeLinkSuccess = TRUE;
(ProcAdd) (TEXT("Message via DLL function, HaHaHa, TUTUTUTUTU\n"));
}
// Free the DLL module.
fFreeResult = FreeLibrary(hinstLib);
}
if (! fRunTimeLinkSuccess)
printf("Load DLL failed\n");
}
存为 run.time.link.c,如下命令编译之:
cl /Ferun.time.link.exe run.time.link.c
5 DLL 中导出C++ 类
与导出 C 风格的函数类似,在定义类时用 __declspec(dllexport):
class __declspec(dllexport) MyCppClass
{
......
};
编译时,依然用:
cl /Fesimple.dll /LD smiple.cc
加载时动态链接,则要在使用前加 __declspec(dllimport) 声明之:
class __declspec(dllimport) MyCppClass;
如下所示列:
----------
comcat.h:
----------
#ifndef _MY_CMATH_H_
#define _MY_CMATH_H_
#ifdef _CLASS_INDLL_
#define _CLASS_DECL_ __declspec(dllexport)
#else
#define _CLASS_DECL_ __declspec(dllimport)
#endif
class _CLASS_DECL_ CMath
{
public:
int Add(int a,int b);
CMath();
~CMath(){};
};
#endif
comcat.cc:
#include "comcat.h"
CMath::CMath()
{
};
int CMath::Add(int a, int b)
{
return a + b;
}
如下命令生成 DLL:
cl /LD /Fecomcat.dll /D_CLASS_INDLL_ comcat.cc
6 加载时动态链接测试
class.load.test.cc
#include "comcat.h"
#include <iostream>
int main()
{
CMath *cm = new CMath;
std::cout << "cmath's result:" << cm->Add(5, 8) << std::endl;
return 0;
}
如下命令编译之:
cl /Feclass.load.test.exe class.load.test.cc comcat.lib