💾 Archived View for republic.circumlunar.space › users › dbane › gemlog › 2022-11-23.gmi captured on 2024-06-16 at 12:50:29. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-01-29)

-=-=-=-=-=-=-

GObject Introspection

When possible, I like to defer technical decisions for as long as possible. For example, if you're using a standardized language & OS interfaces, you don't need to pick an actual compiler/interpreter and OS until quite late.

For example, say I pick Common Lisp and UNIX. The eventual platform will probably be sbcl and Linux, but it doesn't have to be. Similarly, in CL CFFI is a pseudo-standard FFI that is portable to many compilers. But is there such a thing as an FFI that is portable to many languages?

The answer is obviously yes, C is a lingua franca. However it can't express many features of higher-level languages. Solutions to this include:

Swig: Export a C library to a small set of languages

In this post, I look into GObject.

Notably, although lots of languages can call GObject APIs, only C is recommended to actually implement the classes themselves.

Previous Work

As always, I found some interesting code by other people. But you have to be very careful to filter out libraries to call GObject classes, of which there are many.

There's a good tutorial on writing your own classes, complete with source code.

Tutorial

Source code (check out the stageN branches)

It's also possible to write GObject classes in Vala, but I'm avoiding this in favour of standardized languages for now.

Write GObject classes in Vala

cppgir

Another interesting codebase is cppgir. It's primarily a way to call GObject APIs, but there is some test code that is a nice sample to use for writing your own classes.

There's also a "gobject" example that looked promising, but unfortunately it's not actually usable for the purpose of being called by external code.

cppgir, call GObject classes from C++ prettily

What I did & Conclusion

In the end, I worked on the final iteration of skagedal's code, and ported the implementation to C++. The header file still had to remain C so that it could be scanned by g-ir-scanner to generate the interface metadata. But at least I'm confident most of the code could be implemented in a safer language, despite the docs you're not limited to C, just languages that can emit C linkage objects.

For example if you set up your environment correctly:

export LD_LIBRARY_PATH=`pwd`/.libs:$LD_LIBRARY_PATH
export GI_TYPELIB_PATH=`pwd`

... you can call my modified version of skagedal's library using simple Lisp code like:

(ql:quickload "cl-gobject-introspection")
(defvar *tut* (gir:require-namespace "Tut"))
(defvar *gtr* (gir:invoke (*tut* "Greeter" 'new)))
(setf (gir:property *gtr* 'greetee) "Me")
(gir:invoke (*gtr* 'greet))

I stuck with the above library, and not the macro-heavy "cl-gobject-introspection-wrapper" mainly because I couldn't get the latter to work with properties.

I'm happy with this. I think I would use it in future instead of a traditional FFI to call C/C++ from a different language.

Back to my gemlog