学会使用SafeArray之Delphi篇
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
学会使用SafeArray之Delphi篇
学会使用SafeArray 之 Delphi 篇
分类: Delphi 2010-11-05 14:07 966人阅读评论(0) 收藏举报delphiintegerdatasetfunctionstring百度
在学习的时候曾经百度了一下,想查找关于delphi中SafeArray 的用法,没想到资料竟然如此之少,甚至连一篇相对完整的都没有。
也许正如田师傅所说,现在高手们都在实行“技术封锁”了?
在CSDN技术中心有一篇关于C++的使用,说的比较详细。
鉴于手中有田师傅写的代码,特拿来一部分对照自己学习的,翻译为Delphi版本。
留作笔记,日后翻阅。
======================================
========================================= SAFEARRAY的主要目的是用于automation中的数组型参数的传递。
因为在网络环境中,数组是不能直接传递的,而必须将其包装成SafeArray。
实质上SafeArray就是将通常的数组增加一个描述符,说明其维数、长度、边界、元素类型等信息。
SafeArray也并不单独使用,而是将其再包装到VARIANT类型的变量中,然后才作为参数传送出去。
在VARIANT的vt成员的值如果包含VT_ARRAY|...,那么它所封装的就是一个SafeArray,它的parray成员即是指向SafeArray的指针。
SafeArray中元素的类型可以是VARIANT能封装的任何类型,包括VARIANT类型本身。
Delphi中com组件或外部调用需要传递一个对象或者数组,这个时候可以考虑使用SafeArray。
比如三层架构中通常需要将使用的ClientDataSet数据集传出,那么就可以将DataSet转换为SafeArray,再由其他模块转换接收。
======================================
=========================================
代码块:
pSafeArray是一个结构体,其定义在ActiveX单元中,相关定义如下:
PSafeArray = ^TSafeArray;
{$EXTERNALSYM tagSAFEARRAY}
tagSAFEARRAY = record
cDims: Word;//数组的维数
fFeatures: Word;//用来描述数组如何分配和如何被释放的标志
cbElements: Longint;//数组元素的大小
cLocks: Longint;//一个计数器,用来跟踪该数组被锁定的次数
pvData: Pointer;//指向数据缓冲的指针
rgsabound: array[0..0] of TSafeArrayBound;//描述数组每维的数组结构,该数组的大小是可变的
end;
TSafeArray = tagSAFEARRAY;
{$EXTERNALSYM SAFEARRAY}
SAFEARRAY = TSafeArray;
====================================== ========================================= 一维数组的传递:
//一维数组传递
procedure TForm1.ArrayT oSafeArray(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对象
//将数组元素放到SafeArray中
for i := Low(DataArray) to High(DataArray) do
begin
AV1 := DataArray[i];
SafeArrayPutElement(psa, i, TVarData(AV1).VPointer^);
end;
//封装到Varaint变量中
TVarData(OleValue).VType := VT_ARRAY or VT_BSTR;
TVarData(OleValue).VArray := pVarArray(psa);
end;
读取一维safeArray的步骤:
//使用SafeArrayGetLBound、SafeArrayGetUBound方法获取safeArray数组上下限
function TForm1.SafeArrayT oText(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((SafeArrayGetLBound(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. VArray), 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: array[0..1] of TVarArrayBound;
Demen: array[0..1] of DWORD;
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
DataArray[i][Count] := ClientData.Fields[i].FieldName
else
DataArray[i][Count] := ClientData.Fields[i].Value;
end;
if Count > 0 then
ClientData.Next;
inc(Count);
end;
//--------开始转换为SafeArray-----------
//初始化OleValue
VariantInit(OleValue);
VarBound[0].LowBound := 0;
VarBound[0].ElementCount := ClientData.FieldCount + 1; VarBound[1].LowBound := 0;
VarBound[1].ElementCount := ClientData.RecordCount + 1; psa := SafeArrayCreate(VT_BSTR, 2, VarBound);
for i := Low(DataArray) to High(DataArray) do
begin
Demen[0] := i;
for j := Low(DataArray[i]) to High(DataArray[i]) do
begin
Demen[1] := j;
AV1 := DataArray[i][j];
SafeArrayPutElement(psa, Demen, TVarData(AV1).VPointer^);
end;
end;
TVarData(OleValue).VType := VT_ARRAY or VT_BSTR;
TVarData(OleValue).VArray := pVarArray(psa);
end;
//读多维数组,读出后再转换为想要的格式:
function TForm1.SafeArrayT oDataSet(oleValue: OleVariant): string;
var
RVarData: TVarData;
RBound: array[0..1] of TVarArrayBound;
Demen: array[0..1] of DWORD;
i, j, DCount, UCount, iCount: 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, RBound[i].LowBound)));
VarResultCheck(SafeArrayGetUBound(pSafearray(RVarData. VArray), i + 1, UCount));
RBound[i].ElementCount := UCount - RBound[i].LowBound;
end;
for j := RBound[1].LowBound to RBound[1].ElementCount do begin
Demen[1] := j;
for iCount := RBound[0].LowBound to RBound[0].ElementCount do
begin
Demen[0] := iCount;
VarResultCheck(SafeArrayGetElement(PSafeArray(RVarData. VArray), demen, aValue));
if Result = '' then
Result := Result + aValue
else
Result := Result + ',' + aValue;
end;
end;
end;。