I omitted to mention the self mapping that also must occur if vapi
wrapped structs can contain virtual methods.
The wrapped struct contains a private data pointer (they generally do)
which in this case will point to the subclass instance.
The subclass instance of course has a pointer to the super class
instance, as usual, and this will point to the struct instance.
When ANY vala code calls a method which is virtual to the vapi-wrapped
class, the "self" that is passed is the super-class instance of the
first subclass - i.e. the wrapped struct instance. I guess there will be
a variable number of parent-instance de-referencing going on, depending
on the depth of inheritance.
Conversely, the override methods for any method that is virtual to the
vapi-wrapped class will receive a "self" which is the wrapped struct,
and so it will have to follow the private data pointer of the struct to
get the real self.
When a subclass calls it's own overridden method this will involve
un-neccessary referencing to the wrapped struct and back again, but I
don't see a way around it.
This is all simple to build in, and requires a CCode directive for the
vapi code to identify which struct member is the private data, to be
used to hold subclass "self"
Finally, each subclass of a vapi-wrapped object having virtual methods
will need to have a backup table of overridden methods, so that
base.method can be used.
When the instance_init overrides the vmt in the wrapped struct, the old
value will be stored and used if base.method is invoked.
I think thats all?
Sam
Sam Liddicott wrote:
These suggested changes would permit vapi files to wrap structs that
contained a virtual method table.
If they are not objectionable to the development of Vala, I intend to
provide patches.
I like how vapi classes can wrap structs as classes; I'm investigating
how these can be almost first-class classes, especially in the case
where the struct contains function pointers, effectively a virtual
method table.
Vala implements calling virtual methods with a wrapper like this:
struct _youngerClass {
olderClass parent_class;
gint (*use_the_internet) (younger* self);
};
...
gint younger_use_the_internet (younger* self) {
return YOUNGER_GET_CLASS (self)->use_the_internet (self);
}
It seems like the line:
return YOUNGER_GET_CLASS (self)->use_the_internet (self);
Could be replaced with:
return YOUNGER_GET_VMT (self)->use_the_internet (self);
where in most cases
#define YOUNGER_GET_VMT YOUNGER_GET_CLASS
but this can be overridden in the VAPI file, maybe with
vmt_expression=".."
For samba4 ntvfs struct it would become
#define YOUNGER_GET_VMT(self) self->ops
so that the expanded code becomes
return self->ops->use_the_internet (self);
which would be spot on
However we need to convince vapi files to permit virtual methods too;
this vapi:
namespace Ntvfs {
[CCode (cname = "struct ntvfs_module_context", cprefix = "",
free_function = "talloc_free", create_function="xx", ref_function =
"talloc_reference", unref_function = "talloc_free"
vmt_expression="self->ops")]
public class Ntvfs {
public virtual int something_virtual();
}
}
does nothing with regard to "virtual" and calls in a subclass (or
anything) to something_virtual are left as calls to cprefix .
"something_virtual" but I think it should render to:
"self->ops->" . cprefix . "something_virtual(self)" (where the
position of self depends on instancepos and all that stuff as it
currently does).
It would likewise be possible to override such methods, in the instead
of this in the subclass _class_init:
NTVFS_CLASS (klass)->something_virtual = subclass_real_something_virtual;
have this in the _instance_init
YOUNGER_GET_VMT(self)->something_virtual =
subclass_real_something_virtual;
So I guess we would need a CCode directive to indicate if the vmt was
per-class or per-instance.
Are these objectionable to the direction of Vala?
I would do something likewise for properties so they could be mapped
to the members or expressions of the struct instance.
Later, I also want to add C (or vala? - probably not) code blocks to
vapi files which would be treated as inline methods (!!) to the
caller, this can encapsulate special construction steps or other
massaging which is not in the wrapped library but which ought to be done.
Sam
_______________________________________________
Vala-list mailing list
Vala-list@gnome.org
http://mail.gnome.org/mailman/listinfo/vala-list
_______________________________________________
Vala-list mailing list
Vala-list@gnome.org
http://mail.gnome.org/mailman/listinfo/vala-list