celix-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Pepijn Noltes <pepijnnol...@gmail.com>
Subject [DISCUSS] C++ Celix Framework
Date Mon, 07 Jan 2019 21:25:31 GMT
Hi All,

The last weeks I put some effort in exploring the benefits and
downsides of changing the primary language of Celix from C to C++ in
an experimental branch.

As you probably already know Celix start around 2010 with the focus on
a OSGi implementation in C;  following the Java OSGi spec very
strictly. And IMO that was correct choice at that time and with our
given experience.
My current vision is that we should follow the concepts of OSGi and
where possible the nomenclature, but focus on delivering a (as much as
possible) easy to use dynamic services framework for C/C++.

IMO this also means that we should think about moving to C++. Because:
a) With the concepts of C++11 we can create a much easier to use and
hopefully also easier to develop/maintain framework.
b) More type safe
c) RAII; which really helps a lot in dealing with volatile services
and trying to keep track of which services are still in use.
b) C++ is simply more relevant and popular, which should help in
getting more traction for Celix.

To get the discussion rolling and for me to get a feeling what the
effect of moving to C++ would mean, I created C++ experimental (but
functionally quite complete) Celix C++ framework [1].
And I would like some feedback/discussion if this is an improvement
for Celix or any remarks on the Celix C++ framework implementation.

There are a few interesting changes in the approach/design of the C++ framework:
1) There is a separate (static) Registry library [2], which delivers
the functionality to register/use/track (and TODO listener hooks)
services. This library, by design, can be used without the rest of the
framework. I designed the Registry library separate to keep it clean
of bundles lifecycle stuff.
   - ServiceRegistration/ServiceRegistry uses RAII to make it easier
in use, specifically for cleanup.
   - The registry also support registering std::function as services,
this seems logical for C++.
   - The service template argument is used to deduce the service name.
   - The concept of services versions is dropped. I do think versions
on API is important, but more in a distributed environment. In my
experience for Celix everything should be build against the same
service API's. Playing around with backwards compatibility on binary
level with C++ is just reasonable.
2) The framework library [3].  Here the focus in on the BundleContext
api so that almost everything can be done through the bundle context
  - It is now also possible to register "static" bundles. These
bundles are installed on every created Framework object. This make it
possible to register bundles with use  a __attribute__((constructor))
decorated function. With support for "static" bundles, bundles can be
created as shared objects, which "just work" if you link against them.
See the C++ Shell example [4]. IMO this is a much .. much more natural
way to handle bundles in a C/C++ environment.
 - Support for zip bundles and dynamically loaded shared object - with
use a the bundle create, start,stop ..etc symbols is still TODO
 - BundleActivator now work on the constructor/destructor, i.e. also
following a RAII approach.
 - There is no concept of a ServiceReference (same as in the updated C api).
3) Resources can be linked against a shared object and in that way
OSGi extender pattern concept can be used without using zip files as
bundles. See the C++ Shell implementation as an example (this bundles
has a version.properties resource) [5].
4) For now glog is used as logging framework.
5) libzip is used to handle the zip files. Note that resources linked
against the shared object bundles are packed as a zip file.
6) googletest is used for testing.
  - It is also easier to test bundles, because the test executable
"just" has to link against the bundle shared objects to make them
available. See the tests of the C++ Shell bundle [5]
7) For now there is no way to export/import (versioned) shared objects
from other bundles. I personally do no think this is really needed (I
never use it myself). I also think that this should be solved by the
language itself (i.e. C++ Modules).
8) As far as I can see it is possible to create a (mostly) backwards
compatibility C API from the C++ framework. As long as we only support
the updated C API, i.e. the the celix_* headers.

The C++ framework API has no documentation yet, please be aware. I do
think that it should be clear enough for experience users and the
developers, but this is still a TODO.
Currently for C++ there is a Registry [2] library, a Framework library
[3], a C++ Shell bundle [5],  a C++ Shell TUI bundle [6] and a single
example executable to run everything [4].
I also took some effort to ensure that the code coverage result are
generated and somewhat respectable.

My experience thus far is mostly positive. Fewer lines of code are
needed (duh), but also (mainly because of RAII) less if else branches
are needed / error handling is needed.
I do have some trouble arrange the code, because some part need to be
in the header (template) or in Impl classes to ensure a more clean
user API and the rest is in the sources files.

Please feel free to let me know what you think. Note that this is
still experimental and we will discuss how to move forward later.

[1] feature/cxx branch (for the 807b88 .. commit):
[2] registry dir:
[3] https://github.com/apache/celix/tree/807b88b5bb166e253dc1c517326d2865bc60584f/libs/framework_cxx
[4] https://github.com/apache/celix/tree/807b88b5bb166e253dc1c517326d2865bc60584f/examples/celix-examples/cxx_shell_example
[5] https://github.com/apache/celix/tree/807b88b5bb166e253dc1c517326d2865bc60584f/bundles/shell/cxx_shell
[6] https://github.com/apache/celix/tree/807b88b5bb166e253dc1c517326d2865bc60584f/bundles/shell/cxx_shell_tui


View raw message