Accessing a pygtk object from c++ or vice versa

Hello –

I’m porting a project from gtk2 to gtk3. It’s a mixture of C++ and Python. The old code has a GUI written entirely with pygtk, except for libgnomecanvas, which is created and used in C++. In order to install the canvas into a pygtk window, the canvas was wrapped in a PyObject by pygobject_new(), and the PyObject* was returned to Python. Since libgnomecanvas doesn’t exist for gtk3, I’m calling cairo from C++, writing directly to a GtkLayout.

I’m having trouble figuring out the how to add the GtkLayout created in C++ to a window created in python. Is there a simple way to do this? Have I missed something in the docs? (I’ve checked the pygobject and gobject introspection manuals.)

Many thanks.
– Steve

Hi! I have found this: https://bloerg.net/2013/02/23/integrating-gtk-c-widget-in-python.html . Does it help?

Thanks, but that helps for gtk2, not gtk3. In gtk3, pygobject_get returns a GObject*, not a PyObject*. I’d like to convert the GObject to a PyObject.

– Steve

The simplest way to achieve this is to create a small, private utility library with a C API and generate the introspection data for it, using g-ir-scanner and g-ir-compiler. The library can act as the barrier between Python code and C++ code.

Can you point me towards a simple example? I read documentation for introspection but didn’t find a good description of what actually has to be in the input files.
Thanks.
– Steve

You will need to write a small C library that calls into C++ code; I don’t have anything handy, at the moment, but it should not be exceedingly hard to find something.

As for the introspection parts, you can look at the instructions on how to integrate with existing build systems so that the introspection tools can parse the C sources and generate the binary data that pygobject can load.

The introspection scanner parses C code, so you will need:

  • C headers
  • C source files

Symbols need to be annotated as to clarify the transfer and ownership rules.

I had found the GObject Introspection manual, and found it to be particularly opaque, which is why I posted here. I will give it another try.

Meanwhile, I was poking around on the Python side, and found that if I create a widget in Python and pass it as a PyObject* to C++, I can extract a GtkWidget from it like this:

PyObject *capsule = PyObject_GetAttrString(pywidget, "__gpointer__");
if(!PyCapsule_CheckExact(capsule))
   handle_error...;
const char *capsulename = PyCapsule_GetName(capsule);
GtkWidget *cwidget = (GtkWidget*) PyCapsule_GetPointer(capsule, capsulename);

This appears to solve my immediate problem, since I don’t care if the widget is created in Python or C++, as long as I can access it from both languages. I presume I’ll have to fiddle with reference counts.

Is this legitimate, or just asking for trouble?

– Steve