Skip to content

Commit 1b9a71c

Browse files
committed
Improved handling of dynamic arrays in WrapDelphi.pas.
1 parent 3c22cb7 commit 1b9a71c

File tree

3 files changed

+35
-54
lines changed

3 files changed

+35
-54
lines changed

Source/WrapDelphi.pas

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,18 +1937,25 @@ function ValidateClassRef(PyValue: PPyObject; RefClass: TClass;
19371937
end;
19381938

19391939
{$IFDEF EXTENDED_RTTI}
1940-
function DynArrayToPython(const Value: TValue): PPyObject;
1940+
function DynArrayToPython(const Value: TValue; DelphiWrapper: TPyDelphiWrapper;
1941+
out ErrMsg: string): PPyObject;
19411942
var
19421943
I: Integer;
1943-
V: Variant;
19441944
PyEngine: TPythonEngine;
1945+
PyObj: PPyObject;
19451946
begin
19461947
PyEngine := GetPythonEngine();
19471948
Result := PyEngine.PyList_New(Value.GetArrayLength);
19481949
for I := 0 to Value.GetArrayLength() - 1 do
19491950
begin
1950-
V := Value.GetArrayElement(i).AsVariant;
1951-
PyEngine.PyList_SetItem(Result, I, PyEngine.VariantAsPyObject(V));
1951+
PyObj := TValueToPyObject(Value.GetArrayElement(i), DelphiWrapper, ErrMsg);
1952+
if not Assigned(PyObj) then
1953+
begin
1954+
PyEngine.Py_DECREF(Result);
1955+
Result := nil;
1956+
Break;
1957+
end;
1958+
PyEngine.PyList_SetItem(Result, I, PyObj);
19521959
end;
19531960
end;
19541961

@@ -1986,14 +1993,8 @@ function SimpleValueToPython(const Value: TValue; out ErrMsg: string): PPyObject
19861993
Result := SetToPython(Value.TypeData.CompType^,
19871994
PInteger(Value.GetReferenceToRawData)^);
19881995
end;
1989-
tkArray, tkDynArray:
1990-
Result := DynArrayToPython(Value);
1991-
tkClass, tkMethod,
1992-
tkRecord, tkInterface, {$IFDEF MANAGED_RECORD} tkMRecord,{$ENDIF}
1993-
tkClassRef, tkPointer, tkProcedure:
1994-
ErrMsg := rs_ErrValueToPython;
19951996
else
1996-
ErrMsg := rs_ErrUnexpected;
1997+
ErrMsg := rs_ErrValueToPython;
19971998
end;
19981999
except
19992000
on E: Exception do begin
@@ -2128,9 +2129,10 @@ function ValidateDynArray(PyValue: PPyObject; const RttiType: TRttiType;
21282129
Arr: array of TValue;
21292130
I: Integer;
21302131
elType: PPTypeInfo;
2131-
V: Variant;
2132-
Num: Int64;
21332132
PyEngine: TPythonEngine;
2133+
RttiContext: TRttiContext;
2134+
ElementType: TRttiType;
2135+
ArrElem: PPyObject;
21342136
begin
21352137
Result := False;
21362138
PyEngine := GetPythonEngine;
@@ -2149,18 +2151,17 @@ function ValidateDynArray(PyValue: PPyObject; const RttiType: TRttiType;
21492151
if elType = nil then
21502152
Exit;
21512153

2154+
ElementType := RttiContext.GetType(elType^);
2155+
if ElementType = nil then
2156+
Exit;
2157+
21522158
try
21532159
SetLength(Arr, PyEngine.PySequence_Length(PyValue));
21542160
for I := 0 to PyEngine.PySequence_Length(PyValue) - 1 do
21552161
begin
2156-
V := PyEngine.GetSequenceItem(PyValue, i);
2157-
if elType^.Kind = tkEnumeration then
2158-
begin
2159-
Num := TValue.FromVariant(V).Cast(TypeInfo(Int64)).AsInt64;
2160-
Arr[i] := TValue.FromOrdinal(elType^, Num);
2161-
end
2162-
else
2163-
Arr[i] := TValue.FromVariant(V).Cast(elType^);
2162+
ArrElem := PyEngine.PySequence_GetItem(PyValue, I);
2163+
if not PyObjectToTValue(ArrElem, ElementType, Arr[I], ErrMsg) then
2164+
Break;
21642165
end;
21652166
ParamValue := TValue.FromArray(RttiType.Handle, Arr);
21662167
Result := True;
@@ -2169,7 +2170,7 @@ function ValidateDynArray(PyValue: PPyObject; const RttiType: TRttiType;
21692170
end;
21702171
end;
21712172

2172-
function PyObjectToTValue(PyArg : PPyObject; ArgType: TRttiType;
2173+
function PyObjectToTValue(PyArg: PPyObject; ArgType: TRttiType;
21732174
out Arg: TValue; out ErrMsg: string): Boolean;
21742175
var
21752176
Obj: TObject;
@@ -2245,6 +2246,8 @@ function TValueToPyObject(const Value: TValue;
22452246
tkInterface: Result := DelphiWrapper.WrapInterface(Value);
22462247
tkRecord{$IFDEF MANAGED_RECORD},tkMRecord{$ENDIF}:
22472248
Result := DelphiWrapper.WrapRecord(Value);
2249+
tkArray, tkDynArray:
2250+
Result := DynArrayToPython(Value, DelphiWrapper, ErrMsg);
22482251
else
22492252
Result := SimpleValueToPython(Value, ErrMsg);
22502253
end;

Tests/FMX/Android/WrapDelphiTest.pas

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -425,25 +425,14 @@ procedure TTestWrapDelphi.TestStringField;
425425
end;
426426

427427
procedure TTestWrapDelphi.TestDynArrayParameters;
428-
{var
429-
rc: TRttiContext;
430-
rt: TRttiType;
431-
rm: TRttiMethod;
432-
rp: TArray<TRttiParameter>;
433-
ra: TArray<TValue>;}
434-
begin
435-
{ rc := TRttiContext.Create;
436-
rt := rc.GetType(TypeInfo(TTestRttiAccess));
437-
rm := rt.GetMethod('SellFruitsInt');
438-
rp := rm.GetParameters;
439-
SetLength(ra, 1);
440-
ra[0] := TValue.FromArray(TypeInfo(TIntegerDynArray), [TValue.From<Integer>(0)]);
441-
rm.Invoke(TestRttiAccess, ra);}
428+
begin
429+
// Integer dynamic array parameter
442430
TestRttiAccess.Fruits := [TFruit.Apple, TFruit.Banana, TFruit.Orange];
443-
Rtti_Var.SellFruitsInt(VarPythonCreate([0, 1], stList));
431+
Rtti_Var.SellFruitsInt(VarPythonCreate([Ord(TFruit.Apple), Ord(TFruit.Banana)], stList));
444432
Assert.IsTrue(TestRttiAccess.Fruits = [Orange]);
433+
// Enumeration dynamic array parameter
445434
TestRttiAccess.Fruits := [TFruit.Apple, TFruit.Banana, TFruit.Orange];
446-
Rtti_Var.SellFruits(VarPythonCreate([Ord(TFruit.Apple), Ord(TFruit.Banana)], stList));
435+
Rtti_Var.SellFruits(VarPythonCreate(['Apple', 'Banana'], stList));
447436
Assert.IsTrue(TestRttiAccess.Fruits = [Orange]);
448437
end;
449438

Tests/WrapDelphiTest.pas

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -506,25 +506,14 @@ procedure TTestWrapDelphi.TestVarArgs;
506506
end;
507507

508508
procedure TTestWrapDelphi.TestDynArrayParameters;
509-
{var
510-
rc: TRttiContext;
511-
rt: TRttiType;
512-
rm: TRttiMethod;
513-
rp: TArray<TRttiParameter>;
514-
ra: TArray<TValue>;}
515-
begin
516-
{ rc := TRttiContext.Create;
517-
rt := rc.GetType(TypeInfo(TTestRttiAccess));
518-
rm := rt.GetMethod('SellFruitsInt');
519-
rp := rm.GetParameters;
520-
SetLength(ra, 1);
521-
ra[0] := TValue.FromArray(TypeInfo(TIntegerDynArray), [TValue.From<Integer>(0)]);
522-
rm.Invoke(TestRttiAccess, ra);}
509+
begin
510+
// Integer dynamic array parameter
523511
TestRttiAccess.Fruits := [TFruit.Apple, TFruit.Banana, TFruit.Orange];
524-
Rtti_Var.SellFruitsInt(VarPythonCreate([0, 1], stList));
512+
Rtti_Var.SellFruitsInt(VarPythonCreate([Ord(TFruit.Apple), Ord(TFruit.Banana)], stList));
525513
Assert.IsTrue(TestRttiAccess.Fruits = [Orange]);
514+
// Enumeration dynamic array parameter
526515
TestRttiAccess.Fruits := [TFruit.Apple, TFruit.Banana, TFruit.Orange];
527-
Rtti_Var.SellFruits(VarPythonCreate([Ord(TFruit.Apple), Ord(TFruit.Banana)], stList));
516+
Rtti_Var.SellFruits(VarPythonCreate(['Apple', 'Banana'], stList));
528517
Assert.IsTrue(TestRttiAccess.Fruits = [Orange]);
529518
end;
530519

0 commit comments

Comments
 (0)