At Fri, 31 Jul 2020 17:05:27 -0400, Hendrik Boom wrote:
> For example, there's glGetCompressedTexImageARB.  It receivees a 
> pointer to an image area and fills it in with a compressed image.
> According the the Racket C interface, the way to write this 
> would be:
> 
> (define-gl glGetCompressedTexImageARB 2 
>   ( (target : _int32)
>     (level : _int32) 
>     (img : _pointer/intptr)
>   -> _void -> img)
>  (->> exact-integer? exact-integer? gl-pointer?)
>  check-gl-error)

If I understand correctly that `target` and `level` provide enough
information to specify how big `img` should be, then I agree that
something analogous to

   (_fun
     (target : _int32)
     (level : _int32) 
     (img : _pointer/intptr = (malloc (COMPSIZE target level)))
    -> _void
    -> img)

is a fine way to wrap the function.

But when I work at the level of C APIs, I usually prefer this kind of
interface:

> But the old binding instead used
>  ( (target : _int32)
>    (level : _int32)
>    (img : _pointer/intptr)
>   -> _void)
> 
> In other words, it ignored the fact that img is used as an output 
> parameter.

Although, when I use this kind of binding, I have to know which
pointers must already be filled with information when I pass it to the
function versus which ones will be filled by the function, exposing the
pointer to to-be-filled memory gives me control over the way that the
memory. It also avoids having to specify anything about the
deallocation rules of the result of a binding (e.g., whether it needs
to be explicitly freed).

Still, I can also see the advantage of building allocation into the
wrapper to make clear that the argument corresponds to to-be-filled
memory.

Perhaps it depends on the overall shape of the API. If the API is going
to be wrapped further to make it more Rackety, then I'd go for less
wrapping at the immediate FFI bindings. If the API looks fairly Rackety
with a few tweaks to arguments and results, then I'd favor more
wrapping in the bindings. I think the old GL binding was in the former
camp: it first exposed GL functions in as raw as possible form, and
then wrapped those with a higher-level library.

> Now what should I do with this?  As I said there are very many such 
> functions.  It's not an isolated case.
> 
> Are all these glGet functions simply something that never happened to 
> get used in Racket code so no one noticed the discrepancy?
> Is there some idiom in Racket programming where all this just works 
> anyway?
> Is there some efficency reason for not recognising output parameters?
> Do they parhaps cause new storage allocation every time they are called?

I wouldn't say there's any "discrepancy" in `img` being an output
argument instead of an input argument. This kind of input--output
distinction doesn't exist at C ABI level, so no distinction is
inherently necessary in the FFI binding. Certainly, though, you can
create FFI wrappers that better reflect the intent of parameters than
the ABI-level types do.

You're right that exposing details like to-be-filled pointer arguments
usually offers the best available performance, but it's not always an
issue. This example looks like one where callers will practically
always allocate the destination memory just before calling the
function, so it will work out the same.


Matthew

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/20200801114806.1d8%40sirmail.smtps.cs.utah.edu.

Reply via email to