unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* ffi for glutInit
@ 2012-07-25 22:19 Aleix Conchillo Flaqué
  2012-07-26  2:30 ` Nala Ginrut
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Aleix Conchillo Flaqué @ 2012-07-25 22:19 UTC (permalink / raw)
  To: guile-devel

Hi,

I have started working on bindings for OpenGL and GLUT.

https://github.com/aconchillo/guile-gl

The work is very preliminar, which means I can't even show a window yet.

The scm files are semi-automatically generated by a python script that
uses pycparser. So that saved quite a lot of time.

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.

All other functions in glut.scm should work (at least they evaluate
fine), except the ones related to fonts. So I would say that glutInit
is the last one to have a basic program that runs OpenGL.

Thanks in advance,

Aleix



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ffi for glutInit
  2012-07-25 22:19 ffi for glutInit Aleix Conchillo Flaqué
@ 2012-07-26  2:30 ` Nala Ginrut
  2012-07-26 15:46   ` Aleix Conchillo Flaqué
  2012-07-26 16:33 ` Mark H Weaver
  2013-01-21 12:04 ` Andy Wingo
  2 siblings, 1 reply; 8+ messages in thread
From: Nala Ginrut @ 2012-07-26  2:30 UTC (permalink / raw)
  To: Aleix Conchillo Flaqué; +Cc: guile-devel

hi Aleix!
For our FFI system:
char** <==> '* <==> (quote *)

I'm not sure I understand your question correctly.
I assume that you want to know what's the presentation of char** for
dynamic-func.

On Thu, Jul 26, 2012 at 6:19 AM, Aleix Conchillo Flaqué
<aconchillo@gmail.com> wrote:
> Hi,
>
> I have started working on bindings for OpenGL and GLUT.
>
> https://github.com/aconchillo/guile-gl
>
> The work is very preliminar, which means I can't even show a window yet.
>
> The scm files are semi-automatically generated by a python script that
> uses pycparser. So that saved quite a lot of time.
>
> 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.
>
> All other functions in glut.scm should work (at least they evaluate
> fine), except the ones related to fonts. So I would say that glutInit
> is the last one to have a basic program that runs OpenGL.
>
> Thanks in advance,
>
> Aleix
>



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ffi for glutInit
  2012-07-26  2:30 ` Nala Ginrut
@ 2012-07-26 15:46   ` Aleix Conchillo Flaqué
  0 siblings, 0 replies; 8+ messages in thread
From: Aleix Conchillo Flaqué @ 2012-07-26 15:46 UTC (permalink / raw)
  To: Nala Ginrut; +Cc: guile-devel

On Wed, Jul 25, 2012 at 7:30 PM, Nala Ginrut <nalaginrut@gmail.com> wrote:
> hi Aleix!
> For our FFI system:
> char** <==> '* <==> (quote *)
>
> I'm not sure I understand your question correctly.
> I assume that you want to know what's the presentation of char** for
> dynamic-func.
>

Let me try again: how do I create a C array of strings in scheme?

I took define-foreign from guile-gdbm (thanks Ian!):

(define libglut (dynamic-link "libglut"))

(define-syntax-rule (define-foreign name ret string-name args)
  (define name
    (pointer->procedure ret (dynamic-func string-name libglut) args)))

Then, for glutInit I already use '* as you suggest:

(define-foreign %glutInit void "glutInit" '(list '* '*))

Finally, I implement (glutInit):

(define (glutInit)
  (%glutInit %null-pointer %null-pointer))

Which is obviously not working right now. I need to know how to create
char** to be given to %glutInit. I think I know it for the first
argument, which is  a int* (I'll use a struct with an int and then
make-c-struct and then get the pointer).

But, how to create char**?

I'll probably go into this again in a couple of days, I feel like a
truck has ran over me today.

Best,

Aleix



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ffi for glutInit
  2012-07-25 22:19 ffi for glutInit Aleix Conchillo Flaqué
  2012-07-26  2:30 ` Nala Ginrut
@ 2012-07-26 16:33 ` Mark H Weaver
  2012-07-26 16:39   ` Mark H Weaver
  2012-08-04 16:19   ` Aleix Conchillo Flaqué
  2013-01-21 12:04 ` Andy Wingo
  2 siblings, 2 replies; 8+ messages in thread
From: Mark H Weaver @ 2012-07-26 16:33 UTC (permalink / raw)
  To: guile-devel

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




^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ffi for glutInit
  2012-07-26 16:33 ` Mark H Weaver
@ 2012-07-26 16:39   ` Mark H Weaver
  2012-07-26 18:07     ` Nala Ginrut
  2012-08-04 16:19   ` Aleix Conchillo Flaqué
  1 sibling, 1 reply; 8+ messages in thread
From: Mark H Weaver @ 2012-07-26 16:39 UTC (permalink / raw)
  To: guile-devel

Sorry, the indentation of my example code got messed up by tabs.
Here it is again:

   (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)))

      Mark




^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ffi for glutInit
  2012-07-26 16:39   ` Mark H Weaver
@ 2012-07-26 18:07     ` Nala Ginrut
  0 siblings, 0 replies; 8+ messages in thread
From: Nala Ginrut @ 2012-07-26 18:07 UTC (permalink / raw)
  To: Mark H Weaver, Aleix Conchillo Flaqué; +Cc: guile-devel

Hmm...Mark you enlightened me how to deal with 2 dimension array with
pure Guile code. thanks!
But I'll suggest Aleix to handle this issue with C code which is
easier.  Anyway, we don't have to do all the things with Guile code
since Guile is designed to interact with C code. We just choose the
way we like.
I think the principle is the same:
---------------pseudo code-----------------
// ac is integer ,av is a list of strings
SCM  scm_glut_init (SCM ac ,SCM av)
{
  int *argc = scm_gc_malloc(sizeof(int) ,"glut-init-argc");
  char **argv = NULL;
  SCM p;
  int i = 0;

  *argc = scm_to_int(ac);
  for(p = scm_car(av) ;i < *argc ;i++ ,p = scm_cdr(p))
   {
      argv[i] = scm_to_locale_string(p);
   }

  argv[*argc] = NULL;
  glut_init(argc ,argv);

  return SCM_UNSPECIFIED;
}
---------------end------------------

PS: I didn't guarantee the code above can be used directly, just
describe the principle.

On Fri, Jul 27, 2012 at 12:39 AM, Mark H Weaver <mhw@netris.org> wrote:
> Sorry, the indentation of my example code got messed up by tabs.
> Here it is again:
>
>
>   (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)))
>
>      Mark
>
>



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ffi for glutInit
  2012-07-26 16:33 ` Mark H Weaver
  2012-07-26 16:39   ` Mark H Weaver
@ 2012-08-04 16:19   ` Aleix Conchillo Flaqué
  1 sibling, 0 replies; 8+ messages in thread
From: Aleix Conchillo Flaqué @ 2012-08-04 16:19 UTC (permalink / raw)
  To: Mark H Weaver; +Cc: guile-devel

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 <mhw@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
>
>



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ffi for glutInit
  2012-07-25 22:19 ffi for glutInit Aleix Conchillo Flaqué
  2012-07-26  2:30 ` Nala Ginrut
  2012-07-26 16:33 ` Mark H Weaver
@ 2013-01-21 12:04 ` Andy Wingo
  2 siblings, 0 replies; 8+ messages in thread
From: Andy Wingo @ 2013-01-21 12:04 UTC (permalink / raw)
  To: Aleix Conchillo Flaqué; +Cc: guile-devel

On Thu 26 Jul 2012 00:19, Aleix Conchillo Flaqué <aconchillo@gmail.com> writes:

> I have started working on bindings for OpenGL and GLUT.
>
> https://github.com/aconchillo/guile-gl

This looks really neat :)

You know, I was thinking of generating a binding based on the XML
documentation that they provide:

  https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/docs/man3/glActiveTexture.xml

It seems that you could even give the parameters nice names and generate
a docstring and all kinds of nice things.

Idle thoughts, though.  Until then your binding looks quite nice!

Andy
-- 
http://wingolog.org/



^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2013-01-21 12:04 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-07-25 22:19 ffi for glutInit Aleix Conchillo Flaqué
2012-07-26  2:30 ` Nala Ginrut
2012-07-26 15:46   ` Aleix Conchillo Flaqué
2012-07-26 16:33 ` Mark H Weaver
2012-07-26 16:39   ` Mark H Weaver
2012-07-26 18:07     ` Nala Ginrut
2012-08-04 16:19   ` Aleix Conchillo Flaqué
2013-01-21 12:04 ` Andy Wingo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).