Recently (this morning) I began using Gambit Scheme, and so far it has been a wonderful language to work with. I like doing graphical stuff, so I'm trying to use Gambit's FFI to interface with the SDL libraries. I've gotten everything to work so far, compiling and linking with libSDL from within gsc properly, but now I have two questions.
One, is there any way to specify, in comments or some such, what compiler and linker flags a file should have in a call to compile-file? I'm using emacs as an editor, and the C-c C-k command is useless, since the file won't get linked to libSDL like it needs to. This is really only a minor issue though, as
(begin (compile-file "sdl-test" ld-options: "-lSDL") (load "sdl-test"))
is not too hard to use.
Two, am I missing something when it comes to interfacing with C structs? The only references that I've found (http://dynamo.iro.umontreal.ca/~gambit/wiki/index.php/Using_Gambit_with_Exte...) and (http://www.iro.umontreal.ca/~gambit/doc/gambit-c.html#SEC135) seem to contain horrendously complex code for something as simple as accessing a struct like
typedef struct SDL_Rect { Sint16 x, y; Uint16 w, h; } SDL_Rect;
from within Scheme. Does anyone with more experience than I have some pointers on how to do this?
Afficher les réponses par date
Will Donnelly wrote:
Recently (this morning) I began using Gambit Scheme, and so far it has been a wonderful language to work with. I like doing graphical stuff, so I'm trying to use Gambit's FFI to interface with the SDL libraries. I've gotten everything to work so far, compiling and linking with libSDL from within gsc properly, but now I have two questions.
One, is there any way to specify, in comments or some such, what compiler and linker flags a file should have in a call to compile-file? I'm using emacs as an editor, and the C-c C-k command is useless, since the file won't get linked to libSDL like it needs to.
Er, not too sure about that one...
Two, am I missing something when it comes to interfacing with C structs? The only references that I've found (http://dynamo.iro.umontreal.ca/~gambit/wiki/index.php/Using_Gambit_with_Exte...) and (http://www.iro.umontreal.ca/~gambit/doc/gambit-c.html#SEC135) seem to contain horrendously complex code for something as simple as accessing a struct like
typedef struct SDL_Rect { Sint16 x, y; Uint16 w, h; } SDL_Rect;
from within Scheme. Does anyone with more experience than I have some pointers on how to do this?
I'd first like to point out to you that a really nice but incomplete binding to SDL has already been written by Ken Dickey and can be obtained on the gambit code dumping ground (http://dynamo.iro.umontreal.ca/~gambit/wiki/index.php/Dumping_Grounds).
I don't know what is best to do when you need to deal with structs, as it is no very friendly to do so in gambit's ffi. What i usually to would be to have some c-lambda's that will get what I need to be done. Ex:
(define SDL_Rect:x (c-lambda ((pointer "SDL_Rect")) int16 "___result = ___arg1.x;"))
(define SDL_Rect:x-set! (c-lambda ((pointer "SDL_Rect") int16) void "___arg1.x = ___arg2;"))
etc...
This sure is a bit of a pain, and I know there are better ways to do this, but they are too much unfriendly for me to use them.
Hope it helped!
David
Two, am I missing something when it comes to interfacing with C structs?
I don't know what is best to do when you need to deal with structs, as it is no very friendly to do so in gambit's ffi. What i usually to would be to have some c-lambda's that will get what I need to be done. Ex:
(define SDL_Rect:x (c-lambda ((pointer "SDL_Rect")) int16 "___result = ___arg1.x;"))
(define SDL_Rect:x-set! (c-lambda ((pointer "SDL_Rect") int16) void "___arg1.x = ___arg2;"))
etc...
This sure is a bit of a pain, and I know there are better ways to do this, but they are too much unfriendly for me to use them.
Gambit's FFI is pretty scary at first, because it's basically a low- level mechanism for creating your own FFI's. I think most people write a bunch of macros that generate c-lambda's for them. For example, you can write a `define-c-struct' macro that generates the appropriate c-lambda's to access structures. There's probably one on the mailing list somewhere.
This macro would be used like:
(define-c-struct vector (x int) (y int))
and would generate something like (untested):
(c-define-type vector (pointer (struct "vector")))
(define make-vector (c-lambda (int int) vector #<<end-code struct vector *v = (struct vector *)malloc(sizeof(struct vector)); v->x = ___arg1; v->y = ___arg2; ___result = v; end-code))
(define vector-x (c-lambda (vector) int "___return = ___arg1->x")) (define vector-x-set (c-lambda (vector int) vector "___arg1->x = ___arg2; ___return = ___arg1;"))
(define vector-y (c-lambda (vector) int "___return = ___arg1->y")) (define vector-y-set (c-lambda (vector int) vector "___arg1->y = ___arg2; ___return = ___arg1;"))
I think there's a way to make Gambit cleanup the object when the `foreign' object representing it in scheme land is destructed. Look through the FFI's on the dumping grounds and through the mailing list, and you'll probably find some good code to work with the FFI.
Should there be a standard way of doing this in Gambit? Probably. FFI extensions are on the wish list.
-James