简体   繁体   English

Python4Delphi:在函数中返回python对象。 (DelphiWrapper)

[英]Python4Delphi: Returning a python object in a function. (DelphiWrapper)

I am using python4delphi. 我正在使用python4delphi。 How can I return an object from a wrapped Delphi class function? 如何从包装的Delphi类函数返回一个对象?

Code Snippet: 代码片段:

I have a simple Delphi Class that I wrapped to Python Script, right? 我有一个简单的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;

I made the TPySimple like the demo32 to give class access to the Python code. 我使用了类似于demo32的TPySimple来提供对Python代码的类访问。 My Python module name is test. 我的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;

And now the python code: 现在的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.

I have run into the same problem while using DelphiWrapper. 我在使用DelphiWrapper时遇到了同样的问题。

First, enable RTTI using {$METHODINFO ON} will prevent exception: 首先,使用{$ METHODINFO ON}启用RTTI将防止异常:

raise a exception that not find any attributes named getObj. 引发一个异常,找不到任何名为getObj的属性。

Write TSimple class like this: 写这样的TSimple类:

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

Now getObj function returns a value -- an Integer!! 现在getObj函数返回一个值 - 一个Integer !!

I'll show you guys what I did. 我会告诉你们我做了什么。 I modified Demo32: 我修改了Demo32:

Unit1.pas: 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;

Python code in Memo1.Lines: 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

Then it gives a result like this: 然后它给出一个这样的结果:

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

The function returns an int, that's wired. 该函数返回一个有线的int。 Maybe it's a pointer to a TPoint object incorrectly wrapped by DelphiWrapper. 也许它是指向由DelphiWrapper错误包装的TPoint对象的指针。

Finally I found a compromise way in Demo8 using "AddMethod". 最后,我在Demo8中使用“AddMethod”找到了一种折衷方式。 Not beautiful at all!! 一点都不漂亮!! But it works. 但它的确有效。

According to the OP he's found the answer here: http://code.google.com/p/python4delphi/issues/detail?id=17 根据OP,他在这里找到答案: http//code.google.com/p/python4delphi/issues/detail?id = 17

(A copy-paste for reference) (复制粘贴供参考)

Hi, 嗨,

I've a suggestion - make exposing Delphi objects to python painless by utilizing the new RTTI (runtime type information) feature in D2010 (and above). 我有一个建议 - 通过利用D2010(及更高版本)中新的RTTI(运行时类型信息)功能,使Delphi对象暴露于python中。

Currently exposing a class to the hosted Python code needs to you to write too much code (check demo06), I guess if we take advantage of the new RTTI feature in the newer versions of Delphi, the process can be improved a lot. 目前将一个类公开给托管的Python代码需要你编写太多的代码(检查demo06),我想如果我们在新版本的Delphi中利用新的RTTI功能,那么这个过程可以得到很大的改进。

For example, check out the Delphi chromium embedded project, all you have to do to expose the interface of any Delphi class to the JavaScript environment, is to register the class: 例如,查看Delphi chrome嵌入式项目,所有你要做的就是将任何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); 

Cool! 凉! Isn't it? 不是吗?

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

Some intro about RTTI introduced since D2010: http://robstechcorner.blogspot.com/2009/09/delphi-2010-rtti-basics.html 关于RTTI自D2010以来推出的一些介绍: http: //robstechcorner.blogspot.com/2009/09/delphi-2010-rtti-basics.html

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

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