Go to the first, previous, next, last section, table of contents.


C Package

C Package includes procedures and special forms that are used to interface with C functions and variables.

Before using functions and variables in C package, following function call should be made to dynamically load necessary library.

(use 'clang)

Type Representation

In order to interface with C functions/variables effectively, Scheme language should be able to represent types of C language. In KSM-Scheme, following rules of representation are used.

For simple types, there is a one-to-one relationship between C types and Scheme symbols.
<C type> <Scheme representation>
int int
signed int signed-int
unsigned int unsigned-int
char char
signed char signed-char
unsigned char unsigned-char
short short
signed short signed-short
unsigned short unsigned-short
long long
signed long signed-long
unsigned long unsigned-long
double double
float float
void void

A pointer type is represented by a list whose first element represents the pointed type and second element is the symbol *.
<C type> <Scheme representation>
type * (type *)

For example,

int *    <==>  (int *)
char *   <==>  (char *)
char **  <==>  ((char *) *)

An array type is represented by a list whose first element represents the type of the elements, second element is the symbol [], and the last element is the number of elements in the array.
<C type> <Scheme representation>
type symbol[size] (type [] size)

For example,

int a[10]    <==> (int [] 10)
char *s[6]   <==> ((char *) [] 6)
char (*s)[6] <==> ((char [] 6) *)

Structures and unions are represented as lists with the following form. ...} ...}
<C type> <Scheme representation>
struct struct-name (struct struct-name)
struct [struct-name] { type name [bits]; (strcut [struct-name] ((type name [bits]) ...))
union union-name (union union-name)
union [union-name] { type name [bits]; (union [union-name] ((type name [bits]) ...))

For example,

struct point {           (struct point
  int x;            <==>   (int x)
  int y; };                (int y))

struct {                 (struct
  char *name;       <==>   ((char *) name)
  int   id; };             (int id))

struct {                 (struct
  int x;                   (int x)
  int flag: 2;      <==>   (int flag 2)
  int y; }                 (int y))

union {                  (union
  int ival;                (int ival)
  double dval;      <==>   (double dval)
  void *pval; }            ((void *) pval))

Functions and Special Forms

Special Form: clang:sym type symbol
Special Form: clang:sym ret-type (symbol type ...)
In the first form, clang:sym looks up a C variable whose name is symbol then returns a C object that binds the address of the C variable with type. In the second form, clang:sym looks up a C function whose name is symbol and returns a corresponding C object. The return type of the C function is specified by ret-type, and types of arguments are specified by types. See section Type Representation, for details about C type representation in KSM-Scheme.
$ cat src.c
int a = 12;
double b;
char *c;
int get_a(void) { return a; }
int iadd(int a, int b) { return a+b; }
$ gcc -c -fPIC src.c
$ gcc -shared -o src.so src.o -lc
$ ksm
> (use 'clang)
> (load-shared "./src.so")
> (clang:sym int a)        ==> #<C-object>
> (clang:sym double b)     ==> #<C-object>
> (clang:sym (char *) c)   ==> #<C-object>
> (clang:sym int (get_a))  ==> #<C-object>
> (define a (clang:sym int a))
> (define f (clang:sym int (get_a)))
> (define iadd (clang:sym int (iadd int int)))
> a                        ==> 12
> (f)                      ==> 12
> (iadd 60 2)              ==> 62

C object returned by clang:sym can be used to set the value of the C variable as follows.

$ cat src.c
int a = 12;
int get_a(void) { return a; }
$ gcc -c -fPIC src.c
$ gcc -shared -o src.so src.o -lc
$ ksm
> (use 'clang)
> (load-shared "./src.so")
> (clang:sym int a)        ==> #<C-object>
> (clang:sym int (get_a))  ==> #<C-object>
> (define a (clang:sym int a))
> (define f (clang:sym int (get_a)))
> a                        ==> 12
> (f)                      ==> 12
> (set! a 123)             ==> 123
> (f)                      ==> 123

@source{clang/clang.c} @use{clang}

Function: clang:* csym
csym must be a C object whose type is a pointer. Returns the object pointed by csym.
$ cat src.c
int ival = 1;
int *ip = &ival;
int getval(void) { return ival; }
$ gcc -c -fPIC src.c
$ gcc -shared -o src.so src.o -lc
$ ksm
> (use 'clang)
> (load-shared "./src.so")
> (define ip (clang:sym (int *) ip))
> (clang:* ip) ==> 1

clang:* can be used to set the value pointed by cobject as follows.

$ ksm
> (use 'clang)
> (load-shared "./src.so")
> (define f (clang:sym int (getval)))
> (f)                     ==> 1
> (define ip (clang:sym (int *) ip))
> (clang:* ip)            ==> 1
> (set! (clang:* ip) 12)
> (clang:* ip)            ==> 12
> (f)                     ==> 12

@source{clang/clang.c} @use{clang}

Function: clang:[] csym index
csym must be a C object whose type is array or pointer. index should be an integer. Returns the value of index-th element of array csym. "cobject" must have an array type.
$ cat src.c
int a[3] = { 1, 2, 3 };
$ gcc -c -fPIC src.c
$ gcc -shared -o src.so src.o -lc
$ ksm
> (use 'clang)
> (load-shared "./src.so")
> (define a (clang:sym (int [] 3) a))
> (clang:[] a 0) ==> 1
> (clang:[] a 1) ==> 2
> (clang:[] a 2) ==> 3

clang:[] can be used to set the value of array element as follows.

$ cat src.c
int a[3] = { 1, 2, 3 };
int f(void) { return a[0]; }
$ gcc -c -fPIC src.c
$ gcc -shared -o src.so src.o -lc
$ ksm
> (define a (clang:sym (int [] 3) a))
> (define f (clang:sym int (f)))
> (f)            ==> 1
> (clang:[] a 0) ==> 1
> (set! (clang:[] a 0) 12)
> (clang:[] a 0) ==> 12
> (f)            ==> 12

@source{clang/clang.c} @use{clang}

Function: clang:. csym field
csym must be a C object whose type is struct or union. Returns the value of field of csym. If there is no such field, an error is raised.
$ car src_a.so
struct point {
  int x;
  int y;
} pp = { 1, 2 };
$ gcc -c -fPIC src_a.c
$ gcc -shared -o src_a.so src_a.o -lc
$ ksm
> (use 'clang)
> (load-shared "./src_a.so")
> (define pp (clang:sym (struct pp (int x) (int y)) pp))
> (clang:. pp 'x) ==> 1
> (clang:. pp 'y) ==> 2

$ car src_b.c
struct cpoint {
  int x;
  int colored: 1;
  int y;
} cp = { 10, 1, 20 };
$ gcc -c -fPIC src_b.c
$ gcc -shared -o src_b.so src_b.o -lc
$ ksm
> (use 'clang)
> (load-shared "./src_b.so")
> (define cp 
    (clang:sym (struct cp (int x) 
                          (int colored 1) 
                          (int y)) 
                  cp))
> (clang:. pp 'x)        ==> 10
> (clang:. pp 'colored)  ==> -1
> (clang:. pp 'y)        ==> 20

clang:. can be used to set the value of field in csym, as follows.

$ car src_a.so
struct point {
  int x;
  int y;
} pp = { 1, 2 };
int get_x(void) { return pp.x; }
$ gcc -c -fPIC src_a.c
$ gcc -shared -o src_a.so src_a.o -lc
$ ksm
> (use 'clang)
> (load-shared "./src_a.so")
> (define pp (clang:sym (struct pp (int x) (int y)) pp))
> (define get-x (clang:sym int (get_x)))
> (get-x)         ==> 1
> (set! (clang:. pp 'x) 100)
> (get-x)         ==> 100

$ car src_b.c
struct cpoint {
  int x;
  int colored: 1;
  int y;
} cp = { 10, 1, 20 };
int get_colored(void) { return cp.colored; }
$ gcc -c -fPIC src_b.c
$ gcc -shared -o src_b.so src_b.o -lc
$ ksm
> (use 'clang)
> (load-shared "./src_b.so")
> (define cp (clang:sym (struct cp (int x) 
                                   (int colored 1) 
                                   (int y)) 
                          cp))
> (define get-colored (clang:sym int (get_colored)))
> (get-colored)          ==> -1
> (set! (clang:. cp 'colored) 0)
> (get-colored)          ==> 0

@source{clang/clang.c} @use{clang}

Function: clang:-> csym field
csym must be a C object whose type is a pointer to a structure. Returns the value of field in the structure pointed by csym. If there is no such a field, an error is raised.
$ cat src.c
struct point {
  int x;
  int y;
} pp = { 1, 2 };
$ gcc -c -fPIC src.c
$ gcc -shared -o src.so src.o -lc
$ ksm
> (use 'clang)
> (load-shared "./src.so")
> (define p
    (clang:& (clang:sym (struct point (int x) (int y)) pp)))
> (clang:-> p 'x) ==> 1
> (clang:-> p 'y) ==> 2
$ cat src.c
struct point {
  int x;
  int y;
} pp = { 1, 2 };
int get_x(void) { return pp.x; }
$ gcc -c -fPIC src.c
$ gcc -shared -o src.so src.o -lc
$ ksm
> (use 'clang)
> (load-shared "./src.so")
> (define p
    (clang:& (clang:sym (struct point (int x) (int y)) pp)))
> (define f (clang:sym int (get_x)))
> (f)                ==> 1
> (set! (clang:-> p 'x) 100)
> (f)                ==> 100

@source{clang/clang.c} @use{clang}

Function: clang:& csym
csym must be a C object. Returns a C object corresponding to the address csym.
$ cat src.c
int a = 12;
int f(void) { return a; }
$ gcc -c -fPIC src.c
$ gcc -shared -o src.so src.o -lc
$ ksm
> (use 'clang)
> (load-shared "./src.so")
> (define a (clang:sym int a))
> (define ip (clang:& a))
> (clang:* ip)          ==> 12
> (set! (clang:* ip) 123)
> a                     ==> 123
> ((clang:sym int (f))) ==> 123

@source{clang/clang.c} @use{clang}

Function: clang:get-value csym
csym must be a C object. Converts csym to standard Scheme object according to the type of csym. If such a conversion is not possible, csym itself is returned.
$ cat src.c
int a = 1; 
char *f(void) { return "hello"; }
$ gcc -c -fPIC src.c
$ gcc -shared -o src.so src.o -lc
$ ksm
> (use 'clang)
> (load-shared "./src.so")
> (define a (clang:sym int a))
> (define f (clang:sym (char *) (f)))
> a                        ==> 1
> (number? a)              ==> #f
> (number? (get-value a))  ==> #t
> (f)                      ==> #<csym>
> (get-value (f))          ==> "hello"

@source{clang/clang.c} @use{clang}

NOTE: Currently, C object whose type is int, signed int, double, or char * is converted a standard Scheme object.

Special Form: clang:struct struct-name
Special Form: clang:struct [struct-name] (type field-name) ...)
Special Form: clang:union union-name
Special Form: clang:union [union-name] (type field-name) ...)
Declares a structure/union corresponding to a C structure/union. Returns an unspecified value. Syntax of these forms are the same with the syntax of Scheme representation of C structure/union, except that the first struct/union element in the list is replaced by clang:struct/clang:union. See section Type Representation, for details about C type representation in KSM-Scheme.
(clang:struct point (int x) (int y))
(clang:sizeof (struct point))    ==> 8

It is an error to declare a different kind of structure/union under the name of the same struct-name.

$ ksm
> (clang:struct point (int x) (int y))
> (clang:struct point (double x) (double y)) ==> #<error>
> (clang:struct point (int x) (int y))   ;; This is OK.
> (clang:struct point (int p) (int q))       ==> #<error>

Structure/union declarations without field definitions are allowed regardless whether field definitions are conducted elsewhere in the source or not.

$ ksm
> (clang:struct point)
> (clang:struct point (int x) (int y))  ;; This is OK.
$ ksm
> (clang:struct point (int x) (int y))
> (clang:struct)      ;; This is also OK.

@source{clang/clang.c} @use{clang}

Special Form: clang:typedef type symbol
Special Form: clang:typedef type (symbol type ...)
Associates symbol with type, equivalent to `typedef' in C. Returns an unspecified value. See section Type Representation, for details about representation of C type in KSM-Scheme.
(clang:typedef int Integer)
(clang:typedef (int *) int_ptr)
(clang:typedef double Real)
(clang:sizeof Integer)  ==> 4
(clang:sizeof int_ptr)  ==> 4
(clang:sizeof Real)     ==> 8

@source{clang/clang.c} @use{clang}

Special Form: clang:new type
type must be a Scheme object that represents a C type. Allocates a memory area (malloc-ed) with size of type and returns a C object corresponding to the memory area. This memory area is not automatically garbage collected, and it should be explicitly freed by clang:dispose. For details of representation of C type, see clang:sym.
> (define a (clang:new int))
> (set! a 10)
> a ==> 10
> (clang:dispose a)

@source{clang/clang.c} @use{clang}

Function: clang:dispose csym
csym must be a C object allocated by clang:new. Frees the memory allocated to csym. Returns an unspecified value.
> (define a (clang:new int))
> (set! a 10)
> a                 ==> 10
> (clang:dispose a)

@source{clang/clang.c} @use{clang}

Special Form: clang:sizeof type
type must be a Scheme object that represents a C type. Returns the byte-size of type. See section Type Representation, for details about C type representation in KSM-Scheme.
(clang:sizeof int)    ==> 4
(clang:sizeof double) ==> 8
(clang:sizeof (struct (int x) (int y)))    ==> 8
(clang:sizeof (struct (int x) (double y))) ==> 16
(clang:sizeof (int *)) ==> 4

@source{clang/clang.c} @use{clang}

Special Form: clang:align type
type must be a Scheme object that represents a C type. Returns the byte-alignment of type. For details of representation of C type, see clang:sym.
(clang:align int)                         ==> 4
(clang:align double)                      ==> 8
(clang:align (struct (int x) (double y))) ==> 8

@source{clang/clang.c} @use{clang}


Go to the first, previous, next, last section, table of contents.