source: project/wiki/An extended FFI example @ 39091

Last change on this file since 39091 was 39091, checked in by Mario Domenech Goulart, 3 months ago

An extended FFI example: fix broken link to easyffi.

File size: 2.9 KB
Line 
1Here is an example for a simple program that uses CHICKEN's
2foreign function interface. It is the Gtk 2.0 Hello, world
3program as presented in the GTK tutorial, which is available
4[[http://www.gtk.org/tutorial/ch-gettingstarted.html#SEC-HELLOWORLD|here]].
5
6This example is intended to show various features of the FFI
7and to demonstrate that one can go relatively far without writing
8tons of glue code. The comments are only to show the CHICKEN specific
9things, see the original tutorial for more information.
10
11<enscript highlight=scheme>
12 ;;;; gtkhello.scm
13
14 (require-extension easyffi)
15
16 ;; Include this code directly into generated .c file:
17
18 (foreign-declare "#include <gtk/gtk.h>")
19
20 ;; Parse declarations and generate Scheme bindings:
21
22 (foreign-parse "
23 const int GTK_WINDOW_TOPLEVEL;
24
25 void gtk_main_quit();
26 void gtk_init(int *, char ***);
27 GtkWidget *gtk_window_new(int);
28 int g_signal_connect(void *, char *, void *, void *);
29 int g_signal_connect_swapped(void *, char *, void *, void *);
30 void gtk_container_set_border_width(GtkContainer *, int);
31 GtkWidget *gtk_button_new_with_label(char *);
32 void gtk_widget_destroy(GtkWidget *);
33 void gtk_container_add(GtkContainer *, GtkWidget *);
34 void gtk_widget_show(GtkWidget *);
35
36 /* the ___safe marker is needed, because gtk_main() may
37   (and will) call Scheme callbacks. */
38 ___safe void gtk_main();
39 ")
40
41
42 ;; Define a few callback function:
43
44 (define-external (hello ((pointer "GtkWidget") widget)
45                         (c-pointer data))
46   void
47   (print "Hello, world") )
48
49 (define-external (delete_event ((pointer "GtkWidget") widget)
50                                ((pointer "GdkEvent") event)
51                                (c-pointer data) )
52   bool
53   (print "Delete event occured")
54   #t)
55
56 (define-external (destroy ((pointer "GtkWidget") widget)
57                           (c-pointer data) )
58   void
59   (gtk_main_quit) )
60
61 ;; This is a bit ugly, but there is no elegant way to get
62 ;; at argc/argv at the Scheme level and pass pointers to it
63 ;; to foreign code:
64
65 (foreign-code "gtk_init(&C_main_argc, &C_main_argv);")
66
67 (define window (gtk_window_new GTK_WINDOW_TOPLEVEL))
68
69 ;; #$... with a callback-name returns the function pointer:
70
71 (g_signal_connect window "delete_event" #$delete_event #f)
72 (g_signal_connect window "destroy" #$destroy #f)
73
74 (gtk_container_set_border_width window 10)
75
76 (define button (gtk_button_new_with_label "Hello World"))
77
78 (g_signal_connect button "clicked" #$hello #f)
79
80 ;; Here we use foreign-value to get the function pointer.
81 ;; #$gtk_widget_destroy wouldn't work: the function is not
82 ;; a callback:
83
84 (g_signal_connect_swapped button "clicked"
85   (foreign-value gtk_widget_destroy c-pointer) window)
86
87 (gtk_container_add window button)
88 (gtk_widget_show button)
89 (gtk_widget_show window)
90 (gtk_main)
91</enscript>
92
93To compile it, we have to ensure the proper C compiler and linker
94flags are passed:
95
96 $ csc -vk gtkhello.scm -C "`pkg-config --cflags gtk+-2.0`" -L "`pkg-config --libs gtk+-2.0`" -X easyffi
97
98(the [[/eggref/4/easyffi|easyffi]] egg is required)
Note: See TracBrowser for help on using the repository browser.