在Delphi2009(12.0.3300.19037)使用SOAP,总是出现AV错误,跟踪发现是OPToSOAPDomConv这个单元的WriteVarArrayAsB64这个函数的问题。
首先发现VarArrayLock返回的pointer不能当PWideChar来处理,修改S和Encd的定义为ansistring,并修改SetString(S, PChar(P), VSize) 为SetString(S, PAnsiChar(P), VSize),这样就没有AV错误了。
但是又发现传回的资料结果不对,因为我的服务器是把ADO资料用ADOStream转成byte array传到客户端的,客户端再用ADOStream读取,但是现在出现“因为流无效,行集不能被加载”的错误。所以判断是SOAP打包或解包不对。再从ReadVariant函数找进去,发现最后是用EncdDecd.pas的DecodeBase64函数来解码,可是编码怎么用EncodeString函数,不用EncodeBase64函数呢?试试修改后,如下,就好了。
OPToSOAPDomConv.pas
procedure TSOAPDomConv.WriteVarArrayAsB64(RootNode, Node: IXMLNode; const Name: InvString; V: Variant);
var
I, DimCount, VSize: Integer;
LoDim, HiDim: array of integer;
P: Pointer;
//S, Encd: string; // delete by wxh,2009/3/28
S, Encd: AnsiString; //add by wxh,2009/3/28
ElemNode: IXMLNode;
begin
DimCount := VarArrayDimCount(V);
SetLength(LoDim, DimCount);
SetLength(HiDim, DimCount);
for I := 1 to DimCount do
begin
LoDim[I - 1] := VarArrayLowBound(V, I);
HiDim[I - 1] := VarArrayHighBound(V, I);
end;
VSize := 0;
for i := 0 to DimCount - 1 do
VSize := (HiDim - LoDim + 1);
P := VarArrayLock(V);
try
Encd:=EncodeBase64(P,VSize); //add by wxh,2009/3/28
//SetString(S, PAnsiChar(P), VSize); //edit by wxh,2009/3/28,必须用AnsiString/PAnsiChar,否则出现AV
finally
VarArrayUnlock(V);
end;
//Encd := EncodeString(S); //delete by wxh,2009/3/28
ElemNode := CreateScalarNodeXS(RootNode, Node, Name, XMLSchemaNamespace, 'base64Binary', Encd); { do not localize }
end;