Thank you both guys. Mark's code works perfectly, I can open a window with glut and make some gl code work, great!
However, after your recommendations I've started with the wrapper in C, let's see how far I get. Thanks, Aleix On Thu, Jul 26, 2012 at 9:33 AM, Mark H Weaver <m...@netris.org> wrote: > On 07/25/2012 06:19 PM, Aleix Conchillo Flaqué wrote: >> >> I have started working on bindings for OpenGL and GLUT. >> >> https://github.com/aconchillo/guile-gl > > > Excellent! :-) > > >> Now, I'm stuck with glutInit. The signature of the function is like this: >> >> glutInit(int *argc, char **argv); >> >> See: http://www.opengl.org/resources/libraries/glut/spec3/node10.html >> >> I don't really know how to do the char** part, so I need some help here. >> >> For the user, the guile procedure will simply look like (glutInit) and >> internally (command-line) would be ideally used to construct the >> char**, etc. > > > First of all, I should mention that although the dynamic FFI is very > convenient, it is not necessarily the best way to write a robust and > efficient library wrapper. Most notably, things like preprocessor macros > are not handled by the FFI, and there is currently a non-trivial overhead > for each call through the FFI. This overhead arises because the FFI does > not generate native code wrappers, but instead each wrapper has a loop that > iterates over the list of arguments and argument types, and constructs the > stack frame one argument at a time before calling the C function. This is > probably not significant in most cases, but for small and fast C functions > that might be used within an inner loop with a high iteration count, you'd > probably want to write the wrapper in C. > > In this case, we have the problem that libffi, which is the basis for > Guile's dynamic FFI, does not support array types. However, in practice we > can pretend that arrays and structs have the same layout, and I suspect that > this works on most architectures. Here's one way to do it: > > (use-modules (system foreign)) > > (define libglut-obj (dynamic-link "libglut")) > > ;; (glut-init args), where args is the complete list of command > ;; arguments (starting with the program name), calls glutInit and > ;; returns the (possibly) modified list of arguments. > (define glut-init > (let ((foo-init-raw (pointer->procedure > void > (dynamic-func "glutInit" libglut-obj) > (list '* '*))) > (saved-c-strings '())) > (lambda (args) > (let* ((num-args (length args)) > (c-strings (map string->pointer args)) > (argcp (make-c-struct (list int) > (list num-args))) > (argv (make-c-struct (make-list (+ 1 num-args) '*) > (append c-strings > (list %null-pointer))))) > (set! saved-c-strings (append c-strings saved-c-strings)) > (foo-init-raw argcp argv) > (let ((argc (car (parse-c-struct argcp (list int))))) > (map pointer->string > (parse-c-struct argv > (make-list argc '*)))))))) > > ;; Example usage > (set-program-arguments (glut-init (program-arguments))) > > Note the use of 'saved-c-strings' to keep a reference to all of the C string > buffers that we ever pass to 'glutInit'. This is important because the glut > docs specify that 'glutInit' wants the original unmodified 'argv' passed to > 'main', which means that it can assume that the strings will never be freed. > 'string->pointer' returns a C string buffer managed by the garbage > collector, which means that the string may be freed unless the GC can see a > pointer to the _beginning_ of the string. > > Happy hacking! > > Mark > >