Signals, GErrors and Introspection



Hi there,

I think I’ve just hit a GObject limitation, but I want to make sure I’m
seeing the whole picture before I start hacking a solution.

The situation is, I have a GObject implementing an interpreter for the
Brainfuck programming language; whenever the interpreter needs to interact
with the user, it emits a signal (input-request or output-request) and lets
the connected signal handler do the job in an application–specific way. If
you want to poke around the code, you can grab it by cloning [1].

Since I/O can fail, both handlers get the return location for a GError as
last parameter. My marshal.list looks like this:

	BOOLEAN:CHAR,POINTER    # Output
	BOOLEAN:POINTER         # Input

It works fine from C: I can connect an handler, and if the I/O operation
fails I can fill the GError with detailed information. Easy peasy.

I’ve now added support for GObject Introspection, and this is where I’ve
hit the wall: the .gir snippet detailing the signals is the following:

	<glib:signal name="input-request">
	  <return-value transfer-ownership="none">
	    <type name="gboolean"/>
	  </return-value>
	  <parameters>
	    <parameter name="object" transfer-ownership="none">
	      <type name="gpointer"/>
	    </parameter>
	  </parameters>
	</glib:signal>
	<glib:signal name="output-request">
	  <return-value transfer-ownership="none">
	    <type name="gboolean"/>
	  </return-value>
	  <parameters>
	    <parameter name="object" transfer-ownership="none">
	      <type name="gchar"/>
	    </parameter>
	    <parameter name="p0" transfer-ownership="none">
	      <type name="gpointer"/>
	    </parameter>
	  </parameters>
	</glib:signal>

which reflects the situation (except for the parameter names, but I
figure that’s not the problem), but doesn’t work: when the signal is
emitted and a JS handler is connected, I get the following error:

	JS ERROR: !!!   Exception was: Error: Can't convert
	                non-null pointer to JS value

I’ve tried manually changing the type of the last parameter from
gpointer to GLib.Error (with c:type="GError**") but it still gives
me the same error.

The reason is quite simple: when Gjs is about to call the JS handler,
it needs to converts the parameters from GValues to JS values, but it
has no way of knowing how to convert a gpointer which is not null, so
it aborts the function call.

Now, I could replace the signal with a simple callback (I see that done
in Gtk-2.0.gir, so I assume it works fine), but it just feels less nice,
so I’d rather avoid that.

From what I’ve seen, to make my code work seamlessy in Gjs the following
things would need to be done:

	* Add support for boxing a GError** into GValue
	* Add support for a ERROR parameter type to glib-genmarshal
	* Teach gjs how to convert a GError** to/from a JS value

Maybe I’m underestimating the task a bit, but it seems totally doable.

So the questions are: is my analysis correct? Does my proposed fix make
sense, or I’m missing something obvious? If I wrote the code needed to
make this work, would it be accepted into GLib?

Thank you for your patience.


[1] http://kiyuko.org/git/cattle.git
-- 
Andrea Bolognani <eof kiyuko org>
Resistance is futile, you will be garbage collected.

Attachment: signature.asc
Description: Digital signature



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]