guile-user
[Top][All Lists]
Advanced

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

Re: Bytestructures, FFI


From: Amirouche Boubekki
Subject: Re: Bytestructures, FFI
Date: Tue, 31 May 2016 22:13:32 +0200
User-agent: Roundcube Webmail/1.1.2

On 2016-05-31 21:29, address@hidden wrote:
Hi there,

I had announced this project a while ago, here:

  https://lists.gnu.org/archive/html/guile-user/2015-08/msg00034.html

I just added support for converting a bytestructure descriptor into a
type descriptor as per Guile's FFI module.

E.g. the uint8 descriptor in (bytestructures guile numeric) converts to
the value of the uint8 variable in the (system foreign) module, and a
struct descriptor such as (bs:struct `((x ,uint8) (y ,uint16))) converts
to what one would get from evaluating (list uint8 uint16) after
importing (system foreign).  (Such lists are accepted by Guile's FFI to
denote structs; it's yet undocumented in the manual.)

For convenience, a bs:pointer->proc procedure is offered, that wraps
pointer->procedure and adds bytestructure related functionality. Here's
a minimal example of how to use it:


--- start transcript ---

address@hidden:~/src/scheme/bytestructures$ cat test.c
typedef struct {
  struct {
    int x;
    float y;
  } s;
  int z;
  float t[3];
} foo_t;

foo_t testfunc(foo_t arg)
{
  ++arg.s.x;
  ++arg.s.y;
  ++arg.z;
  ++arg.t[0];
  ++arg.t[1];
  ++arg.t[2];
  return arg;
}
address@hidden:~/src/scheme/bytestructures$ gcc -shared -o libtest.so test.c
address@hidden:~/src/scheme/bytestructures$ sudo mv libtest.so /usr/lib/
address@hidden:~/src/scheme/bytestructures$ guile
GNU Guile 2.0.11
Copyright (C) 1995-2014 Free Software Foundation, Inc.

Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'.
This program is free software, and you are welcome to redistribute it
under certain conditions; type `,show c' for details.

Enter `,help' for help.
scheme@(guile-user)> (import (bytestructures guile))
scheme@(guile-user)> (import (bytestructures guile ffi))
scheme@(guile-user)> (define foo_t (bs:struct `((s ,(bs:struct `((x ,int) (y ,float32))))
                                                (z ,int)
(t ,(bs:vector 3 float32)))))

IMO This is a better example:

scheme@(guile-user)> (define contact_t (bs:struct `((address ,(bs:struct `((street_id ,int) (number ,int))))
                                                     (age ,int))))

Or something

scheme@(guile-user)> (define foo (bytestructure address_t '((address ((street 42) (number 12345)))
                                                            (age 66)))

scheme@(guile-user)> (bytestructure-ref address 'address 'street)
$1 = 42
scheme@(guile-user)> (bytestructure-ref address 'age)
$2 = 66


scheme@(guile-user)> (define testfunc
                       (bs:pointer->proc
                        foo_t  ;return value type
(dynamic-func "testfunc" (dynamic-link "libtest"))
                        (list foo_t)))  ;list of argument types

Why don't you use dynamic-link* signature like described in [1]:

  ((dynamic-link* [library-name]) return-type function-name . arguments)

[1] http://www.hyperdev.fr/notes/gnu-guile-ffi.html

scheme@(guile-user)> (define foo2 (testfunc foo))

isn't foo2 `equal?' to foo?


Neat, isn't it?


Awesome!


If test.c instead contained:

void testfunc(foo_t *arg)
{
  ++arg->s.x;
  ++arg->s.y;
  ++arg->z;
  ++arg->t[0];
  ++arg->t[1];
  ++arg->t[2];
}

(i.e. testfunc now takes a struct pointer and modifies it in-place)

then we could create our procedure like:

scheme@(guile-user)> (import (prefix (system foreign) ffi:))
scheme@(guile-user)> (define testfunc
                       (bs:pointer->proc
                        ffi:void
(dynamic-func "testfunc" (dynamic-link "libtest"))
                        (list '*)))

and things would work like this:

scheme@(guile-user)> (testfunc foo)
scheme@(guile-user)> (bytestructure-ref foo 's 'x)
$3 = 2
scheme@(guile-user)> (bytestructure-ref foo 't 1)
$4 = 2.0

Magic!


Note that while bytestructures supports unions and bit-fields, libffi
and therefore (system foreign) does not, so the above won't work yet for types in which unions or bitfields are involved. Unions can possibly be
supported with a little hack, which I'll look into later.

I have not yet made the semantics of bs:pointer->proc concrete, and it's
yet undocumented.  Feel free to ask me questions here or on Freenode
under the nick 'taylan'.  Comments are welcome too!

Taylan

--
Amirouche ~ amz3 ~ http://www.hyperdev.fr



reply via email to

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