[plt-scheme] Problem with FFI functions returning pointers to 'C' functions

From: Tim Brown (tim.brown at cityc.co.uk)
Date: Wed Sep 12 09:07:07 EDT 2007

I've revisited my problem, and I have got a little further
(in fact a solution I can work with).

On 12/09/07 10:10, Tim Brown wrote:
> A more concrete example is setting a signal(3C) call:
> 
> (require (lib "foreign.ss"))
> (unsafe!)
> (define c-signal
>   (get-ffi-obj "signal" #f (_fun _int (_fun _int -> _void) ->
>                                (_fun _int -> _void))))
> (c-signal 15 (lambda (f) #f))
> 
> However, when I run this on: MzScheme v370 [3m]
> SunOS 5.10 x86 or even Linux
> 
> I get the following error:
> ffi-call: expects type <non-null-cpointer> as 1st argument, given: #f;
> other arguments were: (#<ctype>) #<ctype>

This error is caused by the signal function returning a NULL pointer.
Since no signal handler is initially installed for 15 in this case,
a NULL is returned.

Why is the error reported by ffi-call, and not whatever it is that
objected to the #f in the first place?

Anyway, I am returning a _fpointer, and only casting it (with ptr-set)
to an (_fun _int -> _void) if it is (not #f).

Oh, and this is were I come across another problem... if I cast the
pointer to (_fun _int -> _void), I get a:
"Scheme->C: expects argument of type <int32>; given #<void>" when I
call it.

This seems to be a manifestation of the bug described in:
http://www.cs.brown.edu/pipermail/plt-scheme/2005-May/008797.html
"Questions about modules, compilation, namespaces, planet and ffi"

If I mis-declare these callback functions to be returning _int, and
ignore the results, I can get things to work as I wish.

Could someone comment on whether there is a better way to express the
following.

(require (lib "foreign.ss"))
(unsafe!)
(define signal-handler-ptr (_cprocedure (list _int) _int))
(define signal-handler-ptr/null _fpointer)
(define c-signal (get-ffi-obj "signal" #f
   (_fun _int signal-handler-ptr -> signal-handler-ptr/null)))

(define old-signal-handler #f)
(set! old-signal-handler
   (c-signal 15 (lambda (i) (printf "first set callback ~a~%" i) 0)))

(set! old-signal-handler
   (c-signal 15
     (lambda (i)
       (printf "second set callback~%")
       (if old-signal-handler
         ((ptr-ref old-signal-handler signal-handler-ptr) i))
        0)))


I'm not actually using this for signal handling, I'm just using
this as a means to illustrate callbacks.

Regards,

Tim

-- 
Tim Brown <tim.brown at cityc.co.uk>  | City Computing Limited            |
T: +44 20 8770 2110                | City House, Sutton Park Road      |
F: +44 20 8770 2130                | Sutton, Surrey, SM1 2AE, GB       |
-----------------------------------------------------------------------|
BEAUTY:  What's in your eye when you have a bee in your hand           |
-----------------------------------------------------------------------'
City Computing Limited registered in London No. 1767817.
Registered Office: City House, Sutton Park Road, Sutton, Surrey, SM1 2AE
VAT number 372 8290 34.


Posted on the users mailing list.