guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

ffi-help: status to date


From: Matt Wette
Subject: ffi-help: status to date
Date: Sun, 22 Oct 2017 11:31:27 -0700

Hi All,

I am working on a ffi-helper (FH): 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.  

Since last report I have removed the un-hygienic macros: all names are passed 
to macros now.  This makes
the generated Scheme code about double the size it was before, but so what.  
Also, the "wrap" and "unwrap"
functions are now mostly hidden: they should not be needed directly by the user.

I am fine-tuning the type handling.  Note:
1) In Scheme we need to have something that represents the pointer types.  When 
the FH sees a C type like
   typedef struct { ... } foo_t then the it generates SCM types for foo_t and 
foo_t*, a pointer-to-foo_t type.
   These types are connected to that (pointer-to <obj>) for an object of type 
foo_t generates a foo_t* object.
2) The FH does not generate types for numerics: typedef int int_t; is just left 
alone, but wrappers are used
   to convert numerics.
3) The FH does not generate types for typedef enum { ... } enum_t;
4) I am using the bytestructures package from Taylan UB 
(github-dot-com/TaylanUB/scheme-bytestructures).
5) I have developed a function pseudo-descriptor for bytestructures so that 
(bs:pointer (fh:function ...))
   provides a way to deal with function pointers in structs.  Passing Scheme 
procedures as arguments to 
   pointer->procedure generated procedures works also.

Issues:
1) I am still working on a solution to functions w/ varargs.  I believe I have 
a solution for calling C vararg
   functions from Guile: the user provides casts for extra args, e.g., (printf 
"the value is %d\n" (fh-cast int 4)).
   The implementation will take a bit of work.
2) clean up some inefficiencies.  Not going into details here
3) Documentation:  This will have to be good because the FFI helper is not 
bullet proof.  Sometimes one needs
   to add extra pointer-types etc in the dot-ffi module, and there needs to be 
a document to help the user go
   through the process of finding the reason for error messages and how to add 
code to get things working.
4) Maybe a C to Guile C-SMOB generated is needed also.  The gtk2+ dot-go file 
is now ~ 20 MB.

I was able to generate scm code for glib, gobject, gio, pango, and gtk2+.  The 
following demo code actually works.
I get a GUI and click the button and it closes, though with an error message:
    gtkdemo.scm:16:0: Wrong number of arguments to #<procedure hello (widget 
data)>

The code is being worked in the c99dev branch of nyacc, hosted on 
https://savannah.nongnu.org/projects/nyacc.

#!/opt/local/bin/guile
!#

;; https://developer.gnome.org/gtk-tutorial/stable/c39.html#SEC-HELLOWORLD

(use-modules (ffi glib))
(use-modules (ffi gobject))
(use-modules (ffi gtk2+))
(use-modules (bytestructures guile))
(use-modules (system ffi-help-rt))
(use-modules ((system foreign) #:prefix ffi:))

(define NULL ffi:%null-pointer)

(define (hello widget data)
  ;;(g_print "Hello World!\n")
  (display "Hello World!\n")
  )

(define (delete-event widget event data)
  (display "delete event occurred\n")
  1)

(define (destroy widget data)
  (gtk_main_quit))

(define (main)
  (define window #f)
  (define button #f)
  (define argc (bytestructure int 0))

  (gtk_init (pointer-to argc) NULL)

  (set! window (gtk_window_new 'GTK_WINDOW_TOPLEVEL))
  (g_signal_connect window "delete-event" delete-event NULL)
  (g_signal_connect window "destroy" destroy NULL)
  (gtk_container_set_border_width window 10)

  (set! button (gtk_button_new_with_label "Hello World"))
  (g_signal_connect button "clicked" hello NULL)
  (g_signal_connect_swapped button "clicked" gtk_widget_destroy window)
  (gtk_container_add window button)

  (gtk_widget_show button)
  (gtk_widget_show window)

  (gtk_main))

;; --- last line ---

And here, for example, is the FFI module for gtk2+ and gobject:
;; gtk2+.ffi                            -*- Scheme -*-

(define-ffi-module (ffi gtk2+)
  #:pkg-config "gtk+-2.0"
  #:include '("gtk/gtk.h")
  #:inc-filter (lambda (f p) (string-contains p "gtk/" 0))
  #:use-ffi-module (ffi gdk2)
  #:use-ffi-module (ffi pango)
  #:use-ffi-module (ffi gobject)
  #:use-ffi-module (ffi glib)
  )

(define-fh-pointer-type GtkEnumValue* int*-desc
  GtkEnumValue*? make-GtkEnumValue*)
(export GtkEnumValue* GtkEnumValue*? make-GtkEnumValue*)
  
;; --- last line ---

;; gobject.ffi                          -*- Scheme -*-

(define-ffi-module (ffi gobject)
  #:use-ffi-module (ffi glib)
  #:pkg-config "gobject-2.0"
  #:include '("glib-object.h")
  #:inc-filter (lambda (file-spec path-spec)
                 (string-contains path-spec "gobject/" 0))
  #:use-module ((system foreign) #:prefix ffi: #:select(%null-pointer))
  )

(define NULL ffi:%null-pointer)

(define-public (g_signal_connect instance detailed_signal c_handler data)
  (g_signal_connect_data instance detailed_signal c_handler data NULL 0))

(define-public (g_signal_connect_after instance detailed_signal c_handler data)
  (g_signal_connect_data instance detailed_signal c_handler data NULL
                         'G_CONNECT_AFTER))

(define-public (g_signal_connect_swapped instance detailed_signal c_handler
                                         data)
  (g_signal_connect_data instance detailed_signal c_handler data NULL
                         'G_CONNECT_SWAPPED))

;; --- last line ---

; pango.ffi                            -*- Scheme -*-

(define-ffi-module (ffi pango)
  #:pkg-config "pango"
  #:include '("pango/pango.h")
  #:inc-filter (lambda (f p) (string-contains p "pango/" 0))
  #:use-ffi-module (ffi glib)
  #:use-ffi-module (ffi gobject)
  )

;; PangoScript is an enum.  Some routines return pointer to int for this.
(define-public wrap-PangoScript* (fht-wrap int*))

;; --- last line ---




reply via email to

[Prev in Thread] Current Thread [Next in Thread]