Handle SDL_bool like a real boolean
Free-Pascal-meets-SDL-Website opened this issue · 6 comments
Actually we should translate SDL_bool by TSDL_Bool. This will generate compiler errors in situations as shown below:
(from sdl2.pas)
function SDL_VERSION_ATLEAST(X,Y,Z: cuint8): Boolean;
begin
Result := SDL_COMPILEDVERSION >= SDL_VERSIONNUM(X,Y,Z);
end;
How should we handle or fix this?
C and Pascal handle booleans differently. In C they are basically integer values which are interpreted but in Pascal they form a special, separate type (or are at least treated as such).
So, what follows from this:
- Macros which have a
Boolean
type result should be written as function with Pascal nativeBoolean
type orcbool
type depending on the further use of the macro. - SDL functions which have a
SDL_Bool
return value should be converted to returnTSDL_Bool
- SDL functions which need
SDL_Bool
value as argument will treat them correctly obviously - Pascal functions which rely on a
TSDL_Bool
value as argument should evaluate the integer values or typecast (see next point) - Attention: Typecast
Boolean(TSDL_Bool)
should be safe as TSDL_Bool can be 0 or 1 only, but in general care has to be taken with this cast, see http://www.delphigroups.info/2/10/12833.html - A logical expression can be returned into a TSDL_Bool value by typecasting, see example code below
program SDLBoolTest;
uses SDL2, ctypes, SysUtils;
var
a, b: Integer;
function BoolTest(a, b: Integer): TSDL_Bool;
begin
// works
Result := TSDL_Bool(a > b);
// does not work - Error: got "Boolean" expected "TSDL_Bool"
//Result := (a > b);
end;
begin
writeln('Bool Test a > b');
for a:= 0 to 3 do
for b := 0 to 3 do
begin
write('a = ' + IntToStr(a) + '; b = ' + IntToStr(b) +'; Result = ' + IntToStr(BoolTest(a, b)) + ' ');
writeln(Boolean(BoolTest(a, b)));
end;
readln;
end.
So, for the example in the initial post it is correct to use the native Boolean
, because a macro without a defined SDL_Bool return value should not adopt a fictional one.
For me, just change the declaration of TSDL_Bool
to this:
type
TSDL_Bool = System.Boolean;
and adopt all the code to the new type. Casting to native booleans should be avoided — the code should be adopted to the Pascal language, not to the C language. Additionally, some constant values should also be redeclared (eg. SDL_TRUE
or SDL_ENABLE
), since they also contains value 0
or 1
and they act like a booleans to toggle various options.
What do you think about it?
The problem is that we need to maintain binary compatibility with the C library. According to the FPC Language Reference, Boolean
has a size of 1 (the same as char
), whereas the C definition is typedef int SDL_bool
, i.e. the same size as an int
(which is usually 2
or 4
).
We could consider using LongBool
, or ctypes.cbool
, though.
We could consider using
LongBool
, orctypes.cbool
, though.
Exactly. After all, the same goes for the functions of the Win32 API, wherever the multibyte booleans are required.
I added a PR (#70) to solve this issue according to you proposal using cbool
.
The code below works well, too now.
program SDLBoolTest;
uses SDL2, ctypes, SysUtils;
var
a, b: Integer;
function BoolTest(a, b: Integer): TSDL_Bool;
begin
// works
//Result := TSDL_Bool(a > b);
// works, too
Result := (a > b);
end;
begin
SetHeapTraceOutput('heaptrc.txt');
writeln('Bool Test a > b');
for a:= 0 to 3 do
for b := 0 to 3 do
begin
write('a = ' + IntToStr(a) + '; b = ' + IntToStr(b) +'; Result = ');
writeln(BoolTest(a, b));
end;
readln;
end.
Closed by PR #70