轻松使用DLL
关于DLL, 有位仁兄写了几点(http://www.cppblog.com/johndragon/archive/2007/04/17/22159.html),正好我的做法不谋而合,我一直就是按照这几个原则来进行的。其实DLL用起来是很简单的,而且好处很多。下面举一个简单的例子。
(1)首先定义接囗文件,一般有两种做法,一种是采取纯虚类,一种是pimp手法,我倾向于前者。
文件名设为 test.h
// test.h
#pragma once
class Test {
public:
virtual ~Test() {}
virtual void DoIt() =0;
};
就这么多,把你想要的接口加进去,但是不要有其它的东西,与实现有关的东西都放在实现文件test.cpp中
(2)实现文件test.cpp,其中实现两个东西,一个是接口,一个是对象的创建。实现如下
// test.cpp : Defines the entry point for the DLL application.
//
#include <windows.h>
#include "boost/shared_ptr.hpp"
#include "test.h"
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
return TRUE;
}
class CTest : public Test
{
public:
virtual void DoIt()
{ printf("Should do something/n"); }
};
extern "C" __declspec(dllexport)
boost::shared_ptr<Test> CreateTest()
{ return boost::shared_ptr<Test>(new CTest); }
到这里,OK,搞定!这里用了boost:::shared_ptr,否则你要export两个函数:一个Create,一个Release,同时还得小心翼翼得使用它们,用shared_ptr,可以使一切得到简化。
现在,编译,生成test.dll,把它拷到合适的目录下。
(3)客户程序
生成的 dll 能不能用呢?现在测试一下。
对于open ,close成双结对的函数,我习惯性的使用对象封装。
class Library
{
public:
explicit Library(const char* name)
{
m_handle = LoadLibrary(name);
assert(m_handle);
if (!m_handle)
throw std::runtime_error(std::string("Could not find library file:") + name);
}
~Library()
{
FreeLibrary(m_handle);
}
void* GetProc(const char* name)
{
void* proc = ::GetProcAddress(m_handle, name);
assert(proc);
return proc;
}
private:
HMODULE m_handle;
};
下面是main 的实现
#include "test.h" // 这个是刚才的接口文件
#include "boost/shared_ptr.hpp"
using boost::shared_ptr;
int main(int argc, char* argv[])
{
Library lib("test.dll");
shared_ptr<Test> test = ((shared_ptr<Test> (*)()) lib.GetProc("CreateTest"))();
test->DoIt();
return 0;
}
就是这些. That's all!
注: 对 MSVC 的 bug 修正见评论.
更多技术文章请参看施昌权的个人网站: http://www.joyvc.cn