1 SafeArray的作用

  •   使用SafeArray SafeArray是VB中的数组存储方式。通过SafeArray,可以在VC++和VB间相互调用。
  •   SafeArray也是Automation中的标准数组存储方式。SAFEARRAY的主要目的是用于automation中的数组型参数的传递。因为在网络环境中,数组是不能直接传递的,而必须将其包装成SafeArray。
  •   实质上SafeArray就是将通常的数组增加一个描述符,说明其维数、长度、边界、元 素类型等信息。
  •   SafeArray也并不单独使用,而是将其再包装到VARIANT类型的变量中,然后才作为参数传送出去。
  •   在VARIANT的vt成员的值如果包含VT_ARRAY|...,那么它所封装的就是一个SafeArray,它的parray成员即是指向SafeArray的指针。
  •   SafeArray中元素的类型可以是VARIANT能封装的任何类型,包括VARIANT类型本身。

将SafeArray包装到VARIANT变量中

SAFEARRAY *pSa;

VARIANT v1;

VariantInit(&v1);

v1.vt = VT_I4 | VT_ARRAY; // Array of 4 byte integers

v1.parray = pSa;

2 SafeArray结构体

typedef struct tagSAFEARRAY
{
  unsigned short cDims;//维数   unsigned short fFeatures;// 用来描述数组如何分配和如何被释放的标志   unsigned long cbElements;// 数组元素的大小   unsigned long cLocks;// 一个计数器,用来跟踪该数组被锁定的次数   void * pvData;// 指向数据缓冲的指针   SAFEARRAYBOUND rgsabound[ ];// 描述数组每维的数组结构,该数组的大小是可变的 } SAFEARRAY;

这个结构的成员(cDims,cLocks等)是通过API函数来设置和管理的。真正的数据存放在pvData成员中,而SAFEARRAYBOUND结构定义该数组结构的细节。以下就是该结构成员的简要描述:

rgsabound成员是一个SAFEARRAYBOUND结构的数组--每个元素代表SAFEARRAY的一个维。

typedef struct tagSAFEARRAYBOUND

{

unsigned long cElements;// 每维中元素的个数

unsigned long lLbound;//

} SAFEARRAYBOUND;

例如C语言中的数组int a[3][4][5]用安全数组表示的时候则 cDims=3 ;cbElements=sizeof(int) 元素 cElements lLbound

rgsabound[0] 3 0

rgsabound[1] 4 0

rgsabound[2] 5 0

3 SafeArray的初始化方法

方法一 利用SafeArrayAllocDescriptor和SafeArrayAllocData在堆上创建一维数组。 long nData[10]={1,2,3,4,5,6,7,8,9,10};//数据源

SAFEARRAY* pArray=NULL;

HRESULT hr=SafeArrayAllocDescriptor(,&pArray);

HRESULT SafeArrayAllocDescriptor

(

unsigned int cDims,

SAFEARRAY FAR* FAR* ppsaOut

);

pArray->cbElements=sizeof(nData[]);

pArray->rgsabound[].cElements=; pArray->rgsabound[].lLbound=; SafeArrayAllocData(pArray);

long* pData=NULL;

SafeArrayAccessData(pArray,(void**)&pData); long l(),h(); SafeArrayGetLBound(pArray,,&l);//维数索引从1开始

HRESULT SafeArrayGetLBound

(

SAFEARRAY FAR* psa,

unsigned int nDim,

long FAR* plLbound

);

SafeArrayGetUBound(pArray,,&h);

long Size=h-l+; SafeArrayAccessData(pArray,(void**)&pData); for(long Idx=l;Idx<Size;++Idx) { }

SafeArrayUnaccessData(pArray); pData[Idx]=nData[Idx];

方法二 用SafeArrayAllocDescriptor和SafeArrayAllocData在堆上创建二维数组

SAFEARRAY* pArray=NULL;

HRESULT hr=SafeArrayAllocDescriptor(,&pArray)

pArray->rgsabound[].lLbound=;

pArray->rgsabound[].cElements=;

pArray->rgsabound[].lLbound=;

pArray->rgsabound[].cElements=;

pArray->cbElements=sizeof(long);

hr=SafeArrayAllocData(pArray);

赋初值

long Demen[];

for(long i=;i<;++i)

{

for(long j=;j<;++j)

{

Demen[]=i;

}

}

  在SafeArrayPutElement 函数中需要注意的是如何指定所需元素。SafeArrayPutElement 的第二个变量是一指针,它指向数组各维的索引向量。最右边的一维(最低位)放在向量的最前(index[0]);最左边的一维(最低位)放在向量的最后(index【cDims-1]】)。由于在C++中对多维数组的访问正好与此相反,所以需要特别注意这点。

  即用SafeArrayPutElement对二维SAFEARRAY数组使用的时候下标要注意, Demen[1]代表行,Demen[0]代表列。 Demen[0]=j; ong x=i*j; SafeArrayPutElement(pArray,Demen,&x);

访问二维数组

for(long i=;i<;++i)

{

for(long j=;j<;++j)

{

http://9455.net九九文章网

} Demen[]=i; Demen[]=j; long x(); SafeArrayGetElement(pArray,Demen,&x); cout<<"("<<i<<","<<j<<") "<<x<<endl; }

SafeArrayDestroy(pArray);

  在 SafeArrayPutElement 与 SafeArrayGetElement 函数的明显的局限性在于它们每次只能处理一个数值,在处理大量安全数组的数据时会极大地降低性能。此时,可以选择使用函数SafeArrayAccessData 和 SafeArrayUnaccessData。SafeArrayAccessData 和 SafeArrayUnaccessData 将数组锁定在内存中,并返回指向该安全数组数据的指针,这样便可以直接访问安全数组中的数据

例如

SafeArray* psa

long * pData;

long * pData;

SafeArrayAccessData(psa, (LPVOID *)&pData);

// Set or get any values in the array.

*pData = ;

*(pData + ) = ;

*(pData + ) = ;

*(pData + ) = ;

*(pData + ) = ;

*(pData + ) = ;

*(pData + ) =;

*(pData + ) = ;

// Unlock the array.(pData is no longer valid.)

SafeArrayUnaccessData(pSa);

然后进行如下操作

index[] = ;

index[] = ;

SafeArrayGetElement(pSa, index, &NewData);

cout << NewData << endl;

则NewData的值为11

方法四:使用SafeArrayCreate在堆上创建一维数组

SAFEARRAYBOUND Bound[];

Bound[].lLbound=;

Bound[].cElements=; 
SAFEARRAY* pArray=SafeArrayCreate(VT_I4,,Bound);
long* pData=NULL;
HRESULT hr=SafeArrayAccessData(pArray,(void**)&pData);
long Low(),High();
SafeArrayGetLBound(pArray,,&Low);
SafeArrayGetUBound(pArray,,&High);
long Size=High-Low+;
for(long Idx=Low;Idx<Size;++Idx) { } SafeArrayUnaccessData(pArray);
SafeArrayDestroy(pArray);
pData[Idx]=Idx;
cout<<pData[Idx]<<endl;

方法五:使用SafeArrayCreate在堆上创建二维数组

SAFEARRAYBOUND Bound[]; Bound[].lLbound=; Bound[].cElements=; Bound[].lLbound=;

Bound[].cElements=; SAFEARRAY* pArray=SafeArrayCreate(VT_I4,,Bound); long Demen[]; for(long i=;i<;++i) { } for(long j=;j<;++j) { } Demen[]=i; Demen[]=j; long x=i*j; SafeArrayPutElement(pArray,Demen,&x);

//访问二维数组

for(long i=;i<;++i)

{

}

SafeArrayDestroy(pArray); for(long j=;j<;++j) { } Demen[]=i; Demen[]=j; long x(); SafeArrayGetElement(pArray,Demen,&x); cout<<"("<<i<<","<<j<<") "<<x<<endl;

  根据MSDN中SafeArrayAllocDescriptor allows the creation of safe arrays that contain elements with data types other than those provided by After creating an array descriptor using SafeArrayAllocDescriptor, set the element

WINDOWS-基础:SafeArray的使用方法的更多相关文章

  1. Java基础 之 System.getProperty()方法

    Java基础 之 System.getProperty()方法大全 public static void main(String[] args) { System.out.println(" ...

  2. Windows 系统 PostgreSQL 手工安装配置方法

    自从2020年底开始接触 PostgreSQL 以来就喜欢上了这个数据库,个人感觉比 MySQL 好用,多表联合查询性能好很多,同时也不存在 SQLServer 的版权授权费用问题.搭配 .NET 开 ...

  3. SQLSERVER误删除了Windows登录用户验证方式使用Windows身份验证的解决方法

    SQLSERVER误删Windows登录用户验证方式使用Windows身份验证的解决方法 今天看到这篇文章:没有了SA密码,无法Windows集成身份登录,DBA怎么办? 想起来之前着急哥问我的一个问 ...

  4. 转载扩展Windows Mobile模拟器存储空间的方法

    扩展Windows Mobile模拟器存储空间的方法 在Windows Mobile应用程序开发的初期,可以使用SDK自带的模拟器来进行调试,这给我们开发人员提供了一种方便的途径.一般的应用程序,占用 ...

  5. 在Linux下和Windows下遍历目录的方法及如何达成一致性操作

    最近因为测试目的需要遍历一个目录下面的所有文件进行操作,主要是读每个文件的内容,只要知道文件名就OK了.在Java中直接用File类就可以搞定,因为Java中使用了组合模式,使得客户端对单个文件和文件 ...

  6. Windows的拖放操作使用方法

    Windows的拖放操作使用方法

  7. Linux和Windows下查看环境变量方法对比

    摘自:Linux和Windows下查看环境变量方法对比 一.查看所有环境变量的名称和值 Linux下:export Windows下:set 二.根据名称查该环境变量的值 Linux下:echo $环 ...

  8. Delphi一共封装(超类化)了8种Windows基础控件和17种复杂控件

    超类化源码: procedure TWinControl.CreateSubClass(var Params: TCreateParams; ControlClassName: PChar); con ...

  9. 在Linux下访问Windows共享目录的配置方法

    在Linux下访问Windows共享目录的配置方法 1.在Windows上设置一个共享目录 如:将d:\RedHat_disk设置为共享目录 2.在Windows上创建一个用户,如tommy,密码11 ...

  10. windows 下共享内存使用方法示例

    windows下共享内存使用方法较 linux 而言微微复杂 示例实现的功能 有一个视频文件,一块内存区域 : 程序 A,将该视频写入该内存区域 : 程序 B,从该内存区域读取该视频 : 代码模块实现 ...

随机推荐

  1. 洛谷P3200 [HNOI2009]有趣的数列(Catalan数)

    P3200 [HNOI2009]有趣的数列 题目描述 我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件: (1)它是从1到2n共2n个整数的一个排列{ai}: (2)所有的奇数项满足 ...

  2. 2014 Noip提高组 Day2

    P2038 无线网络发射器选址 [题目描述] 随着智能手机的日益普及,人们对无线网的需求日益增大.某城市决定对城市内的公共场所覆盖无线网. 假设该城市的布局为由严格平行的129 条东西向街道和129 ...

  3. 【ZJOI2007】捉迷藏 小小的总结

    2019-01-09 22:56:33 终于终于把这道题目做掉了... 做了两个晚上..不知道为什么自己如此之笨.. 在洛谷上断断续续一共交了24次,感觉自己都要被封号了. 昨天花半个晚上从零开始研究 ...

  4. InstelliJ IDEA使用js+servlet+ajax入门

    对于Ajax,我们先了解三点(完整的JS代码在后面) 一.Ajax的出现对javascript的影响. Ajax是微软提出的一种允许客户端脚本发送HTTP请求的技术(XMLHTTP),拯救了大多数ja ...

  5. Centos下磁盘管理的常用命令记录(如查找大文件)

    Centos下磁盘管理的常用命令记录 查看系统磁盘空间占用,使用命令: df -h 结果: 查看磁盘inode使用情况,如果inode用完了,磁盘就没法写入新的内容了: df -i 结果: 如何查找磁 ...

  6. Jmeter集成Jira提交缺陷

    笔者曾在文章<Jmeter排忧解难—生成excel结果文件>聊到了一种提高接口测试效率的方法.今天,咱们接着对“提高接口测试效率”这个话题做更深入的探讨.作为一名接口测试人员,我们是否一直 ...

  7. jQuery banner切换插件

    今天学写了一个基于jQuery焦点图切换插件,有不对的地方还请多多指教,不多说下面是代码: 1.引jQuery库 <script src="http://code.jquery.com ...

  8. 开发工具~nuget配置本地源

    我们在本地部署了自己的nuget服务器,有时可以需要用到nuget restore命令去恢复包包,它会从下面的nuget.config里读你的配置源信息,就是在这里,我们要把内测的nuget服务器路径 ...

  9. Python踩坑之旅其二裸用os.system的原罪

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4.1 技术关键字 1.5 填坑总结 2. 前坑回顾 2.1 Linux中, 子进程拷贝父进程哪些信息 2.2 Agent常驻进程选择& ...

  10. Java中常见的坑

    概述 Java是门极简风格的语言,比其它语言相比,它故意保持较少的特性,不仅在有些不常见的情况下会出些奇奇怪怪的错误,即使很一般的情况下也有可能让人栽根头.如果你习惯了别的语言,你读Java 的代码很 ...