[pulseaudio-discuss] [Vala] Issues will vala and pulse vapi

Evan Nemerson evan at coeus-group.com
Sat Nov 21 19:54:43 PST 2015


On Sat, 2015-11-21 at 20:48 -0600, Aaron Paden wrote:
> On Sat, Nov 21, 2015 at 6:33 AM, Al Thomas <astavale at yahoo.co.uk>
> wrote:
> > 
> > 
> > This looks complex so I can only give a few pointers.
> > 
> > Does the code actually compile or are you getting an error about an
> > unresolved symbol?
> 
> Right, the code compiles, but the linker fails because of the
> unresolved symbols. I didn't think of this before, but the minimal
> example is pretty simple:
> 
> void main() {
>   PulseAudio.SourceInfo info;
> }
> 
> You can solve this by declaring info unowned. Clearly the issue is
> that vala is managing SourceInfo when it shouldn't be managed, but I
> wasn't sure how to actually fix this given how the API is actually
> used. Ideally, the vapi itself should indicate that the struct is
> unmanaged, but I'm not sure how to do that as of yet.

That's not quite right; the VAPI shouldn't indicate that a *type* is
"unmanaged"…  it's up to your code to indicate whether an instance is
unowned.  However, the question is really what the proper way to
destroy an instance is.

In order to determine how to destroy a struct which doesn't specify a
destroy_function CCode attribute, Vala will look at the members.  If
none of the members require destroy or free functions, then Vala can
assume that simply releasing the memory associated with the struct
itself (i.e., calling g_free on heap-allocated instances, or simply
allowing stack-allocated instances to go out of scope) is sufficient.

For example, consider the following two structs:

    public struct Foo {
    	    public int foo_value;
    }

    public struct Bar {
    	    public string bar_value;
    }

In this case, in order to destroy Foo nothing special is required.
However, to destroy Bar g_free must be called on the bar_value field.
That is where "unowned" comes into play.  If the bar_value field had
been marked as "unowned" then Vala would know that nothing special is
required to free it.

If you don't provide a destroy_function CCode annotation but Vala
determines that it is necessary to call one, it will default to
lower_case_cprefix_destroy, which is why it is generating a call to
pulse_audio_source_info_destroy.

The idea is recursive; if Foo had an owned Bar member then foo would
require a destroy function (which would call Bar's destroy function on
the appropriate field).  On the other hand, if Foo had an owned field
that contained another struct which didn't require a destroy function
then that wouldn't cause Foo to require one, either.

So, the right thing to do is probably to make any fields which require
a destroy or free function unowned.  However, this does have some
implications; if you transfer ownership of an instance to Pulse Audio,
and there is code in the library which calls a free function (such as
g_free) on one of the fields, you'll likely end up with a double free.
That behavior would be pretty unlikely; at that point I would argue
that it is really a bug in the API (unless there is actually a destroy
function but nobody told Vala about it).


-Evan


More information about the pulseaudio-discuss mailing list