SAFEARRAY使用

玛丽莲梦兔
957次浏览
2020年08月08日 03:55
最佳经验
本文由作者推荐

浙江财经东方学院-置业顾问实习报告


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
CComSafeArray类介绍: 8
基本的入门例子: 8
注意事项: 8

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

何谓SAFEARRAY:
SAFEARRAY实际上是一个结构,关于这部分可以参考MSDN。
ms- help:R.2003FEB.2052automathtmchap7_


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

创建SAFEARRAY:
方法一:使用SafeArrayAllocDescriptor在栈上创建一维数组
创建SAFEARRAY数组,每个元素为long型,该数组是一维数组
long nData[10]={1,2,3,4,5,6,7,8,9,10};

SAFEARRAY* pArray=NULL;
HRESULT hr=SafeArr ayAllocDescriptor(1,&pArray);创建SAFEARRAY结构
的对象
pArray->cbElements=sizeof(nData[0]);
pArray->rgsabound[0].cElements=10;
pArray->rgsabound[0].lLbound=0;
pArray->pvData=nData;
pArray->fFeatures=FA DF_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=SafeArr ayAllocDescriptor(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{
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在堆上创建二< br>维数组
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);

二维SAFE ARRAY数组使用的时候下标要注意,这里采用的是列主序的方式,即
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{
pData[Idx]=Idx;
cout<}
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<<
}
}
SafeArrayDestroy(pArray);

方法六:使用SafeArrayCreateEx创建包含结构的一维数组
使用SAFEA RRAY传递UDT(自定义结构)是一项常用的技术,MSDN文档描述得比较齐全,
要注意的一点是 ,自定义结构要求有自己的GUID,这必须在IDL文件中定义。同时还必须
要使用IRecordI nfo接口,该接口将和数组一起传递出去,IRecordInfo接口内部记录
了UDT的描述信息 。
IDL文件中:
[uuid(810930AA-9229-46e7-B20C-41F6218D0B1A)]
struct _BookMarkSchema
{
BSTR Name;
BSTR Context;
BSTR Time;
};


interface IShape : IDispatch
{


[id(6), helpstring(获取属于某用户的书签名称列表

ct _BookMarkSchema)* pBookMarkNames);
}


library SarstShapeLib
{

importlib(
[
uuid(DBDCC0F1-38F3-4EB4-A5BD-79A3707BDE9C),
helpstring(
]
coclass Shape
{
[default] interface IShape;
};
struct _BookMarkSchema;
};


方法的实现为:
STDMETHODIMP CShape::GetBookMarkName(BSTR UserID,SAFEARRAY** pBoo
kMarkNames)
{
获得GIS库信息
CSarstConfigure Configure;
string Flag(
string IP,Database,UserName,Key,Context;


abase Info(Flag,IP,Database,UserName,Key,Context);

读取图层属性数据
USES_CONVERSION;
string user(CString(UserID).GetBuffer());
string sql(书签名,书签描述,时间 FROM 用户书签表 where 用户
ID='时间 desc
FBData data(IP,Database,UserName,Key);
table t=le(sql);
if(())
{
return S_FALSE;
}
创建SafeArray
IRecordInfo* pRecordInfo=NULL;
HRESULT hr=::GetRecordInfoFr omGuids(LIBID_SarstShapeLib,1,0,GetUs
erDefault LCID(),IID_STRUCT_BookMarkSchema,&pRecordInfo);
if(FAILED(hr))
return E_FAIL;
*pBookMa rkNames=::SafeArrayCreateVectorEx(VT_RECORD,0,long (
()-1),(void*)pRecordInfo);
_BookMarkSchema* pData=NULL;
hr=::SafeArra yAccessData(*pBookMarkNames,(void**)&pData);
for(int i=0;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之方法一
请注意,访问完后要调用SafeArr ayUnaccessData方法,并且调用
SafeArrayDestroy销毁数组
这种方式通常用于访问一位数组
方法二:使用SafeArrayGetElement和SafeArrayPutElement
这种方法可以参见创建SAFEARRAY之方法五
这种方式在访问多维数组的时候很有用

CComSafeArray类介绍:
基本的入门例子:
可以参见下面的MSDN链接
ms-help:R.2003FEB.2052vclibh tmlvclrfCComSafeArray.h
tm
注意,我个人认为本例有错,应该最后加上一句代码delete pSar;
因为虽然pv Data指针指向的内存是在堆中,但是tagSAFEARRAY结构对象生存在new
开辟的堆上, 如果不delete的话,将会内存泄漏。


注意事项:
1) SetAt方法有问题
HRESULT SetAt(LONG lIndex, const T& t, BOOL bCopy = TRUE)
{
bCopy;
ATLASSERT(m_psa != NULL);


if(m_psa == NULL)
return E_FAIL;

LONG lLBound = GetLowerBound();
ATLASSERT(lIndex >= lLBound);
ATLASSERT(lIndex <= GetUpperBound());
if ((lIndex < lLBound) || (lIndex > GetUpperBound()))
return E_INVALIDARG;

((T*)m_psa->pvData)[lIndex- lLBound] = t;
return S_OK;
我们可以看到,MSDN中描述的 bCopy如果为true将创建数据的副本,在代码中并没有实
现,事实上bCopy参数并没有起到 任何作用,不知道怎么会出现这样的错误

提纲-2017年日历表


昆明31-过年了作文


国庆音乐-社团活动方案


体系建设-博士留学申请


堆雪人的作文-六年级情书


重庆市人力资源社会保障网-浙江高考理综


推广普通话-本地高薪职位


利物浦约翰摩尔斯大学-我和语文