From fb390e4f7fe64c465f5904583ed7bc1dd9f2ebc5 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Sat, 14 Jul 2007 15:14:11 +0200 Subject: [PATCH] figured out better interface implementation macros --- wiki/support_library.html | 88 +++++++++++++++++++++++++++++---------- 1 file changed, 65 insertions(+), 23 deletions(-) diff --git a/wiki/support_library.html b/wiki/support_library.html index 44097d42b..95f735230 100644 --- a/wiki/support_library.html +++ b/wiki/support_library.html @@ -1691,16 +1691,18 @@ DAMAGE. <html><sub><a href="javascript:;" onclick="scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html> ***/ -
+
Interfaces are declared in headerfiles, they use some tool macros to give a convenient definition language.
 
+! Thoughts
+
+Interfaces are are immutable with the exception that new functions may be added. versioning should stay out of the view most of the time.
+
 ! Brainstorming
 
-This is just a sketch, using preprocessor metaprogramming.
-
-An interface need a name and a version, they form a block where the actual function prototypes can be added
+An interface need a name and a version, they form a block where the actual function prototypes can be added, new prototypes have to be added at the end, existing prototypes must never be changed.
 {{{
-CINELERRA_INTERFACE(foo, 1,
+CINELERRA_INTERFACE(name, version,
 	...
 );
 }}}
@@ -1708,7 +1710,7 @@ CINELERRA_INTERFACE(foo, 1,
 
 each function prototype must be given with its different parts, return type, name, arguments list, version
 {{{
-	CINELERRA_IPROTO(ret, name, (args), version),
+	CINELERRA_IPROTO(ret, name, (args)),
 }}}
 
 
@@ -1716,27 +1718,45 @@ each function prototype must be given with its different parts, return type, nam
 Together this would look like
 {{{
 CINELERRA_INTERFACE(foo, 1,
-	CINELERRA_IPROTO(void, bar, (void), 1),
-	CINELERRA_IPROTO(int, baz, (int i), 1)
+	CINELERRA_IPROTO(void, bar, (void)),
+	CINELERRA_IPROTO(int, baz, (int i))
+);
+
+CINELERRA_INTERFACE(foo, 2,
+	CINELERRA_IPROTO(void, bar, (void)),
+	CINELERRA_IPROTO(int, baz, (float i))
 );
 }}}
 
+Note that the version 2 interface changed the parameter from int to float for the 'baz' function.
+
 which gets expanded to
 {{{
 struct cinelerra_interface_foo_1
 {
 	struct cinelerra_interface interface_header_;
-	void (*cinelerra_proto_foo_bar_1) (void);
-	int (*cinelerra_proto_foo_baz_1) (int i);
+	void (*bar) (void);
+	int (*baz) (int i);
+};
+
+struct cinelerra_interface_foo_2
+{
+	struct cinelerra_interface interface_header_;
+	void (*bar) (void);
+	int (*baz) (float i);
 };
 }}}
-
+
A Plugin realizes an interface, this means actual functions are mapped to the correspondending slots in the interface structure.
 
 {{{
-CINELERRA_IMPLEMENT_INTERFACE(interface, version, name, /* TODO some hooks here */
-	CINELERRA_INTERFACE_FUNC(protoname, version, functionname),
+CINELERRA_INTERFACE_IMPLEMENT(interface, name,
+	CINELERRA_INTERFACE_VERSION(version,
+		/* TODO some hooks here */
+		CINELERRA_INTERFACE_FUNC(protoname, functionname),
+		...
+	),
 	...
 );
 }}}
@@ -1750,20 +1770,41 @@ my_bar_function (void)
 }
 
 int
-my_baz_function (int i)
+my_old_baz_function (int i)
 {
 	...
 }
 
-CINELERRA_IMPLEMENT_INTERFACE(foo, 1, myfoointerface, /* TODO some hooks here */
-	CINELERRA_INTERFACE_FUNC(bar, 1, my_bar_function),
-	CINELERRA_INTERFACE_FUNC(baz, 1, my_baz_function),
+int
+my_baz_function (float i)
+{
+	...
+}
+
+CINELERRA_INTERFACE_IMPLEMENT(foo, myfoointerface,
+	CINELERRA_INTERFACE_VERSION(1,
+		/* TODO some hooks here */
+		CINELERRA_INTERFACE_FUNC(bar, my_bar_function),
+		CINELERRA_INTERFACE_FUNC(baz, my_old_baz_function)
+	),
+	CINELERRA_INTERFACE_VERSION(2,
+		/* TODO some hooks here */
+		CINELERRA_INTERFACE_FUNC(bar, my_bar_function),
+		CINELERRA_INTERFACE_FUNC(baz, my_old_baz_function)
+	)
 );
 }}}
 
-which expands to something like:
+The interface implementations expands to something like:
 {{{
-struct cinelerra_interface_foo_1 myfoointerface =
+struct cinelerra_interface_foo_1 myfoointerface_1 =
+{
+	/* TODO header initialization */
+	my_bar_function,
+	my_old_baz_function
+}
+
+struct cinelerra_interface_foo_2 myfoointerface_2 =
 {
 	/* TODO header initialization */
 	my_bar_function,
@@ -1771,7 +1812,8 @@ struct cinelerra_interface_foo_1 myfoointerface =
 }
 }}}
 
-Note: the protoname and version args for CINELERRA_INTERFACE_FUNC will be used for placement initialization and type checking, not mentioned here. This would allow to initialize this structure out of order.
+Note: the protoname and version args for ~CINELERRA_INTERFACE_FUNC will be used for placement initialization and type checking, not mentioned here. This would allow to initialize this structure out of order.
+
 
@@ -1860,16 +1902,16 @@ always succeeds. !! C++ exceptions
-
+
! Compatibility matrix
 
 |>|>|!Source compatibility|
 |!~~CALLER~~\^^CALLEE^^ *|OLD^^**^^|NEW^^**^^|
 |OLD|works|works<<br>>but a recent interface definition must be available|
-|NEW|update callee using new interface revision|works|
+|NEW|callee has to be updated using new interface revision|works|
 |>|>|!Binary compatibility|
 |OLD|works|works|
-|NEW|caller gets 'revision not sufficient' at runtime<<br>>and needs to implement fallbacks|works|
+|NEW|caller gets 'revision not sufficient' at runtime<<br>>and should implement fallbacks|works|
 
 ^^*^^) CALLER is the user of an interface, CALLEE is the interface provider (usually a plugin)
 ^^**^^) OLD means a initial revision, NEW means some later revision of an interface