unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* ffi-help: varargs ...
@ 2017-11-16 14:00 Matt Wette
  2017-12-07  2:46 ` ffi-help: documentation Matt Wette
  0 siblings, 1 reply; 4+ messages in thread
From: Matt Wette @ 2017-11-16 14:00 UTC (permalink / raw)
  To: Guile User Mailing List

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. 

I have support for functions which use varargs working.  Users must cast undeclared
arguments:

mwette$ cat tryme.h
int printf(char *fmt, ...);

mwette$ cat tryme.ffi
(define-ffi-module (tryme)
  #:include '("tryme.h")
  #:library '("libz")) ;; need dummy

mwette$ guild compile-ffi tryme.ffi
wrote `tryme.scm'

mwette$ guild compile tryme.scm
wrote `/..../tryme.scm.go'

mwette$ guile
scheme@(guile-user)> (use-modules (tryme))
scheme@(guile-user)> (use-modules (system ffi-help-rt))
scheme@(guile-user)> (use-modules (system foreign))

scheme@(guile-user)> (printf "Hello, for the %d-th time\n" (fh-cast int 10))
Hello, for the 10-th time
$1 = 26

scheme@(guile-user)> 




^ permalink raw reply	[flat|nested] 4+ messages in thread

* ffi-help: documentation
  2017-11-16 14:00 ffi-help: varargs Matt Wette
@ 2017-12-07  2:46 ` Matt Wette
  2018-01-07 21:19   ` Thien-Thi Nguyen
  0 siblings, 1 reply; 4+ messages in thread
From: Matt Wette @ 2017-12-07  2:46 UTC (permalink / raw)
  To: Guile User Mailing List; +Cc: guile-devel

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.  

Currently, I'm working on documentation.  I like manuals that start out with 
simple demos to show what's going on.  That is my approach here.   Enjoy ...

FFI Helper for Guile
********************

Matt Wette
December 2017
With NYACC Version 0.00.0

1 Introduction
**************

The acronym FFI stands for "Foreign Function Interface".  It refers to
the Guile facility for binding functions and variables from C source
libraries into Guile programs.  This distribution provides utilities for
generating a loadable Guile module from a set of C declarations and
associated libraries.  The C declarations can, and conventionally do,
come from naming a set of C include files.  The nominal method for use
is to write a _ffi-module_ specification in a file which includes a
'define-ffi-module' declaration and then use the command 'guild
compile-ffi' to convert this to Guile Scheme.
     $ guild compile-ffi ffi/cairo.ffi
     wrote `ffi/cairo.scm'
Note that no C code is generated.  The hooks to access C-coded functions
in the Cairo library are provided in 100% Guile Scheme.

   The compiler for the FFI Helper (FH) is based on the C parser and
utilities which are included in the NYACC (https://www.nongnu.org/nyacc)
package.  Development for the FH is currently being performed in the
'c99dev' branch of the associated git repository.  Within the NYACC
distribution, the relevant modules can be found under the directory
'examples/'.

   Use of the FFI-helper module depends on the _scheme-bytestructure_
package available from
<https://github.com/TaylanUB/scheme-bytestructures>.  Since this package
is currently not under version control we provide a partial copy in the
NYACC distribution.

   You are probably hoping to see an example, so let's do that.

2 Demonstration
***************

This is a small FFI Helper example to illustrate its use.  We will start
with the Cairo (cairographics.org) package because that is the first one
I started with in developing this package.  Say you are an avid Guile
user and want to be able to use cairo in Guile.  On most systems this
comes with associated _pkg-config_ support files.

   WARNING: The FFI-helper package is under active development and there
is some chance the following example will cease to work in the future.

   If you want to follow along and are working in the distribution tree,
you should source the file 'env.sh' in the 'examples' directory.

   By practice, I like to put all FH generated modules under a directory
called 'ffi/', so we will do that.  We start by generating, in the 'ffi'
directory, a file named 'cairo.ffi' with the following contents:
     (define-ffi-module (ffi cairo)
       #:pkg-config "cairo"
       #:include '("cairo.h" "cairo-pdf.h" "cairo-svg.h"))

   Now to generate a Guile module you use 'guild' as follows:
     $ guild compile-ffi ffi/cairo.ffi
     wrote `ffi/cairo.scm'
Though the file 'cairo/cairo.ffi' is only three lines long, the file
'ffi/cairo.scm' will be over five thousand lines long.  It looks like
the following:
     (define-module (ffi cairo)
       #:use-module (system ffi-help-rt)
       #:use-module ((system foreign) #:prefix ffi:)
       #:use-module (bytestructures guile)
       )
     (define link-libs
       (list (dynamic-link "libcairo")))

     ;; int cairo_version(void);
     (define ~cairo_version
       (delay (fh-link-proc
                ffi:int
                "cairo_version"
                (list)
                link-libs)))
     (define (cairo_version)
       (let () ((force ~cairo_version))))
     (export cairo_version)

     ...

     ;; typedef struct _cairo_matrix {
     ;;   double xx;
     ;;   double yx;
     ;;   double xy;
     ;;   double yy;
     ;;   double x0;
     ;;   double y0;
     ;; } cairo_matrix_t;
     (define-public cairo_matrix_t-desc
       (bs:struct
         (list `(xx ,double)
               `(yx ,double)
               `(xy ,double)
               `(yy ,double)
               `(x0 ,double)
               `(y0 ,double))))
     (define-fh-compound-type cairo_matrix_t cairo_matrix_t-desc cairo_matrix_t?
      make-cairo_matrix_t)
     (export cairo_matrix_t cairo_matrix_t? make-cairo_matrix_t)

     ... many, many more declarations ...

     ;; access to enum symbols and #define'd constants:
     (define ffi-cairo-symbol-val
       (let ((sym-tab
               '((CAIRO_SVG_VERSION_1_1 . 0)
                 (CAIRO_SVG_VERSION_1_2 . 1)
                 (CAIRO_PDF_VERSION_1_4 . 0)
                 (CAIRO_PDF_VERSION_1_5 . 1)
                 (CAIRO_REGION_OVERLAP_IN . 0)
                 (CAIRO_REGION_OVERLAP_OUT . 1)
                 (CAIRO_REGION_OVERLAP_PART . 2)
                 (CAIRO_FILTER_FAST . 0)
                 (CAIRO_FILTER_GOOD . 1)
                 (CAIRO_FILTER_BEST . 2)
                 ... more constants ...
                 (CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID
                   .
                   "application/x-cairo.jbig2-global-id"))))
         (lambda (k) (or (assq-ref sym-tab k)))))
     (export ffi-cairo-symbol-val)
     (export cairo-lookup)

     ... more ...
Note that from the _pkg-config_ spec the FH compiler picks up the
required libraries to bind in.  Also, '#define' based constants, as well
as those defined by enums, are provided in a lookup function
'ffi-cairo-symbol-val'.  So, for example
     guile> (use-modules (ffi cairo))
     ;;; ffi/cairo.scm:6112:11: warning: possibly unbound variable `cairo_raster_source_acquire_func_t*'
     ;;; ffi/cairo.scm:6115:11: warning: possibly unbound variable `cairo_raster_source_release_func_t*'
     guile> (ffi-cairo-symbol-val 'CAIRO_FORMAT_ARGB32))
     $1 = 0
We will discuss the warnings later.  These are signals that extra code
needs to be added to the ffi module.  But you see how the constants (but
not CPP function macros) can be accessed.

   Let's try something more useful: a real program.  Create the
following code in a file, say 'cairo-demo.scm', first up a Guile sesion
and 'load' the file.
     (use-modules (ffi cairo))
     (define srf (cairo_image_surface_create 'CAIRO_FORMAT_ARGB32 200 200))
     (define cr (cairo_create srf))
     (cairo_move_to cr 10.0 10.0)
     (cairo_line_to cr 190.0 10.0)
     (cairo_line_to cr 190.0 190.0)
     (cairo_line_to cr 10.0 190.0)
     (cairo_line_to cr 10.0 10.0)
     (cairo_stroke cr)
     (cairo_surface_write_to_png srf "cairo-demo.png")
     (cairo_destroy cr)
     (cairo_surface_destroy srf)
If we set up everything correctly you should have the target 'png' image
of a square.  A few items in the above code are notable.  First, the
call to 'cairo_image_surface_create' accepted a symbolic form
(''CAIRO_FORMAT_ARGB32' for the format.  It would have also accepted the
associated constant '0'.  In addition, '(ffi cairo)' function will
accept Scheme strings where the C function wants "pointer to string."

   Now try this in your Guile session:
     guile> srf
     $4 = #<cairo_surface_t* 0x7fda53e01880>
     guile> cr
     $5 = #<cairo_t* 0x7fda54828800>
Note that the FH keeps track of the C types you use.  This can be useful
for debugging but may bloat the namespace.  The constants you see are
the pointer values.  But it goes further.  Let's generate a matrix type:
     guile> (define m (make-cairo_matrix_t))
     guile> m
     $6 = #<cairo_matrix_t 0x10cc26c00>
     guile> (pointer-to m)
     $7 = #<cairo_matrix_t* 0x10cc26c00>
When it comes to C APIs that expect the user to allocate memory for a
structure and pass the pointer address to the C function, FH provides
the solution:
     guile> (cairo_get_matrix cr (pointer-to m))
     guile> (use-modules (system ffh-help-rt))
     guile> (fh-object-ref m 'xx)
     $9 = 1.0





^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: ffi-help: documentation
  2017-12-07  2:46 ` ffi-help: documentation Matt Wette
@ 2018-01-07 21:19   ` Thien-Thi Nguyen
  2018-01-07 21:21     ` Matt Wette
  0 siblings, 1 reply; 4+ messages in thread
From: Thien-Thi Nguyen @ 2018-01-07 21:19 UTC (permalink / raw)
  To: Matt Wette; +Cc: Guile User Mailing List

[-- Attachment #1: Type: text/plain, Size: 2171 bytes --]


() Matt Wette <matt.wette@gmail.com>
() Wed, 6 Dec 2017 18:46:59 -0800

   Currently, I'm working on documentation.  I like manuals that
   start out with simple demos to show what's going on.  That is
   my approach here.  Enjoy ...

Cool.  Examples are great.  I suggest only one tweak, small but
pervasive, that would improve text output format readability
(IMHO): add blank lines around environments and prior to
non-trivial ‘@item’ lines.

For example, compare the original (at beginning):

| come from naming a set of C include files.  The nominal
| method for use is to write a _ffi-module_ specification in a
| file which includes a 'define-ffi-module' declaration and
| then use the command 'guild compile-ffi' to convert this to
| Guile Scheme.
|      $ guild compile-ffi ffi/cairo.ffi
|      wrote `ffi/cairo.scm'
| Note that no C code is generated.  The hooks to access
| C-coded functions in the Cairo library are provided in 100%
| Guile Scheme.

with a revision that adds blank lines around the ‘@example’:

| come from naming a set of C include files.  The nominal
| method for use is to write a _ffi-module_ specification in a
| file which includes a 'define-ffi-module' declaration and
| then use the command 'guild compile-ffi' to convert this to
| Guile Scheme.
|
|      $ guild compile-ffi ffi/cairo.ffi
|      wrote `ffi/cairo.scm'
|
| Note that no C code is generated.  The hooks to access
| C-coded functions in the Cairo library are provided in 100%
| Guile Scheme.

(NB: This excerpt was refilled, but that is besides the point.)
I find the latter easier to jump in and out of (skim) visually.

For more mumblings on "blank lines" see:
- http://www.gnuvola.org/u/2017/08/08h21.html
- http://www.gnuvola.org/u/2017/05/17h22.html
- http://www.gnuvola.org/u/2017/05/16h15.html

[cc trimmed]

-- 
Thien-Thi Nguyen -----------------------------------------------
 (defun responsep (query)
   (pcase (context query)
     (`(technical ,ml) (correctp ml))
     ...))                              748E A0E8 1CB8 A748 9BFA
--------------------------------------- 6CE4 6703 2224 4C80 7502

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: ffi-help: documentation
  2018-01-07 21:19   ` Thien-Thi Nguyen
@ 2018-01-07 21:21     ` Matt Wette
  0 siblings, 0 replies; 4+ messages in thread
From: Matt Wette @ 2018-01-07 21:21 UTC (permalink / raw)
  To: Guile User Mailing List


> On Jan 7, 2018, at 1:19 PM, Thien-Thi Nguyen <ttn@gnu.org> wrote:
> 
> 
> () Matt Wette <matt.wette@gmail.com>
> () Wed, 6 Dec 2017 18:46:59 -0800
> 
>   Currently, I'm working on documentation.  I like manuals that
>   start out with simple demos to show what's going on.  That is
>   my approach here.  Enjoy ...
> 
> Cool.  Examples are great.  I suggest only one tweak, small but
> pervasive, that would improve text output format readability
> (IMHO): add blank lines around environments and prior to
> non-trivial ‘@item’ lines.
> 
> For example, compare the original (at beginning):
> 
> | come from naming a set of C include files.  The nominal
> | method for use is to write a _ffi-module_ specification in a
> | file which includes a 'define-ffi-module' declaration and
> | then use the command 'guild compile-ffi' to convert this to
> | Guile Scheme.
> |      $ guild compile-ffi ffi/cairo.ffi
> |      wrote `ffi/cairo.scm'
> | Note that no C code is generated.  The hooks to access
> | C-coded functions in the Cairo library are provided in 100%
> | Guile Scheme.
> 
> with a revision that adds blank lines around the ‘@example’:
> 
> | come from naming a set of C include files.  The nominal
> | method for use is to write a _ffi-module_ specification in a
> | file which includes a 'define-ffi-module' declaration and
> | then use the command 'guild compile-ffi' to convert this to
> | Guile Scheme.
> |
> |      $ guild compile-ffi ffi/cairo.ffi
> |      wrote `ffi/cairo.scm'
> |
> | Note that no C code is generated.  The hooks to access
> | C-coded functions in the Cairo library are provided in 100%
> | Guile Scheme.
> 
> (NB: This excerpt was refilled, but that is besides the point.)
> I find the latter easier to jump in and out of (skim) visually.
> 
> For more mumblings on "blank lines" see:
> - http://www.gnuvola.org/u/2017/08/08h21.html
> - http://www.gnuvola.org/u/2017/05/17h22.html
> - http://www.gnuvola.org/u/2017/05/16h15.html
> 
> [cc trimmed]
> 
> -- 
> Thien-Thi Nguyen -----------------------------------------------
> (defun responsep (query)
>   (pcase (context query)
>     (`(technical ,ml) (correctp ml))
>     ...))                              748E A0E8 1CB8 A748 9BFA
> --------------------------------------- 6CE4 6703 2224 4C80 7502

Thanks.  I will take that into serious consideration.

Matt





^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2018-01-07 21:21 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-16 14:00 ffi-help: varargs Matt Wette
2017-12-07  2:46 ` ffi-help: documentation Matt Wette
2018-01-07 21:19   ` Thien-Thi Nguyen
2018-01-07 21:21     ` Matt Wette

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).