Re: pygi: callback funcs and GErrors



The second problem is this:
- you should return True. Returning False indicated to Pixbuf that
your function has failed. This sets the GError, which throws an
Exception, which triggers the crash I mentioned in the last email.
- you can't just "return True" because the typelib says that GError is
an out parameter than needs to be filled.
- you can't "return (True, None)" because we don't yet support
converting of Python types to GErrors. A NotImplementedError is
thrown.

However if you do all that, and catch the NotImplementedError, you can
make it work. The exception won't interrupt the save function because
the pixbuf code isn't aware of Python exceptions. Here is the code
that works now (presuming you have those GdkPixbuf annotations in your
original email compiled):

from gi.repository import GdkPixbuf
x = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, False, 8, 100, 100)

def cb(*args):
 print args
 return True, None

try:
	x.save_to_callbackv(cb, None, 'png', [], [])
except NotImplementedError:
	pass


I have also filed a bug, and attached a patch for ignoring the GError
out parameter. Once I commit this (probably tomorrow) to master, you
can use just "return True" and remove the NotImplementedError except
block:
https://bugzilla.gnome.org/show_bug.cgi?id=642715

On Fri, Feb 18, 2011 at 9:15 PM, Laszlo Pandy <laszlok2 gmail com> wrote:
> So if you "return False, None" from the callback, None becomes the
> GError and it is considered set (I guess because None is a Python
> object and not NULL).
>
> Then Pixbuf.save_to_callbackv() sets the GError and returns in
> failure. There is a bug in PyGObject introspection for handling
> cleanup of arrays when a GError is set. I've reported it, until the
> invoke experts decide how best to solve it:
>
> https://bugzilla.gnome.org/show_bug.cgi?id=642708
>
> On Tue, Feb 15, 2011 at 1:54 PM, Christophe Saout <christophe saout de> wrote:
>> Dear python hackers,
>>
>> I am having some troubles with the new Python bindings via the amazing
>> gobject-introspection project:
>>
>> My attempts to use "gdk_pixbuf_save_to_callback" via
>> gobject-introspection and gi.repository so far have failed.
>>
>> Note that the exact same thing is working with the classic pygtk & co
>> bindings, however I have good reasons to port this to the new system. (I
>> have started writing additional modules where I want to use the
>> pygi-style bindings) And yes, I am aware that this is still kind of
>> experimental, so I'd like to report my observations.
>>
>> It seems like the annotations added so far are mostly to keep the
>> scanner happy.  I've tried to fix up the annotations to get things
>> going, but I am running into a few problems:
>>
>> The method is defined as follows:
>>
>> gboolean gdk_pixbuf_save_to_callback    (GdkPixbuf  *pixbuf,
>>                                         GdkPixbufSaveFunc save_func,
>>                                         gpointer user_data,
>>                                         const char *type,
>>                                         GError    **error,
>>                                         ...) G_GNUC_NULL_TERMINATED;
>>
>> Well, this one doesn't seem to want to work at all (probably due to
>> varargs) - it doesn't even show up as a possible method from python.
>>
>> So I concentrated on its twin:
>>
>> gboolean gdk_pixbuf_save_to_callbackv   (GdkPixbuf  *pixbuf,
>>                                         GdkPixbufSaveFunc save_func,
>>                                         gpointer user_data,
>>                                         const char *type,
>>                                         char      **option_keys,
>>                                         char      **option_values,
>>                                         GError    **error);
>>
>> with the callback func declared as:
>>
>> typedef gboolean (*GdkPixbufSaveFunc)   (const gchar *buf,
>>                                         gsize count,
>>                                         GError **error,
>>                                         gpointer data);
>>
>> I've tried to fix up the annotation as follows:
>>
>> /**
>>  * gdk_pixbuf_save_to_callbackv:
>>  * @pixbuf: a #GdkPixbuf.
>>  * @save_func: (scope call): a function that is called to save each block of data that
>>  *   the save routine generates.
>>  * @user_data: (closure save_func): user data to pass to @save_func
>>  * @type: name of file format.
>>  * @option_keys: (array zero-terminated=1) (element-type utf8): name of options to set, %NULL-terminated
>>  * @option_values: (array zero-terminated=1) (element-type utf8): values for named options
>>  * @error: (allow-none): location to store error, or %NULL.
>>  *
>>  * Saves pixbuf to a callback in format @type, which is currently "jpeg",
>>  * "png", "tiff", "ico" or "bmp".  If @error is set, %FALSE will be returned. See
>>  * gdk_pixbuf_save_to_callback () for more details.
>>  *
>>  * Return value: whether an error was set
>>  *
>>  * Since: 2.4
>>  **/
>>
>> Issues:
>>
>> * Not sure about option_values and being zero-terminated.  It should
>>  have the same size as option_keys (where the zero-termination is
>>  explicitly stated).  I guess I can't tell it I want to have the same
>>  size as another array?  However, that's not my main issue, I just
>>  wondered.
>>
>> * I've added the (scope call) and (closure save_func) to save_func /
>>  user_data
>>
>> Now when calling that method from python it was telling me:
>> app1:/root # python test.py
>> ERROR:pygi-argument.c:1717:_pygi_argument_to_object: code should not be
>> reached
>>
>> Which I traced down to the GError in GdkPixbufSaveFunc.  Apparently it
>> was thinking this is a parameter that is being passed in (instead of
>> automatically seeing that it's an error that can be thrown from inside
>> the closure)
>>
>> So as a workaroung I tried to annotate the SaveFunc as follows:
>>
>> /**
>>  * GdkPixbufSaveFunc:
>>  * @buf:
>>  * @count:
>>  * @error: (out)
>>  * @data: (closure):
>>  */
>>
>> Now my callback is actually being called:
>> ('\x89PNG\r\n\x1a\n\xc8\xb1\xde\x01', 8L, None)
>>
>> But afterwards I get:
>>
>> ERROR:pygi-closure.c:307:_pygi_closure_set_out_arguments: code should
>> not be reached
>>
>> Which presumably is a problem with the GError now being an output
>> parameter? (the Python function has a "return False")
>>
>> Changing that one to "return (False, None)" gives
>>
>> Program received signal SIGSEGV, Segmentation fault.
>> 0x00007ffff7d99ae7 in _pygi_argument_release ()
>>   from /usr/lib64/python2.7/site-packages/gi/_gi.so
>> (gdb) bt
>> #0  0x00007ffff7d99ae7 in _pygi_argument_release ()
>>   from /usr/lib64/python2.7/site-packages/gi/_gi.so
>> #1  0x00007ffff7d99b7e in _pygi_argument_release ()
>>   from /usr/lib64/python2.7/site-packages/gi/_gi.so
>> #2  0x00007ffff7d963c0 in _free_invocation_state ()
>>   from /usr/lib64/python2.7/site-packages/gi/_gi.so
>> #3  0x00007ffff7d978ac in _wrap_g_callable_info_invoke ()
>> [...]
>>
>> Also one further question:
>>
>> * Is it possible t have the (buffer, size) parameters be turned into a
>>  single argument on the Python side?  I'm afraid that passing binary
>>  data from C to Python this way, the converter will look for a
>>  null-terminated string instead of making the buffer exactly the
>>  indicated size.
>>
>> Oh, and in case you haven't noticed, this function is from the
>> gdk-pixbuf package.
>>
>> Software versions used:
>>
>> glib                    2.28.0
>> gobject-introspection   0.10.2
>> python                  2.7.1
>> pygobject               2.90.0
>>
>> Python test code:
>>
>> from gi.repository import GdkPixbuf
>> x = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, False, 8, 100, 100)
>>
>> def cb(*args):
>>  print args
>>  return False
>>
>> x.save_to_callbackv(cb, None, 'png', [], [])
>>
>> I am trying to write a small web service that renders images to a png or
>> something like that and then transmits those directly over the network.
>>
>> Thanks a lot,
>>
>>        Christophe
>>
>>
>> _______________________________________________
>> python-hackers-list mailing list
>> python-hackers-list gnome org
>> http://mail.gnome.org/mailman/listinfo/python-hackers-list
>>
>


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