一个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_
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
//
DllExport
//
#ifdefDLLCPPTMPL_DLLEXPORT
#define
DLLCPPTMPL_DLL__declspec(dllexport)
#elif
defined(DLLCPPTMPL_IMPORTS)
#define
DLLCPPTMPL_DLL__declspec(dllimport)
#else
#define
DLLCPPTMPL_DLL
#endif
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
//
公共头文件
//
#include
<
string
>
using
namespace
std;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#include
<
new
>
//
fornew_handler
#define
DLLCPPTMPL_API__cdecl
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
typedef
void
*
(DLLCPPTMPL_API
*
PtrNew)(size_t);
typedef
void
(DLLCPPTMPL_API
*
PtrDelete)(
void
*
);
typedef
void
(DLLCPPTMPL_API
*
PtrGetNewAndDelete)(PtrNew
&
,PtrDelete
&
);
typedefnew_handler(DLLCPPTMPL_API
*
PtrSetNewHandler)(new_handler);
typedef
void
(DLLCPPTMPL_API
*
PtrSetNewAndDelete)(PtrNew,PtrDelete,PtrSetNewHandler);
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
//
DLLCPPTMPL_IMPORTS
//
#ifdefDLLCPPTMPL_IMPORTS
#ifdef_DLL
//
causeCRTDLLtobeinitializedbeforeCrypto++sothatwecanusemallocandfreeduringDllMain()
#ifdefNDEBUG
#pragma
comment(lib,"msvcrt")
#else
#pragma
comment(lib,"msvcrtd")
#endif
#endif
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#if
!(defined(_MSC_VER)&&(_MSC_VER<1300))
using
std::new_handler;
#endif
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
WhenDllCppTmplattachestoanewprocess,itsearchesallmodulesloaded
//
intotheprocessspaceforexportedfunctions"GetNewAndDeleteFor_DllCppTmpl"
//
and"SetNewAndDeleteFrom_DllCppTmpl".Ifoneofthesefunctionsisfound,
//
Crypto++usesmethods1or2,respectively,bycallingthefunction.
//
Otherwise,method3isused.
static
PtrNew_s_pNew
=
NULL;
static
PtrDelete_s_pDelete
=
NULL;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
extern
"
C
"
__declspec(dllexport)
void
__cdeclSetNewAndDeleteFrom_DllCppTmpl(PtrNewpNew,PtrDeletepDelete,PtrSetNewHandlerpSetNewHandler)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
_s_pNew=pNew;
_s_pDelete=pDelete;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
*
__cdecl
operator
new
(size_tsize)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
return_s_pNew(size);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
__cdecl
operator
delete(
void
*
p)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
_s_pDelete(p);
}
#endif
//
DLLCPPTMPL_IMPORTS
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
//
DLL接口方法
//
namespace
DllCppTmpl
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
voidDLLCPPTMPL_DLLTest1(constchar*in,char**out);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
voidDLLCPPTMPL_DLLTest2(conststring&in,string&out);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
;
//
Canbeignored!
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
/**/
//
#endif
/*ndef_DLLCPPTMPL_H_*/
文件2:DllCppTmpl.cpp
#define
DLLCPPTMPL_DLLEXPORT__declspec(dllexport)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#include
"
DllCppTmpl.h
"
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#include
<
string
.h
>
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#include
<
iostream
>
#include
<
time.h
>
#include
<
windows.h
>
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#if
(_MSC_VER>=1000)
#include
<
crtdbg.h
>
//
forthedebugheap
#endif
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
/**/
////
//
如果使用动态库:DllCppTmpl
using
namespace
DllCppTmpl;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
//
DLL标准输出
//
#ifdefDLLCPPTMPL_EXPORTS
#if
!(defined(_MSC_VER)&&(_MSC_VER<1300))
using
std::new_handler;
using
std::set_new_handler;
#endif
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
_CallNewHandler()
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
new_handlernewHandler=set_new_handler(NULL);
if(newHandler)
set_new_handler(newHandler);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
if(newHandler)
newHandler();
else
throwstd::bad_alloc();
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
static
PtrNew_s_pNew
=
NULL;
static
PtrDelete_s_pDelete
=
NULL;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
static
void
*
New(size_tsize)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
void*p;
while(!(p=malloc(size)))
_CallNewHandler();
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
returnp;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
static
void
SetNewAndDeleteFunctionPointers()
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
void*p=NULL;
HMODULEhModule=NULL;
MEMORY_BASIC_INFORMATIONmbi;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
while(true)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
VirtualQuery(p,&mbi,sizeof(mbi));
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
if(p>=(char*)mbi.BaseAddress+mbi.RegionSize)
break;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
p=(char*)mbi.BaseAddress+mbi.RegionSize;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
if(!mbi.AllocationBase||mbi.AllocationBase==hModule)
continue;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
hModule=HMODULE(mbi.AllocationBase);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
PtrGetNewAndDeletepGetNewAndDelete=(PtrGetNewAndDelete)GetProcAddress(hModule,"GetNewAndDeleteFor_DllCppTmpl");
if(pGetNewAndDelete)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
pGetNewAndDelete(_s_pNew,_s_pDelete);
return;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
PtrSetNewAndDeletepSetNewAndDelete=(PtrSetNewAndDelete)GetProcAddress(hModule,"SetNewAndDeleteFrom_DllCppTmpl");
if(pSetNewAndDelete)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
_s_pNew=&New;
_s_pDelete=&free;
pSetNewAndDelete(_s_pNew,_s_pDelete,&set_new_handler);
return;
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
hModule=GetModuleHandle("msvcrtd");
if(!hModule)
hModule=GetModuleHandle("msvcrt");
if(hModule)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
_s_pNew=(PtrNew)GetProcAddress(hModule,"??2@YAPAXI@Z");//operatornew
_s_pDelete=(PtrDelete)GetProcAddress(hModule,"??3@YAXPAX@Z");//operatordelete
return;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
OutputDebugString("DllCppTmplwasnotabletoobtainnewanddeletefunctionpointers. ");
throw0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
*
operator
new
(size_tsize)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
if(!_s_pNew)
SetNewAndDeleteFunctionPointers();
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
return_s_pNew(size);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
operator
delete(
void
*
p)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
_s_pDelete(p);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
*
operator
new
[](size_tsize)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
returnoperatornew(size);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
operator
delete[](
void
*
p)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
operatordelete(p);
}
#endif
//
#ifdefDLLCPPTMPL_EXPORTS
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
/**/
/////
//
Test
void
DLLCPPTMPL_DLLDllCppTmpl::Test1(
const
char
*
in
,
char
**
out
)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
*out=newchar[strlen(in)+20];
strcpy(*out,"Hello");
strcat(*out,in);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
DLLCPPTMPL_DLLDllCppTmpl::Test2(
const
string
&
in
,
string
&
out
)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
out="hello";
out+=in;
}
好了,开始写客户端。建一个Win32 console项目,如下:
//
testDllCppTmpl.cpp:定义控制台应用程序的入口点。
//
#include
"
stdafx.h
"
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#include
<
windows.h
>
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#define
DLLCPPTMPL_IMPORTS
//
必须定义在前
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#include
"
../DllCppTmpl/DllCppTmpl.h
"
#pragma
comment(lib,"../DllCppTmpl/Debug/DllCppTmpl.lib")
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
/**/
//
using
namespace
DllCppTmpl;
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
/**/
////
int
_tmain(
int
argc,_TCHAR
*
argv[])
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
charin[]="cheungmine";
char*out=0;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
DllCppTmpl::Test1(in,&out);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
printf("Test1:%s ",out);
deleteout;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
stringin2="cheungmine";
stringout2;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
DllCppTmpl::Test2(in2,out2);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
printf("Test2:%s ",out2.c_str());
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
return0;
}
注意路径的正确,和DllCppTmpl.dll要放到system32下。