【问题标题】:Creating Python extension with Delphi使用 Delphi 创建 Python 扩展
【发布时间】:2011-11-23 14:47:57
【问题描述】:

我正在尝试使用 Python4Delphi 将 Python 函数转换为 Delphi(我希望是为了自学和提高速度)。但是我不知道这如何与 Delphi 和 Python 一起工作。这是我原来的功能:

def MyFunc(img, curve):
  C = 160
  for i in xrange(img.dim()[0]):
    p = img[i]
    img[i] = (p[0], p[1], p[2] - curve[p[0]] + C)

(img不是python列表,而是自定义对象)

我从 Python4Delphi 中找到了相关的 Demo09,但找不到任何帮助如何通过该列表、解包元组和修改值。

任何关于创建扩展的文档的指针?

【问题讨论】:

  • 如果我是你,我会选择用 C 编写你的 Python 扩展。文档假定 C。几乎网络上的所有材料都假定 C。我似乎记得 P4D 不是最新的Python。而当你在 Delphi 中编写扩展时,你得到的是带有 Pascal 语法的 C 代码,因为底层 API 是面向 C 的。
  • 怎么不是最新的? Python 3.2 是最新支持的版本。
  • 我以为它没有完全覆盖python api。我错了吗?
  • 我不知道,我刚开始:)
  • 是的,我知道 C - 但这是我现在想在 Delphi 中做的一种自我教育项目。

标签: python delphi python4delphi


【解决方案1】:

Python4Delphi 处理将 Python 的主 DLL 加载到 Delphi 程序中的问题,将 Python 解释器嵌入到您的 delphi 应用程序中,但也有一些反向演示;使用 Delphi 编写扩展。下面是一些工作示例代码。

我在这里找到了一本书 book 参考,以使用 delphi 编写 python 扩展。第 469 页的 Python Programming on Win32,作者 Mark Hammond 和 Andy Robinson (O'Reilly)。

实现 python 扩展的 Delphi DLL 的示例 DLL 框架可能如下所示 这个,取自 Python4Delphi 源代码分发中的 Demo09 文件夹:

项目(.dpr)文件来源:

library demodll;

{$I Definition.Inc}

uses
  SysUtils,
  Classes,
  module in 'module.pas';

exports
  initdemodll;
{$IFDEF MSWINDOWS}
{$E pyd}
{$ENDIF}
{$IFDEF LINUX}
{$SONAME 'demodll'}

{$ENDIF}

begin
end.

实际扩展单元(module.pas):

unit module;

interface
uses PythonEngine;

procedure initdemodll; cdecl;

var
  gEngine : TPythonEngine;
  gModule : TPythonModule;

implementation

function Add( Self, Args : PPyObject ) : PPyObject; far; cdecl;
var
  a, b : Integer;
begin
  with GetPythonEngine do
    begin
      if PyArg_ParseTuple( args, 'ii:Add', [@a, @b] ) <> 0 then
        begin
          Result := PyInt_FromLong( a + b );
        end
      else
        Result := nil;
    end;
end;

procedure initdemodll;
begin
  try
    gEngine := TPythonEngine.Create(nil);
    gEngine.AutoFinalize := False;
    gEngine.LoadDll;
    gModule := TPythonModule.Create(nil);
    gModule.Engine := gEngine;
    gModule.ModuleName := 'demodll';
    gModule.AddMethod( 'add', @Add, 'add(a,b) -> a+b' );
    gModule.Initialize;
  except
  end;
end;

initialization
finalization
  gEngine.Free;
  gModule.Free;
end.

注意,可以从python调用的方法只能有参数Self, Args : PPyObject作为参数签名,而Args值是一个Python元组(一种不可变的数据结构,类似于向量或数组)。然后,您必须解析元组,在其中,将有 1 个或多个不同类型的参数。然后,您必须处理传入的元组对象中的每个项目可能是整数、字符串、元组、列表、字典等的事实。

您将需要学习调用 python 对象上的方法,如在 python 代码中:img.dim(),从列表中获取项目等等。

查找定义了 PyArg_ParseTuple 的任何位置(按住 ctrl 键单击它)并查找以前缀 Py 开头的其他方法,这些方法的名称可能类似于 PyList_GetItem。那是 python (PyCATEGORY_MethodName) 使用的伪 OOP 命名约定。一旦你看到一些示例代码,这一切都很容易。可悲的是,大部分示例代码都是用 C 语言编写的。

您甚至可以使用工具将上面的 Python 代码自动转换为示例 C 代码,然后尝试将其逐行转换为 Python。但这一切对我来说都是浪费时间。

更多 Python API 函数可供查找和学习:

Py_BuildValue - 用于返回值

Py_INCREFPy_DECREF - 对象引用计数所必需的。

您需要在这里了解所有memory rules, and ownership rules

【讨论】:

  • 那本书看起来就像我要找的一样,太棒了。正如您从我的问题中看到的那样,我也找到了 demo09,但我对 Python API 感到很迷茫。
  • 使用 C 编写这些扩展的另一个原因是,您可以研究现有的扩展,然后借鉴他们的技术来阅读 Python 列表、元组、字典、调用 Python 方法等, 等等。哎呀,如果你真的有一些有用的东西要写,它可能已经作为 C 扩展存在于某个地方。说真的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-04
  • 1970-01-01
  • 2019-12-05
相关资源
最近更新 更多