由于需要把自己写的三个hash算法类库化,想生成Dll以供后期程序调用,经过一翻测试,发现和C生成DLL还是有差别,静态链结没有问题,一但想动态加载dll的时候,就会发现程序崩溃,经过调试,发现能取得dll的函数,返回的接口也是正常的,调用算法方法时正常,但在调用toSring方法时,就挂了,显示std::string的 Alloc类调用失败,我去,难道不能动态加载,只能静态用?
通过使用Depend软件查看dll的关联性,还发现一个错误,提示关联的msvcp90.dll丢失,晕。经过一翻思考后,对源代码进行了小范围的改动,将使用STL标准库的方法去掉,用结构体数组进行了替代,去掉了std::string的依赖,这里还有一个思考,或许可以用自己写的string类进行替换,但没有进行实验了。最后将用户使用的接口从hash_comm.h中提取出来,经过测试静态和动态加载,终于成功了!
// hash.h
#ifndef __HASH_HEADER__
#define __HASH_HEADER__
#ifdef EXPORT_DLL
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
#define HASH_MAX 5
#define HASHS_MAX 41
// 算法类型ID
#define HASH_CRC32 0
#define HASH_SHA1 1
#define HASH_MD5 2
struct Hresult
{
unsigned intvalue[HASH_MAX];
unsigned intlen;
charhash[HASHS_MAX];
};
// hash算法接口类
class IHash
{
public:
virtual ~IHash(){}
virtual bool update(const char*, size_t)=0;
virtual void final()=0;
virtual void value(Hresult&)=0;
};
// 接口工厂函数
extern "C"
{
DLL_API IHash* hash_create(int hash_type);
DLL_API void hash_release(IHash *);
}
#endif
// interface.cpp
#include "crc32.h"
#include "md5.h"
#include "sha1.h"
IHash* hash_create(int hash_type)
{
switch(hash_type)
{
case 0:return new Crc32;
case 1:return new Sha1;
case 2:return new Md5;
}
return 0;
}
void hash_release(IHash *ih)
{
if(ih) delete ih;
}
生成的hash.dll只有12K,用Depend查看DLL关联,只和msvcr.dll和kernel.dll相关了。
总结:这个经验对于纯算法的C++类有用,不能使用C++的STL类库,接口工厂函数的实现需要单独放入一个CPP文件中,且使用extern "C"进行申明。这样生成的dll既可以享用C++多态类使用的优点,又可以保持动态加载调用这个Dll特性,各个算法实现在dll中完全隐藏,用户并不可见,非常爽。
吐槽一下:stl的string真的是慢,想要快速的话,慎用。push_back方法,比直接用数组输出慢1000倍,比直接实现string慢23倍以上,十万次执行的所用时间1.089s,直接实现所用时间是0.047s,过度使用设计模式的问题。
通过使用Depend软件查看dll的关联性,还发现一个错误,提示关联的msvcp90.dll丢失,晕。经过一翻思考后,对源代码进行了小范围的改动,将使用STL标准库的方法去掉,用结构体数组进行了替代,去掉了std::string的依赖,这里还有一个思考,或许可以用自己写的string类进行替换,但没有进行实验了。最后将用户使用的接口从hash_comm.h中提取出来,经过测试静态和动态加载,终于成功了!
// hash.h
#ifndef __HASH_HEADER__
#define __HASH_HEADER__
#ifdef EXPORT_DLL
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
#define HASH_MAX 5
#define HASHS_MAX 41
// 算法类型ID
#define HASH_CRC32 0
#define HASH_SHA1 1
#define HASH_MD5 2
struct Hresult
{
unsigned intvalue[HASH_MAX];
unsigned intlen;
charhash[HASHS_MAX];
};
// hash算法接口类
class IHash
{
public:
virtual ~IHash(){}
virtual bool update(const char*, size_t)=0;
virtual void final()=0;
virtual void value(Hresult&)=0;
};
// 接口工厂函数
extern "C"
{
DLL_API IHash* hash_create(int hash_type);
DLL_API void hash_release(IHash *);
}
#endif
// interface.cpp
#include "crc32.h"
#include "md5.h"
#include "sha1.h"
IHash* hash_create(int hash_type)
{
switch(hash_type)
{
case 0:return new Crc32;
case 1:return new Sha1;
case 2:return new Md5;
}
return 0;
}
void hash_release(IHash *ih)
{
if(ih) delete ih;
}
生成的hash.dll只有12K,用Depend查看DLL关联,只和msvcr.dll和kernel.dll相关了。
总结:这个经验对于纯算法的C++类有用,不能使用C++的STL类库,接口工厂函数的实现需要单独放入一个CPP文件中,且使用extern "C"进行申明。这样生成的dll既可以享用C++多态类使用的优点,又可以保持动态加载调用这个Dll特性,各个算法实现在dll中完全隐藏,用户并不可见,非常爽。
吐槽一下:stl的string真的是慢,想要快速的话,慎用。push_back方法,比直接用数组输出慢1000倍,比直接实现string慢23倍以上,十万次执行的所用时间1.089s,直接实现所用时间是0.047s,过度使用设计模式的问题。