@@ -1048,7 +1048,7 @@ function RttiCall(ParentAddress: pointer; DelphiWrapper: TPyDelphiWrapper;
10481048 AParentAddrIsClass: Boolean = false): PPyObject; overload; forward ;
10491049
10501050function RttiCall (ParentAddress: pointer; DelphiWrapper: TPyDelphiWrapper;
1051- Method: TRttiMethod; ob1, ob2: PPyObject;
1051+ Method: TRttiMethod; ob1, ob2: PPyObject; const Args: TArray<TValue>;
10521052 AParentAddrIsClass: Boolean = false): PPyObject; overload; forward ;
10531053
10541054function GetRttiAttr (ParentAddr: Pointer; ParentType: TRttiStructuredType;
@@ -1465,7 +1465,7 @@ function TPyIndexedProperty.MpSubscript(obj: PPyObject) : PPyObject;
14651465 PyArgs := FPyWrapper.Engine.MakePyTuple([obj]);
14661466
14671467 Result := RttiCall(PascalObject, FPyWrapper, FProperty.ReadMethod,
1468- PyArgs, nil );
1468+ PyArgs, nil , [] );
14691469
14701470 if not FPyWrapper.Engine.PyTuple_Check(obj) then
14711471 FPyWrapper.Engine.Py_DECREF(PyArgs); // release created tuple
@@ -1514,7 +1514,7 @@ function TPyIndexedProperty.MpAssSubscript(obj1, obj2: PPyObject) : Integer;
15141514 PyArgs := Engine.MakePyTuple([obj1, obj2]);
15151515
15161516 TempPy := RttiCall(PascalObject, FPyWrapper, FProperty.WriteMethod,
1517- PyArgs, nil );
1517+ PyArgs, nil , [] );
15181518
15191519 Engine.Py_DECREF(PyArgs); // release created tuple
15201520
@@ -2628,24 +2628,30 @@ function RttiCall(ParentAddress: pointer; DelphiWrapper: TPyDelphiWrapper;
26282628 res, param = objref.Test(param) }
26292629
26302630 function FindMethod (const MethName:string; RttiType : TRttiType;
2631- PyArgs: PPyObject; var Args: array of TValue):TRttiMethod;
2631+ PyArgs: PPyObject; var Args: array of TValue;
2632+ out ErrMsg: string):TRttiMethod;
26322633 // Deals with overloaded methods
26332634 // Constructs the Arg Array
26342635 // PyArgs is a Python tuple
26352636 var
26362637 Method: TRttiMethod;
26372638 begin
26382639 Result := nil ;
2640+ ErrMsg := rs_UnknownAttribute;
26392641 for Method in RttiType.GetMethods do
2640- if SameText(Method.Name , MethName) and PyArgsToValues(PyArgs, Method, Args) then
2641- begin
2642- Result := Method;
2643- Break;
2642+ if SameText(Method.Name , MethName) then begin
2643+ if PyArgsToValues(PyArgs, Method, Args) then
2644+ begin
2645+ Result := Method;
2646+ Break;
2647+ end
2648+ else
2649+ ErrMsg := rs_IncompatibleArguments;
26442650 end ;
26452651 end ;
26462652
26472653var
2648- Args: array of TValue;
2654+ Args: TArray< TValue> ;
26492655 ArgCount: Integer;
26502656 meth: TRttiMethod;
26512657 ReturnValue: TValue;
@@ -2654,53 +2660,30 @@ function RttiCall(ParentAddress: pointer; DelphiWrapper: TPyDelphiWrapper;
26542660
26552661begin
26562662 Result := nil ;
2657- // Ignore keyword arguments ob2
2658- // ob1 is a tuple with zero or more elements
26592663
26602664 ArgCount := DelphiWrapper.Engine.PyTuple_Size(ob1);
26612665 SetLength(Args, ArgCount);
26622666
2663- meth := FindMethod(MethName, ParentRtti, ob1, Args);
2667+ meth := FindMethod(MethName, ParentRtti, ob1, Args, ErrMsg );
26642668
26652669 if not Assigned(meth) then begin
2666- InvalidArguments(MethName, rs_IncompatibleArguments );
2670+ InvalidArguments(MethName, ErrMsg );
26672671 Exit;
26682672 end ;
26692673
2670- try
2671- if ParentRtti is TRttiInstanceType then
2672- if meth.IsClassMethod or meth.IsStatic then
2673- if AParentAddrIsClass then
2674- Addr := TValue.From(TClass(ParentAddress))
2675- else
2676- Addr := TValue.From(TObject(ParentAddress).ClassType)
2677- else
2678- Addr := TValue.From(TObject(ParentAddress))
2679- else if ParentRtti is TRttiInterfaceType then
2680- TValue.Make(@ParentAddress, ParentRtti.Handle, Addr)
2681- else
2682- Addr := TValue.From(ParentAddress);
2683- ReturnValue := meth.Invoke(Addr, Args);
2684-
2685- Result := TValueToPyObject(ReturnValue, DelphiWrapper, ErrMsg);
2686- if Result = nil then
2687- with DelphiWrapper.Engine do
2688- PyErr_SetObject(PyExc_TypeError^, PyUnicodeFromString(
2689- Format(rs_ErrInvalidRet, [MethName, ErrMsg])));
2690- except
2691- on E: Exception do begin
2692- Result := nil ;
2693- InvalidArguments(MethName, E.Message);
2694- end ;
2695- end ;
2674+ Result := RttiCall(ParentAddress, DelphiWrapper, meth, ob1, ob2, Args,
2675+ AParentAddrIsClass);
26962676end ;
26972677
2678+ // This overload can be called either directly or from the overload above.
2679+ // When it is called from above Args are already setup and validated
2680+ // When it is called directly Args = []
26982681function RttiCall (ParentAddress: pointer; DelphiWrapper: TPyDelphiWrapper;
2699- Method: TRttiMethod; ob1, ob2: PPyObject;
2682+ Method: TRttiMethod; ob1, ob2: PPyObject; const Args: TArray<TValue>;
27002683 AParentAddrIsClass: Boolean = false): PPyObject;
27012684var
27022685 ArgCount: Integer;
2703- Args: array of TValue;
2686+ LArgs: TArray< TValue> ;
27042687 Addr: TValue;
27052688 ReturnValue: TValue;
27062689 ErrMsg : string;
@@ -2710,12 +2693,18 @@ function RttiCall(ParentAddress: pointer; DelphiWrapper: TPyDelphiWrapper;
27102693 // ob1 is a tuple with zero or more elements
27112694
27122695 ArgCount := DelphiWrapper.Engine.PyTuple_Size(ob1);
2713- SetLength(Args, ArgCount);
2714-
2715- if not PyArgsToValues(ob1, Method, Args) then
2696+ if Length(Args) = ArgCount then
2697+ // already validated
2698+ LArgs := Args
2699+ else
27162700 begin
2717- InvalidArguments(Method.Name , rs_IncompatibleArguments);
2718- Exit;
2701+ SetLength(LArgs, ArgCount);
2702+
2703+ if not PyArgsToValues(ob1, Method, LArgs) then
2704+ begin
2705+ InvalidArguments(Method.Name , rs_IncompatibleArguments);
2706+ Exit;
2707+ end ;
27192708 end ;
27202709
27212710 try
@@ -2732,7 +2721,7 @@ function RttiCall(ParentAddress: pointer; DelphiWrapper: TPyDelphiWrapper;
27322721 else
27332722 Addr := TValue.From(ParentAddress);
27342723
2735- ReturnValue := Method.Invoke(Addr, Args );
2724+ ReturnValue := Method.Invoke(Addr, LArgs );
27362725
27372726 Result := TValueToPyObject(ReturnValue, DelphiWrapper, ErrMsg);
27382727 if Result = nil then
@@ -4000,7 +3989,7 @@ function TPyDelphiObject.MpSubscript(obj: PPyObject) : PPyObject;
40003989 PyArgs := PyDelphiWrapper.Engine.MakePyTuple([obj]);
40013990
40023991 Result := RttiCall(DelphiObject, PyDelphiWrapper, Prop.ReadMethod,
4003- PyArgs, nil );
3992+ PyArgs, nil , [] );
40043993
40053994 if not PyDelphiWrapper.Engine.PyTuple_Check(obj) then
40063995 PyDelphiWrapper.Engine.Py_DECREF(PyArgs); // release created tuple
@@ -4045,7 +4034,7 @@ function TPyDelphiObject.MpAssSubscript(obj1, obj2: PPyObject) : Integer;
40454034 PyArgs := Engine.MakePyTuple([obj1, obj2]);
40464035
40474036 TempPy := RttiCall(DelphiObject, PyDelphiWrapper, Prop.WriteMethod,
4048- PyArgs, nil );
4037+ PyArgs, nil , [] );
40494038
40504039 Engine.Py_DECREF(PyArgs); // release created tuple
40514040
0 commit comments