[gambit-list] Structs in FFI

Ken Dickey Ken.Dickey at whidbey.com
Fri Jul 25 14:03:48 EDT 2008


Hi,

There is and example of getting struct parameters in the current GUI-Toy 
version in "sdl-interface.scm".

=============IN PROCESS FYI================
[YOU CAN SKIP THIS]

FYI, one of the things I am looking at is the difference between direct FFI 
calls and using a pipe to a sub-process.  The "pipe" interface allows for 
rapid porting (currently GUI-Toy runs on Gambit, Larceny, PLT, Ypsilon, Chez, 
and Ikarus Schemes).

To make adding calls easy, I have started a declarative "FFI" which writes 
both the Scheme and C code.

(describe-interface
;   ...
(describe-call 
  (Scheme SDL::load-bmp-file 
          (file-name-string char*))
  (C     "SDL_LoadBMP" 
     (file-name-string) 
     (pointer "SDL_Surface")))

(describe-c-struct SDL_Rect
    (x Sint16) (y Sint16) 
    (w Uint16) (h Uint16))

(describe-access (SDL_Rect rectangle?)
; (c-field-name scheme-getter-name) ...
  (x x) (y y) (w width) (h height))

(describe-call
 (Scheme SDL::draw-rect
       (surface (pointer "SDL_Surface"))
       (rect (access rectangle? SDL_Rect))
       (rgb-color Uint32))
 (C      "SDL_FillRect"
       (surface rect rgb-color) void))
;...
)

The generated Scheme code does basic error checks and reporting, puts out a 
shared call tag/id, and accesses object fields to "spread" the values for 
the "call".

(define (SDL::draw-rect surface rect rgb-color)

  (unless (Uint32? surface)
     (report-arg-check-error 
          'SDL::draw-rect 'surface 'Uint32?))
  (unless (rectangle? rect)
     (report-arg-check-error 
          'SDL::draw-rect 'rect 'rectangle?))
  (unless (Uint32? rgb-color)
     (report-arg-check-error 
          'SDL::draw-rect 'rgb-color 'Uint32?))

  (put-Uint8 port->sdl 34) ; call tag
  (put-Uint32 port->sdl surface)
  (put-Sint16 port->sdl [$ x rect])
  (put-Sint16 port->sdl [$ y rect])
  (put-Uint16 port->sdl [$ width rect])
  (put-Uint16 port->sdl [$ height rect])
  (put-Uint32 port->sdl rgb-color)
  (flush-output-port port->sdl)
)


The generated C code dispatches on the call tag, stack allocates temporaries,
makes the SDL call, and returns a result as required. 

case (char)(34):
{ /* SDL::draw-rect -> SDL_FillRect */
   unsigned char buf[16];
   read(fileno(stdin), buf, 16);
   int offset = 0 ;
         
   /* surface */
   Uint32 surface
          = getUint32( buf, offset ) ;
          offset += sizeof( Uint32 ) ;
   /* rect */
   SDL_Rect rect ;
   rect.x = getSint16(buf, offset) ;
          offset += sizeof( Sint16 ) ;
   rect.y = getSint16(buf, offset) ;
          offset += sizeof( Sint16 ) ;
   rect.w = getUint16(buf, offset) ;
          offset += sizeof( Uint16 ) ;
   rect.h = getUint16(buf, offset) ;
          offset += sizeof( Uint16 ) ;
   /* rgb-color */
   Uint32 rgb_color 
          = getUint32( buf, offset ) ;
          offset += sizeof( Uint32 ) ;
         
   SDL_FillRect( (SDL_Surface*)(surface), 
                 &(rect), 
                 rgb_color ); 
}
break;

I hope at some point to gen both "Scheme native" FFI and the "pipe call" 
interface.  NYI.

This is all stuff in progress, not ready for prime time, but may give you some 
ideas.  I plan to report on things at the upcoming Scheme Workshop in 
Victoria, BC.  If you happen to get there, perhaps we can chat.

Cheers,
-KenD



More information about the Gambit-list mailing list