Hi Matthew,

Wow! Thank you for the detailed response, and the saintly patience behind it.

In following your email, this is the working result after using '_pointer' in 
the function signature:

  (define instance-ptr (malloc _VkInstance))
  (vkCreateInstance instcreateinfo #f instance-ptr)
  (define instance (ptr-ref instance-ptr _VkInstance))
  (vkDestroyInstance instance #f)


My confusion did indeed stem from not understanding how pointer indirection was 
modeled in Racket. I was distracted by questions like "What's the address-of 
operator equivalent?" while staring at the arguments to the wrapper procedures.

I still prefer this form for the unsafe layer because of its faithful 
representation of Vulkan. This is not at all to discount your advice for using 
_ptr as the best working translation. The spec supports a view where I can 
generate a second layer of helpful wrapper procedures that use the first, as 
opposed to generating the most tailored wrapper procedure at the first 
oppurtunity.

Thank you again. I know you didn't have to take the time, so it means a lot to 
me that you did. Hopefully I won't end up confused again. :)

~slg

‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On Tuesday, October 22, 2019 9:28 AM, Matthew Flatt <mfl...@cs.utah.edu> wrote:

&gt; The short answer is: `(_ptr io _VkInstance)` does not mean that a
&gt; pointer to a `_VkInstance` happens on the Racket side. It means that a
&gt; `_VkInstance` (not a pointer to a `_VkInstance`) happens on the Racket
&gt; side, and a pointer to a `_VkInstance` happens on the C side.
&gt;
&gt; Taking it from the top:
&gt;
&gt; At Mon, 21 Oct 2019 19:07:40 +0000, Sage Gerard wrote:
&gt;
&gt; &gt; (define _VkInstance (_cpointer 'VkInstance_T))
&gt;
&gt; So far, so good.`VkInstance` is defined in Vulkan to be a pointer to
&gt; unspecified memory, so this makes sense.
&gt;
&gt; To be clear,
&gt;
&gt; (malloc _VkInstance)
&gt;
&gt; does not create a `_VkInstance`. It creates a pointer to a
&gt; `_VkInstance` (i.e., a pointer to a pointer). That could be what you
&gt; want, depending on how `vkCreateInstance` is defined. Specifically, to
&gt; make this work:
&gt;
&gt; (define instance-ptr (malloc _VkInstance))
&gt;
&gt; (vkCreateInstance instcreateinfo #f instance-ptr)
&gt;
&gt; (define created-instance (ptr-ref instance-ptr _VkInstance))
&gt;
&gt; Define `vkCreateInstance` like this:
&gt;
&gt; (define-vulkan vkCreateInstance
&gt; (_fun _VkInstanceCreateInfo-pointer/null
&gt; _VkAllocationCallbacks-pointer/null
&gt; _pointer ; to a _VkInstance
&gt; -&gt; (r : _VkResult)
&gt;
&gt;           -&gt; (check-vkResult r 'vkCreateInstance)))
&gt;
&gt;
&gt; I've written the third type as just`_pointer` because there's not a
&gt; simple way to say "pointer to a `_VkInstance`". There's no way to write
&gt; that because it would offer no more checking than just `_pointer`. It
&gt; might be a little better to write the comment as a `define`:
&gt;
&gt; (define _VkInstance-pointer _pointer)
&gt;
&gt; (define-vulkan vkCreateInstance
&gt; (_fun _VkInstanceCreateInfo-pointer/null
&gt; _VkAllocationCallbacks-pointer/null
&gt; _VkInstance-pointer
&gt; -&gt; (r : _VkResult)
&gt;
&gt;           -&gt; (check-vkResult r 'vkCreateInstance)))
&gt;
&gt;
&gt; You could go further and write
&gt;
&gt; ;; pointer to a `_VkInstance`:
&gt; (define _VkInstance-pointer (_cpointer 'VkInstance_T*))
&gt;
&gt; (define-vulkan vkCreateInstance
&gt; (_fun _VkInstanceCreateInfo-pointer/null
&gt; _VkAllocationCallbacks-pointer/null
&gt; _VkInstance-pointer
&gt; -&gt; (r : _VkResult)
&gt;
&gt;           -&gt; (check-vkResult r 'vkCreateInstance)))
&gt;
&gt;
&gt; (define instance-ptr (malloc _VkInstance))
&gt; (cpointer-push-tag! instance-ptr 'VkInstance_T*)
&gt; (vkCreateInstance instcreateinfo #f instance-ptr)
&gt; (define created-instance (ptr-ref instance-ptr _VkInstance))
&gt;
&gt; That's probably more trouble than it's worth, and the checking benefits
&gt; depend on `malloc` and `cpointer-push-tag!` begin used consistently
&gt; together. Declaring `_VkInstance-pointer` could make sense if the
&gt; library provides a `make-VkInstance-pointer` function to combine the
&gt; `malloc` and `cpointer-push-tag!` steps, helping to make sure they're
&gt; always consistent.
&gt;
&gt; Instead of `_pointer` or `_VkInstance-pointer`, you've written
&gt;
&gt; (_ptr io _VkInstance)
&gt;
&gt; As an argument type, that means:
&gt;
&gt; -   The caller supplies a `_VkInstance` (not a pointer to a `VkInstance`).
&gt;
&gt; -   Fresh memory for a `_VkInstance` is allocated.
&gt;
&gt; -   The given `_VkInstance` is copied into the fresh memory.
&gt;
&gt; -   The address of the fresh memory is passed to the foreign function as
&gt;     a pointer to a `_VkInstance`.
&gt;
&gt;     So, you're seeing an error because `(malloc _VkInstance)` does not
&gt;     create a `_VkInstance`. Anyway, this is not what you want, because
&gt;     `vkCreateInstance` would set the pointer at the fresh memory, which is
&gt;     then discarded.
&gt;
&gt;     Generally, a `(_ptr io ...)` argument without a name binding doesn't
&gt;     make any sense --- unless you really want to ignore the result (which
&gt;     you don't, in this case).
&gt;
&gt;     It's pretty typical for "middleware" layers like the FFI to take into
&gt;     account the in--out behavior of function arguments, and that's why many
&gt;     C prototype descriptions are augmented with that information. The
&gt;     `ffi/unsafe` layer is meant to be used that way, too, so the
&gt;     translation that works best for `ffi/unsafe` is
&gt;
&gt;     (define-vulkan vkCreateInstance
&gt;     (_fun _VkInstanceCreateInfo-pointer/null
&gt;     _VkAllocationCallbacks-pointer/null
&gt;     (o : (_ptr o _VkInstance))
&gt;     -&gt; (r : _VkResult)
&gt;
&gt;            -&gt; (begin
&gt;
&gt;                 (check-vkResult r 'vkCreateInstance)
&gt;                  o)))
&gt;
&gt;
&gt;
&gt; because the third argument is an out argument.
&gt;
&gt; If you don't make to make these in--out distinctions, then the first or
&gt; second definition of `vkCreateInstance` above is the most practical
&gt; choice.

</mfl...@cs.utah.edu>

-- 
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/OFgCQqCknhxOluTOuTHuCMOMjjJhq6j94EXBtAKrZ1fBp9p_VUatGjTeF0FQsZqnc647BlKn_yrr7urNd6MNCsQWq6Ug0xcrtE1k9jcxH4Y%3D%40sagegerard.com.

Reply via email to