ADD: Simple interface to the Python language

This commit is contained in:
Alexander Koblov 2014-07-04 14:36:23 +00:00
commit c1e4ba0d91

View file

@ -0,0 +1,207 @@
{
Double Commander
-------------------------------------------------------------------------
Simple interface to the Python language
Copyright (C) 2014 Alexander Koblov (alexx2000@mail.ru)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
}
unit uPython;
{$mode delphi}
{$packrecords c}
interface
uses
Classes, SysUtils, CTypes, DCOSUtils;
type
PPyObject = ^TPyObject;
PPyTypeObject = ^TPyTypeObject;
TPyTypeObject = record
ob_refcnt: csize_t;
ob_type: PPyTypeObject;
ob_size: csize_t;
tp_name: PAnsiChar;
tp_basicsize, tp_itemsize: csize_t;
//* Methods to implement standard operations */
tp_dealloc: procedure(obj: PPyObject); cdecl;
end;
TPyObject = record
ob_refcnt: csize_t;
ob_type: PPyTypeObject;
end;
function PythonLoadModule(const ModuleName: UTF8String): PPyObject;
function PythonRunFunction(Module: PPyObject; const FunctionName: UTF8String; FileList: TStrings): UTF8String;
var
HasPython: Boolean = False;
implementation
uses
dynlibs, dl;
var
// pythonrun.h
Py_Initialize: procedure; cdecl;
Py_Finalize: procedure; cdecl;
PyErr_Print: procedure; cdecl;
PyRun_SimpleString: function(s: PAnsiChar): cint; cdecl;
// import.h
PyImport_Import: function(name: PPyObject): PPyObject; cdecl;
// object.h
PyCallable_Check: function(ob: PPyObject): cint; cdecl;
PyObject_GetAttrString: function (ob: PPyObject; c: PAnsiChar): PPyObject; cdecl;
// abstract.h
PyObject_CallObject: function(callable_object, args: PPyObject): PPyObject; cdecl;
PyObject_CallFunctionObjArgs: function(callable: PPyObject): PPyObject; cdecl; varargs;
// stringobject.h
PyString_AsString: function(ob: PPyObject): PAnsiChar; cdecl;
PyString_FromString: function(s: PAnsiChar): PPyObject; cdecl;
// listobject.h
PyList_New: function(size: csize_t): PPyObject; cdecl;
PyList_SetItem: function(ob: PPyObject; index: csize_t; item: PPyObject): cint; cdecl;
// tupleobject.h
PyTuple_New: function(size: csize_t): PPyObject; cdecl;
PyTuple_SetItem: function(ob: PPyObject; index: csize_t; item: PPyObject): cint; cdecl;
procedure Py_DECREF(op: PPyObject);
begin
with op^ do begin
Dec(ob_refcnt);
if ob_refcnt = 0 then begin
ob_type^.tp_dealloc(op);
end;
end;
end;
procedure Py_XDECREF(op: PPyObject); inline;
begin
if Assigned(op) then Py_DECREF(op);
end;
function StringsToPyList(Strings: TStrings): PPyObject;
var
I: LongInt;
begin
Result:= PyList_New(Strings.Count);
if not Assigned(Result) then Exit;
for I:= 0 to Strings.Count - 1 do
begin
PyList_SetItem(Result, I, PyString_FromString(PAnsiChar(Strings[I])));
end;
end;
function PyObjectsToPyTuple(Values: array of PPyObject): PPyObject;
var
Index: csize_t;
begin
Result:= PyTuple_New(Length(Values));
if not Assigned(Result) then Exit;
for Index:= Low(Values) to High(Values) do
begin
PyTuple_SetItem(Result, Index, Values[Index]);
end;
end;
function PythonLoadModule(const ModuleName: UTF8String): PPyObject;
var
pyName: PPyObject;
begin
PyRun_SimpleString('import sys');
PyRun_SimpleString('sys.path.append("")');
pyName:= PyString_FromString(PAnsiChar(ModuleName));
Result:= PyImport_Import(pyName);
Py_DECREF(pyName);
end;
function PythonRunFunction(Module: PPyObject; const FunctionName: UTF8String; FileList: TStrings): UTF8String;
var
pyFunc, pyList: PPyObject;
pyArgs, pyValue: PPyObject;
begin
if Assigned(Module) then
begin
pyFunc:= PyObject_GetAttrString(Module, PAnsiChar(FunctionName));
if (Assigned(pyFunc) and (PyCallable_Check(pyFunc) <> 0)) then
begin
pyList:= StringsToPyList(FileList);
pyArgs:= PyObjectsToPyTuple([pyList]);
pyValue:= PyObject_CallObject(pyFunc, pyArgs);
Py_XDECREF(pyList);
Py_XDECREF(pyArgs);
if (pyValue = nil) then
PyErr_Print()
else begin
Result:= StrPas(PyString_AsString(pyValue));
Py_DECREF(pyValue);
end;
Py_DECREF(pyFunc);
end;
end;
end;
var
libpython: TLibHandle;
procedure Initialize;
begin
libpython:= TLibHandle(dlopen('libpython2.7.so.1', RTLD_NOW or RTLD_GLOBAL));
HasPython:= libpython <> NilHandle;
if HasPython then
try
@Py_Initialize:= SafeGetProcAddress(libpython, 'Py_Initialize');
@Py_Finalize:= SafeGetProcAddress(libpython, 'Py_Finalize');
@PyErr_Print:= SafeGetProcAddress(libpython, 'PyErr_Print');
@PyRun_SimpleString:= SafeGetProcAddress(libpython, 'PyRun_SimpleString');
@PyImport_Import:= SafeGetProcAddress(libpython, 'PyImport_Import');
@PyCallable_Check:= SafeGetProcAddress(libpython, 'PyCallable_Check');
@PyObject_GetAttrString:= SafeGetProcAddress(libpython, 'PyObject_GetAttrString');
@PyObject_CallObject:= SafeGetProcAddress(libpython, 'PyObject_CallObject');
@PyObject_CallFunctionObjArgs:= SafeGetProcAddress(libpython, 'PyObject_CallFunctionObjArgs');
@PyString_AsString:= SafeGetProcAddress(libpython, 'PyString_AsString');
@PyString_FromString:= SafeGetProcAddress(libpython, 'PyString_FromString');
@PyList_New:= SafeGetProcAddress(libpython, 'PyList_New');
@PyList_SetItem:= SafeGetProcAddress(libpython, 'PyList_SetItem');
@PyTuple_New:= SafeGetProcAddress(libpython, 'PyTuple_New');
@PyTuple_SetItem:= SafeGetProcAddress(libpython, 'PyTuple_SetItem');
// Initialize the Python interpreter
Py_Initialize();
except
HasPython:= False;
end;
end;
procedure Finalize;
begin
if HasPython then Py_Finalize();
if libpython <> NilHandle then FreeLibrary(libpython);
end;
initialization
Initialize;
finalization
Finalize;
end.