guile-user
[Top][All Lists]
Advanced

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

Re: how to access c-array member in c-structure?


From: Park SungMin
Subject: Re: how to access c-array member in c-structure?
Date: Thu, 31 Mar 2016 12:02:53 +0900


Thank you!! this library is very good solution for me!
It seems very useful.


On Mar 31, 2016, at 4:54 AM, Taylan Ulrich Bayırlı/Kammer <address@hidden> wrote:

Park SungMin <address@hidden> writes:

If I understood Park SungMin right, the problem is rather with the
representation of a huge array as a list?

correct! (sorry..my poor english)

I think huge c-array should be representation as bytevector or pointer
object.

(define type (list int (make-list 10 int)))

(define struct (make-c-struct type (list 42 (make-list 10 42))))

(parse-c-struct struct (list int '*))
=> (42 #<pointer 0x2a0000002a>)

but….when i access to that pointer object
(pointer->bytevector (cadr (parse-c-struct struct (list int '*)))
     (* 10 (sizeof int)))

=> shutdown guile!

I see.  The problem here is, a struct like

   struct {
     int a;
     int b;
     int c[2000];
   } foo;

declares a memory region of 2002 consecutive ints, whereas

   struct {
     int a;
     int b;
     int *c;
   } bar;

declares a memory region of two consecutive ints followed by one
pointer.  These are not the same thing.  The C language partly upholds
an illusion that they're same because "foo.c" implicitly returns a
pointer to the first integer in the array (i.e. the third integer in the
struct, after a and b).  On the other hand, "bar.c" returns the pointer
value that's stored in the struct.

When we tell Guile to treat foo like bar, it takes an int from the array
and treats it like a pointer.  So dereferencing it segfaults.

I don't know what a simple solution would be.

My bytestructures library *might* help, though it's not properly
integrated with the FFI yet.

   https://github.com/taylanub/scheme-bytestructures

Here's an example of how to use it in this case:

|> ,use (system foreign)
|> (define type (list int int (make-list 2000 int)))
|> (define struct (make-c-struct type (list 1 2 (make-list 2000 3))))
|> ,use (bytestructures guile)
|> (define bs-type (bs:struct `((a ,int) (b ,int) (c ,(bs:vector 2000 int)))))
WARNING: (guile-user): `int' imported from both (system foreign) and (bytestructures guile)
|> (define size (bytestructure-descriptor-size bs-type))
|> (define bs-struct
    (make-bytestructure (pointer->bytevector struct size) 0 bs-type))
|> (bytestructure-ref bs-struct 'a)
$2 = 1
|> (bytestructure-ref bs-struct 'b)
$3 = 2
|> (bytestructure-ref bs-struct 'c 0)
$5 = 3
|> (bytestructure-ref bs-struct 'c 1)
$6 = 3
|> (bytestructure-ref bs-struct 'c 2)
$7 = 3

As you see in the warning, the bytestructures library overrides some
variables of Guile's FFI library.  I usually import the FFI library with

   (use-modules ((system foreign) #:prefix ffi:))

to work around that issue.  (So now the original int is "ffi:int".)

I don't know if the library is ideal for your use-case, but if you
decide to use it or want to try it out, ask for help any time. :-)

Taylan


reply via email to

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