Repository: celix
Updated Branches:
  refs/heads/feature/CELIX-426-cxx-api 34914e827 -> d9e95de89


CELIX-446: Adds ServiceAdaptors concept, which - with the use of type erasure - 
make it possible to register/use C++ service which are automatically wrapper 
to/from their C counterpart.


Project: http://git-wip-us.apache.org/repos/asf/celix/repo
Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/d9e95de8
Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/d9e95de8
Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/d9e95de8

Branch: refs/heads/feature/CELIX-426-cxx-api
Commit: d9e95de8998db686ce95ebb866685f1cda3bfa89
Parents: 34914e8
Author: Pepijn Noltes <[email protected]>
Authored: Mon Jul 9 21:49:16 2018 +0200
Committer: Pepijn Noltes <[email protected]>
Committed: Mon Jul 9 21:49:16 2018 +0200

----------------------------------------------------------------------
 .../shell/shell/include/celix/IShellCommand.h   |  45 +++
 .../include/celix/ShellCommandServiceAdapters.h | 110 +++++++
 bundles/shell/shell/include/command.h           |   4 +-
 examples/celix-examples/CMakeLists.txt          |   3 +
 .../shell_command_example/CMakeLists.txt        |  30 ++
 .../shell_command_example/src/Activator.cc      |  58 ++++
 .../shell_command_example/src/activator.c       |  81 ++++++
 libs/framework/gtest/CMakeLists.txt             |   1 +
 .../gtest/src/cxx_ServiceAdapter_tests.cc       | 290 +++++++++++++++++++
 libs/framework/include/celix/BundleContext.h    |  59 ++--
 libs/framework/include/celix/ServiceAdapter.h   | 148 ++++++++++
 .../include/celix/impl/BundleContextImpl.h      | 268 +++++++++++++----
 libs/framework/src/service_tracker.c            |   4 +-
 13 files changed, 1020 insertions(+), 81 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/celix/blob/d9e95de8/bundles/shell/shell/include/celix/IShellCommand.h
----------------------------------------------------------------------
diff --git a/bundles/shell/shell/include/celix/IShellCommand.h 
b/bundles/shell/shell/include/celix/IShellCommand.h
new file mode 100644
index 0000000..8ae7acc
--- /dev/null
+++ b/bundles/shell/shell/include/celix/IShellCommand.h
@@ -0,0 +1,45 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <string>
+#include <iostream>
+
+#include "command.h"
+
+#ifndef CXX_CELIX_ISHELLCOMMAND_H
+#define CXX_CELIX_ISHELLCOMMAND_H
+
+namespace celix {
+
+    class IShellCommand {
+    public:
+        static constexpr const char * const COMMAND_NAME = 
OSGI_SHELL_COMMAND_NAME;
+        static constexpr const char * const COMMAND_USAGE = 
OSGI_SHELL_COMMAND_USAGE;
+        static constexpr const char * const COMMAND_DESCRIPTION = 
OSGI_SHELL_COMMAND_DESCRIPTION;
+
+        virtual ~IShellCommand() = default;
+        virtual int executeCommand(const std::string &commandLine, 
std::ostream &out, std::ostream &err) = 0;
+    };
+
+}
+
+#include "ShellCommandServiceAdapters.h"
+
+
+#endif //CXX_CELIX_ISHELLCOMMAND_H

http://git-wip-us.apache.org/repos/asf/celix/blob/d9e95de8/bundles/shell/shell/include/celix/ShellCommandServiceAdapters.h
----------------------------------------------------------------------
diff --git a/bundles/shell/shell/include/celix/ShellCommandServiceAdapters.h 
b/bundles/shell/shell/include/celix/ShellCommandServiceAdapters.h
new file mode 100644
index 0000000..1b5dbcf
--- /dev/null
+++ b/bundles/shell/shell/include/celix/ShellCommandServiceAdapters.h
@@ -0,0 +1,110 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <sstream>
+
+#include "command.h"
+#include "celix/ServiceAdapter.h"
+#include "celix/Constants.h"
+
+#ifndef CXX_CELIX_SHELLCOMMANDSERVICEADAPTERS_H
+#define CXX_CELIX_SHELLCOMMANDSERVICEADAPTERS_H
+
+namespace celix {
+
+
+    //From a C++ service to a C service when registering IShellCommand 
services.
+    class ShellServiceRegistrationAdapterFactory : public 
celix::IServiceRegistrationAdapterFactory<celix::IShellCommand, 
command_service_t> {
+    public:
+        class ServiceAdapter : public 
celix::IServiceAdapter<command_service_t> {
+        public:
+            ServiceAdapter(celix::IShellCommand *svc) {
+                cSvc.handle = static_cast<void*>(svc);
+                cSvc.executeCommand = [](void* handle, char* commandLine, FILE 
*outStream, FILE *errStream) -> celix_status_t {
+                    auto *local_cmd = static_cast<IShellCommand*>(handle);
+                    std::ostringstream out;
+                    std::ostringstream err;
+                    int status = 
local_cmd->executeCommand(std::string{commandLine}, out, err);
+                    std::fprintf(outStream, "%s", out.str().c_str());
+                    std::fprintf(errStream, "%s", err.str().c_str());
+                    return status;
+                };
+            }
+            virtual ~ServiceAdapter() = default;
+            command_service_t* adapt() override { return &cSvc; }
+        private:
+            command_service_t cSvc{};
+        };
+
+        virtual ~ShellServiceRegistrationAdapterFactory() = default;
+        std::string serviceName() override { return 
OSGI_SHELL_COMMAND_SERVICE_NAME; }
+        std::string serviceVersion() override { return ""; }
+        std::string serviceLanguage() override { return 
celix::Constants::SERVICE_C_LANG; }
+        celix::IServiceAdapter<command_service_t>* 
createAdapter(celix::IShellCommand* svc) override { return new 
ServiceAdapter{svc}; }
+    };
+
+    celix::IServiceRegistrationAdapterFactory<celix::IShellCommand, 
command_service_t>& serviceRegistrationAdapterFactoryFor(celix::IShellCommand 
*/*dummy*/) {
+        static ShellServiceRegistrationAdapterFactory factory{};
+        return factory;
+    }
+
+    //From a C to a C++ services when using IShellCommand services.
+    class ShellServiceUsageAdapterFactory : public 
celix::IServiceUsageAdapterFactory<celix::IShellCommand> {
+    public:
+        class ServiceAdapter : public 
celix::IServiceAdapter<celix::IShellCommand>, public celix::IShellCommand {
+        public:
+            ServiceAdapter(void *_svc) : 
cSvc{static_cast<command_service_t*>(_svc)} {}
+            virtual ~ServiceAdapter() = default;
+            celix::IShellCommand* adapt() override { return this; }
+
+            int executeCommand(const std::string &commandLine, std::ostream 
&out, std::ostream &err) override {
+                char *outBuf = nullptr;
+                char *errBuf = nullptr;
+                FILE *outStream = open_memstream(&outBuf, nullptr);
+                FILE *errStream = open_memstream(&errBuf, nullptr);
+                int status = cSvc->executeCommand(cSvc->handle, 
(char*)commandLine.c_str(), outStream, errStream);
+                fflush(outStream);
+                fclose(outStream);
+                fflush(errStream);
+                fclose(errStream);
+                out << outBuf;
+                err << errBuf;
+                free(outBuf);
+                free(errBuf);
+                return status;
+            }
+        private:
+            command_service_t* cSvc;
+        };
+
+        virtual ~ShellServiceUsageAdapterFactory() = default;
+        std::string serviceName() override { return 
OSGI_SHELL_COMMAND_SERVICE_NAME; }
+        std::string serviceVersionRange() override { return ""; }
+        std::string serviceLanguage() override { return 
celix::Constants::SERVICE_C_LANG; }
+        celix::IServiceAdapter<celix::IShellCommand>* createAdapter(void 
*registeredSvc) override { return new ServiceAdapter{registeredSvc}; }
+    };
+
+    celix::IServiceUsageAdapterFactory<celix::IShellCommand>& 
serviceUsageAdapterFactoryFor(celix::IShellCommand* /*dummy_used_for_infer*/) {
+        static ShellServiceUsageAdapterFactory factory{};
+        return factory;
+    }
+}
+
+
+#endif //CXX_CELIX_SHELLCOMMANDSERVICEADAPTERS_H

http://git-wip-us.apache.org/repos/asf/celix/blob/d9e95de8/bundles/shell/shell/include/command.h
----------------------------------------------------------------------
diff --git a/bundles/shell/shell/include/command.h 
b/bundles/shell/shell/include/command.h
index 65e4306..f856648 100644
--- a/bundles/shell/shell/include/command.h
+++ b/bundles/shell/shell/include/command.h
@@ -34,8 +34,8 @@
 #define OSGI_SHELL_COMMAND_USAGE "command.usage"
 #define OSGI_SHELL_COMMAND_DESCRIPTION "command.description"
 
-static const char * const OSGI_SHELL_COMMAND_SERVICE_NAME = "commandService";
-static const char * const OSGI_SHELL_COMMAND_SERVICE_VERSION = "1.0.0";
+#define OSGI_SHELL_COMMAND_SERVICE_NAME "commandService"
+#define OSGI_SHELL_COMMAND_SERVICE_VERSION "1.0.0"
 
 typedef struct commandService command_service_t;
 typedef command_service_t * command_service_pt;

http://git-wip-us.apache.org/repos/asf/celix/blob/d9e95de8/examples/celix-examples/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/celix-examples/CMakeLists.txt 
b/examples/celix-examples/CMakeLists.txt
index c313e8e..7edfd30 100644
--- a/examples/celix-examples/CMakeLists.txt
+++ b/examples/celix-examples/CMakeLists.txt
@@ -37,4 +37,7 @@ if (EXAMPLES)
     add_subdirectory(service_hook_example)
     add_subdirectory(log_service_example)
 
+
+    add_subdirectory(shell_command_example)
+
 endif(EXAMPLES)

http://git-wip-us.apache.org/repos/asf/celix/blob/d9e95de8/examples/celix-examples/shell_command_example/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/celix-examples/shell_command_example/CMakeLists.txt 
b/examples/celix-examples/shell_command_example/CMakeLists.txt
new file mode 100644
index 0000000..467bc0d
--- /dev/null
+++ b/examples/celix-examples/shell_command_example/CMakeLists.txt
@@ -0,0 +1,30 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_celix_bundle(shell_example_c SOURCES src/activator.c VERSION 1.0.0)
+target_link_libraries(shell_example_c PRIVATE Celix::shell_api)
+
+add_celix_bundle(shell_example_cxx SOURCES src/Activator.cc VERSION 1.0.0)
+target_link_libraries(shell_example_cxx PRIVATE Celix::shell_api)
+
+add_celix_container(shell_example
+    BUNDLES
+        Celix::shell
+        Celix::shell_tui
+        shell_example_c
+        shell_example_cxx
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/d9e95de8/examples/celix-examples/shell_command_example/src/Activator.cc
----------------------------------------------------------------------
diff --git a/examples/celix-examples/shell_command_example/src/Activator.cc 
b/examples/celix-examples/shell_command_example/src/Activator.cc
new file mode 100644
index 0000000..75835b0
--- /dev/null
+++ b/examples/celix-examples/shell_command_example/src/Activator.cc
@@ -0,0 +1,58 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <iostream>
+#include <thread>
+#include <atomic>
+#include <vector>
+
+#include "celix/BundleActivator.h"
+#include "celix/IShellCommand.h"
+
+namespace {
+    class BundleActivator : public celix::IBundleActivator, public 
celix::IShellCommand {
+    public:
+        celix_status_t start(celix::BundleContext &_ctx)  override {
+            this->ctx = &_ctx;
+            celix::Properties props{};
+            props[OSGI_SHELL_COMMAND_NAME] = "cxx_exmpl";
+            svcId = ctx->registerService<celix::IShellCommand>(this, props);
+            return  CELIX_SUCCESS;
+        }
+
+        celix_status_t  stop(celix::BundleContext &ctx) override {
+            ctx.unregisterService(svcId);
+            return CELIX_SUCCESS;
+        }
+
+        virtual int executeCommand(const std::string &, std::ostream &out, 
std::ostream &) override {
+            ctx->useServices<celix::IShellCommand>([&out](celix::IShellCommand 
&) {
+                out << "found a IShellCommandService" << std::endl;
+                //TODO use useServicesWithOptionts -> useWithProperties !
+            });
+            return 0;
+        }
+
+    private:
+        celix::BundleContext *ctx;
+        long svcId{-1};
+    };
+}
+
+CELIX_GEN_CXX_BUNDLE_ACTIVATOR(BundleActivator)

http://git-wip-us.apache.org/repos/asf/celix/blob/d9e95de8/examples/celix-examples/shell_command_example/src/activator.c
----------------------------------------------------------------------
diff --git a/examples/celix-examples/shell_command_example/src/activator.c 
b/examples/celix-examples/shell_command_example/src/activator.c
new file mode 100644
index 0000000..ca42deb
--- /dev/null
+++ b/examples/celix-examples/shell_command_example/src/activator.c
@@ -0,0 +1,81 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "celix_bundle_activator.h"
+#include "constants.h"
+
+#include "command.h"
+
+typedef struct activator_data {
+    celix_bundle_context_t *ctx;
+    command_service_t svc;
+    long svcId;
+} activator_data_t;
+
+struct useShellServiceHandle {
+    activator_data_t* data;
+    FILE *out;
+    int count;
+};
+
+static void useShellService(void *handle, void *_svc __attribute__((unused)), 
const celix_properties_t *props) {
+    struct useShellServiceHandle *useHandle = handle;
+    const char *name = celix_properties_getWithDefault(props, 
OSGI_SHELL_COMMAND_NAME, "Not Found");
+    fprintf(useHandle->out, "%i: Command %s found\n", useHandle->count++, 
name);
+}
+
+static celix_status_t executeCommand(void *handle, char * commandLine, FILE 
*outStream, FILE *errorStream) {
+    activator_data_t *data = handle;
+    struct useShellServiceHandle useHandle = { .data = data, .out = outStream, 
.count = 0};
+
+    celix_service_use_options_t opts = CELIX_EMPTY_SERVICE_USE_OPTIONS;
+    opts.filter.serviceName = OSGI_SHELL_COMMAND_SERVICE_NAME;
+    opts.useWithProperties = useShellService;
+    opts.callbackHandle = &useHandle;
+    celix_bundleContext_useServicesWithOptions(data->ctx, &opts);
+    fprintf(outStream, "Found %i command_service_t services\n", 
useHandle.count);
+
+    return CELIX_SUCCESS;
+}
+
+
+static celix_status_t activator_start(activator_data_t *data, 
celix_bundle_context_t *ctx) {
+    data->ctx = ctx;
+    data->svc.handle = data;
+    data->svc.executeCommand = executeCommand;
+
+    data->svcId = -1L;
+    celix_properties_t *props = celix_properties_create();
+    celix_properties_set(props, OSGI_SHELL_COMMAND_NAME, "c_exmpl");
+    data->svcId = celix_bundleContext_registerService(ctx, &data->svc, 
OSGI_SHELL_COMMAND_SERVICE_NAME, props);
+    printf("Registered command service with service id %li\n", data->svcId);
+
+    return CELIX_SUCCESS;
+}
+
+static celix_status_t activator_stop(activator_data_t *data, 
celix_bundle_context_t *ctx) {
+    celix_bundleContext_unregisterService(ctx, data->svcId);
+    printf("Unregistered command service with service id %li\n", data->svcId);
+    return CELIX_SUCCESS;
+}
+
+CELIX_GEN_BUNDLE_ACTIVATOR(activator_data_t, activator_start, activator_stop)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/d9e95de8/libs/framework/gtest/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/libs/framework/gtest/CMakeLists.txt 
b/libs/framework/gtest/CMakeLists.txt
index 4ecd47a..26af024 100644
--- a/libs/framework/gtest/CMakeLists.txt
+++ b/libs/framework/gtest/CMakeLists.txt
@@ -21,6 +21,7 @@ set(SOURCES
         src/cxx_FrameworkFactory_tests.cc
         src/cxx_BundleContext_tests.cc
         src/cxx_Bundle_tests.cc
+        src/cxx_ServiceAdapter_tests.cc
 )
 add_executable(cxx_framework_tests ${SOURCES})
 target_link_libraries(cxx_framework_tests PRIVATE gtest Celix::framework)

http://git-wip-us.apache.org/repos/asf/celix/blob/d9e95de8/libs/framework/gtest/src/cxx_ServiceAdapter_tests.cc
----------------------------------------------------------------------
diff --git a/libs/framework/gtest/src/cxx_ServiceAdapter_tests.cc 
b/libs/framework/gtest/src/cxx_ServiceAdapter_tests.cc
new file mode 100644
index 0000000..63add3a
--- /dev/null
+++ b/libs/framework/gtest/src/cxx_ServiceAdapter_tests.cc
@@ -0,0 +1,290 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include "gtest/gtest.h"
+
+#include "celix/FrameworkFactory.h"
+
+class ServiceAdapterTest : public ::testing::Test {
+public:
+    ServiceAdapterTest() {
+        celix::Properties config{};
+        config["org.osgi.framework.storage.clean"] = "onFirstInit";
+        config["org.osgi.framework.storage"] = "test-cache"; //TODO tmp dir?
+        this->fw_ptr = 
std::unique_ptr<celix::Framework>{celix::FrameworkFactory::newFramework(std::move(config))};
+    }
+
+    ~ServiceAdapterTestd(){}
+
+    celix::Framework& framework() { return *(this->fw_ptr); }
+private:
+    std::unique_ptr<celix::Framework> fw_ptr{nullptr};
+};
+
+//Test interface
+class ITestSvc {
+public:
+    static constexpr const char * const NAME = "ITestSvc";
+
+    virtual ~ITestSvc(){};
+    virtual int calc(int input) = 0;
+};
+
+//Test implementation
+class TestImpl : public ITestSvc {
+public:
+    virtual ~TestImpl(){};
+    int calc(int input) override { return input * 42; }
+};
+
+
+/*This service can be used with the DefaulServiceWrapper*/
+class IHelloService {
+public:
+    static constexpr const char * const SERVICE_NAME = "IHelloService";
+    static constexpr const char * const SERVICE_VERSION = "1.0.0";
+
+    virtual ~IHelloService() = default;
+    virtual std::string hello() = 0;
+};
+
+TEST_F(ServiceAdapterTest, RegisterServiceWithWrapperTest) {
+    auto &ctx = this->framework().getFrameworkContext();
+
+    class HelloServiceImpl : public IHelloService {
+    public:
+        virtual ~HelloServiceImpl() = default;
+        std::string hello() override {
+            return std::string{"hello1"};
+        }
+    };
+
+    HelloServiceImpl svc{};
+    IHelloService* svcPointer = &svc;
+    long svcId = ctx.registerService<IHelloService>(svcPointer);
+
+    //use without wrapper
+    bool called;
+    called = ctx.useService<IHelloService>(IHelloService::SERVICE_NAME, 
[](IHelloService &svc) {
+        ASSERT_EQ(std::string{"hello1"}, svc.hello());
+    });
+    ASSERT_TRUE(called);
+
+    //use with wrapper
+    called = ctx.useService<IHelloService>([](IHelloService &svc) {
+        auto result = svc.hello();
+        ASSERT_EQ(std::string{"hello1"}, result);
+    });
+    ASSERT_TRUE(called);
+
+    ctx.unregisterService(svcId);
+}
+
+/* Because this service has no SERVICE_NAME/SERVICE_VERSION is can not be 
wrapped by the DefaultServiceWrapper.
+ * Custom wrapper is needed to achieve the same effect
+ */
+class IHelloServiceNoDefaultWrapper {
+public:
+    virtual ~IHelloServiceNoDefaultWrapper() = default;
+    virtual std::string hello() = 0;
+};
+
+class HelloServiceRegistrationAdapter : public 
celix::IServiceRegistrationAdapterFactory<IHelloServiceNoDefaultWrapper, 
IHelloServiceNoDefaultWrapper> {
+public:
+    class ServiceAdapter : public 
celix::IServiceAdapter<IHelloServiceNoDefaultWrapper> {
+    public:
+        ServiceAdapter(IHelloServiceNoDefaultWrapper *_svc) : svc{_svc} {}
+        virtual ~ServiceAdapter() = default;
+        IHelloServiceNoDefaultWrapper* adapt() override { return svc; }
+    private:
+        IHelloServiceNoDefaultWrapper* svc;
+    };
+
+    virtual ~HelloServiceRegistrationAdapter() = default;
+    std::string serviceName() override { return "HelloService"; }
+    std::string serviceVersion() override { return "1.0.0"; }
+    std::string serviceLanguage() override { return 
celix::Constants::SERVICE_CXX_LANG; }
+    celix::IServiceAdapter<IHelloServiceNoDefaultWrapper>* 
createAdapter(IHelloServiceNoDefaultWrapper *svc) override { return new 
ServiceAdapter{svc}; }
+};
+
+celix::IServiceRegistrationAdapterFactory<IHelloServiceNoDefaultWrapper,IHelloServiceNoDefaultWrapper>&
 serviceRegistrationAdapterFactoryFor(IHelloServiceNoDefaultWrapper */*dummy*/) 
{
+    static HelloServiceRegistrationAdapter factory{};
+    return factory;
+}
+
+class HelloServiceUsageAdapter : public 
celix::IServiceUsageAdapterFactory<IHelloServiceNoDefaultWrapper> {
+public:
+    class ServiceAdapter : public 
celix::IServiceAdapter<IHelloServiceNoDefaultWrapper> {
+    public:
+        ServiceAdapter(void *_svc) : 
svc{static_cast<IHelloServiceNoDefaultWrapper*>(_svc)} {}
+        virtual ~ServiceAdapter() = default;
+        IHelloServiceNoDefaultWrapper* adapt() override { return svc; }
+    private:
+        IHelloServiceNoDefaultWrapper* svc;
+    };
+
+    virtual ~HelloServiceUsageAdapter() = default;
+    std::string serviceName() override { return "HelloService"; }
+    std::string serviceVersionRange() override { return "[1,2)"; }
+    std::string serviceLanguage() override { return 
celix::Constants::SERVICE_CXX_LANG; }
+    celix::IServiceAdapter<IHelloServiceNoDefaultWrapper>* createAdapter(void 
*registeredSvc) override { return new ServiceAdapter(registeredSvc); }
+};
+
+
+
+celix::IServiceUsageAdapterFactory<IHelloServiceNoDefaultWrapper>& 
serviceUsageAdapterFactoryFor(IHelloServiceNoDefaultWrapper*) {
+    static HelloServiceUsageAdapter factory{};
+    return factory;
+}
+
+TEST_F(ServiceAdapterTest, RegisterServiceWithCustomWrapperTest) {
+    auto &ctx = this->framework().getFrameworkContext();
+
+    class HelloServiceImpl : public IHelloServiceNoDefaultWrapper {
+    public:
+        virtual ~HelloServiceImpl() = default;
+        std::string hello() override {
+            return std::string{"hello1"};
+        }
+    };
+
+    HelloServiceImpl svc{};
+    long svcId = ctx.registerService<IHelloServiceNoDefaultWrapper>(&svc);
+
+    //use without wrapper
+    bool called = 
ctx.useService<IHelloServiceNoDefaultWrapper>("HelloService", 
[](IHelloServiceNoDefaultWrapper &svc) {
+        ASSERT_EQ(std::string{"hello1"}, svc.hello());
+    });
+    ASSERT_TRUE(called);
+
+    //use with wrapper
+    called = 
ctx.useService<IHelloServiceNoDefaultWrapper>([](IHelloServiceNoDefaultWrapper 
&svc) {
+        ASSERT_EQ(std::string{"hello1"}, svc.hello());
+    });
+    ASSERT_TRUE(called);
+
+    ctx.unregisterService(svcId);
+}
+
+#define HELLO_SERVICE_NAME "hello_service"
+#define HELLO_SERVICE_VERSION "1.0.0"
+
+//The underlining c service
+typedef struct do_service {
+    void *handle;
+    int (*do_something)(void* handle);
+} do_service_t;
+
+//The C++ service to use in the C++ context
+class IDoService {
+public:
+    virtual ~IDoService() = default;
+    virtual int do_something() = 0;
+};
+
+class DoServiceToCWrapper : public 
celix::IServiceRegistrationAdapterFactory<IDoService, do_service_t> {
+public:
+    class ServiceAdapter : public celix::IServiceAdapter<do_service_t> {
+    public:
+        ServiceAdapter(IDoService *svc) {
+            cSvc.handle = static_cast<void*>(svc);
+            cSvc.do_something = [](void *handle) -> int {
+                auto* s = static_cast<IDoService*>(handle);
+                return s->do_something();
+            };
+        }
+        virtual ~ServiceAdapter() = default;
+        do_service_t* adapt() override { return &cSvc; }
+    private:
+        do_service_t cSvc{};
+    };
+
+    virtual ~DoServiceToCWrapper() = default;
+    std::string serviceName() override { return "do_service"; }
+    std::string serviceVersion() override { return "1.0.0"; }
+    std::string serviceLanguage() override { return 
celix::Constants::SERVICE_C_LANG; }
+    celix::IServiceAdapter<do_service_t>* createAdapter(IDoService* svc) 
override { return new ServiceAdapter{svc}; }
+};
+
+celix::IServiceRegistrationAdapterFactory<IDoService, do_service_t>& 
serviceRegistrationAdapterFactoryFor(IDoService */*dummy*/) {
+    static DoServiceToCWrapper factory{};
+    return factory;
+}
+
+class DoServiceFromCWrapper : public 
celix::IServiceUsageAdapterFactory<IDoService> {
+public:
+    class ServiceAdapter : public celix::IServiceAdapter<IDoService>, public 
IDoService {
+    public:
+        ServiceAdapter(void *_svc) : cSvc{static_cast<do_service_t*>(_svc)} {}
+        virtual ~ServiceAdapter() = default;
+        IDoService* adapt() override { return this; }
+
+        int do_something() override {
+            return cSvc->do_something(cSvc->handle);
+        }
+    private:
+        do_service_t* cSvc;
+    };
+
+    virtual ~DoServiceFromCWrapper() = default;
+    std::string serviceName() override { return "do_service"; }
+    std::string serviceVersionRange() override { return "[1,2)"; }
+    std::string serviceLanguage() override { return 
celix::Constants::SERVICE_C_LANG; }
+    celix::IServiceAdapter<IDoService>* createAdapter(void *registeredSvc) 
override { return new ServiceAdapter{registeredSvc}; }
+};
+
+celix::IServiceUsageAdapterFactory<IDoService>& 
serviceUsageAdapterFactoryFor(IDoService* /*dummy_used_for_infer*/) {
+    static DoServiceFromCWrapper factory{};
+    return factory;
+}
+
+TEST_F(ServiceAdapterTest, RegisterServiceWithCxxToCWrapperTest) {
+    auto &ctx = this->framework().getFrameworkContext();
+
+    class DoServiceImpl : public IDoService {
+    public:
+        virtual ~DoServiceImpl() = default;
+        int do_something() override {
+            return 42;
+        }
+    };
+
+    DoServiceImpl svc{};
+    long svcId = ctx.registerService<IDoService>(&svc);
+    ASSERT_TRUE(svcId >= 0);
+    //TODO assert properties has C as svc lang
+
+    bool called = ctx.useService<IDoService>([](IDoService &svc) {
+        int result = svc.do_something();
+        ASSERT_EQ(42, result);
+    });
+    ASSERT_TRUE(called);
+
+
+    called = false;
+    long trkId = ctx.trackService<IDoService>([&](IDoService *svc) {
+        called = true;
+        ASSERT_EQ(42, svc->do_something());
+    });
+    ASSERT_TRUE(trkId >= 0);
+    ASSERT_TRUE(called);
+    ctx.stopTracker(trkId);
+
+    ctx.unregisterService(svcId);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/d9e95de8/libs/framework/include/celix/BundleContext.h
----------------------------------------------------------------------
diff --git a/libs/framework/include/celix/BundleContext.h 
b/libs/framework/include/celix/BundleContext.h
index 319cbfb..b3ce0b4 100644
--- a/libs/framework/include/celix/BundleContext.h
+++ b/libs/framework/include/celix/BundleContext.h
@@ -26,6 +26,7 @@
 #include "celix/Properties.h"
 #include "celix/Bundle.h"
 #include "celix/IServiceFactory.h"
+#include "celix/ServiceAdapter.h"
 
 #ifndef CXX_CELIX_BUNDLECONTEXT_H
 #define CXX_CELIX_BUNDLECONTEXT_H
@@ -138,6 +139,10 @@ namespace celix {
         BundleContext(celix_bundle_context_t *ctx, celix::Framework& fw); 
//TODO hide somehow ... friend ?
         virtual ~BundleContext();
 
+        //TODO document, only possible if a service wrapper is available
+        template<typename I>
+        long registerService(I *svcWithWrapper, celix::Properties props = {}) 
noexcept;
+
         template<typename I>
         long registerService(I *svc, const std::string &serviceName, 
celix::Properties props = {}) noexcept;
 
@@ -172,6 +177,19 @@ namespace celix {
         long trackService(const std::string &serviceName, std::function<void(I 
*svc)> set) noexcept;
 
         /**
+        * track service for the provided service type using a 
ServiceUsageAdaptor.
+        * The highest ranking services will used for the callback.
+        * If a new and higher ranking services the callback with be called 
again with the new service.
+        * If a service is removed a the callback with be called with next 
highest ranking service or NULL as service.
+        *
+        * @param serviceName The required service name to track
+        * @param set is a required callback, which will be called when a new 
highest ranking service is set.
+        * @return the tracker id or < 0 if unsuccessful.
+        */
+        template<typename I>
+        long trackService(std::function<void(I *svc)> set) noexcept;
+
+        /**
          * track services for the provided serviceName and/or filter.
          *
          * @param serviceName The required service name to track
@@ -193,22 +211,35 @@ namespace celix {
         template<typename I>
         long trackServicesWithOptions(const celix::ServiceTrackingOptions<I>& 
opts) noexcept;
 
-
-        /**
-         * Note use function by const reference. Only used during the call.
-         * @param serviceId
-         * @param I
-         * @return
-         */
+        //TODO remove if WithOptions is available
         template<typename I>
         bool useServiceWithId(long serviceId, const std::string 
&/*serviceName*/ /*sanity*/, const std::function<void(I &svc, const 
celix::Properties &props, const celix::Bundle &svcOwner)> &use) noexcept;
 
         template<typename I>
+        bool useServiceWithId(long serviceId, const std::string 
&/*serviceName*/ /*sanity*/, const std::function<void(I &svc)> &use) noexcept;
+
+        //TODO remove if WithOptions is available
+        template<typename I>
         bool useService(const std::string &serviceName, const 
std::function<void(I &svc, const celix::Properties &props, const celix::Bundle 
&svcOwner)> &use) noexcept;
 
         template<typename I>
+        bool useService(const std::string &serviceName, const 
std::function<void(I &svc)> &use) noexcept;
+
+        //TODO remove if WithOptions is available
+        template<typename I>
         void useServices(const std::string &serviceName, const 
std::function<void(I &svc, const celix::Properties &props, const celix::Bundle 
&svcOwner)> &use) noexcept;
 
+        template<typename I>
+        void useServices(const std::string &serviceName, const 
std::function<void(I &svc)> &use) noexcept;
+
+        //TODO rest of variants with service & wrapper for useServiceWithId, 
useService and useServices
+        template<typename I>
+        bool useService(const std::function<void(I &svc)> &use) noexcept;
+
+        template<typename I>
+        void useServices(const std::function<void(I &svc)> &use) noexcept;
+
+
         //TODO add useService(s)WithOptions
         //TODO add useCService(s) variants
 
@@ -243,20 +274,6 @@ namespace celix {
 
         celix::dm::DependencyManager& getDependencyManager() noexcept;
 
-        /** TODO
-        long registerEmbeddedBundle(
-                std::string id,
-                std::function<void(celix::BundleContext& ctx)> start,
-                std::function<void(celix::BundleContext& ctx)> stop,
-                celix::Properties manifest = {},
-                bool autoStart = true
-        ) noexcept;
-
-         void registerEmbeddedBundle(const celix::BundleRegistrationOptions 
&opts) noexcept = 0;
-        */
-
-
-
         long installBundle(const std::string &bundleLocation, bool autoStart = 
true) noexcept;
 
         void useBundles(const std::function<void(const celix::Bundle &bnd)> 
&use) noexcept;

http://git-wip-us.apache.org/repos/asf/celix/blob/d9e95de8/libs/framework/include/celix/ServiceAdapter.h
----------------------------------------------------------------------
diff --git a/libs/framework/include/celix/ServiceAdapter.h 
b/libs/framework/include/celix/ServiceAdapter.h
new file mode 100644
index 0000000..7030b7d
--- /dev/null
+++ b/libs/framework/include/celix/ServiceAdapter.h
@@ -0,0 +1,148 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <string>
+
+#include "celix/Constants.h"
+
+#ifndef CXX_CELIX_SERIVCEADAPTOR_H
+#define CXX_CELIX_SERIVCEADAPTOR_H
+
+namespace celix {
+
+    class IServiceAdapterFactoryBase {
+    public:
+        virtual ~IServiceAdapterFactoryBase() = default;
+        virtual std::string serviceName() = 0; //TODO make const std::string?
+        virtual std::string serviceLanguage() = 0;
+
+    };
+
+    class IServiceAdapterBase {
+    public:
+        virtual ~IServiceAdapterBase() = default;
+    };
+
+    template<typename I>
+    class IServiceAdapter : public IServiceAdapterBase {
+    public:
+        virtual ~IServiceAdapter() = default;
+        virtual I* adapt() = 0;
+    };
+
+    template<typename I /*from*/, typename T /*to -> register version*/>
+    class IServiceRegistrationAdapterFactory : public 
IServiceAdapterFactoryBase {
+    public:
+        using fromType = I;
+        using registeringType = T;
+        virtual ~IServiceRegistrationAdapterFactory() = default;
+        virtual std::string serviceVersion() = 0;
+        virtual IServiceAdapter<T>* createAdapter(I *fromSvc) = 0;
+    };
+
+    template<typename I>
+    class IServiceUsageAdapterFactory : public IServiceAdapterFactoryBase {
+    public:
+        using type = I;
+        virtual ~IServiceUsageAdapterFactory() = default;
+        virtual std::string serviceVersionRange() = 0;
+        virtual IServiceAdapter<I>* createAdapter(void *registeredSvc) = 0;
+    };
+
+    /**
+     * The default Service Registration Adaptor. This wrapper assumes that a 
SERVICE_NAME, SERVICE_VERSION is available.
+     * It also assumes the service is a C++ service for registering and for 
using.
+     *
+     * It is valid to create the wrapper with a nulllptr svc object, but then 
the servicePointer() method result
+     * will also be a nullptr.
+     *
+     * @tparam I The C++ Service Type
+     */
+    template<typename I>
+    class DefaultServiceRegistrationAdapterFactory : public 
IServiceRegistrationAdapterFactory<I, I> {
+    public:
+        class DefaultServiceAdapter : public IServiceAdapter<I> {
+        public:
+            DefaultServiceAdapter(I *_svc) : svc{_svc} {}
+            virtual ~DefaultServiceAdapter() = default;
+            I* adapt() override { return svc; }
+        private:
+            I* svc;
+        };
+
+        virtual ~DefaultServiceRegistrationAdapterFactory() = default;
+        std::string serviceName() override { return I::SERVICE_NAME; }
+        std::string serviceVersion() override { return I::SERVICE_VERSION; }
+        std::string serviceLanguage() override { return 
celix::Constants::SERVICE_CXX_LANG; }
+        IServiceAdapter<I>* createAdapter(I* svc) override { return new 
DefaultServiceAdapter{svc}; }
+    };
+
+
+    template<typename I>
+    IServiceRegistrationAdapterFactory<I,I>& 
serviceRegistrationAdapterFactoryFor(I */*dummy for infer*/) {
+        static DefaultServiceRegistrationAdapterFactory<I> factory{};
+        return factory;
+    }
+
+    /**
+     * The default Service Usage Adaptor. This wrapper assumes that a 
SERVICE_NAME, SERVICE_VERSION is available.
+     * It also assumes the service is a registered C++ service to be used for 
C++.
+     *
+     * @tparam I The C++ Service Type
+     */
+    template<typename I>
+    class DefaultServiceUsageAdapterFactory : public 
IServiceUsageAdapterFactory<I> {
+    public:
+        class DefaultServiceAdapter : public IServiceAdapter<I> {
+        public:
+            DefaultServiceAdapter(void *_svc) : svc{static_cast<I*>(_svc)} {}
+            virtual ~DefaultServiceAdapter() = default;
+            I* adapt() override { return svc; }
+        private:
+            I* svc;
+        };
+
+        virtual ~DefaultServiceUsageAdapterFactory() = default;
+        std::string serviceName() override { return I::SERVICE_NAME; }
+        std::string serviceVersionRange() override { return ""; /* TODO 
std::string{"["} + I::SERVICE_VERSION + std::string{"]"};*/ }
+        std::string serviceLanguage() override { return 
celix::Constants::SERVICE_CXX_LANG; }
+        IServiceAdapter<I>* createAdapter(void *registeredSvc) override { 
return new DefaultServiceAdapter{registeredSvc}; }
+    };
+
+    template<typename I>
+    IServiceUsageAdapterFactory<I>& serviceUsageAdapterFactoryFor(I* 
/*dummy_used_for_infer*/) {
+        static DefaultServiceUsageAdapterFactory<I> factory{};
+        return factory;
+    }
+
+    /* TODO enable/improve for a better error message when function using 
adaptors are used, but no adaptor can be created
+    void* createServiceUsageAdapter(void *) {
+        static_assert(false, "No matching createServiceUsageAdaptor found. 
Please provide one!");
+        return nullptr;
+    }
+
+    void* createServiceRegistrationAdapter(void *) {
+        static_assert(false, "No matching createServiceRegistrationAdaptor   
found. Please provide one!");
+        return nullptr;
+    }
+     */
+
+}
+
+#endif //CXX_CELIX_SERIVCEADAPTOR_H

http://git-wip-us.apache.org/repos/asf/celix/blob/d9e95de8/libs/framework/include/celix/impl/BundleContextImpl.h
----------------------------------------------------------------------
diff --git a/libs/framework/include/celix/impl/BundleContextImpl.h 
b/libs/framework/include/celix/impl/BundleContextImpl.h
index 67f079b..85269d7 100644
--- a/libs/framework/include/celix/impl/BundleContextImpl.h
+++ b/libs/framework/include/celix/impl/BundleContextImpl.h
@@ -56,12 +56,16 @@ namespace celix {
 
             celix_service_factory_t factory = {nullptr, nullptr, nullptr};
             celix_service_registration_options_t cOpts = {nullptr, nullptr, 
nullptr, nullptr, nullptr, nullptr};
+            std::unique_ptr<IServiceAdapterBase> adapter{nullptr};
         };
 
         struct ServiceTrackingEntry {
             celix_service_tracking_options_t cOpts{{nullptr, nullptr, nullptr, 
nullptr}, nullptr, nullptr, nullptr, nullptr,
                                                    nullptr, nullptr, nullptr, 
nullptr, nullptr, nullptr};
             std::unique_ptr<ServiceTrackingEntryFunctions> functions{nullptr};
+            std::unique_ptr<celix::IServiceAdapterFactoryBase> 
adapter{nullptr};
+            std::map<void*, std::unique_ptr<celix::IServiceAdapterBase>> 
setAdaptersCache{};
+            std::map<void*, std::unique_ptr<celix::IServiceAdapterBase>> 
addAndRemoveAdaptersCache{};
         };
     }
 
@@ -81,13 +85,16 @@ namespace celix {
         celix::dm::DependencyManager dm;
 
         std::mutex mutex{};
-        std::map<long,celix::impl::ServiceTrackingEntry> trackingEntries{};
+        std::map<long,std::unique_ptr<celix::impl::ServiceTrackingEntry>> 
trackingEntries{};
         std::map<long,celix::impl::ServiceRegistrationEntry> 
registrationEntries{};
 
         long registerServiceInternal(celix::impl::ServiceRegistrationEntry 
&&entry) noexcept;
-        long trackServicesInternal(celix::impl::ServiceTrackingEntry &&entry) 
noexcept;
-        bool useServiceInternal(const std::string &serviceName, const 
std::function<void(void *svc, const celix::Properties &props, const 
celix::Bundle &svcOwner)> &use) noexcept;
-        void useServicesInternal(const std::string &serviceName, const 
std::function<void(void *svc, const celix::Properties &props, const 
celix::Bundle &svcOwner)> &use) noexcept;
+
+        template<typename I>
+        long trackServicesInternal(const celix::ServiceTrackingOptions<I> 
&opts, celix::IServiceUsageAdapterFactory<I> *factory);
+        long 
trackServicesInternal(std::unique_ptr<celix::impl::ServiceTrackingEntry> entry) 
noexcept;
+        bool useServiceInternal(const std::string &serviceName, const 
std::string &serviceVersionRange, const std::string &serviceLang, const 
std::function<void(void *svc, const celix::Properties &props, const 
celix::Bundle &svcOwner)> &use) noexcept;
+        void useServicesInternal(const std::string &serviceName, const 
std::string &serviceVersionRange, const std::string &serviceLang, const 
std::function<void(void *svc, const celix::Properties &props, const 
celix::Bundle &svcOwner)> &use) noexcept;
     };
 }
 
@@ -239,8 +246,8 @@ inline long 
celix::BundleContext::Impl::registerServiceInternal(celix::impl::Ser
     return svcId;
 }
 
-inline long 
celix::BundleContext::Impl::trackServicesInternal(celix::impl::ServiceTrackingEntry
 &&entry) noexcept {
-    long trkId = celix_bundleContext_trackServicesWithOptions(this->c_ctx, 
&entry.cOpts);
+inline long 
celix::BundleContext::Impl::trackServicesInternal(std::unique_ptr<celix::impl::ServiceTrackingEntry>
 entry) noexcept {
+    long trkId = celix_bundleContext_trackServicesWithOptions(this->c_ctx, 
&entry->cOpts);
     if (trkId >= 0) {
         std::lock_guard<std::mutex> lock{this->mutex};
         this->trackingEntries[trkId] = std::move(entry);
@@ -250,6 +257,8 @@ inline long 
celix::BundleContext::Impl::trackServicesInternal(celix::impl::Servi
 
 inline bool celix::BundleContext::Impl::useServiceInternal(
         const std::string &serviceName,
+        const std::string &serviceVersionRange,
+        const std::string &serviceLang,
         const std::function<void(void *svc, const celix::Properties &props, 
const celix::Bundle &svcOwner)> &use) noexcept {
     auto c_use = [](void *handle, void *svc, const celix_properties_t 
*c_props, const celix_bundle_t *c_svcOwner) {
         auto *fn = static_cast<const std::function<void(void *svc, const 
celix::Properties &props, const celix::Bundle &svcOwner)> *>(handle);
@@ -263,7 +272,8 @@ inline bool celix::BundleContext::Impl::useServiceInternal(
     std::memset(&opts, 0, sizeof(opts));
 
     opts.filter.serviceName = serviceName.empty() ? nullptr : 
serviceName.c_str();;
-    opts.filter.serviceLanguage = celix::Constants::SERVICE_CXX_LANG;
+    opts.filter.versionRange = serviceVersionRange.empty() ? nullptr : 
serviceVersionRange.c_str();
+    opts.filter.serviceLanguage = serviceLang.empty() ? 
celix::Constants::SERVICE_CXX_LANG : serviceLang.c_str();
     opts.callbackHandle = (void*)&use;
     opts.useWithOwner = c_use;
 
@@ -272,6 +282,8 @@ inline bool celix::BundleContext::Impl::useServiceInternal(
 
 inline void celix::BundleContext::Impl::useServicesInternal(
         const std::string &serviceName,
+        const std::string &serviceVersionRange,
+        const std::string &serviceLang,
         const std::function<void(void *svc, const celix::Properties &props, 
const celix::Bundle &svcOwner)> &use) noexcept {
     auto c_use = [](void *handle, void *svc, const celix_properties_t 
*c_props, const celix_bundle_t *c_svcOwner) {
         auto *fn = static_cast<const std::function<void(void *svc, const 
celix::Properties &props, const celix::Bundle &svcOwner)> *>(handle);
@@ -285,13 +297,36 @@ inline void 
celix::BundleContext::Impl::useServicesInternal(
     std::memset(&opts, 0, sizeof(opts));
 
     opts.filter.serviceName = serviceName.empty() ? nullptr : 
serviceName.c_str();;
-    opts.filter.serviceLanguage = celix::Constants::SERVICE_CXX_LANG;
+    opts.filter.versionRange = serviceVersionRange.empty() ? nullptr : 
serviceVersionRange.c_str();
+    opts.filter.serviceLanguage = serviceLang.empty() ? 
celix::Constants::SERVICE_CXX_LANG : serviceLang.c_str();
     opts.callbackHandle = (void*)&use;
     opts.useWithOwner = c_use;
 
     celix_bundleContext_useServicesWithOptions(this->c_ctx, &opts);
 }
 
+template<typename I>
+long celix::BundleContext::registerService(I *svc, Properties props) noexcept {
+    using namespace celix;
+    auto &factory = serviceRegistrationAdapterFactoryFor(svc /*note svc value 
not used, just the pointer type*/);
+    auto *adapter = factory.createAdapter(svc);
+
+    celix_properties_t *c_props = celix_properties_create();
+    for (auto &pair : props) {
+        celix_properties_set(c_props, pair.first.c_str(), pair.second.c_str());
+    }
+
+    celix::impl::ServiceRegistrationEntry re{};
+    re.cOpts = CELIX_EMPTY_SERVICE_REGISTRATION_OPTIONS;
+    re.cOpts.svc = static_cast<void*>(adapter->adapt());
+    re.cOpts.serviceName = factory.serviceName().c_str();
+    re.cOpts.serviceVersion = factory.serviceVersion().c_str();
+    re.cOpts.serviceLanguage = factory.serviceLanguage().c_str();
+    re.cOpts.properties = c_props;
+    re.adapter = std::unique_ptr<IServiceAdapterBase>{adapter};
+
+    return this->pimpl->registerServiceInternal(std::move(re));
+}
 
 template<typename I>
 long celix::BundleContext::registerService(I *svc, const std::string 
&serviceName, Properties props) noexcept {
@@ -368,6 +403,19 @@ long 
celix::BundleContext::registerServiceWithOptions(const celix::ServiceRegist
 }
 
 template<typename I>
+long celix::BundleContext::trackService(std::function<void(I *svc)> set) 
noexcept {
+    using namespace celix;
+    I* dummy = nullptr;
+    auto &factory = serviceUsageAdapterFactoryFor(dummy);
+
+    celix::ServiceTrackingOptions<I> opts{factory.serviceName()};
+    opts.filter.serviceLanguage = factory.serviceLanguage();
+    opts.filter.versionRange = factory.serviceVersionRange();
+    opts.set = set;
+    return this->pimpl->trackServicesInternal<I>(opts, &factory);
+}
+
+template<typename I>
 long celix::BundleContext::trackService(const std::string &serviceName, 
std::function<void(I *svc)> set) noexcept {
     celix::ServiceTrackingOptions<I> opts{serviceName};
     opts.set = std::move(set);
@@ -384,18 +432,70 @@ long celix::BundleContext::trackServices(const 
std::string &serviceName,
 }
 
 template<typename I>
-long celix::BundleContext::trackServicesWithOptions(const 
celix::ServiceTrackingOptions<I>& opts) {
-    celix::impl::ServiceTrackingEntry entry{};
-    entry.functions = 
std::unique_ptr<celix::impl::ServiceTrackingEntryFunctions>{new 
celix::impl::ServiceTrackingEntryFunctions()};
+long celix::BundleContext::trackServicesWithOptions(const 
celix::ServiceTrackingOptions<I> &opts) {
+    return this->pimpl->trackServicesInternal<I>(opts, nullptr);
+}
+
+template<typename I>
+static I* svcFor(celix::IServiceUsageAdapterFactory<I> *factory, 
std::map<void*, std::unique_ptr<celix::IServiceAdapterBase>> &cache, void *svc) 
{
+    I* result = nullptr;
+    if (svc != nullptr) {
+        if (factory != nullptr) {
+            //checking cache
+            auto it = cache.find(svc);
+            if (it != cache.end()) {
+                celix::IServiceAdapterBase *base = it->second.get();
+                auto *adapter = static_cast<celix::IServiceAdapter<I>*>(base);
+                result = adapter->adapt();
+            } else {
+                celix::IServiceAdapter<I> *adapter = 
factory->createAdapter(svc);
+                cache[svc] = 
std::unique_ptr<celix::IServiceAdapterBase>{adapter};
+                result = adapter->adapt();
+            }
+        } else {
+            result = static_cast<I*>(svc);
+        }
+    }
+    return result;
+}
+
+static inline void updateSetCache(std::map<void*, 
std::unique_ptr<celix::IServiceAdapterBase>> &cache, void *currentSetSvc) {
+    if (currentSetSvc == nullptr) {
+        cache.clear();
+    } else {
+        auto it = cache.begin();
+        while (it != cache.end()) {
+            if (it->first != currentSetSvc) {
+                cache.erase(it++);
+            } else {
+                ++it;
+            }
+        }
+    }
+}
+
+static inline void removeFromCache(std::map<void*, 
std::unique_ptr<celix::IServiceAdapterBase>> &cache, void *removedSvc) {
+    auto it = cache.find(removedSvc);
+    if (it != cache.end()) {
+        cache.erase(it);
+    }
+}
+
+template<typename I>
+long celix::BundleContext::Impl::trackServicesInternal(const 
celix::ServiceTrackingOptions<I> &opts, celix::IServiceUsageAdapterFactory<I> 
*factory) {
+    auto entry = std::unique_ptr<celix::impl::ServiceTrackingEntry>{new 
celix::impl::ServiceTrackingEntry()};
+    auto *entryPtr = entry.get();
+    entry->functions = 
std::unique_ptr<celix::impl::ServiceTrackingEntryFunctions>{new 
celix::impl::ServiceTrackingEntryFunctions()};
 
     auto set = opts.set;
     if (set) {
-        auto voidfunc = [set](void *voidSvc) {
-            I *typedSvc = static_cast<I*>(voidSvc);
+        auto voidfunc = [entryPtr, factory, set](void *voidSvc) {
+            I *typedSvc = svcFor<I>(factory, entryPtr->setAdaptersCache, 
voidSvc);
             set(typedSvc);
+            updateSetCache(entryPtr->setAdaptersCache, voidSvc);
         };
-        entry.functions->set = voidfunc;
-        entry.cOpts.set = [](void *handle, void *svc) {
+        entry->functions->set = voidfunc;
+        entry->cOpts.set = [](void *handle, void *svc) {
             auto *fentry = 
static_cast<celix::impl::ServiceTrackingEntryFunctions*>(handle);
             (fentry->set)(svc);
         };
@@ -403,12 +503,13 @@ long celix::BundleContext::trackServicesWithOptions(const 
celix::ServiceTracking
 
     auto setWithProperties = opts.setWithProperties;
     if (setWithProperties) {
-        auto voidfunc = [setWithProperties](void *voidSvc, const 
celix::Properties &props) {
-            I *typedSvc = static_cast<I*>(voidSvc);
+        auto voidfunc = [entryPtr, factory, setWithProperties](void *voidSvc, 
const celix::Properties &props) {
+            I *typedSvc = svcFor<I>(factory, entryPtr->setAdaptersCache, 
voidSvc);
             setWithProperties(typedSvc, props);
+            updateSetCache(entryPtr->setAdaptersCache, voidSvc);
         };
-        entry.functions->setWithProperties = voidfunc;
-        entry.cOpts.setWithProperties = [](void *handle, void *svc, const 
celix_properties_t *c_props) {
+        entry->functions->setWithProperties = voidfunc;
+        entry->cOpts.setWithProperties = [](void *handle, void *svc, const 
celix_properties_t *c_props) {
             auto *fentry = 
static_cast<celix::impl::ServiceTrackingEntryFunctions*>(handle);
             celix::Properties props = createFromCProps(c_props);
             (fentry->setWithProperties)(svc, props);
@@ -417,12 +518,13 @@ long celix::BundleContext::trackServicesWithOptions(const 
celix::ServiceTracking
 
     auto setWithOwner = opts.setWithOwner;
     if (setWithOwner) {
-        auto voidfunc = [setWithOwner](void *voidSvc, const celix::Properties 
&props, const celix::Bundle &bnd) {
-            I *typedSvc = static_cast<I*>(voidSvc);
+        auto voidfunc = [entryPtr, factory, setWithOwner](void *voidSvc, const 
celix::Properties &props, const celix::Bundle &bnd) {
+            I *typedSvc = svcFor<I>(factory, entryPtr->setAdaptersCache, 
voidSvc);
             setWithOwner(typedSvc, props, bnd);
+            updateSetCache(entryPtr->setAdaptersCache, voidSvc);
         };
-        entry.functions->setWithOwner = voidfunc;
-        entry.cOpts.setWithOwner = [](void *handle, void *svc, const 
celix_properties_t *c_props, const celix_bundle_t *c_bnd) {
+        entry->functions->setWithOwner = voidfunc;
+        entry->cOpts.setWithOwner = [](void *handle, void *svc, const 
celix_properties_t *c_props, const celix_bundle_t *c_bnd) {
             auto *fentry = 
static_cast<celix::impl::ServiceTrackingEntryFunctions*>(handle);
             celix::Properties props = createFromCProps(c_props);
             auto m_bnd = const_cast<celix_bundle_t *>(c_bnd);
@@ -433,12 +535,12 @@ long celix::BundleContext::trackServicesWithOptions(const 
celix::ServiceTracking
 
     auto add = opts.add;
     if (add) {
-        auto voidfunc = [add](void *voidSvc) {
-            I *typedSvc = static_cast<I*>(voidSvc);
+        auto voidfunc = [entryPtr, factory, add](void *voidSvc) {
+            I *typedSvc = svcFor<I>(factory, 
entryPtr->addAndRemoveAdaptersCache, voidSvc);
             add(typedSvc);
         };
-        entry.functions->add = voidfunc;
-        entry.cOpts.add = [](void *handle, void *svc) {
+        entry->functions->add = voidfunc;
+        entry->cOpts.add = [](void *handle, void *svc) {
             auto *fentry = 
static_cast<celix::impl::ServiceTrackingEntryFunctions*>(handle);
             (fentry->add)(svc);
         };
@@ -446,26 +548,26 @@ long celix::BundleContext::trackServicesWithOptions(const 
celix::ServiceTracking
 
     auto addWithProperties = opts.addWithProperties;
     if (addWithProperties) {
-        auto voidfunc = [addWithProperties](void *voidSvc, const 
celix::Properties &props) {
-            I *typedSvc = static_cast<I*>(voidSvc);
+        auto voidfunc = [entryPtr, factory, addWithProperties](void *voidSvc, 
const celix::Properties &props) {
+            I *typedSvc = svcFor<I>(factory, 
entryPtr->addAndRemoveAdaptersCache, voidSvc);
             addWithProperties(typedSvc, props);
         };
-        entry.functions->addWithProperties = voidfunc;
-        entry.cOpts.addWithProperties = [](void *handle, void *svc, const 
celix_properties_t *c_props) {
+        entry->functions->addWithProperties = voidfunc;
+        entry->cOpts.addWithProperties = [](void *handle, void *svc, const 
celix_properties_t *c_props) {
             auto *fentry = 
static_cast<celix::impl::ServiceTrackingEntryFunctions*>(handle);
             celix::Properties props = createFromCProps(c_props);
             (fentry->addWithProperties)(svc, props);
         };
     }
 
-    auto addWithOwner = opts.setWithOwner;
+    auto addWithOwner = opts.addWithOwner;
     if (addWithOwner) {
-        auto voidfunc = [addWithOwner](void *voidSvc, const celix::Properties 
&props, const celix::Bundle &bnd) {
-            I *typedSvc = static_cast<I*>(voidSvc);
+        auto voidfunc = [entryPtr, factory, addWithOwner](void *voidSvc, const 
celix::Properties &props, const celix::Bundle &bnd) {
+            I *typedSvc = svcFor<I>(factory, 
entryPtr->addAndRemoveAdaptersCache, voidSvc);
             addWithOwner(typedSvc, props, bnd);
         };
-        entry.functions->addWithOwner = voidfunc;
-        entry.cOpts.addWithOwner = [](void *handle, void *svc, const 
celix_properties_t *c_props, const celix_bundle_t *c_bnd) {
+        entry->functions->addWithOwner = voidfunc;
+        entry->cOpts.addWithOwner = [](void *handle, void *svc, const 
celix_properties_t *c_props, const celix_bundle_t *c_bnd) {
             auto *fentry = 
static_cast<celix::impl::ServiceTrackingEntryFunctions*>(handle);
             celix::Properties props = createFromCProps(c_props);
             auto m_bnd = const_cast<celix_bundle_t *>(c_bnd);
@@ -476,12 +578,13 @@ long celix::BundleContext::trackServicesWithOptions(const 
celix::ServiceTracking
 
     auto remove = opts.remove;
     if (remove) {
-        auto voidfunc = [remove](void *voidSvc) {
-            I *typedSvc = static_cast<I*>(voidSvc);
+        auto voidfunc = [entryPtr, factory, remove](void *voidSvc) {
+            I *typedSvc = svcFor<I>(factory, 
entryPtr->addAndRemoveAdaptersCache, voidSvc);
             remove(typedSvc);
+            removeFromCache(entryPtr->addAndRemoveAdaptersCache, voidSvc);
         };
-        entry.functions->remove = voidfunc;
-        entry.cOpts.remove = [](void *handle, void *svc) {
+        entry->functions->remove = voidfunc;
+        entry->cOpts.remove = [](void *handle, void *svc) {
             auto *fentry = 
static_cast<celix::impl::ServiceTrackingEntryFunctions*>(handle);
             (fentry->add)(svc);
         };
@@ -489,12 +592,13 @@ long celix::BundleContext::trackServicesWithOptions(const 
celix::ServiceTracking
 
     auto removeWithProperties = opts.removeWithProperties;
     if (removeWithProperties) {
-        auto voidfunc = [removeWithProperties](void *voidSvc, const 
celix::Properties &props) {
-            I *typedSvc = static_cast<I*>(voidSvc);
+        auto voidfunc = [entryPtr, factory, removeWithProperties](void 
*voidSvc, const celix::Properties &props) {
+            I *typedSvc = svcFor<I>(factory, 
entryPtr->addAndRemoveAdaptersCache, voidSvc);
             removeWithProperties(typedSvc, props);
+            removeFromCache(entryPtr->addAndRemoveAdaptersCache, voidSvc);
         };
-        entry.functions->removeWithProperties = voidfunc;
-        entry.cOpts.removeWithProperties = [](void *handle, void *svc, const 
celix_properties_t *c_props) {
+        entry->functions->removeWithProperties = voidfunc;
+        entry->cOpts.removeWithProperties = [](void *handle, void *svc, const 
celix_properties_t *c_props) {
             auto *fentry = 
static_cast<celix::impl::ServiceTrackingEntryFunctions*>(handle);
             celix::Properties props = createFromCProps(c_props);
             (fentry->removeWithProperties)(svc, props);
@@ -503,12 +607,13 @@ long celix::BundleContext::trackServicesWithOptions(const 
celix::ServiceTracking
 
     auto removeWithOwner = opts.removeWithOwner;
     if (removeWithOwner) {
-        auto voidfunc = [removeWithOwner](void *voidSvc, const 
celix::Properties &props, const celix::Bundle &bnd) {
-            I *typedSvc = static_cast<I*>(voidSvc);
+        auto voidfunc = [entryPtr, factory, removeWithOwner](void *voidSvc, 
const celix::Properties &props, const celix::Bundle &bnd) {
+            I *typedSvc = svcFor<I>(factory, 
entryPtr->addAndRemoveAdaptersCache, voidSvc);
             removeWithOwner(typedSvc, props, bnd);
+            removeFromCache(entryPtr->addAndRemoveAdaptersCache, voidSvc);
         };
-        entry.functions->removeWithOwner = voidfunc;
-        entry.cOpts.removeWithOwner = [](void *handle, void *svc, const 
celix_properties_t *c_props, const celix_bundle_t *c_bnd) {
+        entry->functions->removeWithOwner = voidfunc;
+        entry->cOpts.removeWithOwner = [](void *handle, void *svc, const 
celix_properties_t *c_props, const celix_bundle_t *c_bnd) {
             auto *fentry = 
static_cast<celix::impl::ServiceTrackingEntryFunctions*>(handle);
             celix::Properties props = createFromCProps(c_props);
             auto m_bnd = const_cast<celix_bundle_t *>(c_bnd);
@@ -517,14 +622,14 @@ long celix::BundleContext::trackServicesWithOptions(const 
celix::ServiceTracking
         };
     }
 
-    entry.cOpts.filter.serviceName = opts.filter.serviceName.c_str();
-    entry.cOpts.filter.serviceLanguage = opts.filter.serviceLanguage.c_str();
-    entry.cOpts.filter.versionRange = opts.filter.versionRange.c_str();
-    entry.cOpts.filter.filter = opts.filter.filter.c_str();
+    entry->cOpts.filter.serviceName = opts.filter.serviceName.c_str();
+    entry->cOpts.filter.serviceLanguage = opts.filter.serviceLanguage.c_str();
+    entry->cOpts.filter.versionRange = opts.filter.versionRange.c_str();
+    entry->cOpts.filter.filter = opts.filter.filter.c_str();
 
-    entry.cOpts.callbackHandle = entry.functions.get();
+    entry->cOpts.callbackHandle = entry->functions.get();
 
-    return this->pimpl->trackServicesInternal(std::move(entry));
+    return this->trackServicesInternal(std::move(entry));
 }
 
 template<typename I>
@@ -535,20 +640,71 @@ bool celix::BundleContext::useServiceWithId(long 
serviceId, const std::string &/
 }
 
 template<typename I>
+bool celix::BundleContext::useServiceWithId(long serviceId, const std::string 
&/*serviceName*/ /*sanity*/, const std::function<void(I &svc)> &/*use*/) 
noexcept {
+    std::string filter = std::string{"(service.id="} + 
std::to_string(serviceId) + std::string{")"};
+    //TODO use useServiceWithOptions return this->useService<I>(serviceName, 
"", filter, use);
+    return false;
+}
+
+template<typename I>
 bool celix::BundleContext::useService(const std::string &serviceName, const 
std::function<void(I &svc, const celix::Properties &props, const celix::Bundle 
&svcOwner)> &use) noexcept {
-    return this->pimpl->useServiceInternal(serviceName, [use](void *voidSvc, 
const celix::Properties &props, const celix::Bundle &svcOwner) {
+    return this->pimpl->useServiceInternal(serviceName, "", "", [use](void 
*voidSvc, const celix::Properties &props, const celix::Bundle &svcOwner) {
         I *typedSvc = static_cast<I*>(voidSvc);
         use(*typedSvc, props, svcOwner);
     });
 }
 
 template<typename I>
+bool celix::BundleContext::useService(const std::string &serviceName, const 
std::function<void(I &svc)> &use) noexcept {
+    return this->pimpl->useServiceInternal(serviceName, "", "", [use](void 
*voidSvc, const celix::Properties &, const celix::Bundle &) {
+        I *typedSvc = static_cast<I*>(voidSvc);
+        use(*typedSvc);
+    });
+}
+
+template<typename I>
+bool celix::BundleContext::useService(const std::function<void(I &svc)> &use) 
noexcept {
+    using namespace celix;
+    I* dummy = nullptr;
+    auto &factory = serviceUsageAdapterFactoryFor(dummy);
+    bool called = this->pimpl->useServiceInternal(factory.serviceName(), 
factory.serviceVersionRange(), factory.serviceLanguage(), [&](void *voidSvc, 
const celix::Properties&, const celix::Bundle&){
+        auto *adapter = factory.createAdapter(voidSvc);
+        auto *adapted = adapter->adapt();
+        use(*adapted);
+        free(adapter);
+    });
+    return called;
+}
+
+template<typename I>
+void celix::BundleContext::useServices(const std::function<void(I &svc)> &use) 
noexcept {
+    using namespace celix;
+    I* dummy = nullptr;
+    auto &factory = serviceUsageAdapterFactoryFor(dummy);
+    this->pimpl->useServicesInternal(factory.serviceName(), 
factory.serviceVersionRange(), factory.serviceLanguage(), [&](void *voidSvc, 
const celix::Properties&, const celix::Bundle&){
+        auto *adapter = factory.createAdapter(voidSvc);
+        auto *adapted = adapter->adapt();
+        use(*adapted);
+        free(adapter);
+    });
+}
+
+template<typename I>
 void celix::BundleContext::useServices(const std::string &serviceName, const 
std::function<void(I &svc, const celix::Properties &props, const celix::Bundle 
&svcOwner)> &use) noexcept {
-    this->pimpl->useServicesInternal(serviceName, [use](void *voidSvc, const 
celix::Properties &props, const celix::Bundle &svcOwner) {
+    this->pimpl->useServicesInternal(serviceName, "", "", [use](void *voidSvc, 
const celix::Properties &props, const celix::Bundle &svcOwner) {
         I *typedSvc = static_cast<I*>(voidSvc);
         use(*typedSvc, props, svcOwner);
     });
 }
 
+template<typename I>
+void celix::BundleContext::useServices(const std::string &serviceName, const 
std::function<void(I &svc)> &use) noexcept {
+    this->pimpl->useServicesInternal(serviceName, "", "", [use](void *voidSvc, 
const celix::Properties &, const celix::Bundle &) {
+        I *typedSvc = static_cast<I*>(voidSvc);
+        use(*typedSvc);
+    });
+}
+
+
 
 #endif //CELIX_IMPL_BUNDLECONTEXTIMPL_H

http://git-wip-us.apache.org/repos/asf/celix/blob/d9e95de8/libs/framework/src/service_tracker.c
----------------------------------------------------------------------
diff --git a/libs/framework/src/service_tracker.c 
b/libs/framework/src/service_tracker.c
index e718874..c2d236f 100644
--- a/libs/framework/src/service_tracker.c
+++ b/libs/framework/src/service_tracker.c
@@ -606,10 +606,10 @@ celix_service_tracker_t* 
celix_serviceTracker_createWithOptions(
             //setting filter
             if (opts->filter.filter != NULL && opts->filter.versionRange != 
NULL) {
                 //TODO version range
-                asprintf(&tracker->filter, "&((%s=%s)(%s=%s)%s)", 
OSGI_FRAMEWORK_OBJECTCLASS, opts->filter.serviceName, 
CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang, opts->filter.filter);
+                asprintf(&tracker->filter, "(&(%s=%s)(%s=%s)%s)", 
OSGI_FRAMEWORK_OBJECTCLASS, opts->filter.serviceName, 
CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang, opts->filter.filter);
             } else if (opts->filter.versionRange != NULL) {
                 //TODO version range
-                asprintf(&tracker->filter, "&((%s=%s)(%s=%s))", 
OSGI_FRAMEWORK_OBJECTCLASS, opts->filter.serviceName, 
CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang);
+                asprintf(&tracker->filter, "(&(%s=%s)(%s=%s))", 
OSGI_FRAMEWORK_OBJECTCLASS, opts->filter.serviceName, 
CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang);
             } else if (opts->filter.filter != NULL) {
                 asprintf(&tracker->filter, "(&(%s=%s)(%s=%s)%s)", 
OSGI_FRAMEWORK_OBJECTCLASS, opts->filter.serviceName, 
CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang, opts->filter.filter);
             } else {

Reply via email to