GNOME Bugzilla – Bug 640671
Unable to use gpointers
Last modified: 2011-02-07 16:58:25 UTC
Created attachment 179397 [details] [review] Pointer test case It seems that it's impossible to properly use methods that take gpointers. Even though it might seem useless for dynamic languages to support gpointers, it might be useful in cases when a method returns a gpointer and this can be passed to another function which will return a usable object from the gpointer. I added a simple test which reads a gpointer property from a GObject and tries to pass this to GLib.direct_hash - and this should return the int value of the pointer, yet it seems that it passes some internal pointer of a corresponding PyObject. While testing this also another bug was found - the behaviour of instance.props.prop_name is different than instance.get_property('prop_name').
I don't see how this can work. When asking for a gpointer we pass the python object pointer because in most cases that is what you want. Gpointer means an untyped pointer so there is no way to know if you want to pass the python object pointer or the raw pointer for the underlying object (which would be a gobject pointer for gobject types). The problem is types like integers don't have an underlying pointer, they need to be marshalled. Usually passing a python pointer works fine since you grab it out and then pass it to a method that knows how to marshal that python pointer to the correct C type. I'll look at your test case closer but I'm not sure if there is a fix here.
Comment on attachment 179397 [details] [review] Pointer test case >diff --git a/tests/test_everything.py b/tests/test_everything.py >index 701c4ad..c5ba363 100644 >--- a/tests/test_everything.py >+++ b/tests/test_everything.py >@@ -393,6 +393,16 @@ class TestProperties(unittest.TestCase): > self.assertTrue(isinstance(object_.props.boxed, Everything.TestBoxed)) > self.assertEquals(object_.props.boxed.some_int8, 42) > >+ def test_pointer(self): >+ object_ = Everything.TestObj() >+ >+ object_.props.list = ['1', '2', '3'] >+ ptr = object_.get_property('list') something is wrong here, get_property should return you a marshalled list just like object_.props.list does. We have the type info in the param specs. >+ # this should actually fail, but at least we can test pointers >+ self.assertTrue(isinstance(object_.get_property('list'), GObject.GPointer)) >+ ptr_value = int(repr(ptr)[13:-1], 16) >+ self.assertEquals(GLib.direct_hash(ptr), ptr_value) Most GLib functions should be marked as not introspectable. I discourage the use of the GLib module. It is too low level and is mostly represented by python data structures. We don't support everything you can do in C (for that you can always write a a small C module). Perhaps it would help for you to explain a specific usecase but as I said you most likely do not want to hash marshalled data structures as they will change every time you cross the C/Python boundaries. I have toyed with the idea with creating sequence and mapping types that hold the original pointer to the GObject data type object but as soon as you use things like slice or pass a python sequence type we would have to convert anyway so raw pointers are not a reliable way to track data structures. In any case we really don't want to expose C'isms like pointers. I am tempted to close this as wontfix but if you have a legitimate usecase that can't be done any other way we can see what can be done about it.
I'm asking for one specific use case - if an API has a method/property that is marked as returning gpointer (so you wrap it in gobject.GPointer), why do you pass a pointer to your PyObject wrapper instead of the gpointer value? Pass whatever pointer you want when the type != gobject.GPointer, that's apparently wrong use of the API.
Pointers will never be able to pass, it does not make sense to expose them to python in any way. Closing this as wontfix.