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.

simple-libc.idio
;; 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-05-21T06:11:38Z+0000 from 77077af (dev) for Idio 0.3