C++使用純虛函數和單例模式導出接口的動態庫的寫法

要寫一個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程序那邊,

添加父類純虛函數接口的頭文件,

然後引入獲取單例接口的函數。

 

使用獲取單例接口的函數 獲取單例的類,然後使用父類接口類聲明。

這樣便達成了我的目的。

只導出特定的接口函數(實際上,只導出了一個獲取單例的函數)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章