GNOME Bugzilla – Bug 622278
g_object_bind_property_full() is not introspection/binding friendly
Last modified: 2010-08-03 11:41:12 UTC
as it turns out, passing a single user_data,notify pair for two functions does not make the introspection and language bindings people happy. one way to solve this issue is to make the _full() variant take two (func, data, notify) triplets, which would solve most of our problems, though it would make the function call, at a whopping 11 arguments, a bit unwieldy from the C developer perspective: GBinding * g_object_bind_property_full (source, source_property, target, target_property, flags, transform_to, data1, notify1, transform_from, data2, notify2); so, the proposal is to rename the function to be: GBinding * g_object_bind_property_transform_with_data (source, source_property, target, target_property, flags, transform_to, data1, notify1, transform_from, data2, notify2); and have a C convenience function that only takes the transformation functions: GBinding * g_object_bind_property_transform (source, source_property, target, target_property, flags, transform_to, transform_from); on the rationale that C developers will probably only need to pass transformation functions and handle the memory themselves.
Created attachment 164208 [details] [review] binding: Rename _full to _transform_with_data() Using a single DestroyNotify and user data for two functions confuses both static and introspection generated bindings, and makes the memory management of the closure data fuzzy. We should use two (func, data, notify) triplets, one for each transformation function - though this means making the _full() variant of g_object_bind_property() a bit unwieldy for the C developer, with 11 arguments. A way out is to have a C convenience function called: g_object_bind_property_transform() and make the g_object_bind_property_full() a variant of _transform() and rename it: g_object_bind_property_transform_with_data() Mostly only for language bindings.
I think that makes these very inconvenient to use from C. I want to pass user data to the transform funcs, but the same user data for both directions. So I have to use the variant with the 2 destroy notify's, and thus create the same data twice (usually it's an allocated struct; or I need to introduce refcounting for my ad-hoc data struct... both alternatives suck). (Also I think the alleged 'problem' is a misunderstanding on the part of the binding developers (or a limitation in the binding itself). It's simply that the (user data, destroy notify) pair is bound to the lifetime of the GBinding*, *not* the callbacks.)
(In reply to comment #2) > (Also I think the alleged 'problem' is a misunderstanding on the part of the > binding developers (or a limitation in the binding itself). It's simply that > the (user data, destroy notify) pair is bound to the lifetime of the GBinding*, > *not* the callbacks.) encoding this behaviour in the annotations is not trivial.
[damn, bugzilla ate the rest of the comment...] in any case, if we can find a way to express this in the language bindings then I'll be happy to close this as RESOLVED WONTFIX.
after much prodding and deliberation, here's a GClosure-based implementation bolted on top of g_object_bind_property_full(), to preserve the "free once" semantics. there is a fair amount of GValue copying going on - which I'm afraid is unavoidable; also, the marshaller will have to be hand-written anyway. finally, language bindings will have to write their own conversion functions to transform GValues into native objects - though all language bindings already have this kind of code internally.
Created attachment 165773 [details] [review] binding: Add a closure-based variant of bind_property_full() Since using the function pointer version muddles the memory management requirements of language bindings, we should implement a GClosure-based variant on top of g_object_bind_property_full().
Attachment 165773 [details] pushed as 3be3ad6 - binding: Add a closure-based variant of bind_property_full()