The short answer is: `(_ptr io _VkInstance)` does not mean that a
pointer to a `_VkInstance` happens on the Racket side. It means that a
`_VkInstance` (not a pointer to a `_VkInstance`) happens on the Racket
side, and a pointer to a `_VkInstance` happens on the C side.

Taking it from the top:

At Mon, 21 Oct 2019 19:07:40 +0000, Sage Gerard wrote:
> (define _VkInstance (_cpointer 'VkInstance_T))

So far, so good. `VkInstance` is defined in Vulkan to be a pointer to
unspecified memory, so this makes sense.

To be clear,

 (malloc _VkInstance)

does not create a `_VkInstance`. It creates a pointer to a
`_VkInstance` (i.e., a pointer to a pointer). That could be what you
want, depending on how `vkCreateInstance` is defined. Specifically, to
make this work:

 (define instance-ptr (malloc _VkInstance))

 (vkCreateInstance instcreateinfo #f instance-ptr)

 (define created-instance (ptr-ref instance-ptr _VkInstance))

Define `vkCreateInstance` like this:

 (define-vulkan vkCreateInstance
    (_fun _VkInstanceCreateInfo-pointer/null
          _VkAllocationCallbacks-pointer/null
          _pointer ; to a _VkInstance
          -> (r : _VkResult)
          -> (check-vkResult r 'vkCreateInstance)))

I've written the third type as just `_pointer` because there's not a
simple way to say "pointer to a `_VkInstance`". There's no way to write
that because it would offer no more checking than just `_pointer`. It
might be a little better to write the comment as a `define`:

 (define _VkInstance-pointer _pointer)

 (define-vulkan vkCreateInstance
    (_fun _VkInstanceCreateInfo-pointer/null
          _VkAllocationCallbacks-pointer/null
          _VkInstance-pointer
          -> (r : _VkResult)
          -> (check-vkResult r 'vkCreateInstance)))

You could go further and write

  ;; pointer to a `_VkInstance`:
  (define _VkInstance-pointer (_cpointer 'VkInstance_T*))

  (define-vulkan vkCreateInstance
    (_fun _VkInstanceCreateInfo-pointer/null
          _VkAllocationCallbacks-pointer/null
          _VkInstance-pointer
          -> (r : _VkResult)
          -> (check-vkResult r 'vkCreateInstance)))

  (define instance-ptr (malloc _VkInstance))
  (cpointer-push-tag! instance-ptr 'VkInstance_T*)
  (vkCreateInstance instcreateinfo #f instance-ptr)
  (define created-instance (ptr-ref instance-ptr _VkInstance))

That's probably more trouble than it's worth, and the checking benefits
depend on `malloc` and `cpointer-push-tag!` begin used consistently
together. Declaring `_VkInstance-pointer` could make sense if the
library provides a `make-VkInstance-pointer` function to combine the
`malloc` and `cpointer-push-tag!` steps, helping to make sure they're
always consistent.


Instead of `_pointer` or `_VkInstance-pointer`, you've written

   (_ptr io _VkInstance)

As an argument type, that means:

 * The caller supplies a `_VkInstance` (not a pointer to a `VkInstance`).

 * Fresh memory for a `_VkInstance` is allocated.

 * The given `_VkInstance` is copied into the fresh memory.

 * The address of the fresh memory is passed to the foreign function as
   a pointer to a `_VkInstance`.

So, you're seeing an error because `(malloc _VkInstance)` does not
create a `_VkInstance`. Anyway, this is not what you want, because
`vkCreateInstance` would set the pointer at the fresh memory, which is
then discarded.

Generally, a `(_ptr io ...)` argument without a name binding doesn't
make any sense --- unless you really want to ignore the result (which
you don't, in this case).


It's pretty typical for "middleware" layers like the FFI to take into
account the in--out behavior of function arguments, and that's why many
C prototype descriptions are augmented with that information. The
`ffi/unsafe` layer is meant to be used that way, too, so the
translation that works best for `ffi/unsafe` is

  (define-vulkan vkCreateInstance
    (_fun _VkInstanceCreateInfo-pointer/null
          _VkAllocationCallbacks-pointer/null
          (o : (_ptr o _VkInstance))
          -> (r : _VkResult)
          -> (begin
               (check-vkResult r 'vkCreateInstance)
                o)))

because the third argument is an out argument.

If you don't make to make these in--out distinctions, then the first or
second definition of `vkCreateInstance` above is the most practical
choice.

-- 
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/5daf041b.1c69fb81.5359b.b097SMTPIN_ADDED_MISSING%40mx.google.com.

Reply via email to