一个Win32 C++ 动态连接库的模板
cheungmine
一般情形下,使用C++编写动态库(DLL),在方法参数中不能输出STL对象类型, 如 std::string,这给我们的工作带来极大的麻烦。我参考一些资料,写了个C++ DLL模板,专门解决了这个问题。
使用VS2003新建一个Win32 DLL工程——DllCppTmpl,选择空项目,即什么也不自动创建。然后把下面2个文件加入到你的工程中,编译之。
文件1:DllCppTmpl.h
//
//DllCppTmpl.h-Win32CPPDllTemplate
//cheungmine
//underlicenceBSD
//2007
//
#ifndef_DLLCPPTMPL_H_
#define_DLLCPPTMPL_H_
//
//DllExport
//
#ifdefDLLCPPTMPL_DLLEXPORT
#defineDLLCPPTMPL_DLL__declspec(dllexport)
#elifdefined(DLLCPPTMPL_IMPORTS)
#defineDLLCPPTMPL_DLL__declspec(dllimport)
#else
#defineDLLCPPTMPL_DLL
#endif
//
//公共头文件
//
#include<string>
usingnamespacestd;
#include<new>//fornew_handler
#defineDLLCPPTMPL_API__cdecl
typedefvoid*(DLLCPPTMPL_API*PtrNew)(size_t);
typedefvoid(DLLCPPTMPL_API*PtrDelete)(void*);
typedefvoid(DLLCPPTMPL_API*PtrGetNewAndDelete)(PtrNew&,PtrDelete&);
typedefnew_handler(DLLCPPTMPL_API*PtrSetNewHandler)(new_handler);
typedefvoid(DLLCPPTMPL_API*PtrSetNewAndDelete)(PtrNew,PtrDelete,PtrSetNewHandler);
//
//DLLCPPTMPL_IMPORTS
//
#ifdefDLLCPPTMPL_IMPORTS
#ifdef_DLL
//causeCRTDLLtobeinitializedbeforeCrypto++sothatwecanusemallocandfreeduringDllMain()
#ifdefNDEBUG
#pragmacomment(lib,"msvcrt")
#else
#pragmacomment(lib,"msvcrtd")
#endif
#endif
#if!(defined(_MSC_VER)&&(_MSC_VER<1300))
usingstd::new_handler;
#endif

//WhenDllCppTmplattachestoanewprocess,itsearchesallmodulesloaded
//intotheprocessspaceforexportedfunctions"GetNewAndDeleteFor_DllCppTmpl"
//and"SetNewAndDeleteFrom_DllCppTmpl".Ifoneofthesefunctionsisfound,
//Crypto++usesmethods1or2,respectively,bycallingthefunction.
//Otherwise,method3isused.
staticPtrNew_s_pNew=NULL;
staticPtrDelete_s_pDelete=NULL;
extern"C"__declspec(dllexport)void__cdeclSetNewAndDeleteFrom_DllCppTmpl(PtrNewpNew,PtrDeletepDelete,PtrSetNewHandlerpSetNewHandler)
...{
_s_pNew=pNew;
_s_pDelete=pDelete;
}
void*__cdecloperatornew(size_tsize)
...{
return_s_pNew(size);
}
void__cdecloperatordelete(void*p)
...{
_s_pDelete(p);
}
#endif//DLLCPPTMPL_IMPORTS

//
//DLL接口方法
//
namespaceDllCppTmpl
...{
voidDLLCPPTMPL_DLLTest1(constchar*in,char**out);
voidDLLCPPTMPL_DLLTest2(conststring&in,string&out);
};//Canbeignored!
/**///////////////////////////////////////////////////////////////////////////////////
#endif/*ndef_DLLCPPTMPL_H_*/
文件2:DllCppTmpl.cpp
#defineDLLCPPTMPL_DLLEXPORT__declspec(dllexport)
#include"DllCppTmpl.h"
#include<string.h>
#include<iostream>
#include<time.h>
#include<windows.h>

#if(_MSC_VER>=1000)
#include<crtdbg.h>//forthedebugheap
#endif


/**/////////////////////////////////////////////////////
//如果使用动态库:DllCppTmpl
usingnamespaceDllCppTmpl;
//
//DLL标准输出
//
#ifdefDLLCPPTMPL_EXPORTS
#if!(defined(_MSC_VER)&&(_MSC_VER<1300))
usingstd::new_handler;
usingstd::set_new_handler;
#endif
void_CallNewHandler()
...{
new_handlernewHandler=set_new_handler(NULL);
if(newHandler)
set_new_handler(newHandler);
if(newHandler)
newHandler();
else
throwstd::bad_alloc();
}
staticPtrNew_s_pNew=NULL;
staticPtrDelete_s_pDelete=NULL;
staticvoid*New(size_tsize)
...{
void*p;
while(!(p=malloc(size)))
_CallNewHandler();
returnp;
}
staticvoidSetNewAndDeleteFunctionPointers()
...{
void*p=NULL;
HMODULEhModule=NULL;
MEMORY_BASIC_INFORMATIONmbi;
while(true)
...{
VirtualQuery(p,&mbi,sizeof(mbi));
if(p>=(char*)mbi.BaseAddress+mbi.RegionSize)
break;
p=(char*)mbi.BaseAddress+mbi.RegionSize;
if(!mbi.AllocationBase||mbi.AllocationBase==hModule)
continue;
hModule=HMODULE(mbi.AllocationBase);
PtrGetNewAndDeletepGetNewAndDelete=(PtrGetNewAndDelete)GetProcAddress(hModule,"GetNewAndDeleteFor_DllCppTmpl");
if(pGetNewAndDelete)
...{
pGetNewAndDelete(_s_pNew,_s_pDelete);
return;
}
PtrSetNewAndDeletepSetNewAndDelete=(PtrSetNewAndDelete)GetProcAddress(hModule,"SetNewAndDeleteFrom_DllCppTmpl");
if(pSetNewAndDelete)
...{
_s_pNew=&New;
_s_pDelete=&free;
pSetNewAndDelete(_s_pNew,_s_pDelete,&set_new_handler);
return;
}
}
hModule=GetModuleHandle("msvcrtd");
if(!hModule)
hModule=GetModuleHandle("msvcrt");
if(hModule)
...{
_s_pNew=(PtrNew)GetProcAddress(hModule,"??2@YAPAXI@Z");//operatornew
_s_pDelete=(PtrDelete)GetProcAddress(hModule,"??3@YAXPAX@Z");//operatordelete
return;
}
OutputDebugString("DllCppTmplwasnotabletoobtainnewanddeletefunctionpointers. ");
throw0;
}
void*operatornew(size_tsize)
...{
if(!_s_pNew)
SetNewAndDeleteFunctionPointers();
return_s_pNew(size);
}
voidoperatordelete(void*p)
...{
_s_pDelete(p);
}
void*operatornew[](size_tsize)
...{
returnoperatornew(size);
}
voidoperatordelete[](void*p)
...{
operatordelete(p);
}
#endif//#ifdefDLLCPPTMPL_EXPORTS


/**//////////////////////////////////////////
//Test
voidDLLCPPTMPL_DLLDllCppTmpl::Test1(constchar*in,char**out)
...{
*out=newchar[strlen(in)+20];
strcpy(*out,"Hello");
strcat(*out,in);
}
voidDLLCPPTMPL_DLLDllCppTmpl::Test2(conststring&in,string&out)
...{
out="hello";
out+=in;
}
好了,开始写客户端。建一个Win32 console项目,如下:
//testDllCppTmpl.cpp:定义控制台应用程序的入口点。
//
#include"stdafx.h"
#include<windows.h>
#defineDLLCPPTMPL_IMPORTS//必须定义在前
#include"../DllCppTmpl/DllCppTmpl.h"
#pragmacomment(lib,"../DllCppTmpl/Debug/DllCppTmpl.lib")

/**///////////////////////////////////////////////////////////////////////
usingnamespaceDllCppTmpl;
/**/////////////////////////////////////////////////////////
int_tmain(intargc,_TCHAR*argv[])
...{
charin[]="cheungmine";
char*out=0;
DllCppTmpl::Test1(in,&out);
printf("Test1:%s ",out);
deleteout;

stringin2="cheungmine";
stringout2;
DllCppTmpl::Test2(in2,out2);
printf("Test2:%s ",out2.c_str());

return0;
}
本文介绍了一个C++动态链接库(DLL)的模板,该模板解决了在DLL方法参数中使用STL对象(如std::string)的问题。通过此模板,开发者可以更方便地在DLL中处理字符串和其他STL类型。
1015

被折叠的 条评论
为什么被折叠?



