[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: ffi for glutInit

From: Aleix Conchillo Flaqué
Subject: Re: ffi for glutInit
Date: Sat, 4 Aug 2012 09:19:17 -0700

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.



On Thu, Jul 26, 2012 at 9:33 AM, Mark H Weaver <address@hidden> wrote:
> On 07/25/2012 06:19 PM, Aleix Conchillo Flaqué wrote:
>> I have started working on bindings for OpenGL and GLUT.
> Excellent! :-)
>> Now, I'm stuck with glutInit. The signature of the function is like this:
>> glutInit(int *argc, char **argv);
>> See:
>> 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

reply via email to

[Prev in Thread] Current Thread [Next in Thread]