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
Booleantype result should be written as function with Pascal nativeBooleantype orcbooltype depending on the further use of the macro. - SDL functions which have a
SDL_Boolreturn value should be converted to returnTSDL_Bool - SDL functions which need
SDL_Boolvalue as argument will treat them correctly obviously - Pascal functions which rely on a
TSDL_Boolvalue 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