3

I'm trying to convert Python function to Delphi using Python4Delphi (to educate myself and to gain speed, I hope). However I've no idea how this works with Delphi and Python. Here's my original function:

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 is not python list, but custom object)

I found related Demo09 from Python4Delphi, but couldn't find any help how to go thru that list, unpack the tuple and modify value.

Any pointers for documentation creating extensions?

Harriv
  • 6,029
  • 6
  • 44
  • 76
  • 2
    If I were you I would elect to write your Python extension in C. The documentation assumes C. Almost all material on the web will assume C. I seem to recall that P4D is not up to date with Python. And when you write extensions in Delphi, what you get is C code with Pascal syntax because the underlying API is C oriented. – David Heffernan Nov 23 '11 at 16:20
  • How it's not up to date? Python 3.2 is latest supported version. – Harriv Nov 23 '11 at 18:24
  • I thought it did not have full coverage of python api. Am I wrong? – David Heffernan Nov 23 '11 at 18:52
  • I don't know, I just started :) – Harriv Nov 23 '11 at 19:21
  • Yes, I know C - but this is kind of self education project which I want to do in Delphi now. – Harriv Nov 23 '11 at 20:42
  • Python4Delphi seems a bit out date and stale. I really think you're better off writing your extensions using Visual C++ if you have it. – Warren P Nov 23 '11 at 20:42

1 Answers1

8

Python4Delphi handles the problem of loading Python's main DLL into a Delphi program, embedding the Python interpreter into your delphi application, but also has some demos for the reverse; to write an extension using Delphi. Below is some working example code.

I found a book book reference here to writing python extensions using delphi. Page 469 of the Python Programming on Win32, by Mark Hammond & Andy Robinson (O'Reilly).

A sample DLL skeleton for a Delphi DLL that implements a python extension might look like this, taken from the Demo09 folder in Python4Delphi source distribution:

Project (.dpr) file source:

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.

Actual extension unit (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.

Note that methods that can be called from python can only have parameters Self, Args : PPyObject as their parameter signature, and the Args value is a Python tuple (an immutable data structure similar to a vector or array). You then have to parse the tuple, and inside it, there will be 1 or more arguments of various types. You then have to deal with the fact that each item inside the tuple object passed in could be an integer, a string, a tuple, a list, a dictionary, etc etc.

You're going to need to learn to call method on a python object as in python code: img.dim(), get items from a list and so on.

Look for whereever PyArg_ParseTuple is defined (ctrl-click it) and look for other methods that start with the prefix Py that might have names like PyList_GetItem. That is the pseudo-OOP naming convention used by python (PyCATEGORY_MethodName). It's all pretty easy once you see some sample code. Sadly, most of that sample code is in C.

You could probably even use a tool to auto-convert your Python code above into sample C code, then try translating it into Python, line by line. But it all sounds like a waste of time to me.

Some more Python API functions to look up and learn:

Py_BuildValue - useful for return values

Py_INCREF and Py_DECREF - necessary for object reference counting.

You will need to know all the memory rules, and ownership rules here.

Warren P
  • 65,725
  • 40
  • 181
  • 316
  • That book looks like what I was looking for, great. As you can read from my question, I found demo09 too, but I feel pretty lost with the Python API. – Harriv Nov 23 '11 at 20:46
  • One of the other reasons to go with C for writing these extensions is that you can study existing extensions, and then crib their techniques for reading Python Lists, Tuples, Dictionaries, invoking Python methods, and so on, and so on. Heck, if you actually have something USEFUL to write, it probably already EXISTS as a C extension out there somewhere. Seriously. – Warren P Nov 23 '11 at 21:29