【问题标题】:Python4Delphi: Returning a python object in a function. (DelphiWrapper)Python4Delphi:在函数中返回一个 python 对象。 (德尔福包装)
【发布时间】:2012-03-19 13:40:21
【问题描述】:

我正在使用 python4delphi。如何从包装好的 Delphi 类函数中返回对象?

代码片段:

我有一个简单的 Delphi 类,我将其包装到 Python 脚本中,对吗?

TSimple = Class
Private
  function getvar1:string;
Public    
Published
  property var1:string read getVar1;
  function getObj:TSimple;
end;
... 
function TSimple.getVar1:string;
begin
  result:='hello';
end;
function TSimple.getObj:TSimple;
begin
  result:=self;
end;

我制作了类似于 demo32 的 TPySimple,以便让类访问 Python 代码。我的 Python 模块名称是 test。

TPySimple = class(TPyDelphiPersistent)
  // Constructors & Destructors
  constructor Create( APythonType : TPythonType ); override;
  constructor CreateWith( PythonType : TPythonType; args : PPyObject ); override;
  // Basic services
  function  Repr : PPyObject; override;

  class function  DelphiObjectClass : TClass; override;
end;
...

{ TPySimple }

constructor TPySimple.Create(APythonType: TPythonType);
begin
  inherited;
  // we need to set DelphiObject property
  DelphiObject := TSimple.Create;
  with TSimple(DelphiObject) do begin
  end;
  Owned := True; // We own the objects we create
end;

constructor TPySimple.CreateWith(PythonType: TPythonType; args: PPyObject);
begin
  inherited;
  with GetPythonEngine, DelphiObject as TSimple do
    begin
      if PyArg_ParseTuple( args, ':CreateSimple' ) = 0 then
        Exit;
    end;
end;

class function TPySimple.DelphiObjectClass: TClass;
begin
  Result := TSimple;
end;

function TPySimple.Repr: PPyObject;
begin
  with GetPythonEngine, DelphiObject as TSimple do
    Result := VariantAsPyObject(Format('',[]));
    // or Result := PyString_FromString( PAnsiChar(Format('()',[])) );
end;

现在是python代码:

import test

a = test.Simple()
# try access the property var1 and everything is right
print a.var1
# work's, but..
b = a.getObj();
# raise a exception that not find any attributes named getObj.
# if the function returns a string for example, it's work.

【问题讨论】:

  • 有人投了反对票,但没有说明原因(有些人有一个坏习惯,我希望我能对他们投反对票!)不过我的猜测是你应该更多地解释你的意思(也许是一个代码 sn-p ) 以及什么不起作用或您已经尝试过什么。
  • 这个问题对我来说似乎很模糊。缺乏活动支持了这种感觉。
  • 好吧伙计们,拿一些代码 sn-ps。
  • 乍一看确实很奇怪。更简单的方法是否有效,例如一个返回一个整数?也许它返回指向类本身的指针这一事实使包装器感到困惑——它将如何处理?你如何“让 TPySimple 像 demo32 一样让类访问 python 代码”?您能否链接到他们的文档或显示生成的导入文件中的内容(如果这是人类可读的,我不知道。)
  • 这是一个糟糕的文档化组件 (code.google.com/p/python4delphi) 但您可以下载源代码并运行演示,在 demo32 中它们向我们展示了如何在您的 python 脚本中使用 delphi 类,我认为 TPySimple 的代码对我们没有帮助,但现在就在这里。

标签: delphi delphi-xe2 python4delphi


【解决方案1】:

我在使用 DelphiWrapper 时遇到了同样的问题。

首先,使用 {$METHODINFO ON} 启用 RTTI 将防止异常:

引发未找到任何名为 getObj 的属性的异常。

像这样编写 TSimple 类:

{$METHODINFO ON}
TSimple = Class
Private
  function getvar1:string;
Public    
Published
  property var1:string read getVar1;
  function getObj:TSimple;
end;
{$METHODINFO OFF}

现在 getObj 函数返回一个值——一个整数!!

我会告诉你们我做了什么。我修改了Demo32:

Unit1.pas:

TPoint = class(TPersistent)
private
  fx, fy : Integer;
  fName : String;
public
  constructor Create();
  procedure OffsetBy( dx, dy : integer );
  function MySelf: TPoint;  //**access self using function**
published
  property x : integer read fx write fx;
  property y : integer read fy write fy;
  property Name : string read fName write fName;
  property MySelf2: TPoint read MySelf; //**access self using property**
end;

Memo1.Lines 中的 Python 代码:

import spam

p = spam.Point(2, 5)

b = p.MySelf()  //**using function**
print 'Using MySelf: ', type(b), b
c = p.MySelf2   //**using property**
print 'Using MySelf2: ', type(c), c

然后它给出这样的结果:

Using MySelf:  <type 'int'> 31957664
Using MySelf2:  <type 'Point'> (2, 5)

该函数返回一个 int,这是有线的。也许它是一个指向被 DelphiWrapper 错误包装的 TPoint 对象的指针。

最后我在 Demo8 中找到了一种使用“AddMethod”的折衷方法。一点都不漂亮!!但它有效。

【讨论】:

    【解决方案2】:

    根据 OP,他在这里找到了答案:http://code.google.com/p/python4delphi/issues/detail?id=17

    (复制粘贴供参考)

    嗨,

    我有一个建议 - 通过利用 D2010(及更高版本)中的新 RTTI(运行时类型信息)功能,让 Delphi 对象轻松暴露给 python。

    目前将一个类暴露给托管的Python代码需要你写太多的代码(查看demo06),我想如果我们利用较新版本的Delphi中新的RTTI特性,这个过程可以改进很多.

    例如,查看 Delphi chromium 嵌入式项目,将任何 Delphi 类的接口暴露给 JavaScript 环境所需要做的就是注册该类:

    // this is your class exposed to JS 
      Test = class 
        class procedure doit(const v: string); 
      end; 
    
    initialization 
    // Register your class 
      TCefRTTIExtension.Register('app', Test);
    
    // and in JavaScript code to call that class above:
    app.doit(''foo'')', '', 0); 
    

    酷!不是吗?

    以上代码摘自:http://groups.google.com/group/delphichromiumembedded/browse_thread/thread/1793e7ca66012f0c/8ab31a5ecdb6bf48?lnk=gst&q=JavaScript+return+#

    关于自 D2010 以来引入的 RTTI 的一些介绍: http://robstechcorner.blogspot.com/2009/09/delphi-2010-rtti-basics.html

    【讨论】:

      猜你喜欢
      • 2018-02-11
      • 2012-12-13
      • 1970-01-01
      • 2014-07-08
      • 1970-01-01
      • 1970-01-01
      • 2013-03-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多