文档章节

关于SafeArray的使用说明(转)

小青_1989
 小青_1989
发布于 2014/06/06 15:52
字数 1532
阅读 17
收藏 0
点赞 0
评论 0

  猛料资料,首先介绍SafeArray使用,在介绍SafeArray中的结构。看完该节文章,SafeArray的陌生感一扫而去。

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

使用SafeArray的具体步骤:

方法一:

 包装一个SafeArray:

(1)定义变量,如:

   VARIANT varChunk;

   SAFEARRAY *psa;

   SAFEARRAYBOUND rgsabound[1];

(2) 创建SafeArray描述符:

 //read array from a file.

 uIsRead=f.Read(bVal,ChunkSize);

 if(uIsRead==0)

break;

 rgsabound[0].cElements = uIsRead;

 rgsabound[0].lLbound = 0;

 psa = SafeArrayCreate(VT_UI1,1,rgsabound);

(3)放置数据元素到SafeArray:

 for(long index=0;index<uIsRead;index++)         

 {

    if(FAILED(SafeArrayPutElement(psa,&index,&bVal[index])))

    ::MessageBox(NULL,"出毛病了。","提示",MB_OK | MB_ICONWARNING);

  }

 一个一个地放,挺麻烦的。

(4)封装到VARIANT内:

   varChunk.vt = VT_ARRAY|VT_UI1;

   varChunk.parray = psa;

 这样就可以将varChunk作为参数传送出去了。

读取SafeArray中的数据的步骤:

(1)用SafeArrayGetElement一个一个地读

 BYTE buf[lIsRead];

 for(long index=0; index<lIsRead; index++)        

 {          

    ::SafeArrayGetElement(varChunk.parray,&index,buf+index);  

 }

 就读到缓冲区buf里了。

方法二:

 使用SafeArrayAccessData直接读写SafeArray的缓冲区:

(1)读缓冲区:

 BYTE *buf;

 SafeArrayAccessData(varChunk.parray, (void **)&buf);

 f.Write(buf,lIsRead);

 SafeArrayUnaccessData(varChunk.parray);

(2)写缓冲区:

 BYTE *buf;

 ::SafeArrayAccessData(psa, (void **)&buf);

 for(long index=0;index<uIsRead;index++)         

 {

     buf[index]=bVal[index]; 

 }

 ::SafeArrayUnaccessData(psa);

 varChunk.vt = VT_ARRAY|VT_UI1;

 varChunk.parray = psa;

   

    这种方法读写SafeArray都可以,它直接操纵SafeArray的数据缓冲区,比用SafeArrayGetElement和 SafeArrayPutElement速度快。特别适合于读取数据。但用完之后不要忘了调用::SafeArrayUnaccessData (psa),否则会出错的。

以下就是SAFEARRAY的Win32定义:

  typedef struct tagSAFEARRAY

   {

    unsigned short cDims;

    unsigned short fFeatures;

    unsigned long cbElements;

    unsigned long cLocks;

    void * pvData;

    SAFEARRAYBOUND rgsabound[ 1 ];

   } SAFEARRAY;

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

成员

描述

cDims

数组的维数

fFeatures

用来描述数组如何分配和如何被释放的标志

cbElements

数组元素的大小

cLocks

一个计数器,用来跟踪该数组被锁定的次数

pvData 

指向数据缓冲的指针

rgsabound

描述数组每维的数组结构,该数组的大小是可变的

 rgsabound是一个有趣的成员,它的结构不太直观。它是数据范围的数组。该数组的大小依safe array维数的不同而有所区别。rgsabound成员是一个SAFEARRAYBOUND结构的数组--每个元素代表SAFEARRAY的一个维。

  typedef struct tagSAFEARRAYBOUND

   {

    unsigned long cElements;

    unsigned long lLbound;

   } SAFEARRAYBOUND;

  维数被定义在cDims成员中。例如,一个\'C\'类数组的维数可以是[3][4][5]-一个三维的数组。如果我们使用一个SAFEARRAY来表示这个结构,我们定义一个有三个元素的rgsabound数组--一个代表一维。

  cDims = 3;

    ...

  SAFEARRAYBOUND rgsabound[3];

  rgsabound[0]元素定义第一维。在这个例子中ILBOUND元素为0,是数组的下界。cElements成员的值等于三。数组的第二维 ([4])可以被rgsabound结构的第二个元素定义。下界也可以是0,元素的个数是4,第三维也是这样。

   要注意,由于这是一个"C"数组,因此由0 开始,对于其它语言,例如Visual Basic,或者使用一个不同的开始。该数组的详细情况如下所示:

元素

cElements

ILbound

rgsabound[0] 

0

rgsabound[1]

0

rgsabound[2]

5

0

   关于SAFEARRAYBOUND结构其实还有很多没说的。我们将要使用的SAFEARRAY只是一个简单的单维字节数组。我们通过API函数创建数组的时候,SAFEARRAYBOUND将会被自动设置。只有在你需要使用复杂的多维数组的时候,你才需要操作这个结构。

  还有一个名字为cLocks的成员变量。很明显,它与时间没有任何的关系--它是一个锁的计数器。该参数是用来控制访问数组数据的。在你访问它之前,你必须锁定数据。通过跟踪该计数器,系统可以在不需要该数组时安全地删除它。 

创建SAFEARRAY

  创建一个单维SAFEARRAY的简单方法是通过使用SafeArrayCreateVector API函数。该函数可分配一个特定大小的连续内存块。

  SAFEARRAY *psa;

  //  create a safe array to store the stream data

  //  llen is the number of bytes in the array.

  psa = SafeArrayCreateVector( VT_UI1, 0, llen );

   SafeArrayCreateVector API创建一个SAFEARRAY,并且返回一个指向它的指针。首个参数用来定义数组的类型--它可以是任何有效的变量数据类型。为了传送一个串行化的对 象,我们将使用最基本的类型--一个非负的字节数组。VT--UI1代表非负整形的变量类型,1个字节。

  常数\'0\'定义数组的下界;在C++中,通常为0。最后的参数llen定义数组元素的个数。在我们的例子中,这与我们将要传送对象的字节数是一样的。我们还没有提数组大小(llen)是怎样来的,这将在我们重新考查串行化时提及。

  在你访问SAFEARRAY数据之前,你必须调用SafeArrayAccessData。该函数锁定数据并且返回一个指针。在这里,锁定数组意味着增加该数组的内部计数器(cLocks)。

  //  define a pointer to a byte array

  unsigned char *pData = NULL;

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

   ... use the safe array

  SafeArrayUnaccessData(psa);

  相应用来释放数据的函数是SafeArrayUnaccessData(),该功能释放该参数的计数。



本文转载自:http://www.cppblog.com/kenlistian/archive/2008/02/13/42695.html

共有 人打赏支持
小青_1989
粉丝 3
博文 75
码字总数 12913
作品 0
大连
程序员
Class SafeArray

Class SafeArray public final class SafeArray{ // Constructors public SafeArray(int vt); public SafeArray(int vt, int celems); public SafeArray(int vt, int celems1, int celems2);......

小青_1989
2014/06/06
0
1
SAFEARRAY使用实例

目录: SAFEARRAY使用实例... 1 目录:... 1 前言:... 1 何谓SAFEARRAY:... 1 创建SAFEARRAY:2 方法一:使用SafeArrayAllocDescriptor在栈上创建一维数组... 2 方法二:使用SafeArrayAllo...

长平狐
2012/08/28
902
0
在C#中int,string等各种类型之间的相互转换--现在写点技术文档

简单方法:int转String:ToString();int转string:int.Parse() 复杂方法:int转String:System.Convert.ToString();int转string:System.Convert.ToIntXX() 2. int32.parse(xxxxxx); xx.t......

C_Sharp大大
2013/06/12
0
2
Excel插件开发

1、 新建ATL工程,在ATL项目向导中选中“允许合并代理/存根代码(P)”以及“支持MFC(M)”,如下图所示: 单击完成,类视图如下所示: 2、 接下来为工程新建一个简单的ATL对象,并键入类名Excel...

ucliaohh
2016/03/03
146
0
COM封装字节数组,并用于C#/c++中

由于项目开发需要,原有的程序用C++开发,但是现有用C#开发,所以需要对用C++开发的接口利用COM进行封装,供c#语言调用,在此处用到一个字节数组,所以此处对其进行封装。 (一)用到的COM接...

西昆仑
2012/04/27
0
1
深度集成 xmake 和 Intellij-IDEA 的插件--xmake-idea

xmake-idea插件深度集成了xmake和Intellij-IDEA (CLion/Android Studio/ ..),提供方便快速的跨平台c/c++构建。 注:使用此插件,需要先安装xmake,更多关于xmake的使用说明,请阅读:文档手...

ruki
2017/11/07
241
3
xmake-sublime 插件 v1.0.3 正式版本发布

xmake-sublime插件深度集成了xmake和sublime,提供方便快速的跨平台c/c++构建。 注:使用此插件,需要先安装xmake,更多关于xmake的使用说明,请阅读:文档手册 特性 快速开始 语法色彩高亮 ...

ruki
2017/10/25
763
6
集成 Xmake 的 Sublime Text 插件--xmake-sublime

xmake-sublime插件深度集成了xmake和sublime text,提供方便快速的跨平台c/c++构建。 注:使用此插件,需要先安装xmake,更多关于xmake的使用说明,请阅读:文档手册 特性 快速开始 语法色彩...

ruki
2017/10/25
99
0
xmake-idea v1.0.3,集成 xmake 的 Intellij-IDEA 插件

xmake-idea 插件深度集成了xmake和Intellij-IDEA,提供方便快速的跨平台c/c++构建。 并且它也支持其他基于Intellij的IDE环境, 例如:Clion, Android Studio等等。 注:使用此插件,需要先安装...

ruki
2017/11/08
808
7
VC如何把浮点数组写入数据库

我的代码是这样的,把浮点数组转成了safearray安全数组,再写入数据库,可是在写入的时候出错了 float Code[220]; SAFEARRAY* psb; SAFEARRAYBOUND rgsbbound[1]; rgsbbound[0].lLbound = 0...

lich_
2013/02/21
546
1

没有更多内容

加载失败,请刷新页面

加载更多

下一页

OSChina 周一乱弹 —— 你的朋友圈有点生锈了

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @Devoes :分享Trademark的单曲《Only Love (电视剧《妙手仁心 II》插曲)》: 《Only Love (电视剧《妙手仁心 II》插曲)》- Trademark 手机党少...

小小编辑
今天
130
6
【面试题】盲人坐飞机

有100位乘客乘坐飞机,其中有一位是盲人,每位乘客都按自己的座位号就坐。由于盲人看不见自己的座位号,所以他可能会坐错位置,而自己的座位被占的乘客会随便找个座位就坐。问所有乘客都坐对...

garkey
今天
1
0
谈谈神秘的ES6——(二)ES6的变量

谈谈神秘的ES6——(二)ES6的变量 我们在《零基础入门JavaScript》的时候就说过,在ES5里,变量是有弊端的,我们先来回顾一下。 首先,在ES5中,我们所有的变量都是通过关键字var来定义的。...

JandenMa
今天
1
0
arts-week1

Algorithm 594. Longest Harmonious Subsequence - LeetCode 274. H-Index - LeetCode 219. Contains Duplicate II - LeetCode 217. Contains Duplicate - LeetCode 438. Find All Anagrams ......

yysue
今天
2
0
NNS拍卖合约

前言 关于NNS的介绍,这里就不多做描述,相关的信息可以查看NNS的白皮书http://doc.neons.name/zh_CN/latest/nns_background.html。 首先nns中使用的竞价货币是sgas,关于sgas介绍可以戳htt...

红烧飞鱼
今天
1
0
Java IO类库之管道流PipeInputStream与PipeOutputStream

一、java管道流介绍 在java多线程通信中管道通信是一种重要的通信方式,在java中我们通过配套使用管道输出流PipedOutputStream和管道输入流PipedInputStream完成线程间通信。多线程管道通信的...

老韭菜
今天
0
0
AB 压力测试

Ubuntu 安装AB apapt-get install apache2-utils 使用AB 压力测试 -c 并发数 -n请求总数 ab -c 3000 -n 10000 http://localhost/test/index.php AB只能测试localhost 返回结果 This is Apac......

xiawet
今天
0
0
用Python绘制红楼梦词云图,竟然发现了这个!

Python在数据分析中越来越受欢迎,已经达到了统计学家对R的喜爱程度,Python的拥护者们当然不会落后于R,开发了一个个好玩的数据分析工具,下面我们来看看如何使用Python,来读红楼梦,绘制小...

猫咪编程
今天
1
0
Java中 发出请求获取别人的数据(阿里云 查询IP归属地)

1.效果 调用阿里云的接口 去定位IP地址 2. 代码 /** * 1. Java中远程调用方法 * http://localhost:8080/mavenssm20180519/invokingUrl.action * @Title: invokingUrl * @Description: * @ret......

Lucky_Me
今天
1
0
protobuf学习笔记

相关文档 Protocol buffers(protobuf)入门简介及性能分析 Protobuf学习 - 入门

OSC_fly
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部