PascalGameDevelopment / SDL2-for-Pascal

Unit files for building Free Pascal and Delphi applications using the SDL2 library

Home Page:https://pascalgamedevelopment.github.io/SDL2-for-Pascal/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Handle SDL_bool like a real boolean

Free-Pascal-meets-SDL-Website opened this issue · 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 native Boolean type or cbool type depending on the further use of the macro.
  • SDL functions which have a SDL_Bool return value should be converted to return TSDL_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?

commented

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, or ctypes.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