[plt-scheme] FFI and pointer manipulations
Eli Barzilay wrote:
>On Feb 11, Jens Axel Søgaard wrote:
>
>
>>Eli Barzilay wrote:
>>
>>
>>>On Feb 9, Jens Axel Søgaard wrote:
>>>
>>>
>>ould calculate the md5 of the 3 bytes 2 3 4.
>>
>>I can't figure out what to write instead of <cpointer-to-bs+2>.
>>
>>
>Here's an example of what you want -- I have this function in x.so:
>
> void foo(char *a) { printf("received %d: \"%s\"\n", (int)a, a); }
>
>and I do this interaction in MzScheme which should make it clear how
>to play with pointers:
>
> > (define p (get-ffi-obj "foo" "~/tmp/x.so" (_fun _pointer -> _void)))
> > (define buf #"0123456789")
> > (p buf)
> received 180307632: "0123456789"
> > (define tmp (malloc (max (ctype-sizeof _int) (ctype-sizeof _pointer))))
> > (ptr-set! tmp _pointer buf)
> > (ptr-ref tmp _int)
> 180307632
> > (ptr-set! tmp _int (+ 3 (ptr-ref tmp _int)))
> > (ptr-ref tmp _int)
> 180307635
>
>
Okay, got it.
>>>This is intentional. Having a pointer to the middle of a malloced
>>>object will not work right with 3m. In fact, I think that it may
>>>cause damage even if you use it in some harmless way. One way to
>>>deal with this would be to provide a kind of pointer-with-offset,
>>>and another would be to add a new kind of "dangerous pointer" type.
>>>Both will not be easy to understand and to use, and nothing is
>>>implemented yet.
>>>
>>>
>>It is the pointer-with-offset I need. In my case the C code doesn't
>>store the pointer, so it ought to be safe.
>>
>>
>
>The fact that C doesn't store the pointer is not too relevant -- you
>have to be very careful for everything that is done in Scheme code,
>because as long as you're there a GC can happen -- and in 3m this
>means that pointers are likely to change. Here's an example that
>demonstrates this:
>
>
Okay, that's why you mentioned the possibility of having an
pointer+offset type, so that
the FFI could be responsible for the pointer arithmetic.
>Moreover, according to what Matthew told me (which might not be true
>now), it can even make the GC crash because something it thinks is a
>pointer to a block of memory is actually pointing to the middle of a
>real object.
>
Yours and Matthew's post make it clear, that I can't use (bytes ...) to
allocate my byte
string, since 3m might move it. Can I instead use malloc with either the
mode 'eternal
or 'raw ? That is, is the following supposed to work?
(require (planet "digest.ss" ("soegaard" "digest.plt"))
(lib "foreign.ss"))
(unsafe!)
; allocate an unmovable array
(define unmovable-bytes (malloc 100 'eternal))
(define u unmovable-bytes)
; store #"abcde" into the array
(ptr-set! u _byte 'abs 0 (char->integer #\a))
(ptr-set! u _byte 'abs 1 (char->integer #\b))
(ptr-set! u _byte 'abs 2 (char->integer #\c))
(ptr-set! u _byte 'abs 3 (char->integer #\d))
(ptr-set! u _byte 'abs 4 (char->integer #\e))
; test, that the store worked
(md5 #"ab")
(md5 (make-sized-byte-string u 2))
; u+i : natural -> cpointer
; return pointer to the i'th byte of the array u
(define u+i
(let ([*u (malloc (max (ctype-sizeof _int) (ctype-sizeof _pointer)))])
(ptr-set! *u _pointer u)
(let* ([*u_int (ptr-ref *u _int)]
[*u+i (malloc (max (ctype-sizeof _int) (ctype-sizeof
_pointer)))])
(lambda (i)
(ptr-set! *u+i _int (+ *u_int i))
(ptr-ref *u+i _pointer)))))
; test whether u+i works
(md5 #"bc")
(md5 (make-sized-byte-string (u+i 1) 2))
--
Jens Axel Søgaard