实现一个类第一个例子可以工作,并且能够演示注册模块,函数和一些基本的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结合之二相关推荐

  1. [ 转]Python模块(二)import和from...import的区别

    Python模块(二)import和from...import的区别 听语音 原创 | 浏览:2975 | 更新:2018-04-02 13:02 | 标签:PYTHON 1 2 3 4 5 6 7 ...

  2. 如何用python制作动态二维码,提升表白成功率?

    来源:凹凸数据 本文约1000字,建议阅读5分钟. 本文教你用python制作动态二维码,助你表白成功! 关注数据派THU(DatapiTHU)后台回复"20200520"获取完整 ...

  3. 深入浅出python机器学习_如何用python画(绘制)二维函数(二维图)?

    参考文档 python 如何绘制二维函数? from matplotlib import pyplot as plt import numpy as np low=lambda x:10000 if ...

  4. 第一章 TensorFlow基础——python语法(二)

    简明Python基础(二) 此为jupyter notebook导出文档,如果习惯jupyter界面可以下载文件 链接:https://pan.xunlei.com/s/VMn5sAsjVypJElz ...

  5. 转 Python爬虫入门二之爬虫基础了解

    静觅 » Python爬虫入门二之爬虫基础了解 2.浏览网页的过程 在用户浏览网页的过程中,我们可能会看到许多好看的图片,比如 http://image.baidu.com/ ,我们会看到几张的图片以 ...

  6. python实现logistic_使用python实现logistic二分类

    这段时间做了一个二分类的任务,训练数据是8000个包含1000个特征和一个label的数据.下面记录一下使用python实现logistic二分类的代码. import os import time ...

  7. python在材料模拟中的应用_基于Python的ABAQUS二次开发及在板料快速冲压成形模拟中的应用...

    2009 doi :10 1 3969/ j 1 issn 1 1007 2 2012 1 2009 1 04 1 013 基于 Python 的 ABAQUS 二次开发及在板料快速 冲压成形模拟中的 ...

  8. Python基础(二)--数据类型,运算符与流程控制

    目录 Python基础(二)--数据类型,运算符与流程控制 1 数据类型 1.1 Python中的数据类型 1.2 整数类型(int) 1.3 布尔类型 1.4 浮点类型 1.5 复数类型 1.6 类 ...

  9. python对abaqus本构二次开发_基于Python的Abaqus二次开发实例讲解

    第 1 页 共 11 页 基于 Python 的 Abaqus 二次开发实例讲解 ( asian58 2013.6.26 ) 基于 Python 的 Abaqus 的二次开发便捷之处在于: 1 .所有 ...

  10. python接口自动化测试二十四:上传多个附件,参数化

    python接口自动化测试二十四:上传多个附件,参数化 # 添加多个附件参数化files = [("1.png", "1.png") ("2.png& ...

最新文章

  1. datalist,Repeater和Gridview的区别分析
  2. 普适的GPIO引脚操作方法
  3. python中5个json库的速度对比
  4. SQL注入学习——时间盲注详解 sqli-labs(Less 9)
  5. C++编译出现binding ‘const string {aka const std::__cxx11::basic_string<char>}’ to reference of type ‘std
  6. 计算机减法英语,英语加减乘除的表达
  7. 2017.9.6 音量调节 思考记录
  8. 基于asp.net sql社区物业管理系统毕业设计网站
  9. 【leetcode】 Unique Binary Search Trees (middle)☆
  10. Ninth scrum meeting - 2015/11/3
  11. 微型计算机原理及应用课后习题答案,微型计算机原理及应用课后习题答案.doc...
  12. Typora下载与安装
  13. 尚硅谷redis6文档,代码
  14. 此时墨迹在计算机上不起作用,win7系统自带截图工具不见了怎么找回
  15. qq登录界面句柄_天天玩QQ!知道登录界面那两个人是谁吗?网友:不是情侣?...
  16. cocos2d-x 使用位图工具制作 fnt字体
  17. C++实现简易图书馆管理系统
  18. 行通选、列通选、片选
  19. 界面开发(3)--- PyQt5用户登录界面连接数据库
  20. kali linux amd显卡驱动,AMD 显卡安装debian

热门文章

  1. matlab如何获得一个二值掩码,1.3矩阵的掩码操作 - osc_uarhdl2n的个人空间 - OSCHINA - 中文开源技术交流社区...
  2. directx修复工具v3.2增强版_「电脑知识」USBOS 超级PE启动维护工具增强版及标准版...
  3. 风变编程python第一关_风变编程python学习心得
  4. mysql start tran_mysql事务,START TRANSACTION, COMMIT和ROLLBACK,SET AUTOCOMMIT语法
  5. suse mysql完全卸载_SUSE Linux下通过RPM方式卸载MySQL 5过程笔记
  6. Introduction to Computer Networking学习笔记(七):ICMP协议
  7. 华为手机 图标消失_华为手机升级EMUI 10后解决Google Play“消失”教程
  8. sentinel 时间窗口_sentinel 滑动窗口统计机制
  9. mysql grant命令详解_mysql grant命令详解 设置mysql远程连接
  10. matlab 离散积分器设置,MATLABSIULINK积分器相关操作.docx