From 55deffdb5ca626689b3e08d7e9adeab9f0e5ad5f Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Wed, 11 Dec 2019 14:32:41 +0100 Subject: [PATCH] object: Improve documentation of interfaces MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit QOM interfaces allow a limited form of multiple inheritance, at the condition of being stateless. That is, they cannot be instantiated and a pointer to an interface shouldn't be dereferenceable in any way. This is achieved by making the QOM instance type an incomplete type, which is, as mentioned by Markus Armbruster, the closest you can get to abstract class in C. Incomplete types are widely used to hide implementation details, but people usually expect to find at least one place where the type is fully defined. The fact that it doesn't happen with QOM interfaces is quite disturbing, especially since it isn't documented anywhere as recently discussed in this thread: https://lists.gnu.org/archive/html/qemu-devel/2019-12/msg01579.html Amend the documentation in the object.h header file to provide more details about why and how to implement QOM interfaces using incomplete types. Signed-off-by: Greg Kurz Reviewed-by: Marc-André Lureau Signed-off-by: Paolo Bonzini --- include/qom/object.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/include/qom/object.h b/include/qom/object.h index f9ad692f21..bd68d1938c 100644 --- a/include/qom/object.h +++ b/include/qom/object.h @@ -200,8 +200,14 @@ typedef struct InterfaceInfo InterfaceInfo; * * Interfaces allow a limited form of multiple inheritance. Instances are * similar to normal types except for the fact that are only defined by - * their classes and never carry any state. You can dynamically cast an object - * to one of its #Interface types and vice versa. + * their classes and never carry any state. As a consequence, a pointer to + * an interface instance should always be of incomplete type in order to be + * sure it cannot be dereferenced. That is, you should define the + * 'typedef struct SomethingIf SomethingIf' so that you can pass around + * 'SomethingIf *si' arguments, but not define a 'struct SomethingIf { ... }'. + * The only things you can validly do with a 'SomethingIf *' are to pass it as + * an argument to a method on its corresponding SomethingIfClass, or to + * dynamically cast it to an object that implements the interface. * * # Methods # * -- 2.11.4.GIT