|
@@ -0,0 +1,207 @@
|
|
|
+{
|
|
|
+ Double Commander
|
|
|
+ -------------------------------------------------------------------------
|
|
|
+ Simple interface to the Python language
|
|
|
+
|
|
|
+ Copyright (C) 2014 Alexander Koblov ([email protected])
|
|
|
+
|
|
|
+ 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.
|
|
|
+
|