How does _array/list work?

I have a list that I want to convert into a C array. _array/list looks promising, as "the Racket representation is a list". But how exactly can I convert my list into a C array?

I believe part 2 has an example.

Thank you, that was a very interesting read. Unfortunately, I couldn't apply the example in the blog. This is the function I want to call (from the raylib wrapper):

(DrawLineStrip points pointCount color) → _void
  points : (_pointer-to _Vector2)
  pointCount : _int
  color : _Color

Now in order to create the points parameter I need to make use of some _array function, correct? I've played a little with it and it doesn't really make sense:

> (define bar (_array _int 5))
> (array? bar)
#f
> (array-set! bar 0 7)
; array-length: contract violation
;   expected: array?
;   given: #<compound-ctype>
; [,bt for context]
> (array-type bar)
; array-type: contract violation
;   expected: array?
;   given: #<compound-ctype>
; [,bt for context]
> 

Why does this not work? The documentation for _array states:

Creates an array type whose Racket representation is an array that works with array-ref and array-set!.

That doesn't seem to be correct. What am I missing?

From the documentation of

I see that Vector2 is a struct consisting of two floats.

_Vector2 : ctype?
struct

(struct Vector2 (x y)
#:constructor-name make-Vector2)
x : _float
y : _float

So I think, you can pass (vector (make-Vector2 1. 2.) (make-Vector2 3. 4.)) for the first argument points.

Unfortunately, that doesn't work:

cpointer-accessor: contract violation
  expected: cpointer?
  given: '#(#<cpointer> ...

In the meantime I've learned about cvector, which didn't work either:

cpointer-accessor: contract violation
  expected: cpointer?
  given: #<cvector>

Edit: I found the cvector-ptr procedure, which did the trick :slight_smile:

_array creates a ctype? not an array. Either the array is allocated by the C library, or you can allocate it with malloc and then follow this guidance from the make-array-type docs:

Since an array is treated like a struct, casting a pointer type to an array type does not work. Instead, use ptr-ref with a pointer, an array type constructed with _array, and index 0 to convert a pointer to a Racket representation that works with array-ref and array-set!.

Something like this should work:

(define _shape-array-1d (_array _int 1))
(define shape (malloc _shape-array-1d))
(array-set! (ptr-ref shape _shape-array-1d 0) 0 10)
(array-ref (ptr-ref shape _shape-array-1d 0) 0)

This is from some example code I had commented out because dealing with array types in the FFI is a pain! There are ways to avoid having to do this manually, like letting the fun auto-convert from vectors for you or just using pointers.

I think I get the idea of how arrays work, but I haven't implemented it. Instead I went for cvector. This is roughly what I'm doing:

(define (draw-outline list-of-Vector2 color)
  (let ((cvec (list->cvector list-of-Vector2 _Vector2)))
    (DrawLineStrip (cvector-ptr cvec) (cvector-length cvec) color)))

soegaard said I can use a vector, but I couldn't make that work.

One question remains, just out of curiosity: Is cvector implemented with arrays under the hood? Or are a they implemented independently?