1.前面有介绍动态链接库和静态链接库。
静态链接库:创建和使用静态库(.lib)
隐式调用dll:VS2008创建DLL,并且使用DLL
2.现在主要讲解下显示调用dll,并且结合共享内存
共享内存:C/C++ 日常学习总结(第二十二篇)共享内存实现C++
3.显示调用
这种调用需要调用::LoadLibrary()或者类似的函数,用来动态加载链接库,再使用GetProcAddress()获得要调用的每个函数的函数指针,使用完毕,调用FreeLibrary()卸载dll,
这种方式的调用不需要*.lib文件,也不需要*.h文件。但是必须要知道要调用函数的函数原型,以便为GetProcAddress()的返回值定义相应的函数指针。
创建dll就不用多说,上面链接有介绍。
(1.)Memdll.dll中函数原型:
struct SData
{
int num;
int age;
char name[128];
};
extern "C" __declspec (dllexport) void WriteDataToMem(SData &data,LPCWSTR name)
{
HANDLE hfilemap = NULL;
hfilemap = ::CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,65536,name);
if (NULL==hfilemap)
{
return;
}
PVOID pview = NULL;
pview = ::MapViewOfFile(hfilemap,FILE_MAP_ALL_ACCESS,0,0,1024);
if (NULL==pview)
{
return;
}
memcpy_s(pview,1024,(&data),sizeof(SData));
}
extern "C" __declspec (dllexport) SData* ReadDataFromMem(LPCWSTR name)
{
HANDLE hfilemap = NULL;
hfilemap = ::OpenFileMapping(FILE_MAP_READ,FALSE,name);
if (NULL==hfilemap)
{
return NULL;
}
PVOID pview = NULL;
pview = ::MapViewOfFile(hfilemap,FILE_MAP_READ,0,0,1024);
if (NULL == pview)
{
return NULL;
}
SData *data = (SData*)pview;
return data;
}
(2.)应用程序中的调用:
struct SData
{
int num;
int age;
char name[128];
};
typedef void (*WriteDataToMem)(SData &data,LPCWSTR name);
typedef SData* (*ReadDataFromMem)(LPCWSTR name);
结构体原型是必须和dll文件中相同,然后是定义函数指针,也就是事先必须知道函数原型的原因。 形参不可少。
int main()
{
WriteDataToMem _write;
ReadDataFromMem _read;
hmodule = ::LoadLibrary("MemDll.dll");
if (NULL==hmodule)
{
::FreeLibrary(hmodule);
return 0;
}
_write = (WriteDataToMem)GetProcAddress(hmodule,"WriteDataToMem");
if (NULL==_write)
{
return 0;
}
SData data;
data.age = 100;
data.num = 8080;
strcpy(data.name,"周杰伦");
LPCWSTR name = (LPCWSTR)("password");
_write(data,name);
_read = (ReadDataFromMem)GetProcAddress(hmodule,"ReadDataFromMem");
if (NULL==_read)
{
return 0;
}
SData *dataout = NULL;
dataout = _read(name);
return 0;
}
【说明】:共享内存用于进程之间,上述代码只为了测试方便,写在了同一个进程内。
上面main函数中,先加载dll,然后获得函数指针,然后直接调用即可。