C Types¶
Idio makes use of C base types to interact with the operating system. In general, if it is operating system-oriented it will be using Idio wrappers to C base types or derivatives for arguments and return values.
All of the C-oriented types and functions are in a C/
namespace – partly to avoid name clashes such as the C >
comparator and the shell-like >
I/O redirection operator.
You can create instances of C types with conversion functions
like C/integer-> value C-type
, for example, (C/integer->
1 'uint)
creates a C unsigned integer
with the value
1
.
Idio does not perform any implicit type casting. If you call
any C/
comparison or equality functions then the arguments must be
of the same type.
Beyond C base types, Idio supports the typedef
of basic types. The names of these typedefs are put in a namespace
associated with the library that introduced them, so, commonly,
libc
. Here we might call (C/integer-> 1 libc/pid_t)
to create
a portably typed C value representing a pid_t
with the
value 1
.
If you are manipulating a libc/pid_t
your (portable) code cannot
know if it is implemented by an int
or long
and so you must
reference a libc/pid_t
[1] throughout. The functions expecting a
libc/pid_t
will error if you pass the wrong C type.
Many Idio functions wrapping C library functions
return “pointers” to structs (often where, in C, a pointer to
such a struct would have been passed to the library function as an
argument). These are Idio values containing the underlying
C type so, here, a C/pointer
.
The struct pointer can be tagged with C Structure Identification information which can be verified by subsequent recipients and contains some structure information.
;; libc/gettimeofday returns a C/pointer to a libc/struct-timeval
tv0 := (libc/gettimeofday)
;; sleep(3) would normally be expecting a C unsigned int (or 'uint
;; in Idio) however this is a rare occasion when a fixnum can be
;; passed to C! Otherwise we'd need to convert a fixnum into a
;; specific C base type, here, (C/integer-> 1 'uint)
libc/sleep 1
tvd := libc/subtract-struct-timeval (libc/gettimeofday) tv0
;; the default printing format for a libc/struct-timeval is a stylised
;; floating point number
printf "sleep 1 took %ss\n" tvd
;; we can pick it apart ourselves
printf "aka %ds and %06dus\n" \
(libc/struct-timeval-ref tvd 'tv_sec) \
(libc/struct-timeval-ref tvd 'tv_usec)
;; more conveniently but slightly slower
printf "aka %ds and %06dus\n" \
tvd.'tv_sec \
tvd.'tv_usec
;; What do we know about tvd?
printf "tvd isa %s" (type->string tvd)
if (C/pointer? tvd) {
printf " isa %s: " (C/pointer-name tvd)
for member in (C/pointer-members tvd) {
;; Idio knows the libc/struct-timeval member values have libc/time_t
;; and libc/suseconds_t types however it will resolve these into
;; their underlying base types
;;
;; the types reported are platform-specific
printf "%s isa %s; " member (type->string tvd.member)
}
}
printf "\n"
$ idio simple-libc
sleep 1 took 1.000383s
aka 1s and 000383us
aka 1s and 000383us
tvd isa C/pointer isa libc/struct-timeval: tv_sec isa C/long; tv_usec isa C/long;
Last built at 2024-10-13T06:11:40Z+0000 from 77077af (dev) for Idio 0.3