• 由云台协议DLL浅谈插件程序的编写 .


    由云台协议DLL浅谈插件程序的编写(上)【原创】
    前言:本文通过一个简单的工程描述了一种插件设计的思想。复杂设计和模块化分解能力是衡量一个程序员水平的重要标志,欢迎大家和我探讨。
    1.我们的目的是在Plug-Ins目录里面查找“ptz*.dll”格式的云台插件的动态链接库。每个库可支持多个协议,通过查找该目录下的合法插件,有此插件创建出某个协议的实例,达到通过该协议操作云台的目的。
    2.结构体定义:ComParam为串口通信参数:(定义在include/ComManager/ComParam.h文件中)

    class COMPARAMEXT_API ComParam

    {

    public:

           ComParam(  int nBaudRate,                        // 波特率

                                 int nByteSize = 8,                  // 数据位

                                 int nParity = 0,                      // 校验位 0 - NOPARITY

                                 int nStopBits = 0);                // 停止位 0 - ONESTOPBIT(参考winbase.h中的定义)

    };

    3.为了达到使用dll的目的,先封装几个简单的类:

    CDllLoad类:src/PTZ_Test/controls/DllLoad.h(这个类仅在src/PTZ_Test/controls/PTZDll.h)

    // DllLoad.h
    #pragma once

    class CDllLoad
    {
    public:

        CDllLoad()

        {
        }
        virtual ~CDllLoad(void)
        {
             Close();
        }

        void Open(LPCTSTR lpszName) // 加载DLL
        {
             if (m_hModule)
             {
                  Close();
             }
             m_hModule = ::LoadLibrary(lpszName);
        }

        void Close()
        {
             ::FreeLibrary(m_hModule);  // 卸载DLL
             m_hModule = NULL;
        }

        operator  HMODULE() { return m_hModule;}

        PROC GetProcAddress(LPCSTR lpProcName)
        {
             return ::GetProcAddress(m_hModule, lpProcName);    // 取得函数入口地址
        }

    protected:
        HMODULE m_hModule;
    };
    CPTZDll类:src/PTZ_Test/controls/DllLoad.h(主要功能:根据插件产生出该DLL的支持的协议对象,然后由该对象的函数调用需要的功能,由于函数调用时实际使用的是dll的类的成员函数,所以对象存在时必须也有一份CPTZDll的实例而且是打开状态的。)
    // PTZDll.h
    #pragma once

    #include "DllLoad.h"
    #include "PTZInterface.h"

    class CPTZDll
    {
        typedef CPTZInterface * (__stdcall* CREATE_PTZ_INSTANCE)(const char * pszProtocolsName);
    public:
        CPTZDll()    // 成员初始化
            : m_pDllLoad(0)
            , m_pfnCreatePTZInstance(0)
            , m_ppProtocolsName(0)
        {
        }

        ~CPTZDll()
        {
             Close();

             delete m_pDllLoad;
             m_pDllLoad =0;
        }

        BOOL OpenPlugIn(LPCTSTR lpszName)    // 打开插件,如果是有效的插件返回TRUE,否则FALSE
        {
             if (m_pDllLoad)
                  Close();
             else
             {
                  m_pDllLoad = new CDllLoad();
                  m_pDllLoad->Open(lpszName);
             }

             m_pfnCreatePTZInstance = (CREATE_PTZ_INSTANCE)m_pDllLoad->GetProcAddress("CreatePTZInstance");
             m_ppProtocolsName = (const char **)m_pDllLoad->GetProcAddress("ProtocolNames");

             return (m_ppProtocolsName && m_ppProtocolsName[0]);
        }

        void Close()
        {
             m_pfnCreatePTZInstance = 0;
             m_ppProtocolsName = 0;

            if (m_pDllLoad)
                m_pDllLoad->Close();
        }

        const char ** GetSupportProtocols()
        {
            return m_ppProtocolsName;
        }

        CPTZInterface * CreatePTZInstance(LPCTSTR lpszProtolName)    // 根据该插件内的某个协议产生出一个对象
        {
                if (m_pfnCreatePTZInstance)
            {
                return m_pfnCreatePTZInstance(lpszProtolName);
            }

            return 0;
    }

    private:
        CDllLoad * m_pDllLoad;

        CREATE_PTZ_INSTANCE m_pfnCreatePTZInstance;

        const char ** m_ppProtocolsName;
    };
    CPlugInInfo类:src/PTZ_Test/controls/PTZProtocolFind.h和src/PTZ_Test/controls/ptzprotocolfind.cpp

    //=========================================================
    //

    // Copyright (c) 2000-2004  iWise Technologies,Co. Ltd.
    // All Rights Reserved.
    //
    // Product: iW988
    // File: PTZProtocolFind.h
    // Created: 天衣有缝
    // Data :2004.12.22 PM

    // Description:
    //     ValueAdded main program for iW988.
    //                   Contact:
    //                       waterpub@mail.csdn.net
    //
    //=========================================================

    #pragma once

     

    class CPlugInInfo    // 插件信息类
    {
    public:
        string szFileName                ; // 文件名
        vector<string>                      Protocols                   ; // 协议列表
        string szFullPath    ; // 文件全路径

    public:
        CPlugInInfo(void)
        {
        }
        ~CPlugInInfo(void)
        {
        }
    };

    class CPTZProtocolFind
    {
    public:
        CPTZProtocolFind(void);
        ~CPTZProtocolFind(void);

    public:
        void EnumPlugIns(vector<CPlugInInfo>& PlugInList); // 枚举Plug-Ins目录的所以ptz文件
    };

    //=========================================================
    //

    // Copyright (c) 2000-2004  iWise Technologies,Co. Ltd.
    // All Rights Reserved.
    //
    // Product: iW988
    // File: PTZProtocolFind.cpp
    // Created: 天衣有缝
    // Data :2004.12.22 PM
    // Description:
    //     ValueAdded main program for iW988.
    //                   Contact:
    //                       waterpub@mail.csdn.net
    //
    //=========================================================

    #include "StdAfx.h" 
    #include "ptzprotocolfind.h" 
    #include "PTZDll.h" 
    
    CPTZProtocolFind::CPTZProtocolFind(void)
    {
    }
    
    CPTZProtocolFind::~CPTZProtocolFind(void)
    {
    }
    // 枚举“Plug-Ins”目录下的所有有效插件
    void CPTZProtocolFind::EnumPlugIns(vector<CPlugInInfo>& PlugInList)
    {
        char szFilePath[MAX_PATH];
        ::GetModuleFileName(NULL, szFilePath, MAX_PATH);
        char * pFind = strrchr(szFilePath, '//');
        *pFind = '/0';
        strcat(szFilePath, "//Plug-Ins//ptz*.dll"); // 查找的匹配字符串
    
        CFileFind find;
        BOOL bFind;
        bFind = find.FindFile(szFilePath);
        while (bFind)
        {
            CPTZDll dll;
            bFind = find.FindNextFile();
            if (find.IsArchived()) // 文件而非文件夹
            {
                // 输出这个文件:
                XTRACE("路径:%s/n", find.GetFilePath());
                if ( dll.OpenPlugIn(find.GetFilePath()) ) // 如果是云台插件,则枚举出它的协议
                {
                    CPlugInInfo info;
                    const char ** ppProtocols = dll.GetSupportProtocols();
                    if(!ppProtocols)
                    {
                        continue;
                    }
                    while(0 != *ppProtocols)
                    {
                        string _string = *ppProtocols;
                        info.Protocols.push_back(_string);
                        ppProtocols ++;
                    }
                    info.szFullPath = find.GetFilePath();
                    info.szFileName = find.GetFileName();
                    PlugInList.push_back(info);
                }
            }
            dll.Close();
        }
        find.Close();
        // 下面是调试代码
        XTRACE("插件数量:%d/n",PlugInList.size());
        vector<CPlugInInfo>::iterator it = PlugInList.begin();
        for(; it != PlugInList.end(); it++)
        {
            XTRACE("文件名:%s----》文件路径:%s/n", (*it).szFileName.c_str(), (*it).szFullPath.c_str());
        }
    }
    4.在对话框工程的窗体中加入两个成员变量:
    CPTZDll         m_PTZdll          ; // dll加载对象
    CPTZInterface*  m_PTZInterface    ; // 正在使用的插件协议对象
    用户选择一个插件:BOOL bReturn = m_PTZdll.OpenPlugIn(m_strProtocolPath);
    然后根据该插件选择一个协议:m_PTZInterface = m_PTZdll.CreatePTZInstance(m_strProtocolName);    // 参数是一个表示协议的字符串
    这时我们可以利用这个m_PTZInterface对象来执行各种操作。
    说明:m_PTZInterface的类“CPTZInterface”是一个抽象类,由此派生出各种各样的协议。
    其定义如下:
    //PTZInterface.h
    //iWise DVR PTZ Interface define header file.
    
    #pragma once 
    
    #include "PTZDef.h" 
    #include "ComParam.h" 
    
    class CPTZInterface
    {
    public:
    	virtual void SetPTZSettings(int nComPort, int nAddrID, const ComParam & param) = 0;
    	virtual void Move(MOVEMENT_DIR nDirection) = 0;
    	virtual void Action(int nActionID, int param) = 0;
    	virtual int SetSpeed(int nSpeedTrgID, int nSpeed) = 0;
    	virtual void DeviceSwitch(int nDeviceID, bool bSwitchOn) = 0;
    	virtual int SetPreset(int nIndex) = 0;
    	virtual int CallPreset(int nIndex) = 0;
    	virtual void Reset() = 0;
    	virtual int SelfCheck() = 0;
    	virtual int GetCaps(int nCapID, void * lParam) = 0;
    	virtual int ExtendOp(int nExOpID, void * lParam) = 0;
    	virtual void Destroy() = 0;
    };
    
    

     

     

    参考文档:

    云台控制协议插件开发文档

    本文档描述有关iWise-DVR云台控制协议插件的程序结构、设计原理、插件接口等重要信息,iWisePTZTest为插件的测试程序(插件也可以直接放到iWise-DVR环境中测试)。本文档以下出现的“DVR”均指“iWise-DVR”,本文档适用于使用串口的云台控制设备的基于DVR的云台控制协议插件的开发。

    插件工作原理

    云台控制有多种不同的控制协议,DVR提供统一的插件接口以支持不同的云台控制协议,通过协议插件来进行对云台的控制操作。DVR启动时会扫描Plug-Ins目录里面的所有文件名以“ptz”开头的动态连接库(DLL),并判断这些DLL是否为有效的云台控制协议插件。DVR定义了一套云台控制的基本操作,插件必须提供这些操作的具体实现,当用户要对云台进行控制时,DRV最终将调用插件的方法来控制云台,插件需要根据协议特征产生相应的指令数据并向串口设备发送这些指令。同时DVR提供向串口发送数据的统一的方法。

    云台控制协议插件接口

    DVR定义class CPTZInterface作为云台控制协议接口,该类是接口的核心,插件必须使用CPTZInterface派生一个类并实现所有的方法。CPTZInterface类详细定义如下:

    class CPTZInterface

    {

    public:

         virtual void SetPTZSettings(int nComPort, int nAddrID,

    const ComParam & param) = 0;

         virtual void Move(MOVEMENT_DIR nDirection) = 0;

         virtual void Action(int nActionID, int param) = 0;

         virtual int SetSpeed(int nSpeedTrgID, int nSpeed) = 0;

         virtual void DeviceSwitch(int nDeviceID, bool bSwitchOn) = 0;

         virtual int SetPreset(int nIndex) = 0;

         virtual int CallPreset(int nIndex) = 0;

         virtual void Reset() = 0;

         virtual int SelfCheck() = 0;

         virtual int GetCaps(int nCapID, void * lParam) = 0;

         virtual int ExtendOp(int nExOpID, void * lParam) = 0;

         virtual void Destroy() = 0;

    };

    SetPTZSettings函数设置云台设备所在的串口号、地址码及通信参数。

    nComPort - 云台设备所在串口号

    nAddrID  - 设备地址码

    param    - 通信参数,ComParam结构的引用(请参考《iWise-DVR环境串口操作接口使用说明》)。

     

    Move函数控制云台在各方向上的运动。

    nDirection–运动方向,由MOVEMENT_DIR定义

    enum MOVEMENT_DIR

    {

          MD_STOP,         // 停止运动

          MD_LEFT,          // 向左

          MD_RIGHT,        // 向右

          MD_UP,            // 向上

          MD_DOWN,          // 向下

          MD_LEFT_UP,       // 左上

          MD_LEFT_DOWN,    // 左下

          MD_RIGHT_UP,     // 右上

          MD_RIGHT_DOWN,    // 右下

    };

     

    Action函数控制云台摄像机的动作。

    nActionID–动作定义

    ACTION_ZOOM 缩放,param = 0时为缩小 param = 1时为放大

    ACTION_ZOOM_STOP 停止缩放

    ACTION_FOCUS 聚焦,param = 0时为往近处聚焦 1为往远处

    ACTION_FOCUS_STOP 停止聚焦

    ACTION_AUTO_FOCUS 自动聚焦

    ACTION_AUTO_FOCUS_STOP 停止自动聚焦

    ACTION_AUTO_SCAN 自动扫描

    ACTION_AUTO_SCAN_STOP 停止自动扫描

     

    SetSpeed设置云台运动或摄像机动作的速度。

    nSpeedTrgID–欲设置速度的目标

    SPEED_TRG_PAN 水平方向运动

    SPEED_TRG_TILT 垂直方向运动

    ACTION_AUTO_SCAN 自动扫描

    ACTION_AUTO_SCAN_STOP 停止自动扫描

    nSpeed     –速度值 (0x00-0x40)

    如果成功,该函数返回设置后的速度,否则返回0。

     

    DeviceSwitch函数提供打开、关闭某设备的功能。

    nDeviceID–设备ID定义

    DEVICE_CAMERA照相机

    DEVICE_LIGHT灯光

    DEVICE_RAINBRUSH 雨刷

    DEVICE_IRIS 镜头光圈

    bSwitchOn–true为打开设备false为关闭设备

     

    SetPreset函数设置预置点。

    nIndex–预置点索引号,从1开始,使用GetCaps取得设备可以支持的预置点总数。

    返回0为成功,否则失败

     

    CallPreset函数调用预置点,将云台摄象机移动到指定预置点位置。

    nIndex–预置点索引号,对使用SetPreset设置成功的索引号有效。

    返回0为成功,否则失败

     

    Reset函数使云台摄象机设备恢复到初始状态。

     

    SelfCheck函数使云台摄象机设备自检。

    返回0为成功,否则失败

     

    GetCaps函数可以取得设备所能提供的能力。

    nCapID–欲取得的能力的ID定义,请参考以下值

    GC_BASAL 取得基本能力, lParam为指向PTZBasalCaps结构的指针。

    lParam–指向特定能力结构的指针。

    返回0为成功,否则失败

     

    ExtendOp函数对CPTZInterface接口提供扩展功能。

    nExOpID–扩展功能ID定义。

    lParam–根据不同的nExOpID有不同的意义。

    该函数目前未使用

     

    Destroy函数负责销毁自身对象。

    销毁方式必须和CreatePTZInstance的创建方式一致

     

    设备基本能力结构定义:

    struct PTZBasalCaps

    {

    int nSize;                  // PTZBasalCaps结构的大小

    int nPresetCount;           // 支持预置点的个数

    int nMinSpeed;              // 云台移动速度最小值

    int nMaxSpeed;              // 云台移动速度最大值

    bool bAutoScanSupported;   // 是否支持自动扫描

    }

     

    插件DLL接口约定

    插件DLL在实现了CPTZInterface的具体实现方法之后,必须提供一致的构建和销毁CPTZInterface对象的方法,因此必须导出如下函数:

            CPTZInterface * __declspec(dllexport) CreatePTZInstance(

    const char * pszProtocolsName);

    pszProtocolsName – 协议索名称,该名称由GetSupportProtocols函数取得。

    该函数构造一个协议接口对象并返回其指针,该函数创建的对象必须由CPTZInterface::Destroy()函数自销毁。为安全起见,插件在卸载时也可以销毁使用者没有销毁的所有对象。

            const char ** __declspec(dllexport) GetSupportProtocols();

    nProtocols – 支持的协议数目

    该函数返回插件所支持的协议名称列表指针

     

    GetSupportProtocols代码示例:

    char * szProtocol[] = {

        "PELCO-D",

        "PELCO-P",

        0          // 必须以0表示结束

    };

     

    const char ** __declspec(dllexport) GetSupportProtocols()

    {

        return (const char **)szProtocol;

    }

     

    以上代码表示该插件支持"PELCO-D"、"PELCO-P"两种协议。

    class CPTZInterface声明在ptzInterface.h中。

    有关串口指令的发送请参考《iWise-DVR环境串口操作接口使用说明》。

     

    由云台协议DLL浅谈插件程序的编写(下)【原创】
    1.创建项目,“Visual C++项目”--->“Win32”--->“Win32 项目”--->“DLL”,选中“导出符号”,(VS2003平台),按源码目录组织规范设置项目,参考我的blog 2004.12其中文章。
    2.添加链接库导出定义文件:****.def,加入到项目中。
    ; ptzPelco-D.def : 声明 DLL 的模块参数。
     
    LIBRARY      "ptzPelco-D"
     
    EXPORTS
        ; 此处可以是显式导出
       
    CreatePTZInstance PRIVATE
    ProtocolNames  DATA
    说明:上面分别是导出变量和导出函数。
    3.把工程默认的导出变量和导出函数删除,默认导出的类也删除(头文件可删空)。
    4.在DllMain所在的cpp文件添加定义:
    const char * ProtocolNames[] =
    {
        "PELCO-D",
        "PELCO-P",
        0 // 必须以0表示结束
    };

    CPTZInterface * __stdcall CreatePTZInstance(const char * pszProtocolsName)
    {
        if (0 == strcmp(pszProtocolsName, ProtocolNames[0]))
        {
             return new CPelco_D;    // 看下面的定义!
        }

        if (0 == strcmp(pszProtocolsName, ProtocolNames[1]))
        {
             return new CPelco_P;    // 看下面的定义!
        }

        return 0;
    }
    5.从接口派生出一个类,定义如下:
    class CPelco_P: public CPTZInterface { …… }
    注意上面的CreatePTZInstance函数,这样就达到了创建这个协议对象的目的了。
    6.说明:创建的对象用该类的Destroy()销毁,由使用者调用。
    7.转载请保留完整文档,天衣有缝原创,2004.12.24凌晨0:05,深圳南山科技园

     

  • 相关阅读:
    华为数据之道03
    机器学习10讲 第二讲
    机器学习10讲 第一讲
    07.TensorFlow双向循环神经网络
    06.TensorFlow循环神经网络
    华为数据之道:华为数据治理2
    线性回归
    MySQL配置文件my.cnf的理解
    Linux怎么查看软件安装路径 查看mysql安装在哪
    hadoop-2.7.4-nodemanager无法启动问题解决方案
  • 原文地址:https://www.cnblogs.com/jinsedemaitian/p/5589137.html
Copyright © 2020-2023  润新知