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)
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))
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}
$ 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}
$ 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}
$ 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}
$ 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}
$ 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}
$ 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.
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}
(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}
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}
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}
(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}
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.