Chinaunix首页 | 论坛 | 博客
  • 博客访问: 16498456
  • 博文数量: 5645
  • 博客积分: 9880
  • 博客等级: 中将
  • 技术积分: 68081
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-28 13:35
文章分类

全部博文(5645)

文章存档

2008年(5645)

我的朋友

分类:

2008-04-28 20:58:42

下载本文示例代码
  简介  几个星期以前,我拼命的寻找一个能够通过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;}   现在,下一步就是用一个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数据类型。共2页。 1 2 :   简介  几个星期以前,我拼命的寻找一个能够通过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;}   现在,下一步就是用一个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数据类型。共2页。 1 2 : 下载本文示例代码


向ATL的DLL中传递C 对象参数向ATL的DLL中传递C 对象参数向ATL的DLL中传递C 对象参数向ATL的DLL中传递C 对象参数向ATL的DLL中传递C 对象参数向ATL的DLL中传递C 对象参数向ATL的DLL中传递C 对象参数向ATL的DLL中传递C 对象参数向ATL的DLL中传递C 对象参数向ATL的DLL中传递C 对象参数向ATL的DLL中传递C 对象参数向ATL的DLL中传递C 对象参数向ATL的DLL中传递C 对象参数向ATL的DLL中传递C 对象参数向ATL的DLL中传递C 对象参数
阅读(219) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~