如何将指针类型数组传递给 Delphi 中的 RttiMethods.Invoke
How to pass an array of Pointer types to RttiMethods.Invoke in Delphi
使用 Delphi 10.2 和最新更新
我有一个程序(实际代码):
PyObject = packed record ... end;
PPyObject = ^PyObject
PPyObjectArray = array of PPyObject;
procedure invokeMethod (methodName : string; args : PPyObjectArray);
var ctx: TRttiContext;
rt : TRttiType;
mt : TRttiMethod;
py : TPyArithmetic;
tv : array of TValue;
begin
py := TPyArithmetic.Create;
ctx := TRttiContext.Create;
try
rt := ctx.GetType(TPyArithmetic);
mt := rt.GetMethod (methodName);
setlength (tv, 1);
tv[0].From(args);
mt.Invoke(py, tv);
finally
ctx.Free;
end;
end;
出于调试原因,代码本身在 invokeMethod 中分散到多行中。该过程的目的是使用参数数组 args 调用方法 methodName。但是,我无法成功地将参数传递给调用的方法。尽管调用了正确的函数,但调用方法入口处的参数是乱码。我的问题是我应该如何将 T 数组传递给 invoke 方法?
我也试过使用
调用invoke
mt.Invoke(py, [args]);
但是我得到了编译错误:
E2250 没有可以使用这些参数调用的 'Invoke' 的重载版本。
尝试过
mt.Invoke(py, [@args]);
但我收到运行时错误:
带有消息 'Invalid case typecast' 的 EInvalidCast,尝试跟踪调用但未能成功找出错误原因。
调用端代码为:
class function TPyArithmetic.add (args : PPyObjectArray) : double;
begin
result := TArithmetic.add (GetPythonEngine.PyFloat_AsDouble (args[0]), GetPythonEngine.PyFloat_AsDouble (args[1]));
end;
有什么建议吗?
TValue.From
是 returns 一个新值的函数。此代码错误:
tv[0].From(args);
没有任何内容分配给 tv[0]
。您需要这样做:
tv[0] := TValue.From(args);
更简单的方法是删除动态数组并使用开放数组构造函数:
mt.Invoke(py, [TValue.From(args)]);
并且创建和销毁 RTTI 上下文的代码也是虚假的。它可以按照您的方式正常工作,但同样可以:
procedure invokeMethod(methodName: string; args: PPyObjectArray);
var
ctx: TRttiContext;
rt: TRttiType;
mt: TRttiMethod;
py: TPyArithmetic;
begin
py := TPyArithmetic.Create;
rt := ctx.GetType(TPyArithmetic);
mt := rt.GetMethod (methodName);
mt.Invoke(py, [TValue.From(args)]);
end;
FWIW,看起来您的代码泄漏了 py
。
使用 Delphi 10.2 和最新更新
我有一个程序(实际代码):
PyObject = packed record ... end;
PPyObject = ^PyObject
PPyObjectArray = array of PPyObject;
procedure invokeMethod (methodName : string; args : PPyObjectArray);
var ctx: TRttiContext;
rt : TRttiType;
mt : TRttiMethod;
py : TPyArithmetic;
tv : array of TValue;
begin
py := TPyArithmetic.Create;
ctx := TRttiContext.Create;
try
rt := ctx.GetType(TPyArithmetic);
mt := rt.GetMethod (methodName);
setlength (tv, 1);
tv[0].From(args);
mt.Invoke(py, tv);
finally
ctx.Free;
end;
end;
出于调试原因,代码本身在 invokeMethod 中分散到多行中。该过程的目的是使用参数数组 args 调用方法 methodName。但是,我无法成功地将参数传递给调用的方法。尽管调用了正确的函数,但调用方法入口处的参数是乱码。我的问题是我应该如何将 T 数组传递给 invoke 方法?
我也试过使用
调用invokemt.Invoke(py, [args]);
但是我得到了编译错误:
E2250 没有可以使用这些参数调用的 'Invoke' 的重载版本。
尝试过
mt.Invoke(py, [@args]);
但我收到运行时错误:
带有消息 'Invalid case typecast' 的 EInvalidCast,尝试跟踪调用但未能成功找出错误原因。
调用端代码为:
class function TPyArithmetic.add (args : PPyObjectArray) : double;
begin
result := TArithmetic.add (GetPythonEngine.PyFloat_AsDouble (args[0]), GetPythonEngine.PyFloat_AsDouble (args[1]));
end;
有什么建议吗?
TValue.From
是 returns 一个新值的函数。此代码错误:
tv[0].From(args);
没有任何内容分配给 tv[0]
。您需要这样做:
tv[0] := TValue.From(args);
更简单的方法是删除动态数组并使用开放数组构造函数:
mt.Invoke(py, [TValue.From(args)]);
并且创建和销毁 RTTI 上下文的代码也是虚假的。它可以按照您的方式正常工作,但同样可以:
procedure invokeMethod(methodName: string; args: PPyObjectArray);
var
ctx: TRttiContext;
rt: TRttiType;
mt: TRttiMethod;
py: TPyArithmetic;
begin
py := TPyArithmetic.Create;
rt := ctx.GetType(TPyArithmetic);
mt := rt.GetMethod (methodName);
mt.Invoke(py, [TValue.From(args)]);
end;
FWIW,看起来您的代码泄漏了 py
。