zoukankan      html  css  js  c++  java
  • 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 "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程序那边,

    添加父类纯虚函数接口的头文件,

    然后引入获取单例接口的函数。

    使用获取单例接口的函数 获取单例的类,然后使用父类接口类声明。

    这样便达成了我的目的。

    只导出特定的接口函数(实际上,只导出了一个获取单例的函数)

  • 相关阅读:
    Trie树详解及其应用
    最长回文字符串_Manacher算法_(O(n))
    设置VisualStudio以管理员身份运行
    wcf使用JetEntityFrameworkProvider.dll写access数据库时,报"操作必须使用一个可更新的查询"错误的解决办法
    data:image字符转byte[]
    ID为XXXX的进程当前未运行
    在Windows2003 server 64位系统上使用ArcEngine开发的WCF服务
    关于position的relative和absolute分别是相对于谁进行定位的
    sql语句进行写数据库时,字符串含有'的处理方式
    EF中关于日期字值的处理
  • 原文地址:https://www.cnblogs.com/rixiang/p/14576707.html
Copyright © 2011-2022 走看看