Skip to content

Commit 20dfc9a

Browse files
committed
Fix #504
Import stuff needed for Multi-phase module initialization
1 parent 8b4a78f commit 20dfc9a

File tree

1 file changed

+53
-14
lines changed

1 file changed

+53
-14
lines changed

Source/PythonEngine.pas

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,20 @@ TPythonVersionProp = record
344344
PyBUF_READ = $100;
345345
PyBUF_WRITE = $200;
346346

347+
const
348+
// constants used in PyModuleDef slots from moduleobject.h
349+
Py_mod_create = 1;
350+
Py_mod_exec = 2;
351+
Py_mod_multiple_interpreters = 3; // Added in version 3.12
352+
Py_mod_gil = 4; // Added in version 3.13
353+
354+
Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED: Pointer = Pointer(0);
355+
Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED: Pointer = Pointer(1);
356+
Py_MOD_PER_INTERPRETER_GIL_SUPPORTED: Pointer = Pointer(2);
357+
358+
Py_MOD_GIL_USED: Pointer = Pointer(0);
359+
Py_MOD_GIL_NOT_USED: Pointer = Pointer(1);
360+
347361
//#######################################################
348362
//## ##
349363
//## Non-Python specific constants ##
@@ -643,6 +657,10 @@ TPythonVersionProp = record
643657
m_free : inquiry;
644658
end;
645659

660+
// signature of functions used in slots
661+
Py_create_module_function = function(spec: PPyObject; def: PPyModuleDef):PPyObject; cdecl;
662+
Py_exec_module_function = function(module: PPyObject): Integer; cdecl;
663+
646664
// pybuffer.h
647665

648666
PPy_buffer = ^Py_Buffer;
@@ -1541,6 +1559,9 @@ TPythonInterface=class(TDynamicDll)
15411559
PyCallable_Check: function(ob : PPyObject): integer; cdecl;
15421560

15431561
PyModule_Create2: function(moduledef: PPyModuleDef; Api_Version: Integer):PPyObject; cdecl;
1562+
PyModuleDef_Init: function(moduledef: PPyModuleDef):PPyObject; cdecl;
1563+
PyModule_ExecDef: function(module: PPyObject; moduledef: PPyModuleDef):Integer; cdecl;
1564+
PyModule_FromDefAndSpec2: function(moduledef: PPyModuleDef; spec: PPyObject; Api_Version: Integer):PPyObject; cdecl;
15441565
PyErr_BadArgument: function: integer; cdecl;
15451566
PyErr_BadInternalCall: procedure; cdecl;
15461567
PyErr_CheckSignals: function: integer; cdecl;
@@ -2173,7 +2194,7 @@ TPythonEngine = class(TPythonInterface)
21732194
property IO: TPythonInputOutput read FIO write SetIO;
21742195
property PyFlags: TPythonFlags read FPyFlags write SetPyFlags default DEFAULT_FLAGS;
21752196
property RedirectIO: Boolean read FRedirectIO write FRedirectIO default True;
2176-
property UseWindowsConsole: Boolean read FUseWindowsConsole write FUseWindowsConsole default False;
2197+
property UseWindowsConsole: Boolean read FUseWindowsConsole write SetUseWindowsConsole default False;
21772198
property OnAfterInit: TNotifyEvent read FOnAfterInit write FOnAfterInit;
21782199
property OnSysPathInit: TSysPathInitEvent read FOnSysPathInit write FOnSysPathInit;
21792200
property OnConfigInit: TConfigInitEvent read FOnConfigInit write FOnConfigInit;
@@ -2534,12 +2555,6 @@ TPythonModule = class(TMethodsContainer)
25342555
end;
25352556

25362557

2537-
//-------------------------------------------------------
2538-
//-- --
2539-
//--class: TPythonType derived from TGetSetContainer --
2540-
//-- --
2541-
//-------------------------------------------------------
2542-
25432558
{
25442559
A B C
25452560
+-------------------++------------------------------------------------------+
@@ -2556,15 +2571,15 @@ TPythonModule = class(TMethodsContainer)
25562571
by GetSelf
25572572
25582573
- a Python object must start at A.
2559-
- a Delphi class class must start at B
2574+
- a Delphi class must start at B
25602575
- TPyObject.InstanceSize will return C-B
25612576
- Sizeof(TPyObject) will return C-B
25622577
- The total memory allocated for a TPyObject instance will be C-A,
25632578
even if its InstanceSize is C-B.
2564-
- When turning a Python object pointer into a Delphi instance pointer, PythonToDelphi
2565-
will offset the pointer from A to B.
2566-
- When turning a Delphi instance into a Python object pointer, GetSelf will offset
2567-
Self from B to A.
2579+
- When turning a Python object pointer into a Delphi instance pointer,
2580+
PythonToDelphi will offset the pointer from A to B.
2581+
- When turning a Delphi instance into a Python object pointer, GetSelf
2582+
will offset Self from B to A.
25682583
- Properties ob_refcnt and ob_type will call GetSelf to access their data.
25692584
25702585
Further Notes:
@@ -2581,7 +2596,6 @@ TPythonModule = class(TMethodsContainer)
25812596
FreeInstance.
25822597
- This class is heart of the P4D library. Pure magic!!
25832598
}
2584-
// The base class of all new Python types
25852599
TPyObject = class
25862600
private
25872601
function Get_ob_refcnt: NativeUInt;
@@ -2751,6 +2765,13 @@ TTypeServices = class(TPersistent)
27512765
property Mapping : TMappingServices read FMapping write FMapping;
27522766
end;
27532767

2768+
//-------------------------------------------------------
2769+
//-- --
2770+
//--class: TPythonType derived from TGetSetContainer --
2771+
//-- --
2772+
//-------------------------------------------------------
2773+
2774+
// The base class of all new Python types
27542775
// The component that initializes the Python type and
27552776
// that creates instances of itself.
27562777
{$IF not Defined(FPC) and (CompilerVersion >= 23)}
@@ -3901,6 +3922,9 @@ procedure TPythonInterface.MapDll;
39013922
PyDict_SetItemString := Import('PyDict_SetItemString');
39023923
PyDictProxy_New := Import('PyDictProxy_New');
39033924
PyModule_Create2 := Import('PyModule_Create2');
3925+
PyModuleDef_Init := Import('PyModuleDef_Init');
3926+
PyModule_ExecDef := Import('PyModule_ExecDef');
3927+
PyModule_FromDefAndSpec2 := Import('PyModule_FromDefAndSpec2');
39043928
PyErr_Print := Import('PyErr_Print');
39053929
PyErr_SetNone := Import('PyErr_SetNone');
39063930
PyErr_SetObject := Import('PyErr_SetObject');
@@ -5072,6 +5096,19 @@ procedure TPythonEngine.Initialize;
50725096
if not Initialized then
50735097
Initialize;
50745098

5099+
5100+
{$IFDEF MSWINDOWS}
5101+
if not FRedirectIO and UseWindowsConsole then
5102+
PyRun_SimpleString(
5103+
'import sys, io'#10 +
5104+
'sys.stdout = io.TextIOWrapper(open("CONOUT$", "wb", buffering=0), ' +
5105+
'encoding="utf-8", errors="replace", line_buffering=True)'#10 +
5106+
'sys.stderr = io.TextIOWrapper(open("CONOUT$", "wb", buffering=0), ' +
5107+
'encoding="utf-8", errors="replace", line_buffering=False)'#10 +
5108+
'sys.stdin = io.TextIOWrapper(open("CONIN$", "rb", buffering=0), ' +
5109+
'encoding="utf-8", errors="replace", line_buffering=True)'#10);
5110+
{$ENDIF}
5111+
50755112
if InitScript.Count > 0 then
50765113
ExecStrings(InitScript);
50775114
if Assigned(FOnAfterInit) then
@@ -5127,10 +5164,12 @@ procedure TPythonEngine.InitWinConsole;
51275164
FreeConsole;
51285165
AllocConsole;
51295166
SetConsoleTitle( 'Python console' );
5167+
SetConsoleOutputCP(CP_UTF8);
5168+
SetConsoleCP(CP_UTF8);
51305169
{$ENDIF}
51315170
end;
51325171

5133-
procedure TPythonEngine.SetUseWindowsConsole( const Value : Boolean );
5172+
procedure TPythonEngine.SetUseWindowsConsole(const Value: Boolean);
51345173
begin
51355174
FUseWindowsConsole := Value;
51365175
if (csDesigning in ComponentState) then

0 commit comments

Comments
 (0)