Error on call COM with PSafeArray in delphi7
Pergunta
I have a procedure that I need to call using COM, which is declared like this in C#:
public string ali(int[] num)
{
string r;
r ="";
foreach (int a in num)
{
r = r + Convert.ToString(a) + ";";
}
return r;
}
The Delphi declaration in the imported TypeLibrary is:
function TSqr.ali(num: PSafeArray): WideString;
begin
Result := DefaultInterface.ali(num);
end;
I have this code to convert integer Array into a PSafeArray:
Function ArrayToSafeArray2 (DataArray: array of integer):PSafeArray;
var
SafeArray: PSafeArray;
InDataLength,i: Integer;
vaInMatrix: Variant;
begin
InDataLength := Length(DataArray);
vaInMatrix := VarArrayCreate([Low(DataArray), High(DataArray)], varInteger);
for i:= Low(DataArray) to High(DataArray) do
begin
vaInMatrix[I] := DataArray[I];
end;
SafeArray := PSafeArray(TVarData(vaInMatrix).VArray);
Result := SafeArray;
VarClear(vaInMatrix);
SafeArrayDestroy(SafeArray);
end;
and this code to call my COM function
var
a:array of integer;
Answer:String;
begin
SetLength(a,3);
a[0] := 1;
a[1] := 2;
a[2] := 2;
Answer := Sqr1.ali(ArrayToSafeArray2(a));
ShowMessage(Answer);
end;
but error ocure:
" EOLeExeption with message 'SafeArray of rank 0 has been passed to method expecting an array of rank 1' ..."
what i should be do?
Solução
Your conversion routine is destroying the SafeArray before the caller can use it. Unlike Delphi arrays, COM arrays are not reference counted. Don't destroy the SafeArray until after you have passed it to the COM procedure, eg:
function ArrayToSafeArray2 (DataArray: array of integer): Variant;
var
i: Integer;
begin
Result := VarArrayCreate([Low(DataArray), High(DataArray)], varInteger);
for i:= Low(DataArray) to High(DataArray) do
begin
Result[I] := DataArray[I];
end;
end;
.
var
a:array of integer;
v: Variant;
Answer:String;
begin
SetLength(a,3);
a[0] := 1;
a[1] := 2;
a[2] := 2;
v := ArrayToSafeArray2(a);
Answer := Sqr1.ali(TVarData(v).VArray);
ShowMessage(Answer);
end;
Outras dicas
The VarUtils unit has the SafeArrayCreate function, remember to call SafeArrayDestroy (preferably in a try/finally section)!