program PythonDemo;
{$mode objfpc}{$H+}
{ define DYNAMIC }
{$define PYTHON2 }
(* Assume that there is only superficial similarity between the Python v2 and *)
(* v3 script syntax and semantics. This demo is, more than anything else, the *)
(* "point of contact" between the various implementation possibilities at the *)
(* time of development. *)
{$ifdef PYTHON2 }
{$unitpath ./python2 }
{$note ===== Intending to link to Python v2 ===== }
{$else }
{$unitpath ./python3 }
{$note ===== Intending to link to Python v3 ===== }
{$endif PYTHON2 }
(* WARNING: since the unit path is being set up during compilation, Lazarus's *)
(* build facility might not successfully retire unwanted files. If in doubt do *)
(* a "Clean directory". *)
uses
{$IFDEF UNIX}
cthreads,
{$ENDIF}
Classes,
{$ifdef DYNAMIC }
python_dynamic; (* "Python" is a shared-library object *)
{$note ===== Intending to link dynamically ===== }
{$else }
python; (* "Python" is a unit file *)
{$note ===== Intending to link statically ===== }
{$endif DYNAMIC }
var
localArgv: array of PChar;
debugging: boolean= false;
(* Generate an array of pointers from the flat block of null-terminated strings,
excluding the --DEBUG-- option which is handled specially.
This is temporary, and should be moved to the Python unit/object even if it's
not handled automatically.
*)
procedure initArgv;
var
i, j: integer;
begin
SetLength(localArgv, 1);
localArgv[0] := System.Argv^; (* Program name *)
j := 1;
for i := 1 to ParamCount() do
if ParamStr(i) = '--DEBUG--' then
debugging := true
else begin
SetLength(localArgv, j + 1);
localArgv[j] := localArgv[i - 1] + StrLen(localArgv[i - 1]) + 1;
j += 1
end
end { initArgv } ;
begin
InitializeLibrary; (* Ensures Python.ModuleInMemory valid *)
if Python.IsDynamic then
Write('Python is dynamically linked, ')
else
Write('Python is statically linked, ');
if Python.ModuleInMemory then
Write('and has ')
else
Write('but has not ');
WriteLn('been successfully loaded.');
initArgv; (* localArgv and debugging flag *)
if debugging then
WriteLn('Debugging is enabled.'); (* Special --DEBUG-- option *)
(* Report Python version etc., this calls into libpython but does not rely on *)
(* script execution. Note that while Py_SetProgramName() has to be called *)
(* before Py_Initialize in order to set up internal paths etc., PySys_SetArgv() *)
(* has to be called afterwards. *)
WriteLn(StrPas(Python.Py_GetVersion()));
Python.Py_SetProgramName(PChar(ParamStr(0))); (* Before _Initialize *)
(* Initialise the embedded Python implementation and run the traditional *)
(* trivial script. For the moment at least, expect output to go to the console. *)
Python.Py_Initialize;
try
// Py_InitModule("emb", EmbMethods); // emb would be part of this Pascal program
Python.PySys_SetArgv(Length(localArgv), @localArgv[0]);
Python.PyRun_SimpleString(
'import sys' + LineEnding + (* Just to check EOL convention *)
'print(sys.argv[0:])' + LineEnding +
'print("Hello, World!")' + LineEnding
);
finally
Python.Py_Finalize
end
end.