各位高手,因工作需要,小弟手上有一个别人开发的以伪COM接口开发的动态链接库PcomSerialPort.dll
及对应的头文件和帮助文件库文件PcomSerialPort.dll用Dependency Walker打开只看到如下两个成员:
CreateObject()
GetInterfaceList()对应的头文件完整內容如下:#if !defined(__PCOM_INTERFACE_IPcomSerialPort_H_INCLUDED__)
#define __PCOM_INTERFACE_IPcomSerialPort_H_INCLUDED__namespace PcomSerialPort
{
#define SERIAL_FLOWCTRL_NONE 0
#define SERIAL_FLOWCTRL_HARD 1
#define SERIAL_FLOWCTRL_XONXOFF 2
#define CHAR_BUF_SIZE 1000#define DELAY_ZERO 0
#define _PCOM_OK (HRESULT)0x00000000#define IID_IPcomSerialPort "IPcomSerialPort"
#define WAIT_REG (DWORD)1 //等待参数为正则表达式
#define WAIT_STR ~WAIT_REG //等待参数为普通字符串//information level
#define INFO_SUCCESS 0
#define INFO_HINT 1
#define INFO_WARNING 2
#define INFO_ERROR 3
#define INFO_END 4
typedef DWORD (*PFnRecCall)(LPVOID lpParameter1,LPVOID lpParameter2);
typedef BOOL (*PFnIsStop)(LPVOID lpParameter1,LPVOID lpParameter2); struct SReadPara
{
SReadPara();
~SReadPara();
BOOL m_bRead;           //[out]TRUE: serial port receive data; FALSE:receive nothing 
unsigned char* m_pDest; //[in] dest buffer point
int m_nSize;            //[in] dest buffer size(bytes)
int m_nReaded;          //[out]receive bytes number 
};interface IPcomSerialPort : public IUnknown
{
//设置调试信息输出级别程序
virtual HRESULT __stdcall SetDebugLevel(ULONG ulLevel ,BOOL bFlag) = 0;
//查询错误码对应的错误信息
virtual HRESULT __stdcall GetErrorInfo(ULONG  ulCode, char* pErrorInfo,ULONG ulLength) = 0;
//获取连接使用串口号
virtual HRESULT __stdcall GetCurrentPort(int &nPort) = 0;
//设置连接使用串口号
virtual HRESULT __stdcall SetCurrentPort(int nPort) = 0;
//获取当前串口波特率
    virtual HRESULT __stdcall GetCurrentBaudRate(UINT &uBaudRate) = 0;
//设置当前串口波特率
virtual HRESULT __stdcall SetCurrentBaudRate(UINT uBaudRate) = 0;
//获取当前串口Byte大小
virtual HRESULT __stdcall GetCurrentByteSize(BYTE &byByteSize) = 0;
//设置当前串口Byte大小
virtual HRESULT __stdcall SetCurrentByteSize(BYTE byByteSize) = 0;
//获取当前串口校验方式
virtual HRESULT __stdcall GetCurrentParity(BYTE &byParity) = 0;
//设置当前串口校验方式
virtual HRESULT __stdcall SetCurrentParity(BYTE byParity) = 0;
//获取当前串口stop bits
virtual HRESULT __stdcall GetCurrentStopBits(BYTE &byStopBits) = 0;
//设置当前串口stop bits
virtual HRESULT __stdcall SetCurrentStopBits(BYTE byStopBits) = 0;
//获取当前串口流控方式
virtual HRESULT __stdcall GetCurrentFlowCtrlType(BYTE &byFlowCtrl) = 0;
//设置当前串口流控方式
virtual HRESULT __stdcall SetCurrentFlowCtrlType(BYTE byFlowCtrl) = 0;
//开始串口通信
virtual HRESULT __stdcall StartSerialComm(LPCSTR lpcsParam) = 0;
    //向串口写数据
virtual HRESULT __stdcall WriteCommString(CString& szSend, UINT nLineDelay = 100, UINT nCharDelay = 50) = 0;
        //提供行延迟和字符延迟的写串口数据函数
virtual HRESULT __stdcall WriteCommData(unsigned char* pWriteBuffer, UINT nSize, UINT nLineDelay, UINT nCharDelay) = 0;
 //关闭串口,停止串口通信函数
        virtual HRESULT __stdcall CloseSerialComm(LPCSTR lpcsParam = NULL) = 0;
 //发送字符串并匹配接收字符串函数
        virtual HRESULT __stdcall SendAndWaitFor(LPCSTR lpsSend, CString szWait, CString *pstrGot, UINT nTimeOut, DWORD dwFlag, UINT nLineDelay,UINT nCharDelay) = 0;
//发送字符串用一组字符串匹配接收字符串函数
virtual HRESULT __stdcall SendAndWaitForA(LPCSTR lpsSend, CStringArray& szAryWait, CString *pstrGot, UINT nTimeOut, DWORD dwFlag, UINT nLineDelay,UINT nCharDelay) = 0;
 //开始读取接收字符串
        virtual HRESULT __stdcall StartReadStr(CString* pStr) = 0;
//停止读取接收字符串
virtual HRESULT __stdcall StopReadStr(CString* pStr) = 0;
//停止读等待,停止写串口操作函数
virtual HRESULT __stdcall StopWaitFor() = 0;
//判断串口打开函数
virtual HRESULT __stdcall PortIsOpen() = 0;
//注册接收处理回调函数
virtual HRESULT __stdcall RegisterFn(PFnRecCall pFn, LPVOID pPara2) = 0;
//注销接收处理回调函数
virtual HRESULT __stdcall UnRegisterFn() = 0;
//注册外部中断回调函数
virtual HRESULT __stdcall RegisterStopFn(PFnIsStop pFn, LPVOID para1, LPVOID para2) = 0;
 //注销外部终端回调函数
virtual HRESULT __stdcall UnRegisterStopFn() = 0;
virtual HRESULT __stdcall SendAndWaitData(const void* pInBuffer, void* pOutBuffer, int iOutBuffLen, UINT uTimeOut) = 0;
virtual HRESULT __stdcall StartRead(SReadPara* pReadPara) = 0;
virtual HRESULT __stdcall StopRead(SReadPara* pReadPara) = 0;
virtual HRESULT __stdcall SendAndWaitForB(LPCSTR lpsSend, CStringArray& szAryWait, CString *pstrGot, int& iFound, UINT nTimeOut, DWORD dwFlag, UINT nLineDelay,UINT nCharDelay) = 0;
virtual HRESULT __stdcall SetMode(int nParity,int nBaudRate ,int nStopBits = 0 ,int nByteSize = 8) = 0;
virtual HRESULT __stdcall ClearBuffer(UINT uiLen = CHAR_BUF_SIZE) = 0;
virtual HRESULT __stdcall EscapeCommFunction(DWORD dwFunc) = 0;
virtual HRESULT __stdcall SendAndWaitDataEx(const void* pInBuffer, int iSendDataLen, void* pOutBuffer, int iOutBuffLen, int& iRecvDataLen, UINT uTimeOut) = 0;
//{{PCOM_INSERT_LOCATION}}
};}
#endif // !defined(__PCOM_INTERFACE_IPcomSerialPort_H_INCLUDED__)
帮助文件中关于此库的用法示例如下:       IPcomSerialPort* m_pPcomSerialPort = NULL; 
       int iRet;
       //@if Instrument Device point is NULL, Open Device;       if(NULL == m_pPcomSerialPort)
       {m_pPcomSerialPort = (PcomSerialPort::IPcomSerialPort *)m_pGlobalUnit->OpenTUSDevice ( " IPcomSerialPort",  "1.0.0.0");
              if(NULL == m_pPcomSerialPort)
              {
                     return FALSE;       
              }
       }
       //@Set Serial parameter
       LPCSTR lpcsParam = "";
       m_pPcomSerialPort->SetCurrentPort(m_uPort);
       m_pPcomSerialPort->SetCurrentBaudRate(CBR_9600);
       m_pPcomSerialPort->SetCurrentParity(NOPARITY);
       m_pPcomSerialPort->SetCurrentByteSize(8);
       m_pPcomSerialPort->SetCurrentStopBits(ONESTOPBIT);
       m_pPcomSerialPort->SetCurrentFlowCtrlType(SERIAL_FLOWCTRL_NONE);
       //Open serial and begin serial communication;
       m_pPcomSerialPort->StartSerialComm(lpcsParam);          //@call SendAndWaitFor function for match receive string from serial receive buffer
       HRESULT hr =-1;
       hr = m_pIPcomSerialPort->SendAndWaitFor(m_szInputChar, szWait, &szGot, nTimeOut, dwFlag, nLineDelay, nCharDelay);
       if(SUCCEEDED(hr) )
       {
              AfxMessageBox(szGot);
       }
       else
       {
              AfxMessageBox("Failed");
       }      …
       //@End of serial communication
//@Close Instrument
       if(NULL != m_pPcomSerialPort)
       {
              m_pPcomSerialPort->CloseSerialComm(lpcsParam);
              m_pGlobalUnit->CloseTUSDevice(m_pPcomSerialPort);
              m_pPcomSerialPort = NULL;
       }
请教这种COM的实现原理,现在就是不明白实现文件应该怎么写,还有客户程序应该怎么调用,希望有明白这种写法的高手能
详细解答。谢谢!!!

解决方案 »

  1.   

    不明白什么是伪COM接口!求解释
      

  2.   

    它这个是借助了COM的一些思想,只暴露两个函数给你,让你获取它内部的接口对象等,然后你就可以根据这个对象,来调用它内部封装的方法。
      

  3.   

    先看这个dll, 依给出的客户程序来看,这个dll并非com组件,可以理解成常规的dll导出了2个全局函数,只是它导出函数返回的是一个抽象接口,内部应该有个类继承这个接口并实现了接口的全部虚函数,这个类也即实现类。至于客户如何调用,简单的遵循头文件的说明调用接口里的方法就可以了。一般过程:
    创建接口->使用接口方法->释放接口资源
      

  4.   

    谢谢各位的回复,确实是oyljerry和mmxida所说的这样,再进一步请教:
    OpenTUSDevice和CloseTUSDevice这两个函数怎么理解呢?在他们所有这种DLL中都是用的这两个函数。
    为什么CreateObject()和GetInterfaceList()在示例中没有看到调用?跟下面这种方式是不是一个原理呢?为什么下面这个就不从IUnknow继承呢?
    我把这两个抽象接口做成DLL,然后客户端调用,CA这部分接口的实现,在源文件中,没有在头文件里啊,怎么用呢?谢谢!    // 基于虚函数的接口实现,这里并不是真正的COM组件技术  
        // 真正的COM下,客户端不需要了解组件的实现,只是通过接口来使用组件提供的功能  
          
        #include <objbase.h>  
        #include <iostream.h>  
          
        void trace(const char *pMsg)  
        {  
            cout << pMsg << endl;  
        }  
          
        // 两个抽象接口  
          
        interface IX  
        {  
            virtual void _stdcall Fx1() = 0;   // _stdcall  Pascal方式清理C方式压栈,也称标准方式调用  
            virtual void _stdcall Fx2() = 0;   //           常规c++调用中,栈的清理是由调用者完成  
                                               //           这里是函数自己清理  
        };  
          
        interface IY  
        {  
            virtual void _stdcall Fy1() = 0;  
            virtual void _stdcall Fy2() = 0;  
        };  
          
          
        // 接口实现  
        class CA : public IX,  
                   public IY  
        {  
            public:  
                // 接口1实现:组件1  
                virtual void _stdcall Fx1()  
                {  
                    cout << "CA::Fx1" << endl;  
                }  
          
                virtual void _stdcall Fx2()  
                {  
                    cout << "CA::Fx2" << endl;  
                }  
          
                //////////////////////////////////  
          
                // 接口2实现:组件2  
                virtual void _stdcall Fy1()  
                {  
                    cout << "CA::Fy1" << endl;  
                }  
          
                virtual void _stdcall Fy2()  
                {  
                    cout << "CA::Fy2" << endl;  
                }  
        };  
          
          
          
          
          
          
        // 客户端代码  
        int main()  
        {  
            trace("client: Create an instance of the component.");  
            CA* pA = new CA;  
          
            // 获得一个IX接口  
            IX* pIX = pA;  
          
            trace("client: use the IX interface");  
            pIX->Fx1();  
            pIX->Fx2();  
          
            // 获取IY接口  
            IY* pIY = pA;  
          
            trace("client: use the IY interface");  
            pIY->Fy1();  
            pIY->Fy2();  
          
            trace("client: delete the component");  
            delete pA;  
          
            return 0;  
        }  
      

  5.   

    就是借鉴COM的接口的概念(纯虚类,没有成员变量,所有成员函数都纯虚)而已,不难理解吧?
      

  6.   

    这两个函数CreateObject()和GetInterfaceList()应该是创建接口用的吧?
    为什么在头文件里看不到声明呢?
      

  7.   

    这两个函数是DLL发布出来的函数...COM也有固定的发布函数名称的, 只是平时隐藏起来, DllCanUnloadNow这个就是规定的导出函数. COM和DLL的区别, 在于COM有规定的导出函数名称, 并且函数实现有规定的. 接口的实现也是有规定的, 而自己写的DLL, 导出函数名称自定, 接口也自定, 仅此而已
      

  8.   

    伪COM接口,就是不需要注册的COM
      

  9.   

    帮忙顶一下,最近也遇到了同样的问题,如何在一个PCOM组件中,添加具有一定功能的接口呢?