2010-07-23 18:24:30 +02:00
|
|
|
Design Process : All Plugin Interfaces Are C
|
|
|
|
|
============================================
|
|
|
|
|
|
|
|
|
|
[grid="all"]
|
|
|
|
|
`------------`-----------------------
|
|
|
|
|
*State* _Final_
|
|
|
|
|
*Date* _2007-06-29_
|
|
|
|
|
*Proposed by* link:ct[]
|
|
|
|
|
-------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
C interfaces
|
|
|
|
|
------------
|
2010-07-24 16:48:32 +02:00
|
|
|
When we offer interfaces for plugging in external code, we export them as C
|
|
|
|
|
interfaces.
|
2010-07-23 18:24:30 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Description
|
|
|
|
|
~~~~~~~~~~~
|
2010-07-24 16:48:32 +02:00
|
|
|
Lumiera will be based on a plugin architecture, the core is just a skeleton
|
|
|
|
|
with very few components. Everything else is loaded at runtime as _plugin_. C++
|
|
|
|
|
interfaces are hard to use by other programming languages. Thus I propose to
|
|
|
|
|
export every interface between these plugins as C interface which can much more
|
|
|
|
|
easily integrated in other languages.
|
2010-07-23 18:24:30 +02:00
|
|
|
|
|
|
|
|
.Further notes:
|
|
|
|
|
* dynamic loading of plugins, maybe unloading
|
|
|
|
|
* proper interface versioning
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Implementation Proposal
|
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
* keep the interface in a C struct (POD).
|
|
|
|
|
* the interface is versioned
|
2010-07-24 16:48:32 +02:00
|
|
|
* first member is a _size_ which will be initialized by the actual
|
|
|
|
|
implementation
|
|
|
|
|
* followed by function pointers defining the interface, see:
|
|
|
|
|
link:Lumiera/DesignProcess/CCodingStyleGuide[]
|
2010-07-23 18:24:30 +02:00
|
|
|
|
|
|
|
|
* everything added is considered immutable for this interface version
|
|
|
|
|
* new functions are added to the end (thus changing size)
|
|
|
|
|
* function pointers must be implemented, never be NULL
|
|
|
|
|
|
|
|
|
|
* a given interface version can be extended (but nothing removed)
|
2010-07-24 16:48:32 +02:00
|
|
|
* code using an interface just needs to check once if the size he get from a
|
|
|
|
|
supplier is >= what it expects, then the interface suffices its
|
|
|
|
|
requirements
|
|
|
|
|
* functions are versioned too, old version might be superseded by newer ones,
|
|
|
|
|
but the interface still needs to provide backward compatibility functions
|
|
|
|
|
* when old function are really deprecated, the interface version is bumped
|
|
|
|
|
and the old functions are removed from the struct
|
2010-07-23 18:24:30 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
Example define the interface structure:
|
|
|
|
|
|
|
|
|
|
[source,C]
|
|
|
|
|
----
|
|
|
|
|
struct lumiera_plugin_audio_interface_1
|
|
|
|
|
{
|
|
|
|
|
size_t size;
|
|
|
|
|
|
|
|
|
|
// Now the prototypes for the interface
|
|
|
|
|
AudioSample (*sample_normalize_limit_1)(AudioSample self, int limit);
|
|
|
|
|
unsigned (*sample_rate_1) (AudioSample self);
|
|
|
|
|
AudioSample (*sample_set_rate_1) (AudioSample self, unsigned rate);
|
|
|
|
|
|
|
|
|
|
// a later version might take a double as limit
|
|
|
|
|
AudioSample (*sample_normalize_limit_2)(AudioSample self, double limit);
|
|
|
|
|
}
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Example how a plugin 'thiseffect' initializes the struct:
|
|
|
|
|
|
|
|
|
|
[source,C]
|
|
|
|
|
----
|
2010-07-24 16:48:32 +02:00
|
|
|
struct lumiera_plugin_audio_interface_1
|
|
|
|
|
lumiera_plugin_audio_thiseffect_interface =
|
2010-07-23 18:24:30 +02:00
|
|
|
{
|
|
|
|
|
// maybe we want to initialize size somewhat smarter
|
|
|
|
|
sizeof(struct lumiera_plugin_audio_interface_1),
|
|
|
|
|
|
|
|
|
|
// this are the actual functions implemented in 'thiseffect'
|
|
|
|
|
lumiera_plugin_audio_thiseffect_sample_normalize_limit_1,
|
|
|
|
|
lumiera_plugin_audio_thiseffect_sample_rate_1,
|
|
|
|
|
lumiera_plugin_audio_thiseffect_sample_set_rate_1,
|
|
|
|
|
lumiera_plugin_audio_thiseffect_sample_normalize_limit_2
|
|
|
|
|
}
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Example how it will be used (schematic code):
|
|
|
|
|
|
|
|
|
|
[source,C]
|
|
|
|
|
----
|
|
|
|
|
int main()
|
|
|
|
|
{
|
|
|
|
|
// get the function vector
|
|
|
|
|
void* thiseffecthandle = dlopen("thiseffect.so");
|
|
|
|
|
struct lumiera_plugin_audio_interface_1* thiseffect =
|
|
|
|
|
dlsym(thiseffecthandle, "lumiera_plugin_audio_thiseffect_interface");
|
|
|
|
|
|
|
|
|
|
// call a function
|
|
|
|
|
thiseffect.sample_normalize_limit_1 (somesample, 1);
|
|
|
|
|
}
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Further notes:
|
|
|
|
|
|
2010-07-24 16:48:32 +02:00
|
|
|
That above gives only a idea, the datastructure needs to be extended with some
|
|
|
|
|
more information (reference counter?). The first few functions should be common
|
|
|
|
|
for all interfaces (init, destroy, ...). Opening and initialization will be
|
|
|
|
|
handled more high level than in the example above. Some macros which make
|
|
|
|
|
versioning simpler and so on.
|
2010-07-23 18:24:30 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Tasks
|
|
|
|
|
^^^^^
|
|
|
|
|
* Write some support macros when we know how to do it
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Pros
|
|
|
|
|
^^^^
|
|
|
|
|
* Easier usage/extension from other languages.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Cons
|
|
|
|
|
^^^^
|
2010-07-24 16:48:32 +02:00
|
|
|
* Adds some constraints on possible interfaces, the glue code has to be
|
|
|
|
|
maintained.
|
2010-07-23 18:24:30 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
Alternatives
|
|
|
|
|
^^^^^^^^^^^^
|
|
|
|
|
* Just only use C++
|
|
|
|
|
* Maybe SWIG?
|
|
|
|
|
* Implement lumiera in C instead C++
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Rationale
|
|
|
|
|
~~~~~~~~~
|
|
|
|
|
Not sure yet, maybe someone has a better idea.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Comments
|
|
|
|
|
--------
|
2010-07-24 16:48:32 +02:00
|
|
|
After a talk on IRC ichthyo and me agreed on making lumiera a multi language
|
|
|
|
|
project where each part can be written in the language which will fit it best.
|
|
|
|
|
Language purists might disagree on such a mix, but I believe the benefits
|
|
|
|
|
outweigh the drawbacks.
|
2010-07-23 18:24:30 +02:00
|
|
|
-- link:ct[] [[DateTime(2007-07-03T05:51:06Z)]]
|
|
|
|
|
|
2010-07-24 16:48:32 +02:00
|
|
|
C is the only viable choice here. Perhaps some sort of "test bench" could be
|
|
|
|
|
designed to rigorously test plugins for any problems which may cause Lumiera to
|
|
|
|
|
become unstable (memory leaks etc).
|
2010-07-23 18:24:30 +02:00
|
|
|
-- link:Deltafire[] [[DateTime(2007-07-03T12:17:09Z)]]
|
|
|
|
|
|
2010-07-24 16:48:32 +02:00
|
|
|
after a talk on irc, we decided to do it this way, further work will be
|
|
|
|
|
documented in the repository (tiddlywiki/source)
|
2010-07-23 18:24:30 +02:00
|
|
|
-- link:ct[] [[DateTime(2007-07-11T13:10:07Z)]]
|
|
|
|
|
|
|
|
|
|
''''
|
|
|
|
|
Back to link:Lumiera/DesignProcess[]
|