python - 获取 Python 对象作为变体

标签 python class delphi python4delphi

我正在使用Python4Delphi

我有一个 python 文件,其中有一个类声明如下:

class Student:
  SName = "MyName"
  SAge = 26

  def GetName(self):
    return SName

  def GetAge(self):
    return SAge

我想获取此类的引用并使用我的 Delphi 代码访问它的字段或方法

我在这里找到了一个例子: http://www.atug.com/andypatterns/pythonDelphiTalk.htm

但是当我尝试像该示例那样执行时,会显示错误: “不支持此类接口(interface)”

这是我的德尔福代码:

var
 Err : Boolean;
 S : TStringList;
 MyClass : OLEVariant;
 PObj : PPyObject;
begin
 ...

 S := TStringList.Create;
 try
  S.LoadFromFile(ClassFileEdit.Text);
  Err := False;
  try
   PyEngine.ExecStrings(S);
  except
   on E:Exception do
    begin
     Err := True;

     MessageBox(Handle, PChar('Load Error : ' + #13 + E.Message), '', MB_OK+MB_ICONEXCLAMATION);
    end;
  end;
 finally
  S.Free;
 end;

 if Err then
  Exit;

 Err := False;
 try
  try
   PyEngine.ExecString('ClassVar.Value = Student()');
  except
   on E:Exception do
    begin
     Err := True;

     MessageBox(Handle, PChar('Class Name Error : ' + #13 + E.Message), '', MB_OK+MB_ICONEXCLAMATION);
    end;
  end;
 finally
  if not Err then
   begin
    PObj := ClassDelphiVar.ValueObject;
    MyClass := GetAtom(PObj);
    GetPythonEngine.Py_XDECREF(PObj);

    NameEdit.Text := MyClass.GetName();
    AgeEdit.Text := IntToStr(MyClass.GetAge());
   end;
 end;

此行发生错误:

NameEdit.Text := MyClass.GetName();

MyClass 似乎没有填充 Student 对象

我搜索了很多,发现 GetAtom 在新版本中已被弃用,但我如何以其他方式做到这一点?

  • ClassDelphiVar 是一个 TPythonDelphiVar 组件,其 VarName 为“ClassVar”

最佳答案

我找到了答案,我将在这里发布可能对某人有帮助

在表单上放置一个 PythonDelphiVar 组件并设置它的 OnExtGetDataOnExtSetData 事件,如以下代码:

procedure TMainFrm.ClassDelphiVarExtGetData(Sender: TObject;
  var Data: PPyObject);
begin
 with GetPythonEngine do
   begin
     Data := FMyPythonObject;
     Py_XIncRef(Data); // This is very important
   end;
end;

procedure TMainFrm.ClassDelphiVarExtSetData(Sender: TObject; Data: PPyObject);
begin
 with GetPythonEngine do
  begin
   Py_XDecRef(FMyPythonObject); // This is very important
   FMyPythonObject := Data;
   Py_XIncRef(FMyPythonObject); // This is very important
  end;
end;

我们应该小心Python对象的引用计数

FMyPythonObject 在表单类的公共(public)部分声明为 PPyObject 变量

现在,如果我们在 Python 模块中运行此脚本:

ClassVar.Value = MyClass()

(ClassVar是PythonDelphiVar组件的VarName)

然后我们可以像这样获取 Python 对象的属性:

var
 PObj : PPyObject;
begin
 ...
 PObj := GetPythonEngine.PyObject_GetAttrString(FMyPythonObject, PAnsiChar(WideStringToString('AttrName', 0)));
 AttrValueEdit.Text := GetPythonEngine.PyObjectAsString(PObj);
 ...
end

...

function WideStringToString(const Source: UnicodeString; CodePage: UINT): RawByteString;
var
 strLen: Integer;
begin
 strLen := LocaleCharsFromUnicode(CodePage, 0, PWideChar(Source), Length(Source), nil, 0, nil, nil);
 if strLen > 0 then
  begin
   SetLength(Result, strLen);
   LocaleCharsFromUnicode(CodePage, 0, PWideChar(Source), Length(Source), PAnsiChar(Result), strLen, nil, nil);
   SetCodePage(Result, CodePage, False);
  end;
end;

关于python - 获取 Python 对象作为变体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42907805/

相关文章:

c# - 在类和表单之间传递值

delphi - 当密码为俄语时,通过 HTTPS 授权失败 TIdHTTP

python - 如何使用 Python Django 在本地和远程服务器上运行 Selenium 测试?

python - 如何为WhatsApp .crypt12格式生成页眉和页脚?

Python QTableWidget 不显示全宽

python - TensorFlow 中的 Seq2Seq(无嵌入)

javascript - 是否可以重新定义 JavaScript 类的方法?

Java 参数传递

Delphi 7 TComPort OnRxChar 不火

php - 在没有smtp的情况下在Delphi中发送电子邮件并在服务器上使用php函数