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
