使用Delphi创建Python扩展

3 投票
1 回答
3658 浏览
提问于 2025-04-17 06:55

我正在尝试使用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示例,但没找到关于如何遍历那个列表、解包元组和修改值的帮助。

有没有什么文档可以指导我如何创建扩展?

1 个回答

8

Python4Delphi 这个工具可以帮助你把 Python 的主 DLL 加载到 Delphi 程序中,也就是把 Python 解释器嵌入到你的 Delphi 应用里。此外,它还提供了一些示例,教你如何用 Delphi 来写扩展。下面是一些示例代码。

我找到了一本书,里面有关于用 Delphi 写 Python 扩展的内容。书名是《Python Programming on Win32》,作者是 Mark Hammond 和 Andy Robinson,具体在第469页。

一个 Delphi DLL 的示例框架,用来实现 Python 扩展,可能看起来像这样,取自 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 元组(类似于向量或数组的不可变数据结构)。你需要解析这个元组,里面会有一个或多个不同类型的参数。你还得处理元组中每个项目可能是整数、字符串、元组、列表、字典等等的情况。

你需要学习如何在 Python 对象上调用方法,比如在 Python 代码中写 img.dim(),从列表中获取项目等等。

查找 PyArg_ParseTuple 的定义(按住 Ctrl 点击它),并寻找其他以 Py 开头的方法,可能会有像 PyList_GetItem 这样的名字。这是 Python 使用的伪面向对象命名约定(PyCATEGORY_MethodName)。一旦你看到一些示例代码,这些都很简单。可惜大部分示例代码都是用 C 写的。

你甚至可以使用工具将上面的 Python 代码自动转换成示例 C 代码,然后逐行尝试翻译成 Python。但我觉得这听起来像是在浪费时间。

还有一些 Python API 函数值得你查找和学习:

Py_BuildValue - 对于返回值很有用

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

你需要了解所有的 内存规则和所有权规则

撰写回答