Skip to content

Opaque compact classes

In some of my projects, I'm exposing compact classes in the public api. What I feel is missing is the ability to hide their implementation, while still retaining Valas nice memory management capabilities. I could do something like this:

[Compact]
public class Foo {
	// wrapper methods...

	[DestroysInstance]
	public void destroy () {
		((FooImpl) this).free ();
	}
}

[Compact]
internal class FooImpl {
	// implementation...
	public extern void free ();
}

But that means the api user has to remember to call destroy and foo_free is still emitted. Another approach would be to add a void* priv field that points to an internal class, but that seems to defeat the reason for using compact classes in the first place.

Because of these reasons, I have implemented what I call 'opaque' compact classes. A class is 'opaque' if it contains only private fields. It exposes no struct definition in the generated c header, only a typedef is provided.

This lifts the previous restriction of compact classes not having private fields, with the following caveats:

  • A compact class may not mix private and non-private fields.
  • A compact class may not have both private fields and abstract/virtual methods/properties.

In both cases, an appropriate error is raised during compilation (see also the provided test cases).

I know, there have been valid reasons against allowing private fields in compact classes, but since these are hidden in the public api, there should be no problem. Also it makes compact classes much more useful from Valas side, e.g. allowing properties with backing fields.

Nb. I made some refactoring changes in codegen/ so I could better reason about the struct generation.

Merge request reports