利用Pimpl实现细节隐藏

       利用C++开发运动控制卡的动态链接库,在类的定义有包括了一些WINDOWS的信号量操作,但有些用户在使用QT环境调用时就发生了问题,如下图所示 。

        该动态链接库的部分原始代码(头文件)如下所示:

class myNetSocket;
class CSerialPort;

class EXPORTS_DEMO MoCtrCard
{
public:
	MoCtrCard();
	~MoCtrCard();

	// RS232 接口
	McCard_UINT16 MoCtrCard_Initial(McCard_UINT8 ComPort);
	McCard_UINT16 MoCtrCard_Unload();

	// 四轴的接口
	McCard_UINT16 MoCtrCard_MCrlAxisMove(McCard_UINT8 AxisId, McCard_INT8 SpdDir);
	McCard_UINT16 MoCtrCard_MCrlAxisRelMove(McCard_UINT8 AxisId, McCard_FP32 DistCmnd, McCard_FP32 VCmnd, McCard_FP32 ACmnd);

private:
	CRITICAL_SECTION   mSemCommSync;    ///< 互斥通讯操作 
	McCard_UINT8 nCmndCnt;				///< 指令计数器,每下发指令自增1
	enum ePortLinkType nPortType;		///< 物理链路类型
	myNetSocket* cTCPSocket;			///< 网络接口对像
	CSerialPort* cRSPort;				///< RS232接口

};

        为了实现对 private 部分进行隐藏,达到对用户不可见的目的,上网调研后发现有两种方法可以实现: 1)利用pimpl技术,2)纯虚函数形成接口类

        通过对这两种方式的研究,决定使用pimpl方法进行对现有的DLL进行改造;那什么是pimp技术呢?参考MSDN

pimpl idiom 是一种新式 C++ 技术,用于隐藏实现、最小化耦合和分离接口。 Pimpl 是“指向实现的指针”的缩写。细节就不介绍了,而是直接套用实现。impl的实现有固定格式,如下所示:

// my_class.h
class my_class {
   //  ... all public and protected stuff goes here ...
private:
   class impl; unique_ptr<impl> pimpl; // opaque type here
};

// my_class.cpp
class my_class::impl {  // defined privately here
  // ... all private data and functions: all of these
  //     can now change without recompiling callers ...
};
my_class::my_class(): pimpl( new impl )
{
  // ... set impl values ...
}

在标头实现时,采用了c++的智能指针,因此在头文件中要加入

#include "memory"

在我们的DLL库中,具体实现方式为:

#ifndef _MYCODE_H_
#define _MYCODE_H_

#include "memory"

#ifdef MCC4DLL_EXPORTS
#define EXPORTS_DEMO _declspec( dllexport )
#else
#define EXPORTS_DEMO _declspec(dllimport)
#endif

class EXPORTS_DEMO MoCtrCard
{
public:
	MoCtrCard();
	~MoCtrCard();

	// RS232 接口
	McCard_UINT16 MoCtrCard_Initial(McCard_UINT8 ComPort);
	McCard_UINT16 MoCtrCard_Unload();

	McCard_UINT16 MoCtrCard_MCrlAxisMove(McCard_UINT8 AxisId, McCard_INT8 SpdDir);
	McCard_UINT16 MoCtrCard_MCrlAxisRelMove(McCard_UINT8 AxisId, McCard_FP32 DistCmnd, McCard_FP32 VCmnd, McCard_FP32 ACmnd);

private:
	class MoCtrCardImpl;
	std::unique_ptr<MoCtrCardImpl> m_pImpl;
};

#endif

        在CPP源文件中实现的Impl如下:

class myNetSocket;
class CSerialPort;
class MoCtrCard::MoCtrCardImpl
{
public:
	MoCtrCardImpl() {};

	CRITICAL_SECTION   mSemCommSync;    ///< 互斥通讯操作 
	McCard_UINT8 nCmndCnt;				///< 指令计数器,每下发指令自增1
	enum ePortLinkType nPortType;		///< 物理链路类型
	myNetSocket* cTCPSocket;			///< 网络接口对像
	CSerialPort* cRSPort;				///< RS232接口
};

MoCtrCard::MoCtrCard():pimpl(new MoCtrCardImpl())
{
	pimpl->nCmndCnt = 0x00;
	pimpl->nPortType = ePortNone;					///< 物理链路类型
	pimpl->cTCPSocket = new myNetSocket();		///< 网络接口对像
	pimpl->cRSPort = new CSerialPort();			///< RS232接口
	InitializeCriticalSection(&pimpl->mSemCommSync);	///< 收发信号量
}

        经过以上改造后,DLL可以直接用在现有的应用程序中,在现有的DEMO程序上进行测试,原始程序不做任何修改,测试成功。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值