分享
 
 
 

SAFEARRAY使用实例

王朝vc·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

SAFEARRAY使用实例

目录:

SAFEARRAY使用实例... 1

目录:... 1

前言:... 1

何谓SAFEARRAY:... 1

创建SAFEARRAY: 2

方法一:使用SafeArrayAllocDescriptor在栈上创建一维数组... 2

方法二:使用SafeArrayAllocDescriptor和SafeArrayAllocData在堆上创建一维数组... 2

方法三:使用SafeArrayAllocDescriptor和SafeArrayAllocData在堆上创建二维数组... 3

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

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

方法六:使用SafeArrayCreateEx创建包含结构的一维数组... 5

访问SAFEARRAY: 7

方法一:使用SafeArrayAccessData方法... 7

方法二:使用SafeArrayGetElement和SafeArrayPutElement 7

组件/客户中传递SAFEARRAY的原则:... 8

前言:

SAFEARRAY使用总是困扰很多人,为了把这个问题说个明白,我把我目前掌握的知识做个总结

何谓SAFEARRAY:

SAFEARRAY实际上是一个结构,关于这部分可以参考MSDN。

ms-help://MS.MSDNQTR.2003FEB.2052/automat/htm/chap7_9ntx.htm

我们不需要关心16位操作系统下的定义,因为我们团队只在WIN2000以上平台下开发。

创建SAFEARRAY:

方法一:使用SafeArrayAllocDescriptor在栈上创建一维数组

//创建SAFEARRAY数组,每个元素为long型,该数组是一维数组

long nData[10]={1,2,3,4,5,6,7,8,9,10};

SAFEARRAY* pArray=NULL;

HRESULT hr=SafeArrayAllocDescriptor(1,&pArray);//创建SAFEARRAY结构的对象

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

pArray->rgsabound[0].cElements=10;

pArray->rgsabound[0].lLbound=0;

pArray->pvData=nData;

pArray->fFeatures=FADF_AUTO|FADF_FIXEDSIZE;//FADF_AUTO指定在栈上分配数据,并且大小不可以改变(固定为10)

//访问SAFEARRAY数组

long* pValue=NULL;

SafeArrayAccessData(pArray,(void**)&pValue);

long Low(0),High(0);

hr=SafeArrayGetLBound(pArray,1,&Low);//维数索引从1开始

hr=SafeArrayGetUBound(pArray,1,&High);//维数索引从1开始

SafeArrayUnaccessData(pArray);

SafeArrayDestroy(pArray);

这种方法在栈上分配数组元素所占的空间,即nData数组所用的空间

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

//创建SAFEARRAY数组,每个元素为long型,该数组是一维数组

long nData[10]={1,2,3,4,5,6,7,8,9,10};

SAFEARRAY* pArray=NULL;

HRESULT hr=SafeArrayAllocDescriptor(1,&pArray);//创建SAFEARRAY结构的对象

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

pArray->rgsabound[0].cElements=10;

pArray->rgsabound[0].lLbound=0;

SafeArrayAllocData(pArray);

long* pData=NULL;

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

long l(0),h(0);

SafeArrayGetLBound(pArray,1,&l);

SafeArrayGetUBound(pArray,1,&h);

long Size=h-l+1;

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

for(long Idx=l;Idx<Size;++Idx)

{

pData[Idx]=nData[Idx];

}

SafeArrayUnaccessData(pArray);

//访问SAFEARRAY数组

long* pValue=NULL;

SafeArrayAccessData(pArray,(void**)&pValue);

long Low(0),High(0);

hr=SafeArrayGetLBound(pArray,1,&Low);//维数索引从1开始

hr=SafeArrayGetUBound(pArray,1,&High);//维数索引从1开始

SafeArrayUnaccessData(pArray);

SafeArrayDestroy(pArray);

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

SAFEARRAY* pArray=NULL;

HRESULT hr=SafeArrayAllocDescriptor(2,&pArray);

pArray->rgsabound[0].lLbound=0;

pArray->rgsabound[0].cElements=3;

pArray->rgsabound[1].lLbound=0;

pArray->rgsabound[1].cElements=3;

pArray->cbElements=sizeof(long);

hr=SafeArrayAllocData(pArray);

long lDimension[2];

long x=1;

//为第一行赋值

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

{

lDimension[1]=0;//行

lDimension[0]=i;//列

SafeArrayPutElement(pArray,lDimension,&x);

x++;

}

//为第二行赋值

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

{

lDimension[1]=1;//行

lDimension[0]=i;//列

SafeArrayPutElement(pArray,lDimension,&x);

x++;

}

//读取SafeArray中第二行第三列的数据

long y(0);

lDimension[1]=1;

lDimension[0]=2;

SafeArrayGetElement(pArray,lDimension,&y);

SafeArrayDestroy(pArray);

二维SAFEARRAY数组使用的时候下标要注意,这里采用的是列主序的方式,即lDimension[1]代表行,lDimension[0]代表列。

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

SAFEARRAYBOUND Bound[1];

Bound[0].lLbound=0;

Bound[0].cElements=10;

SAFEARRAY* pArray=SafeArrayCreate(VT_I4,1,Bound);

long* pData=NULL;

HRESULT hr=SafeArrayAccessData(pArray,(void**)&pData);

long Low(0),High(0);

SafeArrayGetLBound(pArray,1,&Low);

SafeArrayGetUBound(pArray,1,&High);

long Size=High-Low+1;

for(long Idx=Low;Idx<Size;++Idx)

{

pData[Idx]=Idx;

cout<<pData[Idx]<<endl;

}

SafeArrayUnaccessData(pArray);

SafeArrayDestroy(pArray);

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

SAFEARRAYBOUND Bound[2];

Bound[0].lLbound=0;

Bound[0].cElements=3;

Bound[1].lLbound=0;

Bound[1].cElements=3;

SAFEARRAY* pArray=SafeArrayCreate(VT_I4,2,Bound);

long Demen[2];

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

{

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

{

Demen[1]=i;

Demen[0]=j;

long x=i*j;

SafeArrayPutElement(pArray,Demen,&x);

}

}

//访问二维数组

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

{

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

{

Demen[1]=i;

Demen[0]=j;

long x(0);

SafeArrayGetElement(pArray,Demen,&x);

cout<<"("<<i<<","<<j<<") "<<x<<endl;

}

}

SafeArrayDestroy(pArray);

方法六:使用SafeArrayCreateEx创建包含结构的一维数组

使用SAFEARRAY传递UDT(自定义结构)是一项常用的技术,MSDN文档描述得比较齐全,要注意的一点是,自定义结构要求有自己的GUID,这必须在IDL文件中定义。同时还必须要使用IRecordInfo接口,该接口将和数组一起传递出去,IRecordInfo接口内部记录了UDT的描述信息。

IDL文件中:

[uuid(810930AA-9229-46e7-B20C-41F6218D0B1A)]

struct _BookMarkSchema

{

BSTR Name;

BSTR Context;

BSTR Time;

};

interface IShape : IDispatch

{

[id(6), helpstring("获取属于某用户的书签名称列表")] HRESULT GetBookMarkName([in] BSTR UserID,[out] SAFEARRAY(struct _BookMarkSchema)* pBookMarkNames);

}

library SarstShapeLib

{

importlib("stdole2.tlb");

[

uuid(DBDCC0F1-38F3-4EB4-A5BD-79A3707BDE9C),

helpstring("Shape Class")

]

coclass Shape

{

[default] interface IShape;

};

struct _BookMarkSchema;

};

方法的实现为:

STDMETHODIMP CShape::GetBookMarkName(BSTR UserID,SAFEARRAY** pBookMarkNames)

{

//获得GIS库信息

CSarstConfigure Configure;

string Flag("GIS");

string IP,Database,UserName,Key,Context;

Configure.GetDatabaseInfo(Flag,IP,Database,UserName,Key,Context);

//读取图层属性数据

USES_CONVERSION;

string user(CString(UserID).GetBuffer());

string sql("SELECT 书签名,书签描述,时间 FROM 用户书签表 where 用户ID='"+user+"' order by 时间 desc");

FBData data(IP,Database,UserName,Key);

table t=data.GetTable(sql);

if(t.empty())

{

return S_FALSE;

}

//创建SafeArray

IRecordInfo* pRecordInfo=NULL;

HRESULT hr=::GetRecordInfoFromGuids(LIBID_SarstShapeLib,1,0,GetUserDefaultLCID(),IID_STRUCT_BookMarkSchema,&pRecordInfo);

if(FAILED(hr))

return E_FAIL;

*pBookMarkNames=::SafeArrayCreateVectorEx(VT_RECORD,0,long(t.size()-1),(void*)pRecordInfo);

_BookMarkSchema* pData=NULL;

hr=::SafeArrayAccessData(*pBookMarkNames,(void**)&pData);

for(int i=0;i<int(t.size()-1);i++)

{

t[i+1].at(0).CopyTo(&pData[i].Name);

t[i+1].at(1).CopyTo(&pData[i].Context);

t[i+1].at(2).ChangeType(VT_BSTR);

t[i+1].at(2).CopyTo(&pData[i].Time);

}

::SafeArrayUnaccessData(*pBookMarkNames);

pRecordInfo->Release();

return S_OK;

}

访问SAFEARRAY:

方法一:使用SafeArrayAccessData方法

这种方法可以参见创建SAFEARRAY之方法一

请注意,访问完后要调用SafeArrayUnaccessData方法,并且调用SafeArrayDestroy销毁数组

这种方式通常用于访问一位数组

方法二:使用SafeArrayGetElement和SafeArrayPutElement

这种方法可以参见创建SAFEARRAY之方法五

这种方式在访问多维数组的时候很有用

组件/客户中传递SAFEARRAY的原则:

1) 在堆上创建SAFEARRAY数组

2) 一方创建,一方回收

3) 接收方不可以修改SAFEARRAY的数据,只能读或者销毁

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有