简体   繁体   English

Python4Delphi - 用 TPyDelphiWrapper.WrapInterface 包装 delphi 接口时出错

[英]Python4Delphi - Error in wrapping delphi interface with TPyDelphiWrapper.WrapInterface

I am using Python 3.8 with Delphi 10.4.2.我在 Delphi 10.4.2 中使用 Python 3.8。

I am trying to use the components of Python4Delphi to access through a Python script some interfaces defined in Delphi.我正在尝试使用Python4Delphi的组件通过 Python 脚本访问 Delphi 中定义的某些接口。

At design-time I added the TPythonEngine, TPythonModule and TPyDelphiWrapper components to my project's VCL form.在设计时,我将 TPythonEngine、TPythonModule 和 TPyDelphiWrapper 组件添加到我项目的 VCL 表单中。

So I defined 3 interfaces, implemented by 3 classes respectively, as below所以我定义了3个接口,分别由3个类实现,如下

type
  IPerson = interface (IUnknown)
    ['{1D21B5B6-25DE-4884-8BDB-8E2D9A239D64}']
    function GetName : string;
    procedure SetName ( value : string );
    property Name: string read GetName write SetName;   
    function GetSurname: string;
    procedure SetSurname(value : string);
    property Surname : string read GetSurname write SetSurname;    
    function GetInfo : string;
  end;

  ICustomer = interface (IPerson)
    ['{8742364C-33E8-4FF4-86FB-C19AF67A735B}']
    function GetCustomerNumber : string;
    procedure SetCustomerNumber ( value : string );
    property CustomerNumber : string read GetCustomerNumber write SetCustomerNumber;
  end;

  ISupplier = interface ( IPerson )
    ['{420FFF78-92DE-4D7E-9958-FDA95748EEB7}']
    function GetSupplierNumber : string;
    procedure SetSupplierNumber ( value : string );
    property SupplierNumber : string read GetSupplierNumber write SetSupplierNumber;
  end;

  TPerson = class ( TInterfacedObject , IPerson)
  private
    FName : string;
    FSurname : string;    
    function GetName : string;
    procedure SetName ( value : string );    
    function GetSurname: string;
    procedure SetSurname(value : string);

  public
    property Surname : string read GetSurname write SetSurname;
    property Name: string read GetName write SetName;    
    function GetInfo : string; virtual;
  end;


  TCustomer = class ( TPerson , ICustomer)
  private
    FCustomerNumber : string;
    function GetCustomerNumber : string;
    procedure SetCustomerNumber ( value : string);

  public    
    property CustomerNumber : string read GetCustomerNumber write SetCustomerNumber;
    function GetInfo: string; override;
  end;


  TSupplier = class ( TPerson , ISupplier)
  private
    FSupplierNumber : string;
    function GetSupplierNumber : string;
    procedure SetSupplierNumber ( value : string );

  public
    property SupplierNumber : string read GetSupplierNumber write SetSupplierNumber;
    function GetInfo : string; override;
  end;

In the Create method of the form, I defined 3 variables, one for each of the 3 interfaces, and through the PyDelphiWrapper I passed them to the Python module in 3 different Python variable.在表单的 Create 方法中,我定义了 3 个变量,3 个接口各一个,并通过 PyDelphiWrapper 将它们传递给 Python 模块中的 3 个不同的 Python 变量。

procedure TFrmTestInterface.FormCreate(Sender: TObject);
var
  LPerson : IPerson;
  LCustomer : ICustomer;
  LSupplier : ISupplier;
  Py: PPyObject;
begin

  LPerson := TPerson.Create;
  LCustomer := TCustomer.Create;
  LSupplier := TSupplier.Create;

  LPerson.Name := 'Pippo';
  LPerson.Surname := 'Rossi';

  LCustomer.Name := 'Pluto';
  LCustomer.Surname := 'Verdi';

  LSupplier.Name := 'Paperino';
  LSupplier.Surname := 'Bianchi';


  Py := PyDelphiWrapper1.WrapInterface(TValue.From(LPerson));
  PythonModule1.SetVar('delphi_person', Py);
  GetPythonEngine.Py_DecRef(Py);

  Py := PyDelphiWrapper1.WrapInterface(TValue.From(LCustomer));
  PythonModule1.SetVar('delphi_customer', Py);
  GetPythonEngine.Py_DecRef(Py);

  Py := PyDelphiWrapper1.WrapInterface(TValue.From(LSupplier));
  PythonModule1.SetVar('delphi_supplier', Py);
  GetPythonEngine.Py_DecRef(Py);

end;

At runtime the variables are correctly interpreted, but every time I try to access one of the properties defined in the interface I always get the same error.在运行时,变量被正确解释,但每次我尝试访问接口中定义的属性之一时,我总是遇到相同的错误。

This is the Python script I try to run:这是我尝试运行的 Python 脚本:

from delphi_module import delphi_person, delphi_customer, delphi_supplier 

print('type(delphi_person) = ', type(delphi_person)) 
print('type(delphi_customer) = ', type(delphi_customer)) 
print('type(delphi_supplier) = ', type(delphi_supplier)) 

print(delphi_person.Name)

And the error I get我得到的错误

Traceback (most recent call last): File "", line 7, in AttributeError: Error in getting property "Name".回溯(最近一次调用):文件“”,第 7 行,在 AttributeError 中:获取属性“名称”时出错。 Error: Unknown attribute错误:未知属性

The type(...) command runs correctly for the three variables. type(...) 命令对三个变量正确运行。

If instead of using 3 variables of the interface type, I declare each variable as a class type, using the PyDelphiWrapper.Wrap method, everything works correctly!如果不是使用接口类型的 3 个变量,而是使用 PyDelphiWrapper.Wrap 方法将每个变量声明为类类型,则一切正常!

procedure TFrmTestInterface.FormCreate(Sender: TObject);
var
  LPerson : IPerson;
  LCustomer : ICustomer;
  LSupplier : ISupplier;
  Py: PPyObject;
begin

  LPerson := TPerson.Create;
  LCustomer := TCustomer.Create;
  LSupplier := TSupplier.Create;

  LPerson.Name := 'Pippo';
  LPerson.Surname := 'Rossi';

  LCustomer.Name := 'Pluto';
  LCustomer.Surname := 'Verdi';

  LSupplier.Name := 'Paperino';
  LSupplier.Surname := 'Grandi';


  Py := PyDelphiWrapper1.Wrap(LPerson, TObjectOwnership.soReference);
  PythonModule1.SetVar('delphi_person', py);
  GetPythonEngine.Py_DECREF(py);

  Py := PyDelphiWrapper1.Wrap(LCustomer, TObjectOwnership.soReference);
  PythonModule1.SetVar('delphi_customer', py);
  GetPythonEngine.Py_DECREF(py);

  Py := PyDelphiWrapper1.Wrap(LSupplier, TObjectOwnership.soReference);
  PythonModule1.SetVar('delphi_supplier', py);
  GetPythonEngine.Py_DECREF(py);

end;

With the same Python script I get the correct output without errors使用相同的 Python 脚本,我得到了正确的输出而没有错误

在此处输入图片说明

Anyone have any idea what I'm doing wrong with using the TPyDelphiWrapper to wrap interface type variables for Python scripts?任何人都知道我在使用 TPyDelphiWrapper 为 Python 脚本包装接口类型变量时做错了什么吗?

Delphi does not add RTTI on properties defined in interfaces. Delphi 不会在接口中定义的属性上添加 RTTI。 Therefore property 'Name' cannot be found by the Python engine.因此,Python 引擎无法找到属性“名称”。 RTTI is available for the methods when you add {$M+} before the interface declaration.当您在接口声明之前添加 {$M+} 时,RTTI 可用于这些方法。 Calling delphi_person.GetName() should work then.然后调用 delphi_person.GetName() 应该可以工作。

There is another issue with using interfaces and the Python engine, the interface is not locked when you call WrapInterface.使用接口和 Python 引擎还有另一个问题,调用 WrapInterface 时接口没有被锁定。 Therefore the object will be released when it goes out of scope.因此,对象在超出范围时将被释放。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM