我正在使用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 组件并设置它的 OnExtGetData
和 OnExtSetData
事件,如以下代码:
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/