Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ad03e54

Browse files
committed
Better treatment of C WChar_t arguments to stay compatible with Windows/OS X/Linux/Android
1 parent f5a6842 commit ad03e54

File tree

1 file changed

+70
-36
lines changed

1 file changed

+70
-36
lines changed

Source/PythonEngine.pas

+70-36
Original file line numberDiff line numberDiff line change
@@ -181,14 +181,29 @@ TPythonVersionProp = record
181181
// Delphi equivalent used by TPyObject
182182
TRichComparisonOpcode = (pyLT, pyLE, pyEQ, pyNE, pyGT, pyGE);
183183

184+
185+
// C long is 8 bytes in non-Windows 64-bit operating systems
186+
// Same Delphi's LongInt but not fpc LongInt which is always 4 bytes
187+
// Hence the following
184188
{$IFDEF MSWINDOWS}
185189
C_Long = Integer;
186190
C_ULong = Cardinal;
187191
{$ELSE}
188-
C_Long= NativeInt;
192+
C_Long = NativeInt;
189193
C_ULong = NativeUInt;
190194
{$ENDIF}
191195

196+
// wchar_t is 4 bytes on Linux/OS X/Android but 2 bytes on Windows
197+
{$IFDEF POSIX}
198+
PWCharT = PUCSChar;
199+
PPWCharT = PUCSChar^;
200+
WCharTString = UCS4String;
201+
{$ELSE}
202+
PWCharT = PWideChar;
203+
PPWCharT = PPWideChar;
204+
WCharTString = UnicodeString;
205+
{$ENDIF}
206+
192207
const
193208
{
194209
Type flags (tp_flags)
@@ -1380,7 +1395,7 @@ TPythonInterface=class(TDynamicDll)
13801395
PyRun_SimpleString: function( str: PAnsiChar): Integer; cdecl;
13811396
PyBytes_AsString: function( ob: PPyObject): PAnsiChar; cdecl;
13821397
PyBytes_AsStringAndSize: function( ob: PPyObject; var buffer: PAnsiChar; var size: NativeInt): integer; cdecl;
1383-
PySys_SetArgv: procedure( argc: Integer; argv: PPWideChar); cdecl;
1398+
PySys_SetArgv: procedure( argc: Integer; argv: PPWCharT); cdecl;
13841399

13851400
PyCFunction_NewEx: function(md:PPyMethodDef;self, ob:PPyObject):PPyObject; cdecl;
13861401
// Removed. Use PyEval_CallObjectWithKeywords with third argument nil
@@ -1539,11 +1554,11 @@ TPythonInterface=class(TDynamicDll)
15391554
PyType_GenericAlloc:function(atype: PPyTypeObject; nitems:NativeInt) : PPyObject; cdecl;
15401555
PyType_GenericNew:function(atype: PPyTypeObject; args, kwds : PPyObject) : PPyObject; cdecl;
15411556
PyType_Ready:function(atype: PPyTypeObject) : integer; cdecl;
1542-
PyUnicode_FromWideChar:function (const w:PWideChar; size:NativeInt):PPyObject; cdecl;
1557+
PyUnicode_FromWideChar:function (const w:PWCharT; size:NativeInt):PPyObject; cdecl;
15431558
PyUnicode_FromString:function (s:PAnsiChar):PPyObject; cdecl;
15441559
PyUnicode_FromStringAndSize:function (s:PAnsiChar;i:NativeInt):PPyObject; cdecl;
15451560
PyUnicode_FromKindAndData:function (kind:integer;const buffer:pointer;size:NativeInt):PPyObject; cdecl;
1546-
PyUnicode_AsWideChar:function (unicode: PPyObject; w:PWideChar; size:NativeInt):integer; cdecl;
1561+
PyUnicode_AsWideChar:function (unicode: PPyObject; w:PWCharT; size:NativeInt):integer; cdecl;
15471562
PyUnicode_AsUTF8:function (unicode: PPyObject):PAnsiChar; cdecl;
15481563
PyUnicode_AsUTF8AndSize:function (unicode: PPyObject; size: PNativeInt):PAnsiChar; cdecl;
15491564
PyUnicode_Decode:function (const s:PAnsiChar; size: NativeInt; const encoding : PAnsiChar; const errors: PAnsiChar):PPyObject; cdecl;
@@ -1570,8 +1585,8 @@ TPythonInterface=class(TDynamicDll)
15701585
Py_GetCopyright : function : PAnsiChar; cdecl;
15711586
Py_GetExecPrefix : function : PAnsiChar; cdecl;
15721587
Py_GetPath : function : PAnsiChar; cdecl;
1573-
Py_SetPythonHome : procedure (home : PWideChar); cdecl;
1574-
Py_GetPythonHome : function : PWideChar; cdecl;
1588+
Py_SetPythonHome : procedure (home : PWCharT); cdecl;
1589+
Py_GetPythonHome : function : PWCharT; cdecl;
15751590
Py_GetPrefix : function : PAnsiChar; cdecl;
15761591
Py_GetProgramName : function : PAnsiChar; cdecl;
15771592

@@ -1580,7 +1595,7 @@ TPythonInterface=class(TDynamicDll)
15801595
PyErr_NewException : function ( name : PAnsiChar; base, dict : PPyObject ) : PPyObject; cdecl;
15811596
PyMem_Malloc : function ( size : NativeUInt ) : Pointer;
15821597

1583-
Py_SetProgramName : procedure( name: PWideChar); cdecl;
1598+
Py_SetProgramName : procedure( name: PWCharT); cdecl;
15841599
Py_IsInitialized : function : integer; cdecl;
15851600
Py_GetProgramFullPath : function : PAnsiChar; cdecl;
15861601
Py_NewInterpreter : function : PPyThreadState; cdecl;
@@ -1754,8 +1769,8 @@ TPythonEngine = class(TPythonInterface)
17541769
FClients: TList;
17551770
FExecModule: AnsiString;
17561771
FAutoFinalize: Boolean;
1757-
FProgramName: UnicodeString;
1758-
FPythonHome: UnicodeString;
1772+
FProgramName: WCharTString;
1773+
FPythonHome: WCharTString;
17591774
FInitThreads: Boolean;
17601775
FOnPathInitialization: TPathInitializationEvent;
17611776
FOnSysPathInit: TSysPathInitEvent;
@@ -1775,6 +1790,8 @@ TPythonEngine = class(TPythonInterface)
17751790
FPyDateTime_TZInfoType: PPyObject;
17761791
FPyDateTime_TimeTZType: PPyObject;
17771792
FPyDateTime_DateTimeTZType: PPyObject;
1793+
function GetPythonHome: UnicodeString;
1794+
function GetProgramName: UnicodeString;
17781795

17791796
protected
17801797
procedure Initialize;
@@ -1892,8 +1909,8 @@ TPythonEngine = class(TPythonInterface)
18921909
property LocalVars : PPyObject read FLocalVars Write SetLocalVars;
18931910
property GlobalVars : PPyObject read FGlobalVars Write SetGlobalVars;
18941911
property IOPythonModule: TObject read FIOPythonModule; {TPythonModule}
1895-
property PythonHome: UnicodeString read FPythonHome write SetPythonHome;
1896-
property ProgramName: UnicodeString read FProgramName write SetProgramName;
1912+
property PythonHome: UnicodeString read GetPythonHome write SetPythonHome;
1913+
property ProgramName: UnicodeString read GetProgramName write SetProgramName;
18971914
published
18981915
property AutoFinalize: Boolean read FAutoFinalize write FAutoFinalize default True;
18991916
property VenvPythonExe: string read FVenvPythonExe write FVenvPythonExe;
@@ -4202,12 +4219,12 @@ procedure TPythonEngine.Initialize;
42024219
if Assigned(Py_SetProgramName) then
42034220
begin
42044221
if FProgramName = '' then
4205-
FProgramName := UnicodeString(ParamStr(0));
4206-
Py_SetProgramName(PWideChar(FProgramName));
4222+
ProgramName := UnicodeString(ParamStr(0));
4223+
Py_SetProgramName(PWCharT(FProgramName));
42074224
end;
42084225
AssignPyFlags;
4209-
if FPythonHome <> '' then
4210-
Py_SetPythonHome(PWideChar(FPythonHome));
4226+
if Length(FPythonHome) > 0 then
4227+
Py_SetPythonHome(PWCharT(FPythonHome));
42114228
Py_Initialize;
42124229
if Assigned(Py_IsInitialized) then
42134230
FInitialized := Py_IsInitialized() <> 0
@@ -4359,34 +4376,25 @@ procedure TPythonEngine.CheckRegistry;
43594376
procedure TPythonEngine.SetProgramArgs;
43604377
var
43614378
i, argc : Integer;
4362-
wargv : array of PWideChar;
4363-
{$IFDEF POSIX}
4364-
UCS4L : array of UCS4String;
4365-
{$ELSE}
4366-
WL : array of UnicodeString;
4367-
{$ENDIF}
4379+
wargv : array of PWCharT;
4380+
WL : array of WCharTString;
43684381
begin
43694382
// we build a string list of the arguments, because ParamStr returns a volatile string
43704383
// and we want to build an array of PAnsiChar, pointing to valid strings.
43714384
argc := ParamCount;
43724385
SetLength(wargv, argc + 1);
43734386
// build the PWideChar array
4374-
{$IFDEF POSIX}
4375-
// Note that Linux uses UCS4 strings, whereas it declares using UCS2 strings!!!
4376-
SetLength(UCS4L, argc+1);
4377-
for i := 0 to argc do begin
4378-
UCS4L[i] := WideStringToUCS4String(ParamStr(i));
4379-
wargv[i] := @UCS4L[i][0];
4380-
end;
4381-
{$ELSE}
43824387
SetLength(WL, argc+1);
43834388
for i := 0 to argc do begin
4389+
{$IFDEF POSIX}
4390+
WL := UnicodeStringToUCS4String(ParamStr(i));
4391+
{$ELSE}
43844392
WL[i] := UnicodeString(ParamStr(i));
4385-
wargv[i] := PWideChar(WL[i]);
4393+
{$ENDIF}
4394+
wargv[i] := PWCharT(WL[i]);
43864395
end;
4387-
{$ENDIF}
43884396
// set the argv list of the sys module with the application arguments
4389-
PySys_SetArgv( argc + 1, PPWideChar(wargv) );
4397+
PySys_SetArgv( argc + 1, PPWCharT(wargv) );
43904398
end;
43914399

43924400
procedure TPythonEngine.InitWinConsole;
@@ -4451,14 +4459,40 @@ procedure TPythonEngine.SetPyFlags(const Value: TPythonFlags);
44514459
end; // of if
44524460
end;
44534461

4462+
function TPythonEngine.GetPythonHome: UnicodeString;
4463+
begin
4464+
{$IFDEF POSIX}
4465+
Result := UCS4StringToUnicodeString(FPythonHome);
4466+
{$ELSE}
4467+
Result := FPythonHome;
4468+
{$ENDIF}
4469+
end;
4470+
4471+
function TPythonEngine.GetProgramName: UnicodeString;
4472+
begin
4473+
{$IFDEF POSIX}
4474+
Result := UCS4StringToUnicodeString(FProgramName);
4475+
{$ELSE}
4476+
Result := FProgramName;
4477+
{$ENDIF}
4478+
end;
4479+
44544480
procedure TPythonEngine.SetPythonHome(const PythonHome: UnicodeString);
44554481
begin
4456-
FPythonHome := PythonHome;
4482+
{$IFDEF POSIX}
4483+
FPythonHome := UnicodeStringToUCS4String(PythonHome);
4484+
{$ELSE}
4485+
FPythonHome := PythonHome;
4486+
{$ENDIF}
44574487
end;
44584488

44594489
procedure TPythonEngine.SetProgramName(const ProgramName: UnicodeString);
44604490
begin
4491+
{$IFDEF POSIX}
4492+
FProgramName := UnicodeStringToUCS4String(ProgramName);
4493+
{$ELSE}
44614494
FProgramName := ProgramName;
4495+
{$ENDIF}
44624496
end;
44634497

44644498
function TPythonEngine.IsType(ob: PPyObject; obt: PPyTypeObject): Boolean;
@@ -5638,7 +5672,7 @@ function TPythonEngine.PyUnicodeAsString( obj : PPyObject ) : UnicodeString;
56385672
if PyUnicode_AsWideChar(obj, @_ucs4Str[0], _size) <> _size then
56395673
raise EPythonError.Create('Could not copy the whole Unicode string into its buffer');
56405674
Result := UCS4StringToWideString(_ucs4Str);
5641-
// remove trailing zeros (needed by Kylix1)
5675+
// remove trailing zeros
56425676
while (Length(Result) > 0) and (Result[Length(Result)] = #0) do
56435677
Delete(Result, Length(Result), 1);
56445678
{$ELSE}
@@ -5683,9 +5717,9 @@ function TPythonEngine.PyUnicodeFromString(const AString : UnicodeString) : PPyO
56835717
{$IFDEF POSIX}
56845718
// Note that Linux uses UCS4 strings, whereas it declares using UCS2 strings!!!
56855719
_ucs4Str := WideStringToUCS4String(AString);
5686-
Result := PyUnicode_FromWideChar( {PWideChar}(@_ucs4Str[0]), Length(_ucs4Str)-1 {trim trailing zero});
5720+
Result := PyUnicode_FromWideChar(@_ucs4Str[0], Length(_ucs4Str)-1 {trim trailing zero});
56875721
{$ELSE}
5688-
Result := PyUnicode_FromWideChar( PWideChar(AString), Length(AString) );
5722+
Result := PyUnicode_FromWideChar(PWideChar(AString), Length(AString));
56895723
{$ENDIF}
56905724
end;
56915725

0 commit comments

Comments
 (0)