How can I use a callback to a drawing function in Gtk4 DrawingArea?

Looking at GitHub - garrigue/lablgtk: LablGTK 2 and 3: an interface to the GIMP Tool Kit did not give me a clue

https://www.reddit.com/r/ocaml/comments/1gyue9e/how_can_i_correctly_pass_cairo_context_for_gtk4/

How do I create cairo context from pointer? · Issue #40 · Chris00/ocaml-cairo · GitHub asking questions

Hello,

I’m not an expert, and some other will probably gives you better answer, but I can stand seeing this post remaining empty. I’ll try to explain as the best as I can the issue you are facing.

As you can see, the Cairo context is abstract (the right part of the type description is not provided). This sometime used as a pattern in a Library, but in the case of a C binding, this is required : OCaml does not know how to represent C types. The best the language can do is just to let the type abstract.

If we take a look in the implementation, we can see that the type is actually a pointer to the context, wrapped into a caml struct. In OCaml you cannot just return the raw pointer because of the garbage collector (the way to proceed is given in the manual).

(I did not checked the source for the GTK binding, but you will probably find something similar)

Switch back in the OCaml API, having an abstract type prevent you to do any assumption on the type. Even if you were able to make the two libraries exchange the data properly (with the help of your own C binding in order to make the data compatible), any update in the library can break your code (as the implementation is not provided, the library is free to change it at any time).

So I think there is no solution for your issue, except if someone wrote it’s own binding (but I’m not aware of).

While it is not an answer, you pointed me in the right direction.

Thank you very much.

In lisp equivalent i have:

(cffi:defcallback %draw-func :void ((area :pointer)
                                    (cr :pointer)
                                    (width :int)
                                    (height :int)
                                    (data :pointer))
  (declare (ignore data))

  ;; create context
  (setf cairo:*context* (make-instance 'cairo:context
                                       :pointer cr
                                       :width width
                                       :height height
                                       :pixel-based-p nil))

So the context is created on a basis of the cr pointer. But I can not find how to do it in OCaml.

CFFI API — CairoCFFI 1.7.1 documentation possibly python clue

Unfortunately, C bindings using the traditionnal way are not compatible with C bindings using CTypes (the FFI library for OCaml). This means that you won’t be able to use the existing libraries like lablGtk, or ocairo with ctypes (I’d really like to be proved wrong on this point)

As far as I know there is no equivalent to zig translate-c in OCaml in order to generate the bindings automaticallly, so if you want to use FFI, you have to write declare all the bindings by yourself (again, please tell me I’m wrong here). This is a very huge task.

I’m sorry not being able to give you better answer :frowning:

Thank you for adding weight to my suspicions.

For minimal example I do not need to implement the whole of Cairo. It may be a starting point for a further conversation if there more people who want it.

manual way without using cairo2 library I can have a window painted red.

In Lablgtk you can find the function

Gdk.Cairo.create : window → Cairo.context

Under the hood, it is implemented calling “ml_gdk_cairo_create”

There are a couple example files in the lablgtk source repository that use Cairo to draw pictures: drawing.ml and cairo.ml)

somethng changed at version 5
https://ocaml.org/manual/5.2/intfc.html#ss:c-outside-head