1、学会使用SafeArray 之 Delphi 篇学会使用SafeArray 之 Delphi 篇 学会使用SafeArray 之 Delphi 篇分类:Delphi2010-11-05 14:07966人阅读评论(0)收藏举报delphiintegerdatasetfunctionstringXX 在学习的时候曾经XX了一下,想查找关于delphi中SafeArray的用法,没想到资料竟然如此之少,甚至连一篇相对完整的都没有。也许正如田师傅所说,现在高手们都在实行“技术封锁”了? 在CSDN技术中心有一篇关于C+的使用,说的比较详细。鉴于手中有田师傅写的代码,特拿来一部分对照自己学习的,翻译为
2、Delphi版本。留作笔记,日后翻阅。= SAFEARRAY的主要目的是用于automation中的数组型参数的传递。因为在网络环境中,数组是不能直接传递的,而必须将其包装成SafeArray。实质上SafeArray就是将通常的数组增加一个描述符,说明其维数、长度、边界、元 素类型等信息。SafeArray也并不单独使用,而是将其再包装到VARIANT类型的变量中,然后才作为参数传送出去。在VARIANT的vt成员的 值如果包含VT_ARRAY|.,那么它所封装的就是一个SafeArray,它的parray成员即是指向SafeArray的指针。 SafeArray中元素的类型可以是VARIA
3、NT能封装的任何类型,包括VARIANT类型本身。 Delphi中com组件或外部调用需要传递一个对象或者数组,这个时候可以考虑使用SafeArray。比如三层架构中通常需要将使用的ClientDataSet数据集传出,那么就可以将DataSet转换为SafeArray,再由其他模块转换接收。= 代码块: pSafeArray是一个结构体,其定义在ActiveX单元中,相关定义如下: PSafeArray = TSafeArray; $EXTERNALSYM tagSAFEARRAY tagSAFEARRAY = record cDims: Word;/数组的维数 fFeatures: Wor
4、d;/用来描述数组如何分配和如何被释放的标志 cbElements: Longint;/数组元素的大小 cLocks: Longint;/一个计数器,用来跟踪该数组被锁定的次数 pvData: Pointer;/指向数据缓冲的指针 rgsabound: array0.0 of TSafeArrayBound;/描述数组每维的数组结构,该数组的大小是可变的 end; TSafeArray = tagSAFEARRAY; $EXTERNALSYM SAFEARRAY SAFEARRAY = TSafeArray;= 一维数组的传递: /一维数组传递procedure TForm1.ArrayToS
5、afeArray(DataArray: array of string);var VarBound: TVarArrayBound; psa: PSafeArray; i: Integer; AV1: OleVariant;begin /初始化OleValue VariantInit(OleValue); VarBound.LowBound := 0; VarBound.ElementCount := High(DataArray) + 1; psa := SafeArrayCreate(VT_BSTR, 1, VarBound);/创建SafeArray对象 /将数组元素放到SafeArra
6、y中 for i := Low(DataArray) to High(DataArray) do begin AV1 := DataArrayi; SafeArrayPutElement(psa, i, TVarData(AV1).VPointer); end; /封装到Varaint变量中 TVarData(OleValue).VType := VT_ARRAY or VT_BSTR; TVarData(OleValue).VArray := pVarArray(psa);end;读取一维safeArray的步骤:/使用SafeArrayGetLBound、SafeArrayGetUBoun
7、d方法获取safeArray数组上下限function TForm1.SafeArrayToText(OleValue: OleVariant): string;var RVarData: TVarData; RBound: TVarArrayBound; j, UCount: Integer; aValue: WideString;begin Result := ; /获取OleVaraint对象指针 RVarData := FindVarData(OleValue); if RVarData.VArray = nil then Exit; VarResultCheck(SafeArrayG
8、etLBound(pSafeArray(RVarData.VArray), 1, RBound.LowBound); VarResultCheck(SafeArrayGetUBound(pSafearray(RVarData.VArray), 1, UCount); RBound.ElementCount := UCount - RBound.LowBound; for j := RBound.LowBound to RBound.ElementCount do begin VarResultCheck(SafeArrayGetElement(PSafeArray(RVarData.VArra
9、y), j, aValue); if Result = then Result := Result + aValue else Result := Result + , + aValue; end;end;/另外附上将DataSet通过SafeArray传递的方法,其实为多维数组的传递:procedure TForm1.DataSetToSafeArray(ClientData: TClientDataSet);var DataArray: TDoubleArray; VarBound: array0.1 of TVarArrayBound; Demen: array0.1 of DWORD;
10、 psa: PSafeArray; i, j, k, Count: Integer; AV1: OleVariant;begin SetLength(DataArray, ClientData.FieldCount + 1, ClientData.RecordCount + 1); Count := 0; ClientData.First; while not ClientData.Eof do begin for i := 0 to ClientData.FieldCount - 1 do begin if Count = 0 then DataArrayiCount := ClientDa
11、ta.Fieldsi.FieldName else DataArrayiCount := ClientData.Fieldsi.Value; end; if Count > 0 then ClientData.Next; inc(Count); end; /-开始转换为SafeArray- /初始化OleValue VariantInit(OleValue); VarBound0.LowBound := 0; VarBound0.ElementCount := ClientData.FieldCount + 1; VarBound1.LowBound := 0; VarBound1.El
12、ementCount := ClientData.RecordCount + 1; psa := SafeArrayCreate(VT_BSTR, 2, VarBound); for i := Low(DataArray) to High(DataArray) do begin Demen0 := i; for j := Low(DataArrayi) to High(DataArrayi) do begin Demen1 := j; AV1 := DataArrayij; SafeArrayPutElement(psa, Demen, TVarData(AV1).VPointer); end
13、; end; TVarData(OleValue).VType := VT_ARRAY or VT_BSTR; TVarData(OleValue).VArray := pVarArray(psa);end;/读多维数组,读出后再转换为想要的格式:function TForm1.SafeArrayToDataSet(oleValue: OleVariant): string;var RVarData: TVarData; RBound: array0.1 of TVarArrayBound; Demen: array0.1 of DWORD; i, j, DCount, UCount, iCo
14、unt: Integer; aValue: WideString;begin Result := ; RVarData := FindVarData(OleValue); if RVarData.VArray = nil then Exit; DCount := RVarData.Varray.DimCount; /取维数 for i := 0 to DCount - 1 do begin VarResultCheck(SafeArrayGetLBound(pSafeArray(RVarData.VArray), i + 1, RBoundi.LowBound); VarResultCheck
15、(SafeArrayGetUBound(pSafearray(RVarData.VArray), i + 1, UCount); RBoundi.ElementCount := UCount - RBoundi.LowBound; end; for j := RBound1.LowBound to RBound1.ElementCount do begin Demen1 := j; for iCount := RBound0.LowBound to RBound0.ElementCount do begin Demen0 := iCount; VarResultCheck(SafeArrayGetElement(PSafeArray(RVarData.VArray), demen, aValue); if Result = then Result := Result + aValue else Result := Result + , + aValue; end; end;end;
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1