New Package: Dynamic FFI - Write C Code Inline

138 views
Skip to first unread message

David Benoit

unread,
Jun 1, 2019, 3:06:29 PM6/1/19
to Racket Users
Hi All,

I've recently released a new library for dynamically generating FFI bindings to C by parsing header files.
It also allows users to create FFI libraries by writing C functions directly inline in Racket programs.  

The library works as a native extension to Racket by linking with Clang's parser libraries and converting AST declarations into FFI objects.
As a result, the package depends on Clang and LLVM headers and libraries.  See the documentation for info on installing dependencies.

I've only built the package on GNU/Linux so far.  If anyone is interested in building the library on other OSes, it should be a fairly trivial port.

I'd like to give a special thanks to Jay McCarthy, who came up with the idea for this project and was my adviser during its implementation.
I hope its something the Racket community might find useful!

More usage examples are available in the docs and the test directory in the source code.

Thanks!
David B

I'll sign off with a quick preview:

#lang at-exp racket/base

(require dynamic-ffi/unsafe)

@define-inline-ffi[struct-test]{
 
#include <stdlib.h>
 
#include <stdio.h>
 
#include <stdint.h>

 
typedef struct {
   
char *name;
    uint64_t value
;
 
} number;

 
char* names[] = {"zero", "one", "two", "three", "four", "five", "six"
                 
"seven", "eight", "nine", "ten", "eleven", "twelve"};

  number add
(number a, number b) {
    number c
;
    c
.value = a.value + b.value;
   
if (c.value >12)  {
      fprintf
(stderr, "error: this example can only count to twelve...\n");
     
exit(1);
   
}
    c
.name = names[c.value];
   
return c;
 
}
}

;; _list-structs are created by default.  I hope to optimize this in the future.

(define n2 (list "two" 2))

(define n7 (list "seven" 7))

(printf "add(n2, n2): ~a\n" (struct-test 'add n2 n2))  ;; output: add(n2, n2): (four 4)
(printf "add(n7, n7): ~a\n" (struct-test '
add n7 n7))  ;; output: error: this example can only count to twelve...




Alexis King

unread,
Jun 1, 2019, 3:49:48 PM6/1/19
to David Benoit, Racket Users
This looks extremely cool. Thanks for your hard work—I will probably give this a try next time I use the FFI.

Alexis

--
You received this message because you are subscribed to the Google Groups "Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to racket-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/eff63a65-d1b7-475b-9240-7158b024d740%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Konrad Hinsen

unread,
Jun 3, 2019, 8:07:04 AM6/3/19
to racket...@googlegroups.com
On 01/06/2019 21:06, David Benoit wrote:
I've recently released a new library for dynamically generating FFI bindings to C by parsing header files.
It also allows users to create FFI libraries by writing C functions directly inline in Racket programs.

Thanks, this looks very promising! Even more so with the option of generating static FFIs that I saw in the documentation. That's important in practice to prevent LLVM and clang becoming dependencies for lots of Racket code.

Now if you could also provide a tool for dynamically generating free time for playing with this, I'd be even happier ;-)


Konrad.

zeRusski

unread,
Jun 3, 2019, 11:53:12 AM6/3/19
to Racket Users
Oh wow! IIUC it is super awesome. Would a natural next step be #lang terra?
Hey Jay McCarthy would you like to mentor that effort ;-)

Jay McCarthy

unread,
Jun 3, 2019, 12:35:04 PM6/3/19
to zeRusski, Racket Users
We're already on it...

https://github.com/jeapostrophe/adqc

See an example here:

https://github.com/jeapostrophe/adqc/blob/master/t/fib.rkt

It'll be more than just C though, because we'll be generating
verification conditions and we'll allow you to enforce time and space
bounds.

Jay

--
Jay McCarthy
Associate Professor @ CS @ UMass Lowell
http://jeapostrophe.github.io
Vincit qui se vincit.
> --
> You received this message because you are subscribed to the Google Groups "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to racket-users...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/628bf864-d261-481b-962c-2e54be297228%40googlegroups.com.

Neil Van Dyke

unread,
Jun 3, 2019, 1:44:36 PM6/3/19
to David Benoit, Racket Users
This looks neat.

I'm glad you noted upfront in the documentation about things it can't
handle automatically (e.g., allocations/lifetimes that need special
management).

In your discussion relating this to other work/approaches, you might
want to contrast with SWIG (e.g., you work from the original headers,
when SWIG not available).  And, as a practical measure, maybe consider
using some of the information from SWIG when available.

If you or someone later someone wants to do work with C code in
pure-Racket (without the Clang dependency), I recall some earlier work
on C parsing, and you might find some packages for that (also check
PLaneT), maybe including by Dave Herman.  A C parser is a lot harder
than one might initially think (it's not just the fairly straightforward
standard grammar with type-based ambiguities, but also getting all the
preprocessing correct while (for some tools needs) retaining
pre-preprocessing information, such as the names of macro uses and fine
source position information), but you can do neat things once you build
it.  One of my past employers used such a fancy C parser for "reverse
engineering" C code into a full CASE system (which included other neat
toys, like a high-level structured systems analysis&design,
network-based in-circuit emulator, embedded system code instrumentation
for path coverage, static complexity analysis, test case generation).

BTW, that's a clever use of `at-exp` for embedded C code in your
example.  For cases in which that doesn't work as cleanly, people can
also use Racket `#<<`...`#>>` "here strings" (or you can make a simple
special embedded reader, which could also be a cue to an editor/IDE to
treat as C code).

Reply all
Reply to author
Forward
0 new messages