近日,做了一个项目,暂且称其为:RC,遇到了些问题,也想办法解决了它们,现在分享出来,希望有助于朋友们的学习交流与工作,不过还是要谢谢我的老总,是他给了我压力,好了,不多说,先把遇到的问题一一列出:
1、因为我是研发一个DLL,提供重要接口与硬件交互,所以必然少不了数据封装的好助手:struct,同时,它也支持C中不能支持的构造,重载,还有继承。所以,我需要提供:RC.h、RC.dll、RC.lib这三个文件,但是,我不可能把struct内部详细构造、重载、乃至继承都在RC.h中实现,这是我老总要求的,估计也是目前通行的,但是我又要实现这些个具体的操作,这可如何是好?
2、在研发一个DLL中很可能需要对这个库的初始化和清理,这不可能交给客户来完成,这又怎么办?
3、如何做到全局常量的比较规范?
... ...
我现在把主要的代码贴出,也相信大家的能力,能够从中知道如何解决问题,如何更好的优化,我就不多说了;
DLL的初始化和清理函数暂且定位:RC_Init() 和 RC_Clear();
另外新建一个h文件,暂且定位:RC_CommDef.h,我用它存放全局常量以及 RC_Init() 和 RC_Clear()的定义;
RC.h:
/// 定义WinSock信息
struct tagWinSockInfo {
/// IP地址,一般格式为×××.×××.×××.×××,例如:192.168.0.100
string strIpAddr;
/// 端口,一般是在区间[1, 65536]内;
UINT iPort;
};
/// 定义串口信息
struct tagCommInfo {
UINT uiPort; /// 串口号,一般在区间[1, 256]内;
/*
波特率,一般是这几种:... 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 56000, 57600, 115200, 128000, 256000;
在Windows系统中WinBase.h文件中有定义:
#define CBR_110 110
#define CBR_300 300
#define CBR_600 600
#define CBR_1200 1200
#define CBR_2400 2400
#define CBR_4800 4800
#define CBR_9600 9600
#define CBR_14400 14400
#define CBR_19200 19200
#define CBR_38400 38400
#define CBR_56000 56000
#define CBR_57600 57600
#define CBR_115200 115200
#define CBR_128000 128000
#define CBR_256000 256000
*/
DWORD dwBaud;
/// 数据位,一般是这几种:... 5, 6, 7, 8;
BYTE ucDataBits;
/*
停止位,一般是这几种:1, 1.5, 2;
在Windows系统中WinBase.h文件中有定义:
#define ONESTOPBIT 0
#define ONE5STOPBITS 1
#define TWOSTOPBITS 2
*/
BYTE ucStopBit;
/*
校验位,一般是这几种:None, Odd, Even, Mark, Sapce;
在Windows系统中WinBase.h文件中有定义:
#define NOPARITY 0
#define ODDPARITY 1
#define EVENPARITY 2
#define MARKPARITY 3
#define SPACEPARITY 4
*/
BYTE ucParity;
};
... ...
RC_CommDef.h:
#include "RC.h"
#define MAX_COM_PORT 256 /// 最大串口号
#define MAX_IP_PORT 65535 /// 最大IP端口号
... ...
typedef struct _XC_RC_WINSOCK_INF : public tagWinSockInfo {
_XC_RC_WINSOCK_INF(void) {
strIpAddr.assign("");
iPort = 0;
}
/// 考虑如果有扩展的情况,即:在基结构体的基础上再添加数据变量。
_XC_RC_WINSOCK_INF& operator = (const _XC_RC_WINSOCK_INF& t) {
if (this != (&t)) {
strIpAddr.assign(t.strIpAddr);
iPort = t.iPort;
}
///
return (*this);
}
///
_XC_RC_WINSOCK_INF& operator = (const tagWinSockInfo& t) {
if (this != (&t)) {
strIpAddr.assign(t.strIpAddr);
iPort = t.iPort;
}
///
return (*this);
}
///
bool operator < (const _XC_RC_WINSOCK_INF& other) const
{
const int _iVal = strIpAddr.compare(other.strIpAddr);
///
if (0 > _iVal)
return true;
else if (0 == _iVal)
return iPort < other.iPort;
///
return false;
}
///
bool operator == (const _XC_RC_WINSOCK_INF& other) const
{
return 0 == strIpAddr.compare(other.strIpAddr) && iPort == other.iPort;
}
} XC_RC_WINSOCK_INF_st, *XC_RC_WINSOCK_INF_pst;
typedef struct _XC_RC_COMM_INF : public tagCommInfo {
_XC_RC_COMM_INF(void) {
uiPort = 0;
dwBaud = 0;
ucDataBits = 8;
ucStopBit = ONESTOPBIT; //0,1,2=0,1.5,2;
ucParity = NOPARITY; /// 0-4=no,odd,even,mark,space;
}
///
_XC_RC_COMM_INF& operator = (const _XC_RC_COMM_INF& t) {
if (this != (&t)) {
uiPort = t.uiPort;
dwBaud = t.dwBaud;
ucDataBits = t.ucDataBits;
ucStopBit = t.ucStopBit;
ucParity = t.ucParity;
}
///
return (*this);
}
///
_XC_RC_COMM_INF& operator = (const tagCommInfo& t) {
if (this != (&t)) {
uiPort = t.uiPort;
dwBaud = t.dwBaud;
ucDataBits = t.ucDataBits;
ucStopBit = t.ucStopBit;
ucParity = t.ucParity;
}
///
return (*this);
}
///
bool operator < (const _XC_RC_COMM_INF& other) const
{
return uiPort < other.uiPort;
}
///
bool operator == (const _XC_RC_COMM_INF& other) const
{
return uiPort == other.uiPort && dwBaud == other.dwBaud && ucDataBits == other.ucDataBits && ucStopBit == other.ucStopBit && ucParity == other.ucParity;
}
} XC_RC_COMM_INF_st, *XC_RC_COMM_INF_pst;
/*
* 函数功能:
* 初始化
*
* 参数描述:
*
* 返回值:
*
*/
void RC_Init(void);
/*
* 函数功能:
* 释放所有占用内存。
*
* 参数描述:
*
* 返回值:
*
*/
void RC_Clear(void);
RC.cpp:
#include "RC_CommDef.h"
RC_Init()
{}
RC_Clear()
{}
dllmain.cpp:
#include "RC_CommDef.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH: /// 进程被调用
{
// 记住,千万不再在DllMain函数中建立线程,像如下的WaitForSingleObject
// 将使得程序发生死锁,详细可参考 Window高级编程指南.pdf 的P-433的DLL系列化问题
//hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadProc,NULL,0,&dwThreadId);
//WaitForSingleObject(hThread,INFINITE);
/// Disables the DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications for the specified
/// dynamic-link library (DLL). This can reduce the size of the working set for some applications.
/// Parameters: hModule [in] - A handle to the DLL module for which the DLL_THREAD_ATTACH and
/// DLL_THREAD_DETACH notifications are to be disabled.
/// Return value: If the function succeeds, the return value is nonzero.
DisableThreadLibraryCalls(hModule);
RC_Init();
break;
}
case DLL_THREAD_ATTACH: /// 线程被调用
case DLL_THREAD_DETACH: /// 线程被停止
break;
case DLL_PROCESS_DETACH: /// 进程被停止
RC_Clear();
break;
}
///
return TRUE;
}