要写一个C++的动态库,里面每个函数都要共用到一个变量。我觉得这样最好写成类的形式,该变量就可以作为类的成员变量来封装。
但我不希望将整个类都导出,希望只导出特定的接口函数。
于是我想到了继承,
让子类继承父类(纯虚函数类)。
另外,使用了单例模式。
最后只导出获取单例的函数即可。
父类接口函数头文件:
#pragma once #define DLL_API _declspec(dllexport) const int OPER_SUCCESS = 0; const int DEV_NOT_CONN = -1; const int INPT_WRONG = -2; class CFluke5500aOperInterface { public: virtual int open_fluke5500a_conn(const char* const rsrc_name) = 0; virtual int close_fluke5500a_conn() = 0; virtual int cmd_oper() = 0; virtual int cmd_rst() = 0; virtual int cmd_out_ma(int ma) = 0; virtual int send_cmd(const char* const str_cmd) = 0; virtual int cmd_stby() = 0; virtual int cmd_clear_all_stat() = 0; };
子类头文件:
#pragma once #include "fluke5500a_gpib_interface.h" #include "includevisa.h" #include "includevisatype.h" class CFluke5500aOper : public CFluke5500aOperInterface { public: ~CFluke5500aOper(void); CFluke5500aOper(const CFluke5500aOper&) = delete; CFluke5500aOper& operator=(const CFluke5500aOper&) = delete; static CFluke5500aOper& get_inst(); int open_fluke5500a_conn(const char* const rsrc_name); int close_fluke5500a_conn(); int cmd_oper(); int cmd_rst(); int cmd_out_ma(int ma); int send_cmd(const char* const str_cmd); int cmd_stby(); int cmd_clear_all_stat(); private: CFluke5500aOper(); ViSession m_vi_session_rm; ViSession m_vi_session; /** 同步互斥,临界区保护 */ CRITICAL_SECTION m_cs_communication_sync; };
类的实现文件(注意只在获取单例的函数这里添加了导出:extern "C" DLL_API CFluke5500aOperInterface& get_fluke5500a_oper()):
#include "pch.h" #include "fluke5500a_gbip_com.h" #include <stdio.h> #include <stdlib.h> #include <string> #pragma comment(lib, "lib\visa32.lib") extern "C" DLL_API CFluke5500aOperInterface& get_fluke5500a_oper() { return CFluke5500aOper::get_inst(); } CFluke5500aOper& CFluke5500aOper::get_inst() { static CFluke5500aOper instance; return instance; } CFluke5500aOper::CFluke5500aOper() { InitializeCriticalSection(&m_cs_communication_sync); m_vi_session_rm = NULL; m_vi_session = NULL; } CFluke5500aOper::~CFluke5500aOper(void) { DeleteCriticalSection(&m_cs_communication_sync); } int CFluke5500aOper::open_fluke5500a_conn(const char* const rsrc_name) { /*进入临界段*/ EnterCriticalSection(&m_cs_communication_sync); ViStatus ret = viOpenDefaultRM(&m_vi_session_rm); if (ret != VI_SUCCESS) { viClose(m_vi_session_rm); /*离开临界段*/ LeaveCriticalSection(&m_cs_communication_sync); return ret; } ret = viOpen(m_vi_session_rm, rsrc_name, VI_EXCLUSIVE_LOCK, VI_NULL, &m_vi_session); if (ret != VI_SUCCESS) { viClose(m_vi_session); viClose(m_vi_session_rm); /*离开临界段*/ LeaveCriticalSection(&m_cs_communication_sync); return ret; } /*离开临界段*/ LeaveCriticalSection(&m_cs_communication_sync); return OPER_SUCCESS; } int CFluke5500aOper::close_fluke5500a_conn() { /*进入临界段*/ EnterCriticalSection(&m_cs_communication_sync); ViStatus ret = viClose(m_vi_session); if (ret != VI_SUCCESS) { /*离开临界段*/ LeaveCriticalSection(&m_cs_communication_sync); return ret; } ret = viClose(m_vi_session_rm); if (ret != VI_SUCCESS) { /*离开临界段*/ LeaveCriticalSection(&m_cs_communication_sync); return ret; } /*离开临界段*/ LeaveCriticalSection(&m_cs_communication_sync); return OPER_SUCCESS; } int CFluke5500aOper::cmd_oper() { return send_cmd("OPER "); } int CFluke5500aOper::cmd_rst() { return send_cmd("*RST "); } int CFluke5500aOper::cmd_clear_all_stat() { return send_cmd("*CLS "); } int CFluke5500aOper::cmd_stby() { return send_cmd("STBY "); } int CFluke5500aOper::cmd_out_ma(int ma) { if (ma < 0) { return INPT_WRONG; } char str_ma[36]; sprintf_s(str_ma, "%d", ma); std::string str_cmd = "OUT "; str_cmd.append(str_ma); str_cmd.append("MA "); return send_cmd(str_cmd.c_str()); } int CFluke5500aOper::send_cmd(const char* const str_cmd) { /*进入临界段*/ EnterCriticalSection(&m_cs_communication_sync); if (m_vi_session == NULL) { /*离开临界段*/ LeaveCriticalSection(&m_cs_communication_sync); return DEV_NOT_CONN; } ViStatus ret = viPrintf(m_vi_session, str_cmd); if (ret != VI_SUCCESS) { /*离开临界段*/ LeaveCriticalSection(&m_cs_communication_sync); return ret; } /*离开临界段*/ LeaveCriticalSection(&m_cs_communication_sync); return OPER_SUCCESS; }
在调用的exe程序那边,
添加父类纯虚函数接口的头文件,
然后引入获取单例接口的函数。
使用获取单例接口的函数 获取单例的类,然后使用父类接口类声明。
这样便达成了我的目的。
只导出特定的接口函数(实际上,只导出了一个获取单例的函数)