WEB开发网
开发学院软件开发VC 向ATL DLL中传递C++对象 阅读

向ATL DLL中传递C++对象

 2006-07-22 22:53:06 来源:WEB开发网   
核心提示:本文示例源代码或素材下载 简介几个星期以前,我拼命的寻找一个能够通过COM接口传递C++对象的例子,向ATL DLL中传递C++对象,但是,没有找到.这就是我发表这篇文章的原因,SAFEARRAY数据,有一个问题:MIDL认不出这个数据类型,向ATL的DLL中传递一个C++对象参数并不是非常之难,但是

本文示例源代码或素材下载

简介

几个星期以前,我拼命的寻找一个能够通过COM接口传递C++对象的例子,但是,没有找到.这就是我发表这篇文章的原因。

向ATL的DLL中传递一个C++对象参数并不是非常之难,但是,当然也会有点难度,也很有趣。

在开始一个工程以前,首先你得确信客户机和服务器组件都是适应C++的程序,其次,你必须知道怎样设置你的客户机和服务器。

接口的局限性

COM技术要求客户机和服务器高度的分离,这是通过接口实现的,但是问题出在:接口的方法中只提供了有限个参数数据类型,如果这个接口是基于IDispatch的,参数类型的可选范围就更加受到限制了,由于这些局限性,C++对象只有在满足以下条件时才能够传递:

  1. 客户机和服务器都是由VC++编写。
  2. 它们必须共享对象的定义(比如 头文件)。
  3. 传递应用程序设计的简单的对象。
  4. 你的应用程序可能需要运行在一个分布式环境下。你希望COM的远程活动,本地/远程活动是透明的,安全的。

我建议,在开始工作之前,先顺序的看一下各个标题,现在,我列出实例,并作以下事情:

  1. 创建一个ATL DLL服务器,
  2. 添加一个MFC类,从CObject类派生,
  3. 在类的头部使用 DECLARE_SERIAL 宏,
  4. 在类的中间使用 IMPLEMENT_SERI 宏,
  5. 覆盖Serialize() 方法, // 你的 CSimpleObj 类应该像这样:
    class CSimpleObj : public CObject
    {
        DECLARE_SERIAL( CSimpleObj )
    public:
      // 构造函数和析构函数
        CSimpleObj();
        virtual ~CSimpleObj();
      // 设置内部字符串数据
        void SetString( CString csData );
      // 用来向存档文件串行输入数据(序列化)
        virtual void Serialize(CArchive& ar);
      // 现实字符串数据
        void Show();
    private:
        CString m_strData;// 内部字符串数据
    };
    // 把这个数据对象写入到文档中
    void CSimpleObj::Serialize(CArchive& ar)
    {
        CObject::Serialize( ar );
      if (ar.IsLoading())
      {
        // 从档案文件提取数据
          ar >> m_strData;
      }
      else
      {
        // 把数据存入档案文件
          ar << m_strData;
      }
    }
    // 显示对象数据的方法
    void CSimpleObj::Show()
    {
        AfxMessageBox(m_strData);
    }
    //把字符串数据保存到一个变量中
    void CSimpleObj::SetString(CString csData)
    {
        m_strData = csData;
    }   
  6. 现在,下一步就是用一个CArchive对象来进行序列化和反序列化(载入和存储对象),我用了一个叫CBlob的新类来实现的 class CBlob
    {
    public:
        CBlob() {};
        virtual ~CBlob() {};
      // 从一个 CObject对象中提取数据并载入到一个 SAFEARRAY对象中.
        SAFEARRAY* Load( CObject *pObj );
      // 重新创建一个SAFEARRAY对象
        BOOL Expand( CObject * &pObj, SAFEARRAY *pVar );
    private:
    };
    // 从一个 CObject对象中提取数据并用它构建一个 SAFEARRAY对象.
    SAFEARRAY* CBlob::Load( CObject *pObj)
    {
        CMemFile memfile; // 内存文件
      // 定义一个用来标记档案文件是读取还是存储的标志
        long lMode = CArchive::store | CArchive::bNoFlushOndelete;
      // 用内存文件创建档案文件
        CArchive ar(&memfile, lMode );
      // m_pDocument 不使用
        ar.m_pDocument = NULL;
      // 序列化对象到档案文件中
        ar.WriteObject(pObj);
      // 关闭档案文件--现在,数据在内存文件中
        ar.Close();
      // 取得内存文件的长度(以字节为单位)
        long llen = memfile.GetLength();
      // 释放缓冲区 关闭文件
        unsigned char *pMemData = memfile.Detach();
      // 设定safearray
        SAFEARRAY *psa;
      // 创建safearray对象存取流数据
        psa = SafeArrayCreateVector( VT_UI1, 0, llen );
      // 指向字节数组的指针
        unsigned char *pData = NULL;
      // 取得一个 safe array的指针. 锁定数组.
        SafeArrayAccessData( psa, (void**)&pData );
      // 拷贝内存文件到 safearray
        memcpy( pData, pMemData, llen );
      // 清理缓冲区
        delete pMemData;
      // 锁定对 safearray的访问
        SafeArrayUnaccessData(psa);
      // 返回一个在这分配的SAFEARRAY的指针
        return psa;
    }
    // 重新创建一个SAFEARRAY对象
    BOOL CBlob::Expand(CObject * &rpObj, SAFEARRAY *psa)
    {
        CMemFile memfile; // 反序列化的内存文件
        long lLength; // 字节数
        char *pBuffer; // 缓冲区指针
      // 锁定数组数据的访问
        SafeArrayAccessData( psa, (void**)&pBuffer );
      // 取得数组中元素个数. 是字节数
        lLength = psa->rgsabound->cElements;
      // 连接缓冲区到内存文件
        memfile.Attach((unsigned char*)pBuffer, lLength);
      // 从缓冲区头部开始
        memfile.SeekToBegin();
      // 创建一个连接到内存文件上的档案文件
        CArchive ar(&memfile, CArchive::load | CArchive::bNoFlushOndelete);
      // 不使用文档指针
        ar.m_pDocument = NULL;
      // 填充对象 取得指针
        rpObj = ar.ReadObject(0);
      // 关闭档案文件
        ar.Close();
      // 注意: 当SAFEARRAY被毁坏时 pBuffer 被释放
      // 释放缓冲区 关闭文件
        pBuffer = (char*) memfile.Detach();
      // 释放safearray 缓冲区
        SafeArrayUnaccessData( psa );
        return TRUE;
    }
在这里 ,我使用SAFEARRAY是因为它对我们来说是最好的选择,它可以包含一些复杂的多维数组,但是,这个例子我们只使用了非常简单的数组,SAFEARRAY数据,有一个问题:MIDL认不出这个数据类型,在下一篇文章中我将讲述最简单的方法:使用 VARIANT数据类型。

1 2  下一页

Tags:ATL DLL 传递

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接