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;
Build.pm6
Description: application/pagemaker
GlibToRakuTypes.pm6
Description: application/pagemaker