Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 64CDF200BCA for ; Mon, 21 Nov 2016 16:41:08 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 633EA160AF9; Mon, 21 Nov 2016 15:41:08 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 3532A160AEF for ; Mon, 21 Nov 2016 16:41:07 +0100 (CET) Received: (qmail 20055 invoked by uid 500); 21 Nov 2016 15:41:06 -0000 Mailing-List: contact commits-help@celix.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@celix.apache.org Delivered-To: mailing list commits@celix.apache.org Received: (qmail 20042 invoked by uid 99); 21 Nov 2016 15:41:06 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 21 Nov 2016 15:41:06 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 2FDABE38F9; Mon, 21 Nov 2016 15:41:06 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: pnoltes@apache.org To: commits@celix.apache.org Message-Id: <5e234dba4c834d3b901566fad811092b@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: celix git commit: CELIX-386: Fixes an issues when C++ objects provide mutiple services. Also extends the example with a mutiple service providing example. Date: Mon, 21 Nov 2016 15:41:06 +0000 (UTC) archived-at: Mon, 21 Nov 2016 15:41:08 -0000 Repository: celix Updated Branches: refs/heads/develop 5e9db3db7 -> 261161fe4 CELIX-386: Fixes an issues when C++ objects provide mutiple services. Also extends the example with a mutiple service providing example. Fixes issue in TypeName where namespace where not used for the service name and added an service with namespace example. Project: http://git-wip-us.apache.org/repos/asf/celix/repo Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/261161fe Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/261161fe Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/261161fe Branch: refs/heads/develop Commit: 261161fe438494a176e756894bfb0b351a1e8008 Parents: 5e9db3d Author: Pepijn Noltes Authored: Tue Nov 15 19:30:23 2016 +0100 Committer: Pepijn Noltes Committed: Mon Nov 21 16:40:21 2016 +0100 ---------------------------------------------------------------------- .../include/celix/dm/Component.h | 6 +-- .../include/celix/dm/Component_Impl.h | 39 +++++++++----- .../include/celix/dm/ServiceDependency_Impl.h | 4 +- dependency_manager_cxx/include/celix/dm/types.h | 11 ++-- examples/dm_example_cxx/api/IName.h | 39 ++++++++++++++ examples/dm_example_cxx/api/IPhase1.h | 1 + examples/dm_example_cxx/api/IPhase2.h | 1 + .../dm_example_cxx/phase1/include/Phase1Cmp.h | 6 ++- .../dm_example_cxx/phase1/src/BarActivator.cc | 57 -------------------- .../phase1/src/Phase1Activator.cc | 1 + examples/dm_example_cxx/phase1/src/Phase1Cmp.cc | 4 ++ .../dm_example_cxx/phase2/include/Phase2Cmp.h | 4 +- .../phase2a/src/Phase2aActivator.cc | 5 ++ 13 files changed, 93 insertions(+), 85 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/celix/blob/261161fe/dependency_manager_cxx/include/celix/dm/Component.h ---------------------------------------------------------------------- diff --git a/dependency_manager_cxx/include/celix/dm/Component.h b/dependency_manager_cxx/include/celix/dm/Component.h index d323389..cd0a16b 100644 --- a/dependency_manager_cxx/include/celix/dm/Component.h +++ b/dependency_manager_cxx/include/celix/dm/Component.h @@ -105,13 +105,13 @@ namespace celix { namespace dm { /** * Adds a C++ interface to provide as service to the Celix framework. - * The interface name will be inferred using the I template. * + * @param serviceName The service name to use * @param version The version of the interface (e.g. "1.0.0"), can be an empty string * @param properties To (meta) properties to provide with the service * @return the DM Component reference for chaining (fluent API) */ - template Component& addInterface(const std::string version, const Properties properties = Properties{}); + template Component& addInterfaceWithName(const std::string serviceName, const std::string version = std::string{}, const Properties properties = Properties{}); /** * Adds a C++ interface to provide as service to the Celix framework. @@ -121,7 +121,7 @@ namespace celix { namespace dm { * @param properties To (meta) properties to provide with the service * @return the DM Component reference for chaining (fluent API) */ - Component& addInterface(const std::string serviceName, const std::string version = std::string{}, const Properties properties = Properties{}); + template Component& addInterface(const std::string version = std::string{}, const Properties properties = Properties{}); /** * Adds a C interface to provide as service to the Celix framework. http://git-wip-us.apache.org/repos/asf/celix/blob/261161fe/dependency_manager_cxx/include/celix/dm/Component_Impl.h ---------------------------------------------------------------------- diff --git a/dependency_manager_cxx/include/celix/dm/Component_Impl.h b/dependency_manager_cxx/include/celix/dm/Component_Impl.h index d2fcf94..b474421 100644 --- a/dependency_manager_cxx/include/celix/dm/Component_Impl.h +++ b/dependency_manager_cxx/include/celix/dm/Component_Impl.h @@ -23,6 +23,7 @@ #include #include +#include using namespace celix::dm; @@ -36,28 +37,38 @@ Component::~Component() { template template -Component& Component::addInterface(const std::string version, const Properties props) { - std::string name = typeName(); - if (name.empty()) { - std::cerr << "Cannot add interface, because type name could not be inferred. function: '" << __PRETTY_FUNCTION__ << "'\n"; +Component& Component::addInterfaceWithName(const std::string serviceName, const std::string version, const Properties properties) { + if (!serviceName.empty()) { + //setup c properties + properties_pt cProperties = properties_create(); + properties_set(cProperties, CELIX_FRAMEWORK_SERVICE_LANGUAGE, CELIX_FRAMEWORK_SERVICE_CXX_LANGUAGE); + for (auto iter = properties.begin(); iter != properties.end(); iter++) { + properties_set(cProperties, (char *) iter->first.c_str(), (char *) iter->second.c_str()); + } + + T* cmpPtr = &this->getInstance(); + I* intfPtr = static_cast(cmpPtr); //NOTE T should implement I + + const char *cVersion = version.empty() ? nullptr : version.c_str(); + component_addInterface(this->cComponent(), (char *) serviceName.c_str(), (char *) cVersion, + intfPtr, cProperties); } else { - this->addInterface(name, version.c_str(), props); + std::cerr << "Cannot add interface with a empty name\n"; } + return *this; } template -Component& Component::addInterface(const std::string serviceName, const std::string version, const Properties properties) { - properties_pt cProperties = properties_create(); - properties_set(cProperties, CELIX_FRAMEWORK_SERVICE_LANGUAGE, CELIX_FRAMEWORK_SERVICE_CXX_LANGUAGE); - for (auto iter = properties.begin(); iter != properties.end(); iter++) { - properties_set(cProperties, (char*)iter->first.c_str(), (char*)iter->second.c_str()); +template +Component& Component::addInterface(const std::string version, const Properties properties) { + //get name if not provided + std::string serviceName = typeName(); + if (serviceName.empty()) { + std::cerr << "Cannot add interface, because type name could not be inferred. function: '" << __PRETTY_FUNCTION__ << "'\n"; } - const char *cVersion = version.empty() ? nullptr : version.c_str(); - component_addInterface(this->cComponent(), (char*)serviceName.c_str(), (char*)cVersion, &this->getInstance(), cProperties); - - return *this; + return this->addInterfaceWithName(serviceName, version, properties); }; template http://git-wip-us.apache.org/repos/asf/celix/blob/261161fe/dependency_manager_cxx/include/celix/dm/ServiceDependency_Impl.h ---------------------------------------------------------------------- diff --git a/dependency_manager_cxx/include/celix/dm/ServiceDependency_Impl.h b/dependency_manager_cxx/include/celix/dm/ServiceDependency_Impl.h index 2bc788d..f22c0c5 100644 --- a/dependency_manager_cxx/include/celix/dm/ServiceDependency_Impl.h +++ b/dependency_manager_cxx/include/celix/dm/ServiceDependency_Impl.h @@ -354,7 +354,7 @@ ServiceDependency& ServiceDependency::setStrategy(DependencyUpdateStra template int ServiceDependency::invokeCallback(void(T::*fp)(I*), const void* service) { T *cmp = this->componentInstance; - I *svc = (I *) service; + I *svc = (I*)service; (cmp->*fp)(svc); return 0; }; @@ -364,7 +364,7 @@ int ServiceDependency::invokeCallbackWithProperties(void(T::*fp)(I*, Proper service_registration_pt reg {nullptr}; properties_pt props {nullptr}; T *cmp = this->componentInstance; - I *svc = (I *) service; + I *svc = (I*)service; serviceReference_getServiceRegistration(ref, ®); serviceRegistration_getProperties(reg, &props); http://git-wip-us.apache.org/repos/asf/celix/blob/261161fe/dependency_manager_cxx/include/celix/dm/types.h ---------------------------------------------------------------------- diff --git a/dependency_manager_cxx/include/celix/dm/types.h b/dependency_manager_cxx/include/celix/dm/types.h index e1f33d9..43f0f04 100644 --- a/dependency_manager_cxx/include/celix/dm/types.h +++ b/dependency_manager_cxx/include/celix/dm/types.h @@ -61,22 +61,21 @@ namespace celix { namespace dm { free(demangled_name); } #else - const char *templateStr = "INTERFACE_TYPENAME ="; + const char *templateStr = "INTERFACE_TYPENAME = "; const size_t templateStrLen = strlen(templateStr); result = __PRETTY_FUNCTION__; //USING pretty function to retrieve the filled in template argument without using typeid() - - size_t bpos = result.find(templateStr) + templateStrLen + 1; //find begin pos after INTERFACE_TYPENAME = entry + size_t bpos = result.find(templateStr) + templateStrLen; //find begin pos after INTERFACE_TYPENAME = entry size_t epos = bpos; - while (isalnum(result[epos]) || result[epos] == '_' || result[epos] == ';') { + while (isalnum(result[epos]) || result[epos] == '_' || result[epos] == ':') { epos += 1; } size_t len = epos - bpos; result = result.substr(bpos, len); #endif - //std::cout << "PRETTY IS '" << __PRETTY_FUNCTION__ << "'\n"; - //std::cout << "RESULT IS '" << result << "'\n"; +// std::cout << "PRETTY IS '" << __PRETTY_FUNCTION__ << "'\n"; +// std::cout << "RESULT IS '" << result << "'\n"; if (result.empty()) { std::cerr << "Cannot infer type name in function call '" << __PRETTY_FUNCTION__ << "'\n'"; http://git-wip-us.apache.org/repos/asf/celix/blob/261161fe/examples/dm_example_cxx/api/IName.h ---------------------------------------------------------------------- diff --git a/examples/dm_example_cxx/api/IName.h b/examples/dm_example_cxx/api/IName.h new file mode 100644 index 0000000..89edb19 --- /dev/null +++ b/examples/dm_example_cxx/api/IName.h @@ -0,0 +1,39 @@ +/** + * 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. + */ + +#ifndef CELIX_INAME_H +#define CELIX_INAME_H + +#define INAME_VERSION "1.0.0" + +#include + +namespace srv { + namespace info { + class IName { + protected: + IName() = default; + ~IName() = default; + public: + virtual std::string getName() = 0; + }; + } +} + +#endif //CELIX_INAME_H http://git-wip-us.apache.org/repos/asf/celix/blob/261161fe/examples/dm_example_cxx/api/IPhase1.h ---------------------------------------------------------------------- diff --git a/examples/dm_example_cxx/api/IPhase1.h b/examples/dm_example_cxx/api/IPhase1.h index 3f5fd3b..d75b3e1 100644 --- a/examples/dm_example_cxx/api/IPhase1.h +++ b/examples/dm_example_cxx/api/IPhase1.h @@ -25,6 +25,7 @@ class IPhase1 { protected: IPhase1() = default; + ~IPhase1() = default; public: virtual int getData() = 0; }; http://git-wip-us.apache.org/repos/asf/celix/blob/261161fe/examples/dm_example_cxx/api/IPhase2.h ---------------------------------------------------------------------- diff --git a/examples/dm_example_cxx/api/IPhase2.h b/examples/dm_example_cxx/api/IPhase2.h index 7b9fa05..20e3774 100644 --- a/examples/dm_example_cxx/api/IPhase2.h +++ b/examples/dm_example_cxx/api/IPhase2.h @@ -25,6 +25,7 @@ class IPhase2 { protected: IPhase2() = default; + ~IPhase2() = default; public: virtual double getData() = 0; }; http://git-wip-us.apache.org/repos/asf/celix/blob/261161fe/examples/dm_example_cxx/phase1/include/Phase1Cmp.h ---------------------------------------------------------------------- diff --git a/examples/dm_example_cxx/phase1/include/Phase1Cmp.h b/examples/dm_example_cxx/phase1/include/Phase1Cmp.h index 4401be0..5a45746 100644 --- a/examples/dm_example_cxx/phase1/include/Phase1Cmp.h +++ b/examples/dm_example_cxx/phase1/include/Phase1Cmp.h @@ -21,10 +21,11 @@ #define CELIX_PHASE1CMP_H #include "IPhase1.h" +#include "IName.h" #include #include -class Phase1Cmp : public IPhase1 { +class Phase1Cmp : public srv::info::IName, public IPhase1 { uint32_t counter = 0; public: Phase1Cmp() = default; @@ -35,8 +36,9 @@ public: void stop(); void deinit(); - virtual int getData(); //implements IPhase1 + int getData() override; //implements IPhase1 virtual int infoCmd(char* line, FILE *out, FILE* err); //implements cmd service + std::string getName() override; }; #endif //CELIX_PHASE1CMP_H http://git-wip-us.apache.org/repos/asf/celix/blob/261161fe/examples/dm_example_cxx/phase1/src/BarActivator.cc ---------------------------------------------------------------------- diff --git a/examples/dm_example_cxx/phase1/src/BarActivator.cc b/examples/dm_example_cxx/phase1/src/BarActivator.cc deleted file mode 100644 index 2f84d8e..0000000 --- a/examples/dm_example_cxx/phase1/src/BarActivator.cc +++ /dev/null @@ -1,57 +0,0 @@ -/** - * 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 "Phase1Cmp.h" -#include "Phase1Activator.h" - -using namespace celix::dm; - -/* This example create a C++ component providing a C++ and C service - * For the C service a service struct in initialized and registered - * For the C++ service the object itself is used - */ - -DmActivator* DmActivator::create(DependencyManager& mng) { - return new Phase1Activator(mng); -} - -void Phase1Activator::init() { - std::shared_ptr cmp {new Phase1Cmp()}; - - Properties cmdProps; - cmdProps[OSGI_SHELL_COMMAND_NAME] = "phase1_info"; - cmdProps[OSGI_SHELL_COMMAND_USAGE] = "phase1_info"; - cmdProps[OSGI_SHELL_COMMAND_DESCRIPTION] = "Print information about the Phase1Cmp"; - - - cmd.handle = cmp.get(); - cmd.executeCommand = [](void *handle, char* line, FILE* out, FILE *err) { - Phase1Cmp* cmp = (Phase1Cmp*)handle; - return cmp->infoCmd(line, out, err); - }; - - createComponent(cmp) //using a pointer a instance. Also supported is lazy initialization (default constructor needed) or a rvalue reference (move) - .addInterface(IPHASE1_VERSION) - .addCInterface(&cmd, OSGI_SHELL_COMMAND_SERVICE_NAME, "", cmdProps) - .setCallbacks(&Phase1Cmp::init, &Phase1Cmp::start, &Phase1Cmp::stop, &Phase1Cmp::deinit); -} - -void Phase1Activator::deinit() { - //nothing to do -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/celix/blob/261161fe/examples/dm_example_cxx/phase1/src/Phase1Activator.cc ---------------------------------------------------------------------- diff --git a/examples/dm_example_cxx/phase1/src/Phase1Activator.cc b/examples/dm_example_cxx/phase1/src/Phase1Activator.cc index 2f84d8e..c957cc6 100644 --- a/examples/dm_example_cxx/phase1/src/Phase1Activator.cc +++ b/examples/dm_example_cxx/phase1/src/Phase1Activator.cc @@ -49,6 +49,7 @@ void Phase1Activator::init() { createComponent(cmp) //using a pointer a instance. Also supported is lazy initialization (default constructor needed) or a rvalue reference (move) .addInterface(IPHASE1_VERSION) .addCInterface(&cmd, OSGI_SHELL_COMMAND_SERVICE_NAME, "", cmdProps) + .addInterface(INAME_VERSION) .setCallbacks(&Phase1Cmp::init, &Phase1Cmp::start, &Phase1Cmp::stop, &Phase1Cmp::deinit); } http://git-wip-us.apache.org/repos/asf/celix/blob/261161fe/examples/dm_example_cxx/phase1/src/Phase1Cmp.cc ---------------------------------------------------------------------- diff --git a/examples/dm_example_cxx/phase1/src/Phase1Cmp.cc b/examples/dm_example_cxx/phase1/src/Phase1Cmp.cc index 1137f72..3d05a85 100644 --- a/examples/dm_example_cxx/phase1/src/Phase1Cmp.cc +++ b/examples/dm_example_cxx/phase1/src/Phase1Cmp.cc @@ -43,6 +43,10 @@ int Phase1Cmp::getData() { return rand(); }; +std::string Phase1Cmp::getName() { + return std::string {"IPhase"}; +} + int Phase1Cmp::infoCmd(char * line, FILE *out, FILE *err) { fprintf(out, "Phase1: number of getData calls: %u\n", counter); return 0; http://git-wip-us.apache.org/repos/asf/celix/blob/261161fe/examples/dm_example_cxx/phase2/include/Phase2Cmp.h ---------------------------------------------------------------------- diff --git a/examples/dm_example_cxx/phase2/include/Phase2Cmp.h b/examples/dm_example_cxx/phase2/include/Phase2Cmp.h index a0de396..23f7b87 100644 --- a/examples/dm_example_cxx/phase2/include/Phase2Cmp.h +++ b/examples/dm_example_cxx/phase2/include/Phase2Cmp.h @@ -20,6 +20,7 @@ #ifndef CELIX_PHASE2CMP_H #define CELIX_PHASE2CMP_H +#include "IName.h" #include "IPhase1.h" #include "IPhase2.h" #include @@ -39,9 +40,10 @@ public: virtual ~Phase2Cmp() { std::cout << "Destroying Phase2\n"; }; void setPhase1(IPhase1* phase); //injector used by dependency manager + void setName(srv::info::IName* name) { std::cout << "Setting IName with name: " << name->getName() << std::endl; } void setLogService(const log_service_t* logSrv); - virtual double getData(); //implements IPhase2 + double getData() override; //implements IPhase2 private: IPhase1* phase1 {nullptr}; const log_service_t* logSrv {nullptr}; http://git-wip-us.apache.org/repos/asf/celix/blob/261161fe/examples/dm_example_cxx/phase2a/src/Phase2aActivator.cc ---------------------------------------------------------------------- diff --git a/examples/dm_example_cxx/phase2a/src/Phase2aActivator.cc b/examples/dm_example_cxx/phase2a/src/Phase2aActivator.cc index fdb8236..5515157 100644 --- a/examples/dm_example_cxx/phase2a/src/Phase2aActivator.cc +++ b/examples/dm_example_cxx/phase2a/src/Phase2aActivator.cc @@ -17,6 +17,7 @@ * under the License. */ +#include #include "Phase2Cmp.h" #include "Phase2Activator.h" #include "log_service.h" @@ -42,6 +43,10 @@ void Phase2Activator::init() { .setRequired(true) .setCallbacks(&Phase2Cmp::setPhase1); + cmp.createServiceDependency() + .setVersionRange("[1.0.0,2)") + .setCallbacks(&Phase2Cmp::setName); + cmp.createCServiceDependency(OSGI_LOGSERVICE_NAME) .setRequired(false) .setCallbacks(&Phase2Cmp::setLogService);