unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
From: Amirouche Boubekki <amirouche@hypermove.net>
To: taylanbayirli@gmail.com
Cc: guile-user@gnu.org,
	guile-user <guile-user-bounces+amirouche=hypermove.net@gnu.org>
Subject: Re: Bytestructures, FFI
Date: Tue, 31 May 2016 22:13:32 +0200	[thread overview]
Message-ID: <c465d7bc7d8fff5a8a0617f433ad0761@hypermove.net> (raw)
In-Reply-To: <87oa7mauvd.fsf@T420.taylan>

On 2016-05-31 21:29, taylanbayirli@gmail.com 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 ---
> 
> taylan@T420:~/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;
> }
> taylan@T420:~/src/scheme/bytestructures$ gcc -shared -o libtest.so 
> test.c
> taylan@T420:~/src/scheme/bytestructures$ sudo mv libtest.so /usr/lib/
> taylan@T420:~/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	other threads:[~2016-05-31 20:13 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-31 19:29 Bytestructures, FFI Taylan Ulrich Bayırlı/Kammer
2016-05-31 20:13 ` Amirouche Boubekki [this message]
2016-05-31 21:07   ` Taylan Ulrich Bayırlı/Kammer
2016-06-01 21:40 ` Ludovic Courtès
2016-06-02  0:07   ` Taylan Ulrich Bayırlı/Kammer
2016-06-02  7:04     ` Ludovic Courtès

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c465d7bc7d8fff5a8a0617f433ad0761@hypermove.net \
    --to=amirouche@hypermove.net \
    --cc=guile-user-bounces+amirouche=hypermove.net@gnu.org \
    --cc=guile-user@gnu.org \
    --cc=taylanbayirli@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).