How to safely cast a _pointer to _bytes?

I'm using racket/draw/unsafe/cairo and a custom ffi for MagickWand C API.
I have this definition, you can see the last parameter is _bytes.

(define-mwand MagickExportImagePixels (_fun _MagickWand-pointer _size _size _size _size _string _StorageType _bytes -> _MagickBooleanType))

The cairo function I'm trying to use is

(define-cairo cairo_image_surface_get_data* (_cfun (s : _cairo_surface_t)
                                                   -> _pointer)
  #:c-id cairo_image_surface_get_data)

Which returns a pointer which then I feed to MagickExportImagePixels, for now I just added another definition called MagickExportImagePixels/pointer which is the same as the namesake function but _bytes is replaced with _pointer.

Yet I still have the question, how to cast a _pointer to _bytes correctly, I just did (cast data-pointer _pointer _bytes) and it crashed or at least I remember doing this, I also realize that _bytes in the docs is syntax, so that might be also part of a problem.

3 Likes

Maybe something like this?

From cairo/main.rkt at 5281c9acf2217015b96b8a6a4788b9ec6eecd179 · soegaard/cairo · GitHub

4 Likes

Thank you for the sample code, I didn't realize there was a wrapper for cairo since I generally check the documentation index and not the package index and I also didn't realize there was two cairo_image_surface_get_data one with _bytes and one with _pointer since I want to avoid more allocations, the solution seems to be to have two functions pointing to the same c function.

Would it be correct to mark @soegaard 's answer as the solution?

The library is still new.

There is no documentation yet.

Also the library has only seen limited testing, so beware for bugs.

well, I'm not using that exactly, but I think I will

Just for the record: converting from _pointer to _bytes requires copying, and when _bytes is used without a size, the copied data's length is inferred from a terminating a nul character. The MagickExportImagePixels binding should almost certainly use _pointer instead of _bytes, since it's not dealing with nul-terminated data. It should be just as convenient, since _pointer as an argument type accepts a byte-string.

4 Likes