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
next prev parent 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).