IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> 刀与剑-COM返回数组 -> 正文阅读

[游戏开发]刀与剑-COM返回数组

????????COM明明是一种编程思想,是一门绝世武功。可时代忽然迈入火器,无数人抛弃掉这晦涩难懂的绝世武功,转身投入速成的技艺时代。

????????“很多不懂 com 的C++程序员会自行发明一个 com 的子集,而且是蹩脚的多的子集。可惜的是,刀与剑的时代结束了,火器时代,掌握 com 这类武功已经没用了。”

---知乎网友

关于使用COM接口返回数组

????????COM处理了未知语言在COM客户之间传递数组,没错。但是这个并不是什么GO之流,而是C#、VB、Delphi、asp之流甚至于py等。它模糊了语言的边界,那模糊边界自然有一个重要的前提,那就是简单易用,否则都是扯犊子。

? ? ? ? 而Com所支持的类型其中一种十分重要的即是VARIANT?,而其中有一个很重要的类型即是SAFEARRAY?这便是安全数组类型,该类型其实就是对数组进行了一些描述如起始,边界等,但是该类型又可以修饰VARIANT?为元素的数组,简直是互相套娃无穷尽也。

? ? ? ? 去百度一搜,好家伙。一来就是SAFEARRAYSAFEARRAYBOUND?。好家伙,这TM,你管这叫简单易用?我真滴服了,而且里面的内容弯弯绕绕,晦涩难懂,这些人写的都是什么博客,互相抄互相爬,感觉像在垃圾堆里找吃的。

COM传递数组涉及结构

SAFEARRAYBOUND:

? ? ? ??指示数组维数,简单来说,一维、2维甚至多维数组。因此在传递多维数组时需要一个结构描述其维度。

? ? ? ? 结构:

typedef struct tagSAFEARRAYBOUND
    {
    ULONG cElements;//表示本维元素的数目
    LONG lLbound;//数组开始的逻辑序号,实际访问需减去这个序号
    } 	SAFEARRAYBOUND;
typedef struct tagSAFEARRAYBOUND *LPSAFEARRAYBOUND;

SAFEARRAY:

????????用来实际指示数组(因为这玩意不是简简单单的指针,用指示一词),涉及的数组的操作函数的参数主体就是它

? ? ? ? 结构:

typedef struct tagSAFEARRAY
    {
    USHORT cDims;//数组的大小
    USHORT fFeatures;//数组元素类型标记值
    ULONG cbElements;//数组元素的大小
    ULONG cLocks;//被锁定次数
    PVOID pvData;//数据指针
    SAFEARRAYBOUND rgsabound[ 1 ];//数组维数描述,如果多维数组,则本数组依次为低维到高维
    } 	SAFEARRAY;
typedef /* [wire_marshal] */ SAFEARRAY *LPSAFEARRAY;

? ? ? ? 主要函数:

//为安全数组描述符分配内存。
HRESULT SafeArrayAllocDescriptor(
  [in]  UINT      cDims,
  [out] SAFEARRAY **ppsaOut
);


//根据SafeArrayAllocDescriptor创建的描述符为安全数组分配内存。
HRESULT SafeArrayAllocData(
  [in] SAFEARRAY *psa
);

//增加数组的锁计数,并检索指向数组数据的指针。
HRESULT SafeArrayAccessData( 
  SAFEARRAY FAR* psa, 
  void HUGEP* FAR* ppvData 
);


//递减数组的锁定计数,并使SafeArrayAccessData检索到的指针无效。
HRESULT SafeArrayUnaccessData(
  [in] SAFEARRAY *psa
);

//获取指定安全数组的任何维度的下边界
HRESULT SafeArrayGetLBound(
  [in]  SAFEARRAY *psa,
  [in]  UINT      nDim,
  [out] LONG      *plLbound
);

//获取指定安全数组的任何维度的上限。
HRESULT SafeArrayGetUBound(
  [in]  SAFEARRAY *psa,
  [in]  UINT      nDim,
  [out] LONG      *plUbound
);

//创建一个新的数组描述符,为数组分配和初始化数据,并返回一个指向新数组描述符的指针。
SAFEARRAY * SafeArrayCreate(
  [in] VARTYPE        vt,
  [in] UINT           cDims,
  [in] SAFEARRAYBOUND *rgsabound
);

//将数据元素存储在数组中的指定位置。
HRESULT SafeArrayPutElement(
  [in] SAFEARRAY *psa,
  [in] LONG      *rgIndices,
  [in] void      *pv
);

//检索数组的单个元素。
HRESULT SafeArrayGetElement(
  [in]  SAFEARRAY *psa,
  [in]  LONG      *rgIndices,
  [out] void      *pv
);

? ? ?用法可参考:https://blog.csdn.net/weikangc/article/details/45745551

????????? 注意事项:

? ? ? ? ? ? ? ? 1、在堆上创建数组

? ? ? ? ? ? ? ? 2、一方创建、另一方回收

? ? ? ? ? ? ? ? 3、接收方不能修改数组,只能读取和销毁

上面说的,全是垃圾

? ? ? ? 按上面这么用,初始化一个数组填值都得写几十行。我只能称之为“垃圾”

? ? ? ? 而百度去搜索的,大多数都是教你这么用,我简直了

????????解决办法

? ? ? ??CComSafeArray 类和?CComSafeArrayBound?类。

? ? ? ? ? ? ? ? 天不生这C++,万古图灵如长夜。

? ? ? ? 这两个类是SAFEARRAY和SAFEARRAYBOUND?结构的装饰模板类,用c++的类可以十分方便的去完成数组的创建,描述,设值,传出。

? ? ? ? 上代码:

? ? ? ? 一维数组创建:

CComSafeArray<long>  csa(10);  //创建一个10个元素的以0为起始下标的一维数组  
  
CComSafeArray<long>  csa(10,0);//创建一个10个元素的以0为起始下标的一维数组  
  
CComSafeArray<long>  csa(10,1);//创建一个10个元素的以1为起始下标的一维数组

? ? ? ? 多维数组创建:

//构建一个[2][3][4]数组

//维度描述
CComSafeArrayBound  b1(2,0);  
CComSafeArrayBound  b2(3,0);  
CComSafeArrayBound  b3(4,0);  
  
//设值描述数组
CComSafeArrayBound  rgBounds[]={b1,b2,b3};  
//创建多维数组  
CComSafeArray<int>  sa(rgBounds, 3);

? ? ? ? 数组设值和取值:

//GetAt  和  SetAt  
  
CComSafeArray<long>  sa(10);  
  
sa.SetAt(1,100);//将第2个元素设置为100  
  
long  value=sa.GetAt(2);     //获得第3个元素的值,放入到value中。 

? ? ? ?获得外部数组值:

void  SetArray(SAFEARRAY * psa)  
{
 CComSafeArray<long>  sa;  
  
 sa.Attach(psa);  
  
 //操作   
 .....  
  
 sa.Detach();  
 }

? ? ? ? 传出数组:

void    GetArray(SAFEARRAY ** ppsa)  
{  
      CComSafeArray  <long> sa(10);  
  
       //...
       //设值数组的值
  
       *ppsa=sa.Detach();  
}          

? ? ? ? 多维数组使用实例

//创建一个 【3】【4】的2维数组  
  
CComSafeArrayBound  b1[3];  
  
CComSafeArrayBound  b2[4];  
  
CComSafeArrayBound   rg[]={b1,b2};  


CComSafeArray<long>  sa(rg,2);  
  
  
  
  
//获得【2】【1】元素的值  
  
int   rgIndexElementA[]={1,2};   
  
long  lVal  
  
sa.MultiDimGetAt(rgIndexElementA,lVal);  
  
  
  
//设置 【0】【1】元素的值为100  
  
int   rgIndexElementB[]={1,0};  
  
long  newVal=100;  
  
sa.MultiDimSetAt(rgIndexElementB,newVal);  

? ? ? ??operator []操作符:(一维可用)

//模板自然是美滋滋重载了[]
CComSafeArray  <int>  sa(5);  
  
sa[2]=100;  

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-04-15 00:35:02  更:2022-04-15 00:38:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 16:49:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码