由于工作需要,自己手动封装一个DLL,简单说就是自己写一个DLL来加载另外一个DLL
第一次写博客,记录自己的一些经验,方便以后查看,少走弯路,新手可以看看,大神略过。
我封装的DLL是阿里的消息队列C++的SDK,阿里只能静态加载,配置麻烦,所以封装使用。
在编写测试过程中出过很多问题,因为我是第一次封装,小问题就不做记录,几个稍微大的问题,第一个封装完成调用运行的时候报错,提示使用错误的调用方式,在网上找了很久都是说调用约定不一致就是所谓的__stdcall __cdecl的问题,但是都是我自己定义好的,同样的工程环境,也是各种琢磨测试也没有用,后来转用release版本,发现就没有问题,对那个问题还是没能很清楚,待以后研究研究,有的时候可能debug版本有问题不妨试一试release版本。
再一个问题就是我调用封装DLL接口传入的参数问题,参入的数据和DLL传出的数据对不上,各种查看,改变传入方式,分配内存等等试了很多,仍然没用,当时很是无助,也咨询过大神,也没有找到个所以然,后来发现是定义宏中char数组和string的问题,两边的数据类型一定要是一致的,不然这两者用起来不报错,但是值就是对不上,很是心塞。
还有一个最后路径的问题,动态加载DLL是可以设置路径的,但是我的DLL里面是静态加载的阿里的DLL,所以这种情况下只能把阿里的DLL和应用程序放在一个目录下面,这样违背了初衷,后来查到资料添加系统环境变量,或者将静态加载的DLL放到系统环境变量的目录下面,就是环境变量下面path中设置的目录,具体怎么设置可以搜一下,很简单,但是我当时设置了环境变量之后还是显示加载DLL未能扎到指定模块,我用DLL调试又没有问题(只是自我测试的小程序),当时要让服务器的插件调用,不能调试,日志输出也看不出问题,很是头痛,这种情况下可以自己写简单的测试程序可以运行的,直接放到服务器上运行,发现是缺少运行库,添加上运行库,完美解决。
第一次做,前后几天,完成之后发现很简单,但是一些小的细节还是要注意。
贴上我封装的DLL的头文件代码,很简单,可以作为通用DLL封装头。
#pragma once
#include <string>
#include <vector>
#ifdef OSN_DLL
#define DLL_API extern "C" __declspec(dllexport)
#else
#define DLL_API extern "C" __declspec(dllimport)
#endif
//消息信息结构
typedef struct _SMSG_INFO
{
char strTag[16];
char strKey[16];
char strMsgID[255];
char strMsgBody[255];
}SMSG_INFO,*PSMSG_INFO;
/*
设计这个接口类的作用:
能采用动态调用方式使用这个类
*/
class CONSInterface
{
public:
virtual ~CONSInterface(void)
{
}
virtual void setConsumerId(const char* chConsumerId) = 0;//您在MQ控制台申请的consumerId
virtual void setProducerId(const char* chProducerId) = 0;//在ONS控制台申请的producerId
virtual void setPublishTopics(const char* chPublishTopics) = 0;//在ONS 控制台申请的msg topic
virtual void setAccessKey(const char* chAccessKey) = 0;//ONS AccessKey
virtual void setSecretKey(const char* chSecretKey) = 0;//ONS SecretKey
virtual void StartProducer() = 0;
virtual void StartConsumer() = 0;
virtual void EndProducer() = 0;
virtual void EndConsumer() = 0;
virtual bool SendMsgQueue(const char* pTag, const char* pKey, const char* pMsgBody, const char* strError) = 0;//发送消息到消息队列
virtual int GetMsgQueue(SMSG_INFO *pMsg) = 0;//获取消息队列信息,返回消息,传入指针为返回地址
};
typedef CONSInterface* (*ONSCreate_t)();
#ifndef OSN_DLL
#include <Windows.h>
class CONSFactory
{
private:
HMODULE m_lib;
ONSCreate_t m_pfnONSCreate;
public:
//--- constructor
CONSFactory(LPCSTR lib_path=NULL):m_lib(NULL)
{
Init(lib_path);
}
//--- destructor
~CONSFactory()
{
if(m_lib)
{
m_pfnONSCreate =NULL;
::FreeLibrary(m_lib);
m_lib=NULL;
}
}
//--- initialization
inline void Init(LPCSTR lib_path=NULL)
{
char path[256]="";
//---
if(lib_path!=NULL)
{
strcpy_s(path,lib_path);
path[sizeof(path)-1]=0;
}
else
{
strcpy_s(path,"Doo_ONSdll.dll");
path[sizeof(path)-1]=0;
}
//---
if(m_lib)
::FreeLibrary(m_lib);
if((m_lib=::LoadLibraryA(path))!=NULL)
{
m_pfnONSCreate =reinterpret_cast<ONSCreate_t>(::GetProcAddress(m_lib,"CreateONSInterface"));
}
else
{
m_pfnONSCreate =NULL;
}
//---
}
//--- winsock startup/cleanup
inline int WinsockStartup() const
{
WSADATA wsa;
return(WSAStartup(0x0202,&wsa)!=0 ? 2:0);
}
inline void WinsockCleanup() const
{
WSACleanup();
}
//---
inline int IsValid() const
{
return(m_lib!=NULL && m_pfnONSCreate!=NULL) ? TRUE:FALSE;
}
inline CONSInterface* Create() const
{
if(m_pfnONSCreate)
return (*m_pfnONSCreate)();
return NULL;
}
};
#endif