Maybe not the proper thread, ... but may be nice to know or even helpful ...

Using native integers I did not know which integer to choose when a C type int was specified in a function signature. It is known that, depending on processor or compiler, an int could have 16 or 32 bits size and a long could have 32 or 64.

So what I've done, to be free of that, is making a mapping of types which is generated at install time. Before the mapping is generated, the program runs a C program which displays the INT_MAX and INT_MIN etc. From that, I can see how many bits are needed and can then make a proper mapping to e.g int16, int32 or int64.

In the attachments there are some scripts and programs used in gnome-native and generates type mappings from glib types to Raku native types. The Build.pm6 module generates this module and is already in use in some of the Gnome::*::* modules. A sample GlibToRakuTypes.pm6 is included.

Regards,
Marcel

/*
 compile: gcc -o c-type-size c-type-size.c

 See also:
   https://www.tutorialspoint.com/c_standard_library/limits_h.htm
   https://www.tutorialspoint.com/cprogramming/c_data_types.htm
   https://en.wikibooks.org/wiki/C_Programming/limits.h
   https://www.gnu.org/software/libc/manual/html_node/Range-of-Type.html
*/

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <float.h>

int main(int argc, char** argv) {

  printf("CHAR_BIT : %d\n", CHAR_BIT);
  printf("CHAR_MAX : %d\n", CHAR_MAX);
  printf("CHAR_MIN : %d\n", CHAR_MIN);

  printf("INT_MAX  : %d\n", INT_MAX);
  printf("INT_MIN  : %d\n", INT_MIN);
  printf("UINT_MAX : %u\n", (unsigned int) UINT_MAX);

  printf("LONG_MAX : %ld\n", (long) LONG_MAX);
  printf("LONG_MIN : %ld\n", (long) LONG_MIN);
  printf("ULONG_MAX: %lu\n", (unsigned long) ULONG_MAX);

  printf("SCHAR_MAX: %d\n", SCHAR_MAX);
  printf("SCHAR_MIN: %d\n", SCHAR_MIN);
  printf("SHRT_MAX : %d\n", SHRT_MAX);
  printf("SHRT_MIN : %d\n", SHRT_MIN);
  printf("UCHAR_MAX: %d\n", UCHAR_MAX);
  printf("USHRT_MAX: %d\n", (unsigned short) USHRT_MAX);

  return 0;
}
use v6;

my Bool $run-ok;
my Hash $c-types = %();

try {
  my Proc $proc;

  # make C program to get the limits of integers, float and doubles
  $proc = run 'gcc', '-o', 'xbin/c-type-size', 'xbin/c-type-size.c';

  # run this C program to read the limits
  $proc = run 'xbin/c-type-size', :out;

  for $proc.out.lines -> $line {
    my ( $limit-name, $limit) = $$line.split(/ \s* ':' \s* /);
  #  note "$limit-name, $limit";
    next if $limit-name ~~ m/ MIN | SCHAR /;

    $limit-name ~~ s/SHRT/SHORT/;
    $limit-name .= lc;
    $limit-name = 'g' ~ $limit-name;

    $limit .= Int;

    given $limit-name {
  #    when 'CHAR_BIT' {
  #      note "$limit-name, $limit, int$limit.base(16)";
  #    }

      when / 'u' .*? '_max' $/ {
        $limit-name ~~ s/ '_max' //;
        $c-types{$limit-name} = 'uint' ~ $limit.base(16).chars * 4;
  #      note sprintf( "%11s uint%d",
  #        $limit-name, $limit.base(16).chars * 4
  #      );
      }

      when / '_max' $/ {
        $limit-name ~~ s/ '_max' //;
        $c-types{$limit-name} = 'int' ~ $limit.base(16).chars * 4;
  #      note sprintf( "%11s int%d",
  #        $limit-name, $limit.base(16).chars * 4
  #      );
      }
  #`{{
      when 'INT_MAX' {
        note "0x$limit.base(16)", 'int' ~ ($limit.base(16).chars * 4).Str;
      }

      when 'INT_MIN' {
        note "0x$limit.base(16)", 'int' ~ ($limit.base(16).chars * 4).Str;
      }

      when 'UINT_MAX' {
        note "0x$limit.base(16), ", 'int' ~ ($limit.base(16).chars * 4).Str;
      }

      when 'LONG_MAX' {
        note "0x$limit.base(16)", 'int' ~ ($limit.base(16).chars * 4).Str;
      }

      when 'LONG_MIN' {
        note "0x$limit.base(16)", 'int' ~ ($limit.base(16).chars * 4).Str;
      }

      when 'ULONG_MAX' {
        note "0x$limit.base(16), ", 'int' ~ ($limit.base(16).chars * 4).Str;
      }
  }}
    }
  }

  $proc.out.close;
#  note $proc.exitcode;
  $run-ok = !$proc.exitcode;

  CATCH {
    default {
      note "Failed to run C program, over to plan B, quesswork...";
      $run-ok = False;
    }
  }
}

# when program fails or did not compile we need some guesswork. Raku has the
# idea that int is in64 on 64 bit machines which is not true in my case...
unless $run-ok {
#  note "\nBits: $*KERNEL.bits(), ", int64.Range;

  $c-types<gchar> = 'int8';
  $c-types<gint> = 'int32';
  $c-types<glong> = $*KERNEL.bits() == 64 ?? 'int64' !! 'int32';
  $c-types<gshort> = 'int16';
  $c-types<guchar> = 'uint8';
  $c-types<guint> = 'uint32';
  $c-types<gulong> = $*KERNEL.bits() == 64 ?? 'uint64' !! 'int32';
  $c-types<gushort> = 'uint16';
}

# add other types which are fixed
$c-types<gint8> = 'int8';
$c-types<gint16> = 'int16';
$c-types<gint32> = 'int32';
$c-types<gint64> = 'int64';
$c-types<guint8> = 'uint8';
$c-types<guint16> = 'uint16';
$c-types<guint32> = 'uint32';
$c-types<guint64> = 'uint64';

$c-types<gfloat> = 'num32';
$c-types<gdouble> = 'num64';

$c-types<gchar-ptr> = 'Str';
$c-types<void-ptr> = 'Pointer[void]';

# and some types which are defined already
$c-types<gboolean> = $c-types<gint>;
$c-types<gsize> = $c-types<gulong>;
$c-types<gssize> = $c-types<glong>;
$c-types<GType> = $c-types<gulong>;
$c-types<gtype> = $c-types<gulong>;
$c-types<GQuark> = $c-types<guint32>;
$c-types<gquark> = $c-types<guint32>;

#note $c-types.gist;

# generate the module text
my Str $module-text = Q:to/EOMOD_START/;

  
#-------------------------------------------------------------------------------
  # This module is generated at installation time.
  # Please do not change any of the contents of this module.
  
#-------------------------------------------------------------------------------

  use v6;
  unit package Gnome::N::GlibToRakuTypes;

  
#-------------------------------------------------------------------------------
  EOMOD_START

for $c-types.keys.sort -> $gtype-name {
  my Str $rtype-name = $c-types{$gtype-name};
  $module-text ~= sprintf "constant \\%-15s is export = %s;\n",
        $gtype-name, $rtype-name;
}

note $module-text;

Attachment: Build.pm6
Description: application/pagemaker

Attachment: GlibToRakuTypes.pm6
Description: application/pagemaker

Reply via email to