一个Win32 C++ 动态连接库的模板 --- 调用方可管理DLL分配的内存
来源:互联网 发布:sql删除表中带约束的列 编辑:程序博客网 时间:2024/05/01 19:40
一个Win32 C++ 动态连接库的模板
cheungmine
一般情形下,使用C++编写动态库(DLL),在方法参数中不能输出STL对象类型, 如 std::string,这给我们的工作带来极大的麻烦。我参考一些资料,写了个C++ DLL模板,专门解决了这个问题。
使用VS2003新建一个Win32 DLL工程——DllCppTmpl,选择空项目,即什么也不自动创建。然后把下面2个文件加入到你的工程中,编译之。
文件1:DllCppTmpl.h
//
// DllCppTmpl.h - Win32 CPP Dll Template
// cheungmine
// under licence BSD
// 2007
//
#ifndef _DLLCPPTMPL_H_
#define _DLLCPPTMPL_H_
//
// DllExport
//
#ifdef DLLCPPTMPL_DLLEXPORT
#define DLLCPPTMPL_DLL __declspec(dllexport)
#elif defined(DLLCPPTMPL_IMPORTS)
#define DLLCPPTMPL_DLL __declspec(dllimport)
#else
#define DLLCPPTMPL_DLL
#endif
//
// 公共头文件
//
#include <string>
using namespace std;
#include <new> // for new_handler
#define DLLCPPTMPL_API __cdecl
typedef void * (DLLCPPTMPL_API * PtrNew)(size_t);
typedef void (DLLCPPTMPL_API * PtrDelete)(void *);
typedef void (DLLCPPTMPL_API * PtrGetNewAndDelete)(PtrNew &, PtrDelete &);
typedef new_handler (DLLCPPTMPL_API * PtrSetNewHandler)(new_handler);
typedef void (DLLCPPTMPL_API * PtrSetNewAndDelete)(PtrNew, PtrDelete, PtrSetNewHandler);
//
// DLLCPPTMPL_IMPORTS
//
#ifdef DLLCPPTMPL_IMPORTS
#ifdef _DLL
// cause CRT DLL to be initialized before Crypto++ so that we can use malloc and free during DllMain()
#ifdef NDEBUG
#pragma comment(lib, "msvcrt")
#else
#pragma comment(lib, "msvcrtd")
#endif
#endif
#if !(defined(_MSC_VER) && (_MSC_VER < 1300))
using std::new_handler;
#endif
// When DllCppTmpl attaches to a new process, it searches all modules loaded
// into the process space for exported functions "GetNewAndDeleteFor_DllCppTmpl"
// and "SetNewAndDeleteFrom_DllCppTmpl". If one of these functions is found,
// Crypto++ uses methods 1 or 2, respectively, by calling the function.
// Otherwise, method 3 is used.
static PtrNew _s_pNew = NULL;
static PtrDelete _s_pDelete = NULL;
extern "C" __declspec(dllexport) void __cdecl SetNewAndDeleteFrom_DllCppTmpl(PtrNew pNew, PtrDelete pDelete, PtrSetNewHandler pSetNewHandler)
...{
_s_pNew = pNew;
_s_pDelete = pDelete;
}
void * __cdecl operator new (size_t size)
...{
return _s_pNew(size);
}
void __cdecl operator delete (void * p)
...{
_s_pDelete(p);
}
#endif // DLLCPPTMPL_IMPORTS
//
// DLL接口方法
//
namespace DllCppTmpl
...{
void DLLCPPTMPL_DLL Test1(const char *in, char** out);
void DLLCPPTMPL_DLL Test2(const string& in, string& out);
}; // Can be ignored!
/**///////////////////////////////////////////////////////////////////////////////////
#endif /* ndef _DLLCPPTMPL_H_ */
// DllCppTmpl.h - Win32 CPP Dll Template
// cheungmine
// under licence BSD
// 2007
//
#ifndef _DLLCPPTMPL_H_
#define _DLLCPPTMPL_H_
//
// DllExport
//
#ifdef DLLCPPTMPL_DLLEXPORT
#define DLLCPPTMPL_DLL __declspec(dllexport)
#elif defined(DLLCPPTMPL_IMPORTS)
#define DLLCPPTMPL_DLL __declspec(dllimport)
#else
#define DLLCPPTMPL_DLL
#endif
//
// 公共头文件
//
#include <string>
using namespace std;
#include <new> // for new_handler
#define DLLCPPTMPL_API __cdecl
typedef void * (DLLCPPTMPL_API * PtrNew)(size_t);
typedef void (DLLCPPTMPL_API * PtrDelete)(void *);
typedef void (DLLCPPTMPL_API * PtrGetNewAndDelete)(PtrNew &, PtrDelete &);
typedef new_handler (DLLCPPTMPL_API * PtrSetNewHandler)(new_handler);
typedef void (DLLCPPTMPL_API * PtrSetNewAndDelete)(PtrNew, PtrDelete, PtrSetNewHandler);
//
// DLLCPPTMPL_IMPORTS
//
#ifdef DLLCPPTMPL_IMPORTS
#ifdef _DLL
// cause CRT DLL to be initialized before Crypto++ so that we can use malloc and free during DllMain()
#ifdef NDEBUG
#pragma comment(lib, "msvcrt")
#else
#pragma comment(lib, "msvcrtd")
#endif
#endif
#if !(defined(_MSC_VER) && (_MSC_VER < 1300))
using std::new_handler;
#endif
// When DllCppTmpl attaches to a new process, it searches all modules loaded
// into the process space for exported functions "GetNewAndDeleteFor_DllCppTmpl"
// and "SetNewAndDeleteFrom_DllCppTmpl". If one of these functions is found,
// Crypto++ uses methods 1 or 2, respectively, by calling the function.
// Otherwise, method 3 is used.
static PtrNew _s_pNew = NULL;
static PtrDelete _s_pDelete = NULL;
extern "C" __declspec(dllexport) void __cdecl SetNewAndDeleteFrom_DllCppTmpl(PtrNew pNew, PtrDelete pDelete, PtrSetNewHandler pSetNewHandler)
...{
_s_pNew = pNew;
_s_pDelete = pDelete;
}
void * __cdecl operator new (size_t size)
...{
return _s_pNew(size);
}
void __cdecl operator delete (void * p)
...{
_s_pDelete(p);
}
#endif // DLLCPPTMPL_IMPORTS
//
// DLL接口方法
//
namespace DllCppTmpl
...{
void DLLCPPTMPL_DLL Test1(const char *in, char** out);
void DLLCPPTMPL_DLL Test2(const string& in, string& out);
}; // Can be ignored!
/**///////////////////////////////////////////////////////////////////////////////////
#endif /* ndef _DLLCPPTMPL_H_ */
文件2:DllCppTmpl.cpp
#define DLLCPPTMPL_DLLEXPORT __declspec(dllexport)
#include "DllCppTmpl.h"
#include <string.h>
#include <iostream>
#include <time.h>
#include <windows.h>
#if (_MSC_VER >= 1000)
#include <crtdbg.h> // for the debug heap
#endif
/**/////////////////////////////////////////////////////
// 如果使用动态库: DllCppTmpl
using namespace DllCppTmpl;
//
// DLL标准输出
//
#ifdef DLLCPPTMPL_EXPORTS
#if !(defined(_MSC_VER) && (_MSC_VER < 1300))
using std::new_handler;
using std::set_new_handler;
#endif
void _CallNewHandler()
...{
new_handler newHandler = set_new_handler(NULL);
if (newHandler)
set_new_handler(newHandler);
if (newHandler)
newHandler();
else
throw std::bad_alloc();
}
static PtrNew _s_pNew = NULL;
static PtrDelete _s_pDelete = NULL;
static void * New (size_t size)
...{
void *p;
while (!(p = malloc(size)))
_CallNewHandler();
return p;
}
static void SetNewAndDeleteFunctionPointers()
...{
void *p = NULL;
HMODULE hModule = NULL;
MEMORY_BASIC_INFORMATION mbi;
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);
PtrGetNewAndDelete pGetNewAndDelete = (PtrGetNewAndDelete)GetProcAddress(hModule, "GetNewAndDeleteFor_DllCppTmpl");
if (pGetNewAndDelete)
...{
pGetNewAndDelete(_s_pNew, _s_pDelete);
return;
}
PtrSetNewAndDelete pSetNewAndDelete = (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"); // operator new
_s_pDelete = (PtrDelete)GetProcAddress(hModule, "??3@YAXPAX@Z"); // operator delete
return;
}
OutputDebugString("DllCppTmpl was not able to obtain new and delete function pointers. ");
throw 0;
}
void * operator new (size_t size)
...{
if (!_s_pNew)
SetNewAndDeleteFunctionPointers();
return _s_pNew(size);
}
void operator delete (void * p)
...{
_s_pDelete(p);
}
void * operator new [] (size_t size)
...{
return operator new (size);
}
void operator delete [] (void * p)
...{
operator delete (p);
}
#endif // #ifdef DLLCPPTMPL_EXPORTS
/**//////////////////////////////////////////
// Test
void DLLCPPTMPL_DLL DllCppTmpl::Test1(const char *in, char** out)
...{
*out = new char[strlen(in) + 20];
strcpy(*out, "Hello ");
strcat(*out, in);
}
void DLLCPPTMPL_DLL DllCppTmpl::Test2(const string& in, string& out)
...{
out = "hello ";
out += in;
}
#include "DllCppTmpl.h"
#include <string.h>
#include <iostream>
#include <time.h>
#include <windows.h>
#if (_MSC_VER >= 1000)
#include <crtdbg.h> // for the debug heap
#endif
/**/////////////////////////////////////////////////////
// 如果使用动态库: DllCppTmpl
using namespace DllCppTmpl;
//
// DLL标准输出
//
#ifdef DLLCPPTMPL_EXPORTS
#if !(defined(_MSC_VER) && (_MSC_VER < 1300))
using std::new_handler;
using std::set_new_handler;
#endif
void _CallNewHandler()
...{
new_handler newHandler = set_new_handler(NULL);
if (newHandler)
set_new_handler(newHandler);
if (newHandler)
newHandler();
else
throw std::bad_alloc();
}
static PtrNew _s_pNew = NULL;
static PtrDelete _s_pDelete = NULL;
static void * New (size_t size)
...{
void *p;
while (!(p = malloc(size)))
_CallNewHandler();
return p;
}
static void SetNewAndDeleteFunctionPointers()
...{
void *p = NULL;
HMODULE hModule = NULL;
MEMORY_BASIC_INFORMATION mbi;
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);
PtrGetNewAndDelete pGetNewAndDelete = (PtrGetNewAndDelete)GetProcAddress(hModule, "GetNewAndDeleteFor_DllCppTmpl");
if (pGetNewAndDelete)
...{
pGetNewAndDelete(_s_pNew, _s_pDelete);
return;
}
PtrSetNewAndDelete pSetNewAndDelete = (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"); // operator new
_s_pDelete = (PtrDelete)GetProcAddress(hModule, "??3@YAXPAX@Z"); // operator delete
return;
}
OutputDebugString("DllCppTmpl was not able to obtain new and delete function pointers. ");
throw 0;
}
void * operator new (size_t size)
...{
if (!_s_pNew)
SetNewAndDeleteFunctionPointers();
return _s_pNew(size);
}
void operator delete (void * p)
...{
_s_pDelete(p);
}
void * operator new [] (size_t size)
...{
return operator new (size);
}
void operator delete [] (void * p)
...{
operator delete (p);
}
#endif // #ifdef DLLCPPTMPL_EXPORTS
/**//////////////////////////////////////////
// Test
void DLLCPPTMPL_DLL DllCppTmpl::Test1(const char *in, char** out)
...{
*out = new char[strlen(in) + 20];
strcpy(*out, "Hello ");
strcat(*out, in);
}
void DLLCPPTMPL_DLL DllCppTmpl::Test2(const string& in, string& out)
...{
out = "hello ";
out += in;
}
好了,开始写客户端。建一个Win32 console项目,如下:
// testDllCppTmpl.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#define DLLCPPTMPL_IMPORTS // 必须定义在前
#include "../DllCppTmpl/DllCppTmpl.h"
#pragma comment(lib, "../DllCppTmpl/Debug/DllCppTmpl.lib")
/**///////////////////////////////////////////////////////////////////////
using namespace DllCppTmpl;
/**/////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
...{
char in[] = "cheungmine";
char* out = 0;
DllCppTmpl::Test1(in, &out);
printf("Test1: %s ", out);
delete out;
string in2="cheungmine";
string out2;
DllCppTmpl::Test2(in2, out2);
printf("Test2: %s ", out2.c_str());
return 0;
}
//
#include "stdafx.h"
#include <windows.h>
#define DLLCPPTMPL_IMPORTS // 必须定义在前
#include "../DllCppTmpl/DllCppTmpl.h"
#pragma comment(lib, "../DllCppTmpl/Debug/DllCppTmpl.lib")
/**///////////////////////////////////////////////////////////////////////
using namespace DllCppTmpl;
/**/////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
...{
char in[] = "cheungmine";
char* out = 0;
DllCppTmpl::Test1(in, &out);
printf("Test1: %s ", out);
delete out;
string in2="cheungmine";
string out2;
DllCppTmpl::Test2(in2, out2);
printf("Test2: %s ", out2.c_str());
return 0;
}
注意路径的正确,和DllCppTmpl.dll要放到system32下。
- 一个Win32 C++ 动态连接库的模板 --- 调用方可管理DLL分配的内存
- 一个Win32 C++ 动态连接库的模板 — 调用方可管理DLL分配的内存
- 调用Win32 API netapi32.dll 实现UNC(网络共享)连接的管理(一)
- C++/C动态内存分配的区别
- 动态内存分配的一个小Demo
- 动态调用win32 dll
- 从.NET平台调用Win32 API(C#调用的dll动态链接库)
- Qt调用win32的dll判断是否连接上了网络
- 动态链接库-Win32 DLL的说明
- Win32 Dll(动态链接库)模板
- C语言的动态内存分配
- C和C++动态内存的分配
- C语言的动态内存分配函数
- C语言的动态内存分配
- 动态内存分配的C代码示例
- DLL专题之动态连接库的静态调用(1)
- DLL专题之动态连接库的静态调用(2)
- c++调用matlab生成的Dll动态连接库
- 一封自白信(下)
- Rails Cookbook翻译(五)
- 购物车
- 新的开始?!
- 4月4日,安全评价软件的安装
- 一个Win32 C++ 动态连接库的模板 --- 调用方可管理DLL分配的内存
- Java: 第一次尝试Java,Thread类
- 在线搜索
- GPGPU::数学基础教程
- OpenGL自动为每个顶点分配坐标
- 落雪木马病毒的手工清除方法
- 线性插值
- OpenGL Performance Optimization
- JAVA 常用知识