Library / SDK
CppMicroServices/CppMicroServices avatar
CppMicroServices/CppMicroServices

C++ Micro Services: an OSGi style service registry for native C++

An OSGi-like C++ dynamic module system and service registry

890 stars291 forksC++Apache-2.0

At a glance

What is it?
C++ Micro Services is an Apache-2.0 framework that gives native C++ applications a dynamic module system and a service registry in the OSGi mould, with bundles loaded from shared or static libraries and a BundleContext as the entry point. It is a serious, long-lived project with a wide compiler matrix, and it asks for a C++17 toolchain and a recursive clone before you can build it.
Who is it for?
Adopt C++ Micro Services if you are building a native C++ system whose components must be started, stopped and reconfigured at runtime, and if the OSGi model of bundles and services fits how your team already thinks. Do not adopt it for a codebase that ships as one binary with no runtime lifecycle, since the whole value is in the dynamic part.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem: a monolith that cannot be reconfigured while it runs

A C++ application is normally a single linked binary. Every module is compiled in, the order of initialisation is decided at link time, and taking a plugin out means relinking and redeploying. That is fine for a command line tool and wrong for a long running service that has to reconfigure itself, load optional capabilities, or fail over parts of itself at runtime without a restart.

C++ Micro Services is a collection of components for building modular and dynamic service-oriented applications. It is based on OSGi, but tailored to support native cross-platform solutions. The word native matters: this is not an emulation of the Java model or a scripting layer, it is a C++ implementation of the same ideas.

The design goals are listed in the documentation, and they read like a list of architectural properties rather than features: re-use of software components, loose coupling between service providers and consumers, separation of concerns based on a service-oriented design, clean APIs based on service interfaces, and extensible and reconfigurable systems. Every one of those is a property of the deployment rather than of the code, which is the giveaway that this framework is aimed at a specific kind of system.

The audience is C++ developers building long lived applications or embedded and edge systems where the module set has to change without a full rebuild, and where the language of components, bundles and services already exists in their heads because of the Java and Eclipse world. The requirements section is refreshingly short: none, except a recent enough C++ compiler, with all third-party library dependencies included and mostly used for implementation details.

The licence is Apache-2.0, the homepage is cppmicroservices.org, and the last push was on 2026-10-05, with the most recent release v3.8.13 from 2026-08-25.

The model: bundles, a bundle context, and a registry

The mechanism is the OSGi one, and understanding it is a matter of three concepts.

The first is the bundle. The documentation describes the library as providing a powerful dynamic service registry on top of a managed lifecycle, and the framework manages logical units of modularity called bundles, which are contained in shared or static libraries. The consequence of bundles living in shared or static libraries is that a module is a link-time unit, so it can be loaded and unloaded at runtime only if it was built as a separate shared library.

The second is the bundle context. Each bundle within a library has an associated cppmicroservices::BundleContext object, through which the service registry is accessed. That is the whole API surface for talking to the framework: you do not call the registry directly, you go through your own context, which is how the framework keeps a service lookup scoped to the module that asked for it.

The third is the service registry itself, which maps an interface to the objects that implement it. Providers register a service object against an interface, consumers look it up by interface, and neither side needs to know the other. That is the loose coupling, and it is the reason the framework can be reconfigured at runtime without recompiling the consumer.

The important caveat is that this is a local, in-process registry. There is no network transport, no service discovery protocol and no remote calls in the described design. A system that needs services to talk across machines needs something else on top, and that distinction is the single most important thing to check before adopting a framework named after microservices.

The lookup API, as the documentation shows it

The code in the quick start is short, and it is the whole client-side story.

To find a service that implements a particular interface, you ask the context for a service reference and then resolve it:

cpp
    #include "cppmicroservices/BundleContext.h"
    #include "SomeInterface.h"

    using namespace cppmicroservices;

    void UseService(BundleContext context)
    {
      auto serviceRef = context.GetServiceReference<SomeInterface>();
      if (serviceRef)
      {
        auto service = context.GetService(serviceRef);
        if (service) { /* do something */ }
      }
    }

Two stages, and the split is deliberate. GetServiceReference<SomeInterface>() asks the registry whether anything is registered against that interface and returns a reference, and GetService resolves that reference into the object. A caller that only wants to know whether a capability is present can stop at the first call, which is the pattern you want when a missing service is a normal state rather than an error.

The type is in the template parameter, so the interface is checked at compile time, and the returned object is already typed as the interface, which is the point of a registry of interfaces rather than a registry of strings. The null checks are also part of the contract: a service reference can legitimately be absent, and the code says so rather than assuming.

Registering a service object against an interface is the mirror operation, and the documentation gives it in the same form, with the same includes and the same namespace. The two snippets together are the entire contract between a provider and a consumer, which is the property that makes the pattern portable.

Cloning with submodules, and the rest of the build

The quick start begins with a step that trips people up.

Start by cloning the project repository, and the documentation is explicit about why: since the project utilizes git submodules, you must clone the repository with the recursive flag, which also clones the submodules and places them in their respective directories. The project links to Git's own documentation for how submodules work and how to clone them into an already existing repository on disk.

That is a real characteristic of the codebase rather than an accident of packaging. The repository layout shows where the weight sits: a framework/ directory for the core, third_party/ for the vendored dependencies, util/ for the utility layer, tools/ for the build and packaging helpers, doc/ and compendium/ for the documentation, schemas/ for the configuration schemas, and cmake/ for the build system with a CMakeLists.txt at the root and CppMicroServicesConfig.cmake.in and CppMicroServicesConfigVersion.cmake.in for the installed package configuration. There is a VERSION file and a CHANGELOG.rst, and CMake variants are described in cmake-variants.json.

The build is CMake based, and the recommended minimum is CMake 3.17.0. For CI builds through GitHub Actions, the documentation notes that the CMake version, and the version of other provided software, is determined by the software provided on the GitHub-hosted runners, and it links to the runner information pages for Ubuntu 22.04, macOS 13 and 14, and Windows 2022 and 2025.

The library makes use of C++17 language and library features and compiles on many different platforms, and the release artefacts are downloadable from the project's GitHub releases page.

The compiler matrix, and the difference between minimum and tested

The requirements section separates two lists, and the distinction is the most useful thing in it for an adopter.

The recommended absolute minimum compiler versions are GCC 7.5.0, Clang 9.0, Clang from Xcode 10.0, which is marked as not tested, and Visual Studio 2017 with MSVC++ 15.0, also marked as not tested. The documentation then says plainly that not all of the absolute minimum compiler versions are tested, and lists what is tested and recommended: GCC 11.3.0, Clang 11.0, Clang from Xcode 15.2 and 15.4, and Visual Studio 2022.

Below that is the list of tested compiler and operating system combinations: GCC 11.4.0 on Ubuntu 22.04, Clang 14.0.0 on Ubuntu 22.04, Apple Clang from Xcode 15.2.0 on OS X 13.3.0, Apple Clang from Xcode 15.4.0 on OS X 14.5.0, Visual Studio 2022, and MinGW-w64.

So the gap between the stated minimum and the tested set is roughly four years of compiler releases. That is normal for a C++ library of this kind, where a new standard library or a new optimiser tends to find problems, and the honest way to read it is that the minimum is where the code is expected to compile and the tested set is where it is expected to work.

The continuous integration table at the top of the documentation names the branches and the jobs: master and development, with a Nix based build and test job and a Windows build and test job for each, plus code coverage status for both branches, along with a Coverity scan build status and a performance status. The performance status being tracked as a separate signal is the one worth noting for a framework whose entire selling point is a runtime system.

The tooling around the code: sanitizers, valgrind and coverage

The repository contents show a project that takes the unpleasant parts of C++ development seriously, and the file names are more informative than any feature list.

There is a tsan_suppressions.txt and a ubsan_suppressions.txt, which are the suppressions for the thread sanitizer and the undefined behaviour sanitizer. A framework whose whole purpose is starting, stopping and running code in modules that share a process is exactly the kind of code where a data race or an undefined behaviour report matters, so the presence of sanitizer suppression lists is a signal that those tools are actually run.

There is also valgrind_suppressions.txt and a valgrindrc, with an install_valgrind.sh script, so valgrind is part of the workflow as well. A .clang-format and a .clang-tidy configuration sit at the root with a format_code.sh script, and there are githooks in a .githooks/ directory.

Coverage is handled with opencppcoverage, with a codecov.yml configuration, a fixcoveragefilepaths.py script, an install_opencppcoverage.ps1 helper for Windows, and a merge script. A CTestConfig.cmake file indicates the test suite is driven through CTest.

The practical meaning of all this is that the cost of adopting the framework is not only the framework. The build is a CMake project with submodules, the CI matrix covers two branches and multiple toolchains, and the debugging infrastructure assumes you are prepared to run sanitizers and valgrind on your own integration. That is a reasonable trade for a project of this kind, and it is a cost that a smaller framework would not impose.

Licence, provenance and where a service registry is the wrong answer

The licence is Apache License v2.0, stated in the documentation and in the LICENSE file at the root of the repository, with a COPYRIGHT file in the top-level directory carrying the detailed copyright information. Apache-2.0 is a permissive licence with an express patent grant, which for an infrastructure framework that vendors third-party code is a sensible choice.

The provenance is worth knowing. The project was initially developed at the German Cancer Research Center, and it still carries that history in its copyright file. For a framework whose target users include medical and scientific software, that origin is context rather than a credential, but it explains the emphasis on correctness tooling.

Where this is the wrong tool is a short list. If your application is a single binary with no runtime lifecycle, the dynamic module system buys you nothing and costs you a build dependency, a bundle discipline and a service lookup convention. If your services need to live in different processes or on different machines, the registry here is in-process, and you would need a remote transport that this framework does not provide. And if your team has no OSGi background, the vocabulary is a barrier: bundle, bundle context, service registry and the lifecycle around them are a specific way of thinking about a running system, and adopting them means adopting that way of thinking.

The project itself is candid about the community side as well, adopting the contributor covenant code of conduct and stating an aim of making the community welcoming to developers with different backgrounds.

The judgement, in short: reach for C++ Micro Services when the runtime composition of a native application is the actual problem, and read the tested compiler matrix rather than the minimum one before you commit.

Editorial conclusion

Adopt C++ Micro Services if you are building a native C++ system whose components must be started, stopped and reconfigured at runtime, and if the OSGi model of bundles and services fits how your team already thinks. Do not adopt it for a codebase that ships as one binary with no runtime lifecycle, since the whole value is in the dynamic part. Before you build, clone the repository with the recursive flag, because the project uses git submodules, and check the compiler matrix against your own toolchain, since the recommended versions are much newer than the stated minimums and the older ones are explicitly marked as not tested.

Frequently asked questions

What is C++ Micro Services and what does it give a C++ project?

It is a collection of components for building modular and dynamic service-oriented applications, based on OSGi but tailored to native cross-platform C++ solutions. It provides a dynamic service registry on top of a managed lifecycle, with logical units of modularity called bundles contained in shared or static libraries, and a BundleContext through which the registry is accessed.

How do I look up a service in C++ Micro Services?

Call GetServiceReference on the bundle context with the interface as a template argument, then resolve it with GetService. The documentation shows both calls returning values you must check, because a service that implements the interface may legitimately not be registered.

How do I build C++ Micro Services from the repository?

Clone with the recursive flag, because the project uses git submodules that must be cloned and placed in their directories. The build is CMake based with a recommended minimum of CMake 3.17.0, and release archives are also available from the GitHub releases page.

Which compilers does C++ Micro Services support?

The recommended absolute minimums are GCC 7.5.0, Clang 9.0, Clang from Xcode 10.0 and Visual Studio 2017, the last two marked as not tested. The tested and recommended versions are GCC 11.3.0, Clang 11.0, Clang from Xcode 15.2 and 15.4, and Visual Studio 2022, with MinGW-w64 in the tested platform list.

Is C++ Micro Services a microservices framework with remote calls?

Not as described. It provides a dynamic service registry in the current process, with bundles loaded from shared or static libraries, and the documentation does not describe any network transport or remote service discovery, so a system that needs services across machines needs a different layer.

Official sources

  1. CppMicroServices/CppMicroServices on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/cppmicroservices-cppmicroservices.svg)](https://hysenlabs.com/projects/cppmicroservices-cppmicroservices)

Was this useful?