mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
ADD: Simple interface to the Python language
This commit is contained in:
parent
46cfdc4066
commit
c1e4ba0d91
1 changed files with 207 additions and 0 deletions
207
src/platform/unix/upython.pas
Normal file
207
src/platform/unix/upython.pas
Normal 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.
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue