Skip to content

Commit 48b9bb5

Browse files
committed
support py 3.12, sync with P4D
1 parent 67b25bf commit 48b9bb5

File tree

1 file changed

+36
-67
lines changed

1 file changed

+36
-67
lines changed

python4lazarus/PythonEngine.pas

Lines changed: 36 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ interface
107107

108108
const
109109
{$ifdef windows}
110-
PYTHON_KNOWN_VERSIONS: array[1..9] of TPythonVersionProp =
110+
PYTHON_KNOWN_VERSIONS: array[1..10] of TPythonVersionProp =
111111
(
112112
(DllName: 'python33.dll'; RegVersion: '3.3'; APIVersion: 1013),
113113
(DllName: 'python34.dll'; RegVersion: '3.4'; APIVersion: 1013),
@@ -117,11 +117,12 @@ interface
117117
(DllName: 'python38.dll'; RegVersion: '3.8'; APIVersion: 1013),
118118
(DllName: 'python39.dll'; RegVersion: '3.9'; APIVersion: 1013),
119119
(DllName: 'python310.dll'; RegVersion: '3.10'; APIVersion: 1013),
120-
(DllName: 'python311.dll'; RegVersion: '3.11'; APIVersion: 1013)
120+
(DllName: 'python311.dll'; RegVersion: '3.11'; APIVersion: 1013),
121+
(DllName: 'python312.dll'; RegVersion: '3.12'; APIVersion: 1013)
121122
);
122123
{$endif}
123124
{$ifdef _so_files}
124-
PYTHON_KNOWN_VERSIONS: array[1..9] of TPythonVersionProp =
125+
PYTHON_KNOWN_VERSIONS: array[1..10] of TPythonVersionProp =
125126
(
126127
(DllName: 'libpython3.3m.so'; RegVersion: '3.3'; APIVersion: 1013),
127128
(DllName: 'libpython3.4m.so'; RegVersion: '3.4'; APIVersion: 1013),
@@ -131,11 +132,12 @@ interface
131132
(DllName: 'libpython3.8.so'; RegVersion: '3.8'; APIVersion: 1013),
132133
(DllName: 'libpython3.9.so'; RegVersion: '3.9'; APIVersion: 1013),
133134
(DllName: 'libpython3.10.so'; RegVersion: '3.10'; APIVersion: 1013),
134-
(DllName: 'libpython3.11.so'; RegVersion: '3.11'; APIVersion: 1013)
135+
(DllName: 'libpython3.11.so'; RegVersion: '3.11'; APIVersion: 1013),
136+
(DllName: 'libpython3.12.so'; RegVersion: '3.12'; APIVersion: 1013)
135137
);
136138
{$endif}
137139
{$ifdef darwin}
138-
PYTHON_KNOWN_VERSIONS: array[1..9] of TPythonVersionProp =
140+
PYTHON_KNOWN_VERSIONS: array[1..10] of TPythonVersionProp =
139141
(
140142
(DllName: 'libpython3.3.dylib'; RegVersion: '3.3'; APIVersion: 1013),
141143
(DllName: 'libpython3.4.dylib'; RegVersion: '3.4'; APIVersion: 1013),
@@ -145,7 +147,8 @@ interface
145147
(DllName: 'libpython3.8.dylib'; RegVersion: '3.8'; APIVersion: 1013),
146148
(DllName: 'libpython3.9.dylib'; RegVersion: '3.9'; APIVersion: 1013),
147149
(DllName: 'libpython3.10.dylib'; RegVersion: '3.10'; APIVersion: 1013),
148-
(DllName: 'libpython3.11.dylib'; RegVersion: '3.11'; APIVersion: 1013)
150+
(DllName: 'libpython3.11.dylib'; RegVersion: '3.11'; APIVersion: 1013),
151+
(DllName: 'libpython3.12.dylib'; RegVersion: '3.12'; APIVersion: 1013)
149152
);
150153
{$endif}
151154

@@ -1254,7 +1257,6 @@ TPythonInterface=class(TDynamicDll)
12541257
procedure AfterLoad; override;
12551258
function GetQuitMessage : String; override;
12561259
procedure CheckPython;
1257-
function GetUnicodeTypeSuffix : String;
12581260

12591261
public
12601262
// define Python flags. See file pyDebug.h
@@ -1585,7 +1587,7 @@ TPythonInterface=class(TDynamicDll)
15851587
PyUnicode_DecodeUTF16:function (const s:PAnsiChar; size: NativeInt; const errors: PAnsiChar; byteoder: PInteger):PPyObject; cdecl;
15861588
PyUnicode_AsEncodedString:function (unicode:PPyObject; const encoding:PAnsiChar; const errors:PAnsiChar):PPyObject; cdecl;
15871589
PyUnicode_FromOrdinal:function (ordinal:integer):PPyObject; cdecl;
1588-
PyUnicode_GetSize:function (unicode:PPyObject):NativeInt; cdecl;
1590+
PyUnicode_GetLength:function (unicode:PPyObject):NativeInt; cdecl;
15891591
PyWeakref_GetObject: function ( ref : PPyObject) : PPyObject; cdecl;
15901592
PyWeakref_NewProxy: function ( ob, callback : PPyObject) : PPyObject; cdecl;
15911593
PyWeakref_NewRef: function ( ob, callback : PPyObject) : PPyObject; cdecl;
@@ -3214,30 +3216,8 @@ procedure TPythonInterface.CheckPython;
32143216
raise Exception.Create('Python is not properly initialized' );
32153217
end;
32163218

3217-
// https://github.com/Alexey-T/Python-for-Lazarus/issues/16
3218-
function TPythonInterface.GetUnicodeTypeSuffix : String;
3219-
begin
3220-
if (fMajorVersion > 3) or ((fMajorVersion = 3) and (fMinorVersion >= 3)) then
3221-
Result := ''
3222-
else
3223-
if APIVersion >= 1011 then
3224-
Result :=
3225-
{$if defined(windows) or defined(darwin) or defined(solaris)}
3226-
'UCS2'
3227-
{$else}
3228-
'UCS4'
3229-
{$endif}
3230-
else
3231-
Result := '';
3232-
end;
3233-
32343219
procedure TPythonInterface.MapDll;
3235-
Var
3236-
UnicodeSuffix : string;
3237-
32383220
begin
3239-
UnicodeSuffix := GetUnicodeTypeSuffix;
3240-
32413221
Py_DebugFlag := Import('Py_DebugFlag');
32423222
Py_VerboseFlag := Import('Py_VerboseFlag');
32433223
Py_InteractiveFlag := Import('Py_InteractiveFlag');
@@ -3546,18 +3526,18 @@ procedure TPythonInterface.MapDll;
35463526
PyType_GenericAlloc := Import('PyType_GenericAlloc');
35473527
PyType_GenericNew := Import('PyType_GenericNew');
35483528
PyType_Ready := Import('PyType_Ready');
3549-
PyUnicode_FromWideChar := Import(AnsiString(Format('PyUnicode%s_FromWideChar',[UnicodeSuffix])));
3550-
PyUnicode_FromString := Import(AnsiString(Format('PyUnicode%s_FromString',[UnicodeSuffix])));
3551-
PyUnicode_FromStringAndSize := Import(AnsiString(Format('PyUnicode%s_FromStringAndSize',[UnicodeSuffix])));
3552-
PyUnicode_FromKindAndData := Import(AnsiString(Format('PyUnicode%s_FromKindAndData',[UnicodeSuffix])));
3553-
PyUnicode_AsWideChar := Import(AnsiString(Format('PyUnicode%s_AsWideChar',[UnicodeSuffix])));
3554-
PyUnicode_AsUTF8 := Import(AnsiString(Format('PyUnicode%s_AsUTF8',[UnicodeSuffix])));
3555-
PyUnicode_AsUTF8AndSize := Import(AnsiString(Format('PyUnicode%s_AsUTF8AndSize',[UnicodeSuffix])));
3556-
PyUnicode_Decode := Import(AnsiString(Format('PyUnicode%s_Decode',[UnicodeSuffix])));
3557-
PyUnicode_DecodeUTF16 := Import(AnsiString(Format('PyUnicode%s_DecodeUTF16',[UnicodeSuffix])));
3558-
PyUnicode_AsEncodedString := Import(AnsiString(Format('PyUnicode%s_AsEncodedString',[UnicodeSuffix])));
3559-
PyUnicode_FromOrdinal := Import(AnsiString(Format('PyUnicode%s_FromOrdinal',[UnicodeSuffix])));
3560-
PyUnicode_GetSize := Import(AnsiString(Format('PyUnicode%s_GetSize',[UnicodeSuffix])));
3529+
PyUnicode_FromWideChar := Import('PyUnicode_FromWideChar');
3530+
PyUnicode_FromString := Import('PyUnicode_FromString');
3531+
PyUnicode_FromStringAndSize := Import('PyUnicode_FromStringAndSize');
3532+
PyUnicode_FromKindAndData := Import('PyUnicode_FromKindAndData');
3533+
PyUnicode_AsWideChar := Import('PyUnicode_AsWideChar');
3534+
PyUnicode_AsUTF8 := Import('PyUnicode_AsUTF8');
3535+
PyUnicode_AsUTF8AndSize := Import('PyUnicode_AsUTF8AndSize');
3536+
PyUnicode_Decode := Import('PyUnicode_Decode');
3537+
PyUnicode_DecodeUTF16 := Import('PyUnicode_DecodeUTF16');
3538+
PyUnicode_AsEncodedString := Import('PyUnicode_AsEncodedString');
3539+
PyUnicode_FromOrdinal := Import('PyUnicode_FromOrdinal');
3540+
PyUnicode_GetLength := Import('PyUnicode_GetLength');
35613541
PyWeakref_GetObject := Import('PyWeakref_GetObject');
35623542
PyWeakref_NewProxy := Import('PyWeakref_NewProxy');
35633543
PyWeakref_NewRef := Import('PyWeakref_NewRef');
@@ -5649,35 +5629,24 @@ function TPythonEngine.PyBytesAsAnsiString(obj: PPyObject): AnsiString;
56495629
raise EPythonError.CreateFmt(SPyConvertionError, ['PyBytesAsAnsiString', 'Bytes']);
56505630
end;
56515631

5652-
function TPythonEngine.PyUnicodeAsString( obj : PPyObject ) : UnicodeString;
5632+
function TPythonEngine.PyUnicodeAsString(obj : PPyObject) : UnicodeString;
56535633
var
5654-
_size : Integer;
5655-
{$IFDEF POSIX}
5656-
_ucs4Str : UCS4String;
5657-
{$ENDIF}
5634+
Buffer: PAnsiChar;
5635+
Size: NativeInt;
5636+
NewSize: Cardinal;
56585637
begin
56595638
if PyUnicode_Check(obj) then
56605639
begin
5661-
_size := PyUnicode_GetSize(obj);
5662-
if _size > 0 then
5663-
begin
5664-
{$IFDEF POSIX}
5665-
// Note that Linux uses UCS4 strings, whereas it declares using UCS2 strings!!!
5666-
SetLength(_ucs4Str, _size+1);
5667-
if PyUnicode_AsWideChar(obj, @_ucs4Str[0], _size) <> _size then
5668-
raise EPythonError.Create('Could not copy the whole Unicode string into its buffer');
5669-
Result := UCS4StringToWideString(_ucs4Str);
5670-
// remove trailing zeros (needed by Kylix1)
5671-
while (Length(Result) > 0) and (Result[Length(Result)] = #0) do
5672-
Delete(Result, Length(Result), 1);
5673-
{$ELSE}
5674-
SetLength(Result, _size);
5675-
if PyUnicode_AsWideChar(obj, @Result[1], _size) <> _size then
5676-
raise EPythonError.Create('Could not copy the whole Unicode string into its buffer');
5677-
{$ENDIF}
5678-
end
5679-
else
5680-
Result := '';
5640+
// Size does not include the final #0
5641+
Buffer := PyUnicode_AsUTF8AndSize(obj, @Size);
5642+
SetLength(Result, Size);
5643+
if (Size = 0) or (Buffer = nil) then
5644+
Exit;
5645+
5646+
// The second argument is the size of the destination (Result) including #0
5647+
NewSize := Utf8ToUnicode(PUnicodeChar(Result), Cardinal(Size + 1), Buffer, Cardinal(Size));
5648+
// NewSize includes #0
5649+
SetLength(Result, NewSize - 1);
56815650
end
56825651
else
56835652
raise EPythonError.CreateFmt(SPyConvertionError, ['PyUnicodeAsString', 'Unicode']);

0 commit comments

Comments
 (0)