Hi All, I am working on a ffi-helper: a program that will read in a C dot-h file and generate a Guile dot-scm file which defines a module to provide hooks into the associated C library. My goal is to have something to release ~Oct 2017.
I have now been able to compile-ffi the following on my Mac. There is some non-standard C syntax in sys/cdefs.h that is driving me crazy, but I have a hack around it (see inc-help below). I’m sure there are numerous bugs. (define-ffi-module (cairo cairo) #:pkg-config "cairo" #:include '("cairo.h" "cairo-pdf.h" "cairo-svg.h" ) #:inc-help (cond ((string-contains %host-type "darwin") '(("__builtin" "__builtin_va_list=void*") ("sys/cdefs.h" "__DARWIN_ALIAS(X)="))) (else '())) ;; the following are bent pipe to scm-module #:export (make-cairo-unit-matrix) ) (define (make-cairo-unit-matrix) (make-cairo_matrix_t #(1.0 0.0 0.0 1.0 0.0 0.0))) Some of the other Cairo headers (e.g., cairo-ft.h) give me problems with the rat’s nest under /usr/include. However, the above generates 397 FFI declarations into a cairo.scm file which is about 6000 lines long. I’m not sure if I want to start testing this code or start converting suggestions and have guile-users do some testing. Matt P.S. Here is some sample code from the auto-generated file cairo/cairo.scm. Notice that the helper includes the original C declarations as comments. ;; typedef struct _cairo_device cairo_device_t; (define-fh-pointer-type cairo_device_t*) ;; union _cairo_path_data_t { ;; struct { ;; cairo_path_data_type_t type; ;; int length; ;; } header; ;; struct { ;; double x, y; ;; } point; ;; }; (define cairo_path_data_t-desc (bs:union (list `(header ,(bs:struct (list `(type ,cairo_path_data_type_t-desc) `(length ,int)))) `(point ,(bs:struct (list `(y ,double) `(x ,double))))))) (export cairo_path_data_t-desc) (define-fh-bytestructure-type/p cairo_path_data_t cairo_path_data_t-desc) (define union-_cairo_path_data_t cairo_path_data_t) ;; typedef enum _cairo_path_data_type { ;; CAIRO_PATH_MOVE_TO, ;; CAIRO_PATH_LINE_TO, ;; CAIRO_PATH_CURVE_TO, ;; CAIRO_PATH_CLOSE_PATH, ;; } cairo_path_data_type_t; (define-fh-enum-type cairo_path_data_type_t '((CAIRO_PATH_MOVE_TO . 0) (CAIRO_PATH_LINE_TO . 1) (CAIRO_PATH_CURVE_TO . 2) (CAIRO_PATH_CLOSE_PATH . 3)) ) ;; typedef void (*cairo_destroy_func_t)(void *data); (define (wrap-cairo_destroy_func_t proc) ;; => pointer (ffi:procedure->pointer ffi:void proc (list '*)) ) (export wrap-cairo_destroy_func_t) ;; cairo_status_t cairo_device_set_user_data(cairo_device_t *device, const ;; cairo_user_data_key_t *key, void *user_data, cairo_destroy_func_t ;; destroy); (define cairo_device_set_user_data (let ((~f (ffi:pointer->procedure ffi:int (lib-func "cairo_device_set_user_data") (list '* '* '* '*)))) (lambda (device key user_data destroy) (let ((~device (unwrap-cairo_device_t* device)) (~key (unwrap-cairo_user_data_key_t* key)) (~user_data (unwrap~pointer user_data)) (~destroy (unwrap-cairo_destroy_func_t destroy))) (wrap-cairo_status_t (~f ~device ~key ~user_data ~destroy)))))) (export cairo_device_set_user_data)