delphi与python_Delphi与Python结合之二
实现一个类第一个例子可以工作,并且能够演示注册模块,函数和一些基本的Python Ext的概念。 对于长期使用Delphi这样的OO语言,仅仅公开函数当然不够方便,我们需要的是全OO编程,即使跨越了语言,也不会放弃这样的习惯。 我们现在要让Delphi的类可以为Python。
你首先看到的依然是一个例子,我们要把Delphi中的TPoint公开出来,让python可以调用,模块名称为dpoint,最终我们要在pythonIDE内看到的效果:>>> from dpoint import *
>>> print SmallPoint(222,111)
>>> SmallPoint.__doc__
'wrapper for Delphi TPoint typen'
P4D为注册类这样的工作提供了TPyDelphiWrapper类,在这个例子里,我们围绕这TPyDelphiWrapper来分析。
例子代码:library dpoint;
uses
Sharemem ,SysUtils,Classes,WrapDelphi,Types,PythonEngine;
{$E pyd}
var
FModule : TPythonModule;
FEngine:TPythonEngine ;
FDelphiWrapper : TPyDelphiWrapper;
procedure initdpoint; cdecl;
begin
FEngine := TPythonEngine.Create(nil);
FModule := TPythonModule.Create(nil);
FModule.Engine := FEngine;
FModule.ModuleName := 'dpoint';
FDelphiWrapper := TPyDelphiWrapper.Create(nil);
FDelphiWrapper.Engine := FEngine;
FDelphiWrapper.Module := FModule;
FEngine.LoadDll;
end;
exports
initdpoint;
var
OldExitProc: pointer;
procedure MyExitProc;
begin
FModule.Free;
FEngine.Free;
ExitProc := OldExitProc;
end;
type
TPyDelphiPoint = class(TPyObject)
private
fValue: TPoint;
protected
public
constructor CreateWith( APythonType : TPythonType; args : PPyObject ); override;
class procedure SetupType( PythonType : TPythonType ); override;
end;
Type
TTypesRegistration = class(TRegisteredUnit)
public
function Name : String; override;
procedure RegisterWrappers(APyDelphiWrapper : TPyDelphiWrapper); override;
end;
function TTypesRegistration.Name: String;
begin
Result := 'Types';
end;
procedure TTypesRegistration.RegisterWrappers(APyDelphiWrapper: TPyDelphiWrapper);
begin
inherited;
APyDelphiWrapper.RegisterHelperType(TPyDelphiPoint);
end;
constructor TPyDelphiPoint.CreateWith(APythonType: TPythonType;
args: PPyObject);
var
x, y : Integer;
begin
inherited;
if APythonType.Engine.PyArg_ParseTuple( args, 'ii:Create', [@x, @y] ) <> 0 then
begin
fValue.X := x;
fValue.Y := y;
end
end;
class procedure TPyDelphiPoint.SetupType(PythonType: TPythonType);
begin
inherited;
PythonType.TypeName := 'SmallPoint';
PythonType.TypeFlags := PythonType.TypeFlags + [tpfBaseType];
PythonType.DocString.Text := '12345';
end;
begin
RegisteredUnits.Add(TTypesRegistration.Create);
OldExitProc := ExitProc;
ExitProc := @MyExitProc;
end.
一个类必然要属于某一个模块,注册一个类就涉及到注册一个模块。关于注册模块,在例子中占据了不少带代码,但是它和第二部分完全一样,我们掠过不看。 本来注册一个类是有些复杂度的,如果想要知道这个复杂度,可以先看看参考文献1内的描述。不过采用P4D的类型注册框架就简单多了。 我们的例子pyd命名为dpoint ,我们准备把TPoint类型公开到Python内。
在initdpoint函数内,TPythonEngine,TPythonModule照样的初始化,比起函数注册来说,不同的地方在于创建了TPyDelphiWrapper的实例gDelphiWrapper, 并且指明他所属的PythonEngine,PythonModule:procedure initdpoint;
begin
gEngine := TPythonEngine.Create(nil);
gEngine.AutoFinalize := False;
gModule := TPythonModule.Create(nil);
gModule.Engine := gEngine;
gModule.ModuleName := 'dpoint';
gDelphiWrapper := TPyDelphiWrapper.Create(nil);
gDelphiWrapper.Engine := gEngine;
gDelphiWrapper.Module := gModule;
gEngine.LoadDll;
end;
gDelphiWrapper将会在RegisteredUnitList寻找RegisteredUnit,并且调用 这个类别内的RegisterWrappers方法,通过这个方法或者需要注册的Python类的Delphi包装类。 因此,我们要做的事情就是: 约定实现两个类,一个是需要公开的类型的Wrapper,这里就是TPyDelphiPoint,一个是注册这个Wrapper的注册类,本例子内就是TTypesRegistration。 TTypesRegistration只要实现两个覆盖基类的方法,从而达到通知TPyDelphiWrapper需要注册的类是TPyDelphiPoint。function Name : String; override; procedure RegisterWrappers(APyDelphiWrapper : TPyDelphiWrapper); override;
我们更多的注意力,尤其是以后的更多对PythonExtension特性的利用,集中于TPyDelphiPoint上。 TPyDelphiPoint,作为一个PythonType,最少要实现的方法有:constructor CreateWith( APythonType : TPythonType; args : PPyObject ); override;
class procedure SetupType( PythonType : TPythonType ); override;
我们可以注意到,CreateWith传递的args依然是PPyObject类型,和前文谈到的add方法对参数和返回值的处理都是一致的。 SetupType将会指明在Python内如何使用这个类型,根据源代码知道,SetupType指明这个类型在Python内的类型为SmallPoint,提供基本服务(fvbase),类型文档__doc__为 '12345', 测试用例3.1代码如果正常运行,就自然的证实了这一点。
以上例子很简单,但是可以表达主旨,是进一步了解和把握P4D编写扩展的基础。 从3.1的测试用例看:>>> print SmallPoint(222,111)
这样的输出很不友好,我们希望他是这样的:>>> print SmallPoint(222,111)
222,111
这样的服务在py内早已存在,它的名字叫做repr,每个对象如果希望打印友好,都应该支持这样的服务。 在Delphi编写的Py扩展中,如何做到这样的效果?
一旦框架铺陈完毕,编写具体的功能就很简单了。repr服务只要覆盖一个方法,加上对返回参数的包装就可以了:function Repr : PPyObject; override;
..
implementation
..
function TPyDelphiPoint.Repr: PPyObject;
begin
with GetPythonEngine do
Result := PyString_FromString(PChar(Format('', [Value.X, Value.Y])));
end;
设置属性,需要覆盖RegisterGetSets方法:class procedure TPyDelphiPoint.RegisterGetSets(PythonType: TPythonType);
begin
inherited;
with PythonType do
begin
AddGetSet('X', @TPyDelphiPoint.Get_X, @TPyDelphiPoint.Set_X,
'Provides access to the X coordinate of a point', nil);
AddGetSet('Y', @TPyDelphiPoint.Get_Y, @TPyDelphiPoint.Set_Y,
'Provides access to the Y coordinate of a point', nil);
end;
end;
别忘了在SetupType内加入一行:PythonType.Services.Basic := PythonType.Services.Basic+[bsGetAttrO, bsSetAttrO];
告诉Python你的服务中有属性的支持。
允许dpoint之间比较大小,需要覆盖Compare方法:function TPyDelphiPoint.Compare(obj: PPyObject): Integer;
var
_other : TPyDelphiPoint;
begin
if IsDelphiObject(obj) and (PythonToDelphi(obj) is TPyDelphiPoint) then
begin
_other := TPyDelphiPoint(PythonToDelphi(obj));
Result := CompareValue(Value.X, _other.Value.X);
if Result = 0 then
Result := CompareValue(Value.Y, _other.Value.Y);
end
else
Result := 1;
end;
同样别忘了在SetupType内加入一行:PythonType.Services.Basic := PythonType.Services.Basic+[bsCompare];
告诉Python你的服务中有bsCompare的支持。编写扩展后做什么?P4d的代码值得已读,因为基于注册的架构,dll直接到类TDynamicDll值得看,了解Python的内部实现,P4d本身就是Python和Delphi结合编程的良好榜样。
可以很好的了解Python类型的内部实现,比如整数的结构里面有那些字段,有那些基本类型服务的方法使用P4D还可以怎么样?这个图景在我自己还并不很清楚。但是Python和Delphi的结合的愿望在我却一直很强烈,希望有更多的朋友参与进来,提出更多的想法。 参考: www.atug.com/andypatterns/pythonDelphiTalk.htm
delphi与python_Delphi与Python结合之二相关推荐
- [ 转]Python模块(二)import和from...import的区别
Python模块(二)import和from...import的区别 听语音 原创 | 浏览:2975 | 更新:2018-04-02 13:02 | 标签:PYTHON 1 2 3 4 5 6 7 ...
- 如何用python制作动态二维码,提升表白成功率?
来源:凹凸数据 本文约1000字,建议阅读5分钟. 本文教你用python制作动态二维码,助你表白成功! 关注数据派THU(DatapiTHU)后台回复"20200520"获取完整 ...
- 深入浅出python机器学习_如何用python画(绘制)二维函数(二维图)?
参考文档 python 如何绘制二维函数? from matplotlib import pyplot as plt import numpy as np low=lambda x:10000 if ...
- 第一章 TensorFlow基础——python语法(二)
简明Python基础(二) 此为jupyter notebook导出文档,如果习惯jupyter界面可以下载文件 链接:https://pan.xunlei.com/s/VMn5sAsjVypJElz ...
- 转 Python爬虫入门二之爬虫基础了解
静觅 » Python爬虫入门二之爬虫基础了解 2.浏览网页的过程 在用户浏览网页的过程中,我们可能会看到许多好看的图片,比如 http://image.baidu.com/ ,我们会看到几张的图片以 ...
- python实现logistic_使用python实现logistic二分类
这段时间做了一个二分类的任务,训练数据是8000个包含1000个特征和一个label的数据.下面记录一下使用python实现logistic二分类的代码. import os import time ...
- python在材料模拟中的应用_基于Python的ABAQUS二次开发及在板料快速冲压成形模拟中的应用...
2009 doi :10 1 3969/ j 1 issn 1 1007 2 2012 1 2009 1 04 1 013 基于 Python 的 ABAQUS 二次开发及在板料快速 冲压成形模拟中的 ...
- Python基础(二)--数据类型,运算符与流程控制
目录 Python基础(二)--数据类型,运算符与流程控制 1 数据类型 1.1 Python中的数据类型 1.2 整数类型(int) 1.3 布尔类型 1.4 浮点类型 1.5 复数类型 1.6 类 ...
- python对abaqus本构二次开发_基于Python的Abaqus二次开发实例讲解
第 1 页 共 11 页 基于 Python 的 Abaqus 二次开发实例讲解 ( asian58 2013.6.26 ) 基于 Python 的 Abaqus 的二次开发便捷之处在于: 1 .所有 ...
- python接口自动化测试二十四:上传多个附件,参数化
python接口自动化测试二十四:上传多个附件,参数化 # 添加多个附件参数化files = [("1.png", "1.png") ("2.png& ...
最新文章
- datalist,Repeater和Gridview的区别分析
- 普适的GPIO引脚操作方法
- python中5个json库的速度对比
- SQL注入学习——时间盲注详解 sqli-labs(Less 9)
- C++编译出现binding ‘const string {aka const std::__cxx11::basic_string<char>}’ to reference of type ‘std
- 计算机减法英语,英语加减乘除的表达
- 2017.9.6 音量调节 思考记录
- 基于asp.net sql社区物业管理系统毕业设计网站
- 【leetcode】 Unique Binary Search Trees (middle)☆
- Ninth scrum meeting - 2015/11/3
- 微型计算机原理及应用课后习题答案,微型计算机原理及应用课后习题答案.doc...
- Typora下载与安装
- 尚硅谷redis6文档,代码
- 此时墨迹在计算机上不起作用,win7系统自带截图工具不见了怎么找回
- qq登录界面句柄_天天玩QQ!知道登录界面那两个人是谁吗?网友:不是情侣?...
- cocos2d-x 使用位图工具制作 fnt字体
- C++实现简易图书馆管理系统
- 行通选、列通选、片选
- 界面开发(3)--- PyQt5用户登录界面连接数据库
- kali linux amd显卡驱动,AMD 显卡安装debian
热门文章
- matlab如何获得一个二值掩码,1.3矩阵的掩码操作 - osc_uarhdl2n的个人空间 - OSCHINA - 中文开源技术交流社区...
- directx修复工具v3.2增强版_「电脑知识」USBOS 超级PE启动维护工具增强版及标准版...
- 风变编程python第一关_风变编程python学习心得
- mysql start tran_mysql事务,START TRANSACTION, COMMIT和ROLLBACK,SET AUTOCOMMIT语法
- suse mysql完全卸载_SUSE Linux下通过RPM方式卸载MySQL 5过程笔记
- Introduction to Computer Networking学习笔记(七):ICMP协议
- 华为手机 图标消失_华为手机升级EMUI 10后解决Google Play“消失”教程
- sentinel 时间窗口_sentinel 滑动窗口统计机制
- mysql grant命令详解_mysql grant命令详解 设置mysql远程连接
- matlab 离散积分器设置,MATLABSIULINK积分器相关操作.docx