/tinyletter

The Programs of the Week We Put Our Face in the Phone

This Week’s Program: Sep 11 - Sep 15

Yo dawgs. I heard you like GObjects. So I put GObjects in your objects so you can Racket when you C.

I wrote a bunch of stuff this week! I had a little mini-light bulb moment and just started writing. Code, docs, all that stuff.

I think I’ve completed the documentation for ffi/unsafe/introspection. It’s been kind of painful writing this, as I had to confront all the little flaws and inconsistencies in the API. But the little light bulb moment I had, along with some more mastery of Scribble led me to get over this hump. You can read the documentation for this module here.

Here are some highlights from the commits this week that led to this final doc.

0ce0ad4ea996c0de8619e0bdade0988b976f2ed7

I update my Makefile to run a slightly altered version of the raco scribble command:

raco scribble +m --html-tree 1 --redirect-main $(RACKET_DOCS) --dest-name $@ $<

This command now tells scribble to make a html-tree with a depth of 1 - that is, instead of a single HTML document, make a directory with one level of depth, and write it out to the destination directory named $@; for those unversed in Makefile quirks that means the thing on the left side of the : — the target, which in this case is “docs”.

3045ffa87c4eacce60c731a6da77b7137927ae4f

Here’s the challenge: I want to bridge the GObject struct that I use to represent instances with the racket/class OOP library. There are a lot of synergies that can be drawn from using the latter. The question is how. After a bit of brooding and mulling, I turn to structure type properties. Like prop:cpointer and prop:procedure, structure type properties are things that allow a structure type to behave a certain way. They’re a bit like Interfaces (The concept. Not to be confused with, uh, interfaces). Instances of a struct type that implement a structure type property conform to certain behaviors. Like how the gi-function struct type implements the prop:procedure property and so returns #t to procedure?.

make-struct-property creates the prop:gobject structure type property, as well as functions to act as a predicate (gobject?) and retrieve the value of the property from the struct gobject-ref. The value of prop:gobject should be a gtype-instance or a function that accepts the struct and returns a gtype-instance. On the newly renamed gobject-instance and the gstruct struct types, I implement this prop with the function identity. Now I can change a bunch of contracts to accept gobject?. Any thing that implements the prop:gobject property can be a GObject.

d98086b796311916f1d253459680a683a9282e2f

Now comes the bridge. First is gobject<%> (the <%> suffix is a convention for a Racket interface). I create this with interface*; this form allows me to attach structure type properties to the interface. I add prop:gobject and look for a field on the object called pointer for the value of the property. Now, every object that implements gobject<%> can be used interchangeably with other gobjects. I also create a base class that extends this interface, for convenience sake.

So the class gobject% extends gobject<%> with the property prop:gobject so that instances will respond #t to gobject?.

I am gobsmacked by the gobs of gobjects!

d083b34e2bb5ce9c1ac19647b385ea8160a9d6b9

Here’s some cute Scribble tricks:

  • I pair racketresult with racketinput (and learn about unsyntax aka @#,) together to make something that looks like a REPL interaction.
  • The procedure function will make content “look” like a Racket procedure: it wraps it like #<procedure:x>.
  • racketmodname will automatically link a module path like racket/class to its documentation.

And there we have it. This feels like a good place to end this spike of work on documentation and GObject Introspection and move on to focusing on GStreamer specifically, using the new tools for OOP to make the ergonomics of that module real good.

👺 Mark