要寫一個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 "include\visa.h" #include "include\visatype.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\n"); } int CFluke5500aOper::cmd_rst() { return send_cmd("*RST\n"); } int CFluke5500aOper::cmd_clear_all_stat() { return send_cmd("*CLS\n"); } int CFluke5500aOper::cmd_stby() { return send_cmd("STBY\n"); } 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\n"); 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程序那邊,
添加父類純虛函數接口的頭文件,
然後引入獲取單例接口的函數。
使用獲取單例接口的函數 獲取單例的類,然後使用父類接口類聲明。
這樣便達成了我的目的。
只導出特定的接口函數(實際上,只導出了一個獲取單例的函數)