From 93b6e5237afee93652654db174d0fa2091d7ff1a Mon Sep 17 00:00:00 2001 From: sangelovic Date: Tue, 9 Apr 2019 21:28:07 +0200 Subject: [PATCH] Clean up some names (rename classes, methods, files) * ConvenienceClasses.h/.inl/.cpp -> ConvenienceApiClasses.h/.inl/.cpp * IObjectProxy class -> IProxy * Interfaces class -> AdaptorInterfaces * Interfaces.h -> split into AdaptorInterfaces.h and ProxyInterfaces.h * createObjectProxy() method -> createProxy() --- CMakeLists.txt | 15 +-- doc/sdbus-c++-class-diagram.png | Bin 33185 -> 35031 bytes doc/sdbus-c++-class-diagram.uml | 14 ++- doc/using-sdbus-c++.md | 64 ++++++----- include/sdbus-c++/AdaptorInterfaces.h | 102 +++++++++++++++++ ...ienceClasses.h => ConvenienceApiClasses.h} | 30 ++--- ...eClasses.inl => ConvenienceApiClasses.inl} | 50 ++++----- include/sdbus-c++/Error.h | 2 +- include/sdbus-c++/IObject.h | 18 +-- .../sdbus-c++/{IObjectProxy.h => IProxy.h} | 90 +++++++-------- include/sdbus-c++/Introspection.h | 6 +- include/sdbus-c++/Message.h | 2 +- .../{Interfaces.h => ProxyInterfaces.h} | 103 ++++++++---------- include/sdbus-c++/sdbus-c++.h | 5 +- ...eClasses.cpp => ConvenienceApiClasses.cpp} | 14 +-- src/{ObjectProxy.cpp => Proxy.cpp} | 82 +++++++------- src/{ObjectProxy.h => Proxy.h} | 28 ++--- stub-generator/ProxyGenerator.cpp | 14 +-- test/CMakeLists.txt | 4 +- test/integrationtests/TestingAdaptor.h | 4 +- test/integrationtests/proxy-glue.h | 4 +- test/perftests/client.cpp | 6 +- test/perftests/org.sdbuscpp.perftests.xml | 2 +- ...perftest-adaptor.h => perftests-adaptor.h} | 6 +- .../{perftest-proxy.h => perftests-proxy.h} | 16 +-- test/perftests/server.cpp | 6 +- test/stresstests/celsius-thermometer-proxy.h | 8 +- test/stresstests/concatenator-proxy.h | 10 +- .../fahrenheit-thermometer-proxy.h | 18 +-- test/stresstests/sdbus-c++-stress-tests.cpp | 16 +-- 30 files changed, 421 insertions(+), 318 deletions(-) create mode 100644 include/sdbus-c++/AdaptorInterfaces.h rename include/sdbus-c++/{ConvenienceClasses.h => ConvenienceApiClasses.h} (90%) rename include/sdbus-c++/{ConvenienceClasses.inl => ConvenienceApiClasses.inl} (93%) rename include/sdbus-c++/{IObjectProxy.h => IProxy.h} (79%) rename include/sdbus-c++/{Interfaces.h => ProxyInterfaces.h} (57%) rename src/{ConvenienceClasses.cpp => ConvenienceApiClasses.cpp} (97%) rename src/{ObjectProxy.cpp => Proxy.cpp} (62%) rename src/{ObjectProxy.h => Proxy.h} (82%) rename test/perftests/{perftest-adaptor.h => perftests-adaptor.h} (90%) rename test/perftests/{perftest-proxy.h => perftests-proxy.h} (53%) diff --git a/CMakeLists.txt b/CMakeLists.txt index bf952e3..4f769df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,11 +25,11 @@ set(SDBUSCPP_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/include/${SDBUSCPP_INCLUDE_SUBDIR}) set(SDBUSCPP_CPP_SRCS ${SDBUSCPP_SOURCE_DIR}/Connection.cpp - ${SDBUSCPP_SOURCE_DIR}/ConvenienceClasses.cpp + ${SDBUSCPP_SOURCE_DIR}/ConvenienceApiClasses.cpp ${SDBUSCPP_SOURCE_DIR}/Error.cpp ${SDBUSCPP_SOURCE_DIR}/Message.cpp ${SDBUSCPP_SOURCE_DIR}/Object.cpp - ${SDBUSCPP_SOURCE_DIR}/ObjectProxy.cpp + ${SDBUSCPP_SOURCE_DIR}/Proxy.cpp ${SDBUSCPP_SOURCE_DIR}/Types.cpp ${SDBUSCPP_SOURCE_DIR}/Flags.cpp ${SDBUSCPP_SOURCE_DIR}/VTableUtils.c @@ -40,21 +40,22 @@ set(SDBUSCPP_HDR_SRCS ${SDBUSCPP_SOURCE_DIR}/IConnection.h ${SDBUSCPP_SOURCE_DIR}/MessageUtils.h ${SDBUSCPP_SOURCE_DIR}/Object.h - ${SDBUSCPP_SOURCE_DIR}/ObjectProxy.h + ${SDBUSCPP_SOURCE_DIR}/Proxy.h ${SDBUSCPP_SOURCE_DIR}/ScopeGuard.h ${SDBUSCPP_SOURCE_DIR}/VTableUtils.h ${SDBUSCPP_SOURCE_DIR}/SdBus.h ${SDBUSCPP_SOURCE_DIR}/ISdBus.h) set(SDBUSCPP_PUBLIC_HDRS - ${SDBUSCPP_INCLUDE_DIR}/ConvenienceClasses.h - ${SDBUSCPP_INCLUDE_DIR}/ConvenienceClasses.inl + ${SDBUSCPP_INCLUDE_DIR}/ConvenienceApiClasses.h + ${SDBUSCPP_INCLUDE_DIR}/ConvenienceApiClasses.inl ${SDBUSCPP_INCLUDE_DIR}/Error.h ${SDBUSCPP_INCLUDE_DIR}/IConnection.h - ${SDBUSCPP_INCLUDE_DIR}/Interfaces.h + ${SDBUSCPP_INCLUDE_DIR}/AdaptorInterfaces.h + ${SDBUSCPP_INCLUDE_DIR}/ProxyInterfaces.h ${SDBUSCPP_INCLUDE_DIR}/Introspection.h ${SDBUSCPP_INCLUDE_DIR}/IObject.h - ${SDBUSCPP_INCLUDE_DIR}/IObjectProxy.h + ${SDBUSCPP_INCLUDE_DIR}/IProxy.h ${SDBUSCPP_INCLUDE_DIR}/Message.h ${SDBUSCPP_INCLUDE_DIR}/MethodResult.h ${SDBUSCPP_INCLUDE_DIR}/Types.h diff --git a/doc/sdbus-c++-class-diagram.png b/doc/sdbus-c++-class-diagram.png index 70f7688641f1ede5b7ccc6b32beac5515627335c..dd2c18b09ebfac6354b19b5023444cf456864fa0 100644 GIT binary patch literal 35031 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 diff --git a/doc/sdbus-c++-class-diagram.uml b/doc/sdbus-c++-class-diagram.uml index 0789363..70c6d3e 100644 --- a/doc/sdbus-c++-class-diagram.uml +++ b/doc/sdbus-c++-class-diagram.uml @@ -12,9 +12,10 @@ interface IObject { +emitSignal() } -interface IObjectProxy { +interface IProxy { +callMethod() +subscribeToSignal() + +get/setProperty() } class Message { @@ -39,21 +40,24 @@ class Object { string objectPath List interfaces List methods + List signals + List properties } -class ObjectProxy { +class Proxy { IConnectionInternal& connection string destination string objectPath + List signalHandlers } IConnection <|-- Connection IConnectionInternal <|- Connection IObject <|-- Object -IObjectProxy <|-- ObjectProxy +IProxy <|-- Proxy Connection <-- Object : "use" -Connection <-- ObjectProxy : "use" +Connection <-- Proxy : "use" Message <.. Object : "send/receive" -Message <.. ObjectProxy : "send/receive" +Message <.. Proxy : "send/receive" @enduml diff --git a/doc/using-sdbus-c++.md b/doc/using-sdbus-c++.md index 06c22b2..b4b1dc1 100644 --- a/doc/using-sdbus-c++.md +++ b/doc/using-sdbus-c++.md @@ -52,7 +52,7 @@ All sdbus-c++ header files reside in the `sdbus-c++` subdirectory within the sta ```cpp #include -#include +#include ``` or just include the global header file that pulls in everything: @@ -87,7 +87,7 @@ The following diagram illustrates the major entities in sdbus-c++. * registering (possibly multiple) interfaces and methods, signals, properties on those interfaces, * emitting signals. -`IObjectProxy` represents the concept of the proxy, which is a view of the `Object` from the client side. Its responsibilities are: +`IProxy` represents the concept of the proxy, which is a view of the `Object` from the client side. Its responsibilities are: * invoking remote methods of the corresponding object, in both synchronous and asynchronous way, * registering handlers for signals, @@ -102,10 +102,10 @@ The following diagram illustrates the major entities in sdbus-c++. sdbus-c++ is thread-aware by design. But, in general, it's not thread-safe. At least not in all places. There are situations where sdbus-c++ provides and guarantees API-level thread safety by design. It is safe to do these operations from multiple threads at the same time: - * Making and destroying `Object`s and `ObjectProxy`s, even on a shared connection that is already running an event loop. Under *making* here is meant a complete atomic sequence of construction, registration of method/signal/property callbacks and export of the `Object`/`ObjectProxy` so it is ready to issue/receive messages. This sequence must be done in one thread. + * Making and destroying `Object`s and `Proxy`s, even on a shared connection that is already running an event loop. Under *making* here is meant a complete atomic sequence of construction, registration of method/signal/property callbacks and export of the `Object`/`Proxy` so it is ready to issue/receive messages. This sequence must be done in one thread. * Creating and sending asynchronous method replies on an `Object` instance. * Creating and emitting signals on an `Object` instance. - * Creating and sending method calls (both synchronously and asynchronously) on an `ObjectProxy` instance. (But it's generally better that our threads use their own exclusive instances of object proxy, to minimize shared state and contention.) + * Creating and sending method calls (both synchronously and asynchronously) on an `Proxy` instance. (But it's generally better that our threads use their own exclusive instances of proxy, to minimize shared state and contention.) Multiple layers of sdbus-c++ API ------------------------------- @@ -115,7 +115,7 @@ sdbus-c++ API comes in two layers: * [the basic layer](#implementing-the-concatenator-example-using-basic-sdbus-c-api-layer), which is a simple wrapper layer on top of sd-bus, using mechanisms that are native to C++ (e.g. serialization/deserialization of data from messages), * [the convenience layer](#implementing-the-concatenator-example-using-convenience-sdbus-c-api-layer), building on top of the basic layer, which aims at alleviating users from unnecessary details and enables them to write shorter, safer, and more expressive code. -sdbus-c++ also ships with a stub generator tool that converts D-Bus IDL in XML format into stub code for the adaptor as well as proxy part. Hierarchically, these stubs provide yet another layer of convenience (the "stubs layer"), making it possible for D-Bus RPC calls to completely look like native C++ calls on a local object. +sdbus-c++ also ships with a stub generator tool that converts D-Bus IDL in XML format into stub code for the adaptor as well as the proxy part. Hierarchically, these stubs provide yet another layer of convenience (the "stubs layer"), making it possible for D-Bus RPC calls to completely look like native C++ calls on a local object. An example: Number concatenator ------------------------------- @@ -130,7 +130,7 @@ In the following sections, we will elaborate on the ways of implementing such an Implementing the Concatenator example using basic sdbus-c++ API layer --------------------------------------------------------------------- -In the basic API layer, we already have abstractions for D-Bus connections, objects and object proxies, with which we can interact via their interface classes (`IConnection`, `IObject`, `IObjectProxy`), but, analogously to the underlying sd-bus C library, we still work on the level of D-Bus messages. We need to +In the basic API layer, we already have abstractions for D-Bus connections, objects and object proxies, with which we can interact via their interface classes (`IConnection`, `IObject`, `IProxy`), but, analogously to the underlying sd-bus C library, we still work on the level of D-Bus messages. We need to * create them, * serialize/deserialize arguments to/from them (thanks to many overloads of C++ insertion/extraction operators, this is very simple), @@ -235,7 +235,7 @@ int main(int argc, char *argv[]) // will create its own connection automatically, and it will be system bus connection. const char* destinationName = "org.sdbuscpp.concatenator"; const char* objectPath = "/org/sdbuscpp/concatenator"; - auto concatenatorProxy = sdbus::createObjectProxy(destinationName, objectPath); + auto concatenatorProxy = sdbus::createProxy(destinationName, objectPath); // Let's subscribe for the 'concatenated' signals const char* interfaceName = "org.sdbuscpp.Concatenator"; @@ -277,7 +277,7 @@ int main(int argc, char *argv[]) } ``` -In simple cases, we don't need to create D-Bus connection explicitly for our proxies. Unless a connection is provided to an object proxy explicitly via factory parameter, the proxy will create a connection of his own, and it will be a system bus connection. This is the case in the example above. (This approach is not scalable and resource-saving if we have plenty of proxies; see section [Working with D-Bus connections](#working-with-d-bus-connections-in-sdbus-c) for elaboration.) So, in the example, we create a proxy for object `/org/sdbuscpp/concatenator` publicly available at bus `org.sdbuscpp.concatenator`. We register signal handlers, if any, and finish the registration, making the object proxy ready for use. +In simple cases, we don't need to create D-Bus connection explicitly for our proxies. Unless a connection is provided to a proxy object explicitly via factory parameter, the proxy will create a connection of his own, and it will be a system bus connection. This is the case in the example above. (This approach is not scalable and resource-saving if we have plenty of proxies; see section [Working with D-Bus connections](#working-with-d-bus-connections-in-sdbus-c) for elaboration.) So, in the example, we create a proxy for object `/org/sdbuscpp/concatenator` publicly available at bus `org.sdbuscpp.concatenator`. We register signal handlers, if any, and finish the registration, making the proxy ready for use. The callback for a D-Bus signal handler on this level is any callable of signature `void(sdbus::Signal& signal)`. The one and only parameter `signal` is the incoming signal message. We need to deserialize arguments from it, and then we can do our business logic with it. @@ -291,11 +291,11 @@ The design of D-Bus connections in sdbus-c++ allows for certain flexibility and How shall we use connections in relation to D-Bus objects and object proxies? -A D-Bus connection is represented by a `Connection` instance. Each connection needs an event loop being run upon it. So it needs a thread handling the event loop. This thread serves all incoming and outgoing messages and all communication towards D-Bus daemon. +A D-Bus connection is represented by a `IConnection` instance. Each connection needs an event loop being run upon it. So it needs a thread handling the event loop. This thread serves all incoming and outgoing messages and all communication towards D-Bus daemon. One process can have multiple D-Bus connections, with assigned unique bus names or without, as long as those with assigned bus names do not share a common bus name. -A D-Bus connection can be created for and used exclusively by one D-Bus object (represented by one `Object` instance) or D-Bus object proxy (represented by one `ObjectProxy` instance), but can very well be used by and shared across multiple objects, multiple proxies or even both multiple objects and proxies at the same time. When shared, one must bear in mind that the access to the connection is mutually exclusive and is serialized. This means, for example, that if an object's callback is going to be invoked for an incoming remote method call and in another thread we use a proxy to call remote method in another process, the threads are contending and only one can go on while the other must wait and can only proceed after the first one has finished, because both are using a shared resource -- the connection. +A D-Bus connection can be created for and used exclusively by one D-Bus object (represented by one `IObject` instance) or one D-Bus proxy (represented by one `IProxy` instance), but can very well be used by and shared across multiple objects, multiple proxies or even both multiple objects and proxies at the same time. When shared, one must bear in mind that the access to the connection is mutually exclusive and is serialized. This means, for example, that if an object's callback is going to be invoked for an incoming remote method call and in another thread we use a proxy to call remote method in another process, the threads are contending and only one can go on while the other must wait and can only proceed after the first one has finished, because both are using a shared resource -- the connection. The former case (1:1) is one extreme; it's usually simple, has zero resource contention, but hurts scalability (for example, 50 proxies in our program need 50 D-Bus connections and 50 event loop threads upon them). The latter case (1:N) is the other extreme -- all D-Bus objects and proxies share one single connection. This is the most scalable solution (since, for example, 5 or 200 objects/proxies use always one single connection), but may increase contention and hurt concurrency (since only one of all those objects/proxies can work with the connection at a time). And then there are limitless options between the two (for example, we can use one connection for all objects, and another connection for all proxies in our service...). sdbus-c++ gives its users freedom to choose whatever approach is more suitable to them in their application at fine granularity. @@ -303,13 +303,13 @@ How can we use connections from the server and the client perspective? * On the *server* side, we generally need to create D-Bus objects and publish their APIs. For that we first need a connection with a unique bus name. We need to create the D-Bus connection manually ourselves, request bus name on it, and manually launch its event loop (in a blocking way, through `enterProcessingLoop()`, or non-blocking async way, through `enterProcessingLoopAsync()`). At any time before or after running the event loop on the connection, we can create and "hook", as well as remove, objects and proxies upon that connection. -* On the *client* side, for our D-Bus object proxies, we have more options (corresponding to three overloads of the `createObjectProxy()` factory): +* On the *client* side, for our D-Bus object proxies, we have more options (corresponding to three overloads of the `createProxy()` factory): * We don't bother about any connection when creating a proxy. For each proxy instance sdbus-c++ also creates an internal connection instance to be used just by this proxy, and it will be a *system bus* connection. Additionally, an event loop thread for that connection is created and run internally. This hurts scalability (see discussion above), but our code is simpler, and since each proxy has its own connection, there is zero contention. - * We create a connection explicitly by ourselves and `std::move` it to the object proxy factory. The proxy becomes an owner of this connection, and will run the event loop on that connection. This is the same as in the above bullet point, but with a flexibility that we can choose the bus type (system, session bus). + * We create a connection explicitly by ourselves and `std::move` it to the proxy object factory. The proxy becomes an owner of this connection, and will run the event loop on that connection. This is the same as in the above bullet point, but with a flexibility that we can choose the bus type (system, session bus). * We are always full owners of the connection. We create the connection, and a proxy only takes and keeps a reference to it. We take care of the event loop upon that connection (and we must ensure the connection exists as long as all its users exist). @@ -402,7 +402,7 @@ int main(int argc, char *argv[]) // Create proxy object for the concatenator object on the server side const char* destinationName = "org.sdbuscpp.concatenator"; const char* objectPath = "/org/sdbuscpp/concatenator"; - auto concatenatorProxy = sdbus::createObjectProxy(destinationName, objectPath); + auto concatenatorProxy = sdbus::createProxy(destinationName, objectPath); // Let's subscribe for the 'concatenated' signals const char* interfaceName = "org.sdbuscpp.Concatenator"; @@ -446,15 +446,15 @@ sdbus-c++ users shall prefer the convenience API to the lower level, basic API. Implementing the Concatenator example using sdbus-c++-generated stubs --------------------------------------------------------------------- -sdbus-c++ ships with the native stub generator tool called `sdbus-c++-xml2cpp`. The tool is very similar to `dbusxx-xml2cpp` tool that comes from dbus-c++ project. +sdbus-c++ ships with the native stub generator tool called `sdbus-c++-xml2cpp`. The tool is very similar to `dbusxx-xml2cpp` tool that comes with the dbus-c++ project. -The generator tool takes D-Bus XML IDL description of D-Bus interfaces on its input, and can be instructed to generate one or both of these: an adaptor header file for use at server side, and a proxy header file for use at client side. Like this: +The generator tool takes D-Bus XML IDL description of D-Bus interfaces on its input, and can be instructed to generate one or both of these: an adaptor header file for use on the server side, and a proxy header file for use on the client side. Like this: ```bash sdbus-c++-xml2cpp database-bindings.xml --adaptor=database-server-glue.h --proxy=database-client-glue.h ``` -The adaptor header file contains classes that can be used to implement described interfaces. The proxy header file contains classes that can be used to make calls to remote objects. +The adaptor header file contains classes that can be used to implement described interfaces (these classes represent object interfaces). The proxy header file contains classes that can be used to make calls to remote objects (these classes represent remote object interfaces). ### XML description of the Concatenator interface @@ -481,7 +481,7 @@ After running this through the stubs generator, we get the stub code that is des ### concatenator-server-glue.h -There is specific class for each interface in the XML IDL file. The class is de facto an interface which shall be implemented by inheriting from it. The class' constructor takes care of registering all methods, signals and properties. For each D-Bus method there is a pure virtual member function. These pure virtual functions must be implemented in the child class. For each signal, there is a public function member that emits this signal. +For each interface in the XML IDL file the generator creates one class that represents it. The class is de facto an interface which shall be implemented by inheriting from it. The class' constructor takes care of registering all methods, signals and properties. For each D-Bus method there is a pure virtual member function. These pure virtual functions must be implemented in the child class. For each signal, there is a public function member that emits this signal. ```cpp /* @@ -531,7 +531,7 @@ private: ### concatenator-client-glue.h -Analogously to the adaptor classes described above, there is specific class for each interface in the XML IDL file. The class is de facto a proxy to the concrete interface of a remote object. For each D-Bus signal there is a pure virtual member function whose body must be provided in a child class. For each method, there is a public function member that calls the method remotely. +Analogously to the adaptor classes described above, there is one class generated for one interface in the XML IDL file. The class is de facto a proxy to the concrete single interface of a remote object. For each D-Bus signal there is a pure virtual member function whose body must be provided in a child class. For each method, there is a public function member that calls the method remotely. ```cpp /* @@ -554,10 +554,10 @@ public: static constexpr const char* interfaceName = "org.sdbuscpp.Concatenator"; protected: - Concatenator_proxy(sdbus::IObjectProxy& object) - : object_(object) + Concatenator_proxy(sdbus::IProxy& proxy) + : proxy_(proxy) { - object_.uponSignal("concatenated").onInterface(interfaceName).call([this](const std::string& concatenatedString){ this->onConcatenated(concatenatedString); }); + proxy_.uponSignal("concatenated").onInterface(interfaceName).call([this](const std::string& concatenatedString){ this->onConcatenated(concatenatedString); }); } virtual void onConcatenated(const std::string& concatenatedString) = 0; @@ -566,12 +566,12 @@ public: std::string concatenate(const std::vector& numbers, const std::string& separator) { std::string result; - object_.callMethod("concatenate").onInterface(interfaceName).withArguments(numbers, separator).storeResultsTo(result); + proxy_.callMethod("concatenate").onInterface(interfaceName).withArguments(numbers, separator).storeResultsTo(result); return result; } private: - sdbus::IObjectProxy& object_; + sdbus::IProxy& object_; }; }} // namespaces @@ -581,17 +581,19 @@ private: ### Providing server implementation based on generated adaptors -To implement a D-Bus object that implements all its D-Bus interfaces, we shall create a class representing the object that inherits from all corresponding `*_adaptor` classes and implements all pure virtual member functions. Specifically, the object class shall inherit from the `Interfaces` template class, the template arguments of which are individual adaptor classes. The `Interfaces` is just a convenience class that hides a few boiler-plate details. For example, in its constructor, it creates an `Object` instance, it takes care of proper initialization of all adaptor superclasses, and exports the object finally. +To implement a D-Bus object that implements all its D-Bus interfaces, we now need to create a class representing the D-Bus object. This class must inherit from all corresponding `*_adaptor` classes (a-ka object interfaces, because these classes are as-if interfaces) and implement all pure virtual member functions. + +How do we do that technically? Simply, our object class just needs to inherit from `AdaptorInterfaces` variadic template class. We fill its template arguments with a list of all generated interface classes. The `AdaptorInterfaces` is a convenience class that hides a few boiler-plate details. For example, in its constructor, it creates an `Object` instance, and it takes care of proper initialization of all adaptor superclasses. ```cpp #include #include "concatenator-server-glue.h" -class Concatenator : public sdbus::Interfaces +class Concatenator : public sdbus::AdaptorInterfaces { public: Concatenator(sdbus::IConnection& connection, std::string objectPath) - : sdbus::Interfaces(connection, std::move(objectPath)) + : sdbus::AdaptorInterfaces(connection, std::move(objectPath)) { } @@ -638,11 +640,13 @@ int main(int argc, char *argv[]) } ``` -It's that simple :) +Now we have a service with a unique bus name and a D-Bus object available on it. Let's write a client. ### Providing client implementation based on generated proxies -To implement a proxy for a remote D-Bus object, we shall create a class representing the object proxy that inherits from all corresponding `*_proxy` classes and -- if applicable -- implements all pure virtual member functions. Specifically, the object proxy class shall inherit from the `ProxyInterfaces` template class. As its template arguments we shall provide all proxy classes. The `ProxyInterfaces` is just a convenience class that hides a few boiler-plate details. For example, in its constructor, it creates an `ObjectProxy` instance, and it takes care of proper initialization of all proxy superclasses. +To implement a proxy for a remote D-Bus object, we shall create a class representing the proxy object. This class must inherit from all corresponding `*_proxy` classes (a-ka remote object interfaces, because these classes are as-if interfaces) and -- if applicable -- implement all pure virtual member functions. + +How do we do that technically? Simply, our proxy class just needs to inherit from `ProxyInterfaces` variadic template class. We fill its template arguments with a list of all generated interface classes. The `ProxyInterfaces` is a convenience class that hides a few boiler-plate details. For example, in its constructor, it can create a `Proxy` instance for us, and it takes care of proper initialization of all generated interface superclasses. ```cpp #include @@ -664,9 +668,9 @@ protected: }; ``` -In the above example, a proxy is created that creates and maintains its own system bus connection. However, there are `ProxyInterfaces` class template constructor overloads that also take the connection from the user as the first parameter, and pass that connection over to the underlying proxy. The connection instance is used for all D-Bus proxy interfaces listed in the `ProxyInterfaces` template parameter list. +In the above example, a proxy is created that creates and maintains its own system bus connection. However, there are `ProxyInterfaces` class template constructor overloads that also take the connection from the user as the first parameter, and pass that connection over to the underlying proxy. The connection instance is used by all interfaces listed in the `ProxyInterfaces` template parameter list. -Note however that there are multiple `ProxyInterfaces` constructor overloads, and they differ in how the proxy behaves towards the D-Bus connection. These overloads precisely map the `sdbus::createObjectProxy` overloads, as they are actually implemented on top of them. See [Proxy and D-Bus connection](#Proxy-and-D-Bus-connection) for more info. +Note however that there are multiple `ProxyInterfaces` constructor overloads, and they differ in how the proxy behaves towards the D-Bus connection. These overloads precisely map the `sdbus::createProxy` overloads, as they are actually implemented on top of them. See [Proxy and D-Bus connection](#Proxy-and-D-Bus-connection) for more info. We can even create a `IProxy` instance on our own, and inject it into our proxy class -- there is a constructor overload for it in `ProxyInterfaces`. This can help if we need to provide mocked implementations in our unit tests. Now let's use this proxy to make remote calls and listen to signals in a real application. diff --git a/include/sdbus-c++/AdaptorInterfaces.h b/include/sdbus-c++/AdaptorInterfaces.h new file mode 100644 index 0000000..8f78d04 --- /dev/null +++ b/include/sdbus-c++/AdaptorInterfaces.h @@ -0,0 +1,102 @@ +/** + * (C) 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland + * + * @file AdaptorInterfaces.h + * + * Created on: Nov 8, 2016 + * Project: sdbus-c++ + * Description: High-level D-Bus IPC C++ library based on sd-bus + * + * This file is part of sdbus-c++. + * + * sdbus-c++ is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * sdbus-c++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with sdbus-c++. If not, see . + */ + +#ifndef SDBUS_CXX_ADAPTORINTERFACES_H_ +#define SDBUS_CXX_ADAPTORINTERFACES_H_ + +#include +#include +#include +#include + +// Forward declarations +namespace sdbus { + class IConnection; +} + +namespace sdbus { + + /********************************************//** + * @class ObjectHolder + * + * ObjectHolder is a helper that simply owns and provides + * access to an object to other classes in the inheritance + * hierarchy of an object based on generated interface classes. + * + ***********************************************/ + class ObjectHolder + { + protected: + ObjectHolder(std::unique_ptr&& object) + : object_(std::move(object)) + { + } + + const IObject& getObject() const + { + assert(object_ != nullptr); + return *object_; + } + + IObject& getObject() + { + assert(object_ != nullptr); + return *object_; + } + + private: + std::unique_ptr object_; + }; + + /********************************************//** + * @class AdaptorInterfaces + * + * AdaptorInterfaces is a helper template class that joins all interface classes of a remote + * D-Bus object generated by sdbus-c++-xml2cpp to be used on the server (the adaptor) side, + * including some auxiliary classes. AdaptorInterfaces is the class that native-like object + * implementation classes written by users should inherit from and implement all pure virtual + * methods. So the _Interfaces template parameter is a list of sdbus-c++-xml2cpp-generated + * adaptor-side interface classes representing interfaces (with methods, signals and properties) + * of the D-Bus object. + * + ***********************************************/ + template + class AdaptorInterfaces + : protected ObjectHolder + , public _Interfaces... + { + public: + AdaptorInterfaces(IConnection& connection, std::string objectPath) + : ObjectHolder(createObject(connection, std::move(objectPath))) + , _Interfaces(getObject())... + { + // TODO: Remove + getObject().finishRegistration(); + } + }; + +} + +#endif /* SDBUS_CXX_ADAPTORINTERFACES_H_ */ diff --git a/include/sdbus-c++/ConvenienceClasses.h b/include/sdbus-c++/ConvenienceApiClasses.h similarity index 90% rename from include/sdbus-c++/ConvenienceClasses.h rename to include/sdbus-c++/ConvenienceApiClasses.h index 821dcbf..57d8c8f 100644 --- a/include/sdbus-c++/ConvenienceClasses.h +++ b/include/sdbus-c++/ConvenienceApiClasses.h @@ -1,7 +1,7 @@ /** * (C) 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland * - * @file ConvenienceClasses.h + * @file ConvenienceApiClasses.h * * Created on: Jan 19, 2017 * Project: sdbus-c++ @@ -23,8 +23,8 @@ * along with sdbus-c++. If not, see . */ -#ifndef SDBUS_CXX_CONVENIENCECLASSES_H_ -#define SDBUS_CXX_CONVENIENCECLASSES_H_ +#ifndef SDBUS_CXX_CONVENIENCEAPICLASSES_H_ +#define SDBUS_CXX_CONVENIENCEAPICLASSES_H_ #include #include @@ -35,7 +35,7 @@ // Forward declarations namespace sdbus { class IObject; - class IObjectProxy; + class IProxy; class Variant; class Error; } @@ -157,7 +157,7 @@ namespace sdbus { class MethodInvoker { public: - MethodInvoker(IObjectProxy& objectProxy, const std::string& methodName); + MethodInvoker(IProxy& proxy, const std::string& methodName); MethodInvoker(MethodInvoker&& other) = default; MethodInvoker& operator=(MethodInvoker&& other) = default; ~MethodInvoker() noexcept(false); @@ -169,7 +169,7 @@ namespace sdbus { void dontExpectReply(); private: - IObjectProxy& objectProxy_; + IProxy& proxy_; const std::string& methodName_; MethodCall method_; int exceptions_{}; // Number of active exceptions when MethodInvoker is constructed @@ -179,13 +179,13 @@ namespace sdbus { class AsyncMethodInvoker { public: - AsyncMethodInvoker(IObjectProxy& objectProxy, const std::string& methodName); + AsyncMethodInvoker(IProxy& proxy, const std::string& methodName); AsyncMethodInvoker& onInterface(const std::string& interfaceName); template AsyncMethodInvoker& withArguments(_Args&&... args); template void uponReplyInvoke(_Function&& callback); private: - IObjectProxy& objectProxy_; + IProxy& proxy_; const std::string& methodName_; AsyncMethodCall method_; }; @@ -193,12 +193,12 @@ namespace sdbus { class SignalSubscriber { public: - SignalSubscriber(IObjectProxy& objectProxy, const std::string& signalName); + SignalSubscriber(IProxy& proxy, const std::string& signalName); SignalSubscriber& onInterface(const std::string& interfaceName); template void call(_Function&& callback); private: - IObjectProxy& objectProxy_; + IProxy& proxy_; std::string signalName_; std::string interfaceName_; }; @@ -206,27 +206,27 @@ namespace sdbus { class PropertyGetter { public: - PropertyGetter(IObjectProxy& objectProxy, const std::string& propertyName); + PropertyGetter(IProxy& proxy, const std::string& propertyName); sdbus::Variant onInterface(const std::string& interfaceName); private: - IObjectProxy& objectProxy_; + IProxy& proxy_; std::string propertyName_; }; class PropertySetter { public: - PropertySetter(IObjectProxy& objectProxy, const std::string& propertyName); + PropertySetter(IProxy& proxy, const std::string& propertyName); PropertySetter& onInterface(const std::string& interfaceName); template void toValue(const _Value& value); private: - IObjectProxy& objectProxy_; + IProxy& proxy_; const std::string& propertyName_; std::string interfaceName_; }; } -#endif /* SDBUS_CXX_CONVENIENCECLASSES_H_ */ +#endif /* SDBUS_CXX_CONVENIENCEAPICLASSES_H_ */ diff --git a/include/sdbus-c++/ConvenienceClasses.inl b/include/sdbus-c++/ConvenienceApiClasses.inl similarity index 93% rename from include/sdbus-c++/ConvenienceClasses.inl rename to include/sdbus-c++/ConvenienceApiClasses.inl index ec22639..47603e1 100644 --- a/include/sdbus-c++/ConvenienceClasses.inl +++ b/include/sdbus-c++/ConvenienceApiClasses.inl @@ -1,7 +1,7 @@ /** * (C) 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland * - * @file ConvenienceClasses.inl + * @file ConvenienceApiClasses.inl * * Created on: Dec 19, 2016 * Project: sdbus-c++ @@ -23,11 +23,11 @@ * along with sdbus-c++. If not, see . */ -#ifndef SDBUS_CPP_CONVENIENCECLASSES_INL_ -#define SDBUS_CPP_CONVENIENCECLASSES_INL_ +#ifndef SDBUS_CPP_CONVENIENCEAPICLASSES_INL_ +#define SDBUS_CPP_CONVENIENCEAPICLASSES_INL_ #include -#include +#include #include #include #include @@ -418,8 +418,8 @@ namespace sdbus { // Moved into the library to isolate from C++17 dependency /* - inline MethodInvoker::MethodInvoker(IObjectProxy& objectProxy, const std::string& methodName) - : objectProxy_(objectProxy) + inline MethodInvoker::MethodInvoker(IProxy& proxyObject, const std::string& methodName) + : proxy_(proxy) , methodName_(methodName) , exceptions_(std::uncaught_exceptions()) { @@ -444,13 +444,13 @@ namespace sdbus { // Therefore, we can allow callMethod() to throw even if we are in the destructor. // Bottomline is, to be on the safe side, the caller must take care of catching and reacting // to the exception thrown from here if the caller is a destructor itself. - objectProxy_.callMethod(method_); + proxy_.callMethod(method_); } */ inline MethodInvoker& MethodInvoker::onInterface(const std::string& interfaceName) { - method_ = objectProxy_.createMethodCall(interfaceName, methodName_); + method_ = proxy_.createMethodCall(interfaceName, methodName_); return *this; } @@ -470,7 +470,7 @@ namespace sdbus { { SDBUS_THROW_ERROR_IF(!method_.isValid(), "DBus interface not specified when calling a DBus method", EINVAL); - auto reply = objectProxy_.callMethod(method_); + auto reply = proxy_.callMethod(method_); methodCalled_ = true; detail::deserialize_pack(reply, args...); @@ -484,15 +484,15 @@ namespace sdbus { } - inline AsyncMethodInvoker::AsyncMethodInvoker(IObjectProxy& objectProxy, const std::string& methodName) - : objectProxy_(objectProxy) + inline AsyncMethodInvoker::AsyncMethodInvoker(IProxy& proxy, const std::string& methodName) + : proxy_(proxy) , methodName_(methodName) { } inline AsyncMethodInvoker& AsyncMethodInvoker::onInterface(const std::string& interfaceName) { - method_ = objectProxy_.createAsyncMethodCall(interfaceName, methodName_); + method_ = proxy_.createAsyncMethodCall(interfaceName, methodName_); return *this; } @@ -512,7 +512,7 @@ namespace sdbus { { SDBUS_THROW_ERROR_IF(!method_.isValid(), "DBus interface not specified when calling a DBus method", EINVAL); - objectProxy_.callMethod(method_, [callback = std::forward<_Function>(callback)](MethodReply& reply, const Error* error) + proxy_.callMethod(method_, [callback = std::forward<_Function>(callback)](MethodReply& reply, const Error* error) { // Create a tuple of callback input arguments' types, which will be used // as a storage for the argument values deserialized from the message. @@ -528,8 +528,8 @@ namespace sdbus { } - inline SignalSubscriber::SignalSubscriber(IObjectProxy& objectProxy, const std::string& signalName) - : objectProxy_(objectProxy) + inline SignalSubscriber::SignalSubscriber(IProxy& proxy, const std::string& signalName) + : proxy_(proxy) , signalName_(signalName) { } @@ -546,9 +546,9 @@ namespace sdbus { { SDBUS_THROW_ERROR_IF(interfaceName_.empty(), "DBus interface not specified when subscribing to a signal", EINVAL); - objectProxy_.registerSignalHandler( interfaceName_ - , signalName_ - , [callback = std::forward<_Function>(callback)](Signal& signal) + proxy_.registerSignalHandler( interfaceName_ + , signalName_ + , [callback = std::forward<_Function>(callback)](Signal& signal) { // Create a tuple of callback input arguments' types, which will be used // as a storage for the argument values deserialized from the signal message. @@ -563,8 +563,8 @@ namespace sdbus { } - inline PropertyGetter::PropertyGetter(IObjectProxy& objectProxy, const std::string& propertyName) - : objectProxy_(objectProxy) + inline PropertyGetter::PropertyGetter(IProxy& proxy, const std::string& propertyName) + : proxy_(proxy) , propertyName_(propertyName) { } @@ -572,7 +572,7 @@ namespace sdbus { inline sdbus::Variant PropertyGetter::onInterface(const std::string& interfaceName) { sdbus::Variant var; - objectProxy_ + proxy_ .callMethod("Get") .onInterface("org.freedesktop.DBus.Properties") .withArguments(interfaceName, propertyName_) @@ -581,8 +581,8 @@ namespace sdbus { } - inline PropertySetter::PropertySetter(IObjectProxy& objectProxy, const std::string& propertyName) - : objectProxy_(objectProxy) + inline PropertySetter::PropertySetter(IProxy& proxy, const std::string& propertyName) + : proxy_(proxy) , propertyName_(propertyName) { } @@ -599,7 +599,7 @@ namespace sdbus { { SDBUS_THROW_ERROR_IF(interfaceName_.empty(), "DBus interface not specified when setting a property", EINVAL); - objectProxy_ + proxy_ .callMethod("Set") .onInterface("org.freedesktop.DBus.Properties") .withArguments(interfaceName_, propertyName_, sdbus::Variant{value}); @@ -607,4 +607,4 @@ namespace sdbus { } -#endif /* SDBUS_CPP_CONVENIENCECLASSES_INL_ */ +#endif /* SDBUS_CPP_CONVENIENCEAPICLASSES_INL_ */ diff --git a/include/sdbus-c++/Error.h b/include/sdbus-c++/Error.h index bc37016..25515e3 100644 --- a/include/sdbus-c++/Error.h +++ b/include/sdbus-c++/Error.h @@ -1,7 +1,7 @@ /** * (C) 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland * - * @file ConvenienceClasses.h + * @file Error.h * * Created on: Nov 8, 2016 * Project: sdbus-c++ diff --git a/include/sdbus-c++/IObject.h b/include/sdbus-c++/IObject.h index bb3856f..f0238f5 100644 --- a/include/sdbus-c++/IObject.h +++ b/include/sdbus-c++/IObject.h @@ -26,7 +26,7 @@ #ifndef SDBUS_CXX_IOBJECT_H_ #define SDBUS_CXX_IOBJECT_H_ -#include +#include #include #include #include @@ -44,14 +44,14 @@ namespace sdbus { /********************************************//** * @class IObject * - * An interface to D-Bus object. Provides API for registration - * of methods, signals, properties, and for emitting signals. + * IObject class represents a D-Bus object instance identified by a specific object path. + * D-Bus object provides its interfaces, methods, signals and properties on a bus + * identified by a specific bus name. * - * All methods throw @c sdbus::Error in case of failure. - * In general, the class is thread-aware, but not thread-safe. - * However, the operation of creating and sending asynchronous - * method replies, as well as creating and emitting - * signals, is thread-safe. + * All IObject member methods throw @c sdbus::Error in case of D-Bus or sdbus-c++ error. + * The IObject class has been designed as thread-aware. However, the operation of + * creating and sending asynchronous method replies, as well as creating and emitting + * signals, is thread-safe by design. * ***********************************************/ class IObject @@ -328,6 +328,6 @@ namespace sdbus { } -#include +#include #endif /* SDBUS_CXX_IOBJECT_H_ */ diff --git a/include/sdbus-c++/IObjectProxy.h b/include/sdbus-c++/IProxy.h similarity index 79% rename from include/sdbus-c++/IObjectProxy.h rename to include/sdbus-c++/IProxy.h index bc69a9c..179a006 100644 --- a/include/sdbus-c++/IObjectProxy.h +++ b/include/sdbus-c++/IProxy.h @@ -1,7 +1,7 @@ /** * (C) 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland * - * @file IObjectProxy.h + * @file IProxy.h * * Created on: Nov 8, 2016 * Project: sdbus-c++ @@ -23,10 +23,10 @@ * along with sdbus-c++. If not, see . */ -#ifndef SDBUS_CXX_IOBJECTPROXY_H_ -#define SDBUS_CXX_IOBJECTPROXY_H_ +#ifndef SDBUS_CXX_IPROXY_H_ +#define SDBUS_CXX_IPROXY_H_ -#include +#include #include #include #include @@ -42,24 +42,26 @@ namespace sdbus { namespace sdbus { /********************************************//** - * @class IObjectProxy + * @class IProxy * - * An interface to D-Bus object proxy. Provides API for calling - * methods, getting/setting properties, and for registering to signals. + * IProxy class represents a proxy object, which is a convenient local object created + * to represent a remote D-Bus object in another process. + * The proxy enables calling methods on remote objects, receiving signals from remote + * objects, and getting/setting properties of remote objects. * - * All methods throw @c sdbus::Error in case of failure. - * In general, the class is thread-aware, but not thread-safe. - * However, the operation of creating and sending method calls - * (both synchronously and asynchronously) is thread-safe. + * All IProxy member methods throw @c sdbus::Error in case of D-Bus or sdbus-c++ error. + * The IProxy class has been designed as thread-aware. However, the operation of + * creating and sending method calls (both synchronously and asynchronously) is + * thread-safe by design. * ***********************************************/ - class IObjectProxy + class IProxy { public: /*! * @brief Creates a method call message * - * @param[in] interfaceName Name of an interface that the method is defined under + * @param[in] interfaceName Name of an interface that provides a given method * @param[in] methodName Name of the method * @return A method call message * @@ -74,7 +76,7 @@ namespace sdbus { /*! * @brief Creates an asynchronous method call message * - * @param[in] interfaceName Name of an interface that the method is defined under + * @param[in] interfaceName Name of an interface that provides a given method * @param[in] methodName Name of the method * @return A method call message * @@ -247,43 +249,41 @@ namespace sdbus { */ PropertySetter setProperty(const std::string& propertyName); - virtual ~IObjectProxy() = 0; + virtual ~IProxy() = default; }; - inline MethodInvoker IObjectProxy::callMethod(const std::string& methodName) + inline MethodInvoker IProxy::callMethod(const std::string& methodName) { return MethodInvoker(*this, methodName); } - inline AsyncMethodInvoker IObjectProxy::callMethodAsync(const std::string& methodName) + inline AsyncMethodInvoker IProxy::callMethodAsync(const std::string& methodName) { return AsyncMethodInvoker(*this, methodName); } - inline SignalSubscriber IObjectProxy::uponSignal(const std::string& signalName) + inline SignalSubscriber IProxy::uponSignal(const std::string& signalName) { return SignalSubscriber(*this, signalName); } - inline PropertyGetter IObjectProxy::getProperty(const std::string& propertyName) + inline PropertyGetter IProxy::getProperty(const std::string& propertyName) { return PropertyGetter(*this, propertyName); } - inline PropertySetter IObjectProxy::setProperty(const std::string& propertyName) + inline PropertySetter IProxy::setProperty(const std::string& propertyName) { return PropertySetter(*this, propertyName); } - inline IObjectProxy::~IObjectProxy() {} - /*! - * @brief Creates object proxy instance + * @brief Creates a proxy object for a specific remote D-Bus object * * @param[in] connection D-Bus connection to be used by the proxy object - * @param[in] destination Bus name that provides a D-Bus object - * @param[in] objectPath Path of the D-Bus object - * @return Pointer to the object proxy instance + * @param[in] destination Bus name that provides the remote D-Bus object + * @param[in] objectPath Path of the remote D-Bus object + * @return Pointer to the proxy object instance * * The provided connection will be used by the proxy to issue calls against the object, * and signals, if any, will be subscribed to on this connection. The caller still @@ -293,19 +293,19 @@ namespace sdbus { * * Code example: * @code - * auto proxy = sdbus::createObjectProxy(connection, "com.kistler.foo", "/com/kistler/foo"); + * auto proxy = sdbus::createProxy(connection, "com.kistler.foo", "/com/kistler/foo"); * @endcode */ - std::unique_ptr createObjectProxy( sdbus::IConnection& connection - , std::string destination - , std::string objectPath ); + std::unique_ptr createProxy( sdbus::IConnection& connection + , std::string destination + , std::string objectPath ); /*! - * @brief Creates object proxy instance + * @brief Creates a proxy object for a specific remote D-Bus object * * @param[in] connection D-Bus connection to be used by the proxy object - * @param[in] destination Bus name that provides a D-Bus object - * @param[in] objectPath Path of the D-Bus object + * @param[in] destination Bus name that provides the remote D-Bus object + * @param[in] objectPath Path of the remote D-Bus object * @return Pointer to the object proxy instance * * The provided connection will be used by the proxy to issue calls against the object, @@ -316,18 +316,18 @@ namespace sdbus { * * Code example: * @code - * auto proxy = sdbus::createObjectProxy(std::move(connection), "com.kistler.foo", "/com/kistler/foo"); + * auto proxy = sdbus::createProxy(std::move(connection), "com.kistler.foo", "/com/kistler/foo"); * @endcode */ - std::unique_ptr createObjectProxy( std::unique_ptr&& connection - , std::string destination - , std::string objectPath ); + std::unique_ptr createProxy( std::unique_ptr&& connection + , std::string destination + , std::string objectPath ); /*! - * @brief Creates object proxy instance that uses its own D-Bus connection + * @brief Creates a proxy object for a specific remote D-Bus object * - * @param[in] destination Bus name that provides a D-Bus object - * @param[in] objectPath Path of the D-Bus object + * @param[in] destination Bus name that provides the remote D-Bus object + * @param[in] objectPath Path of the remote D-Bus object * @return Pointer to the object proxy instance * * No D-Bus connection is provided here, so the object proxy will create and manage @@ -337,14 +337,14 @@ namespace sdbus { * * Code example: * @code - * auto proxy = sdbus::createObjectProxy("com.kistler.foo", "/com/kistler/foo"); + * auto proxy = sdbus::createProxy("com.kistler.foo", "/com/kistler/foo"); * @endcode */ - std::unique_ptr createObjectProxy( std::string destination - , std::string objectPath ); + std::unique_ptr createProxy( std::string destination + , std::string objectPath ); } -#include +#include -#endif /* SDBUS_CXX_IOBJECTPROXY_H_ */ +#endif /* SDBUS_CXX_IPROXY_H_ */ diff --git a/include/sdbus-c++/Introspection.h b/include/sdbus-c++/Introspection.h index 3fa297d..03b3050 100644 --- a/include/sdbus-c++/Introspection.h +++ b/include/sdbus-c++/Introspection.h @@ -27,7 +27,7 @@ #define SDBUS_CXX_INTROSPECTION_H_ #include -#include +#include #include namespace sdbus { @@ -38,7 +38,7 @@ namespace sdbus { static constexpr const char* interfaceName = "org.freedesktop.DBus.Introspectable"; protected: - introspectable_proxy(sdbus::IObjectProxy& object) + introspectable_proxy(sdbus::IProxy& object) : object_(object) { } @@ -52,7 +52,7 @@ namespace sdbus { } private: - sdbus::IObjectProxy& object_; + sdbus::IProxy& object_; }; // Adaptor is not necessary if we want to rely on sdbus-provided introspection diff --git a/include/sdbus-c++/Message.h b/include/sdbus-c++/Message.h index a717d43..de6a8ed 100644 --- a/include/sdbus-c++/Message.h +++ b/include/sdbus-c++/Message.h @@ -71,7 +71,7 @@ namespace sdbus { * by D-Bus. * * You don't need to work with this class directly if you use high-level APIs - * of @c IObject and @c IObjectProxy. + * of @c IObject and @c IProxy. * ***********************************************/ class Message diff --git a/include/sdbus-c++/Interfaces.h b/include/sdbus-c++/ProxyInterfaces.h similarity index 57% rename from include/sdbus-c++/Interfaces.h rename to include/sdbus-c++/ProxyInterfaces.h index 1bc547a..3635da8 100644 --- a/include/sdbus-c++/Interfaces.h +++ b/include/sdbus-c++/ProxyInterfaces.h @@ -1,9 +1,9 @@ /** * (C) 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland * - * @file Interfaces.h + * @file ProxyInterfaces.h * - * Created on: Nov 8, 2016 + * Created on: Apr 8, 2019 * Project: sdbus-c++ * Description: High-level D-Bus IPC C++ library based on sd-bus * @@ -23,11 +23,10 @@ * along with sdbus-c++. If not, see . */ -#ifndef SDBUS_CXX_INTERFACES_H_ -#define SDBUS_CXX_INTERFACES_H_ +#ifndef SDBUS_CXX_PROXYINTERFACES_H_ +#define SDBUS_CXX_PROXYINTERFACES_H_ -#include -#include +#include #include #include #include @@ -39,64 +38,53 @@ namespace sdbus { namespace sdbus { - template - class ObjectHolder + /********************************************//** + * @class ProxyObjectHolder + * + * ProxyObjectHolder is a helper that simply owns and provides + * access to a proxy object to other classes in the inheritance + * hierarchy of a native-like proxy object based on generated + * interface classes. + * + ***********************************************/ + class ProxyObjectHolder { protected: - ObjectHolder(std::unique_ptr<_Object>&& object) - : object_(std::move(object)) + ProxyObjectHolder(std::unique_ptr&& proxy) + : proxy_(std::move(proxy)) { } - const _Object& getObject() const + const IProxy& getProxy() const { - assert(object_ != nullptr); - return *object_; + assert(proxy_ != nullptr); + return *proxy_; } - _Object& getObject() + IProxy& getProxy() { - assert(object_ != nullptr); - return *object_; + assert(proxy_ != nullptr); + return *proxy_; } private: - std::unique_ptr<_Object> object_; + std::unique_ptr proxy_; }; /********************************************//** - * @class Interfaces + * @class ProxyInterfaces * - * A helper template class that a user class representing a D-Bus object - * should inherit from, providing as template arguments the adaptor - * classes representing D-Bus interfaces that the object implements. - * - ***********************************************/ - template - class Interfaces - : protected ObjectHolder - , public _Interfaces... - { - public: - Interfaces(IConnection& connection, std::string objectPath) - : ObjectHolder(createObject(connection, std::move(objectPath))) - , _Interfaces(getObject())... - { - getObject().finishRegistration(); - } - }; - - /********************************************//** - * @class Interfaces - * - * A helper template class that a user class representing a proxy of a - * D-Bus object should inherit from, providing as template arguments the proxy - * classes representing object D-Bus interfaces that the object implements. + * ProxyInterfaces is a helper template class that joins all interface classes of a remote + * D-Bus object generated by sdbus-c++-xml2cpp to be used on the client (the proxy) side, + * including some auxiliary classes. ProxyInterfaces is the class that native-like proxy + * implementation classes written by users should inherit from and implement all pure virtual + * methods. So the _Interfaces template parameter is a list of sdbus-c++-xml2cpp-generated + * proxy-side interface classes representing interfaces of the corresponding remote D-Bus object. * ***********************************************/ template class ProxyInterfaces - : protected ObjectHolder + : protected ProxyObjectHolder , public _Interfaces... { public: @@ -107,13 +95,14 @@ namespace sdbus { * @param[in] objectPath Path of the D-Bus object * * This constructor overload creates a proxy that manages its own D-Bus connection(s). - * For more information on its behavior, consult @ref createObjectProxy(std::string, std::string) + * For more information on its behavior, consult @ref createProxy(std::string, std::string) */ ProxyInterfaces(std::string destination, std::string objectPath) - : ObjectHolder(createObjectProxy(std::move(destination), std::move(objectPath))) - , _Interfaces(getObject())... + : ProxyObjectHolder(createProxy(std::move(destination), std::move(objectPath))) + , _Interfaces(getProxy())... { - getObject().finishRegistration(); + // TODO: Remove + getProxy().finishRegistration(); } /*! @@ -124,13 +113,14 @@ namespace sdbus { * @param[in] objectPath Path of the D-Bus object * * The proxy created this way just references a D-Bus connection owned and managed by the user. - * For more information on its behavior, consult @ref createObjectProxy(IConnection&,std::string, std::string) + * For more information on its behavior, consult @ref createProxy(IConnection&,std::string, std::string) */ ProxyInterfaces(IConnection& connection, std::string destination, std::string objectPath) - : ObjectHolder(createObjectProxy(connection, std::move(destination), std::move(objectPath))) - , _Interfaces(getObject())... + : ProxyObjectHolder(createProxy(connection, std::move(destination), std::move(objectPath))) + , _Interfaces(getProxy())... { - getObject().finishRegistration(); + // TODO: Remove + getProxy().finishRegistration(); } /*! @@ -141,13 +131,14 @@ namespace sdbus { * @param[in] objectPath Path of the D-Bus object * * The proxy created this way becomes an owner of the connection. - * For more information on its behavior, consult @ref createObjectProxy(std::unique_ptr&&,std::string, std::string) + * For more information on its behavior, consult @ref createProxy(std::unique_ptr&&,std::string, std::string) */ ProxyInterfaces(std::unique_ptr&& connection, std::string destination, std::string objectPath) - : ObjectHolder(createObjectProxy(std::move(connection), std::move(destination), std::move(objectPath))) - , _Interfaces(getObject())... + : ProxyObjectHolder(createProxy(std::move(connection), std::move(destination), std::move(objectPath))) + , _Interfaces(getProxy())... { - getObject().finishRegistration(); + // TODO: Remove + getProxy().finishRegistration(); } }; diff --git a/include/sdbus-c++/sdbus-c++.h b/include/sdbus-c++/sdbus-c++.h index 0ff8afa..5d17146 100644 --- a/include/sdbus-c++/sdbus-c++.h +++ b/include/sdbus-c++/sdbus-c++.h @@ -25,8 +25,9 @@ #include #include -#include -#include +#include +#include +#include #include #include #include diff --git a/src/ConvenienceClasses.cpp b/src/ConvenienceApiClasses.cpp similarity index 97% rename from src/ConvenienceClasses.cpp rename to src/ConvenienceApiClasses.cpp index 73fee4b..e346772 100644 --- a/src/ConvenienceClasses.cpp +++ b/src/ConvenienceApiClasses.cpp @@ -1,7 +1,7 @@ /** * (C) 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland * - * @file ConvenienceClasses.cpp + * @file ConvenienceApiClasses.cpp * * Created on: Jan 19, 2017 * Project: sdbus-c++ @@ -23,9 +23,9 @@ * along with sdbus-c++. If not, see . */ -#include -#include -#include +#include "sdbus-c++/ConvenienceApiClasses.h" +#include "sdbus-c++/IObject.h" +#include "sdbus-c++/IProxy.h" #include #include @@ -177,8 +177,8 @@ SignalEmitter::~SignalEmitter() noexcept(false) // since C++11, destructors must } -MethodInvoker::MethodInvoker(IObjectProxy& objectProxy, const std::string& methodName) - : objectProxy_(objectProxy) +MethodInvoker::MethodInvoker(IProxy& proxy, const std::string& methodName) + : proxy_(proxy) , methodName_(methodName) , exceptions_(std::uncaught_exceptions()) // Needs C++17 { @@ -202,7 +202,7 @@ MethodInvoker::~MethodInvoker() noexcept(false) // since C++11, destructors must // Therefore, we can allow callMethod() to throw even if we are in the destructor. // Bottomline is, to be on the safe side, the caller must take care of catching and reacting // to the exception thrown from here if the caller is a destructor itself. - objectProxy_.callMethod(method_); + proxy_.callMethod(method_); } } diff --git a/src/ObjectProxy.cpp b/src/Proxy.cpp similarity index 62% rename from src/ObjectProxy.cpp rename to src/Proxy.cpp index 3975a17..0fc2d8f 100644 --- a/src/ObjectProxy.cpp +++ b/src/Proxy.cpp @@ -1,7 +1,7 @@ /** * (C) 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland * - * @file ObjectProxy.cpp + * @file Proxy.cpp * * Created on: Nov 8, 2016 * Project: sdbus-c++ @@ -23,11 +23,11 @@ * along with sdbus-c++. If not, see . */ -#include "ObjectProxy.h" -#include -#include -#include +#include "Proxy.h" #include "IConnection.h" +#include "sdbus-c++/Message.h" +#include "sdbus-c++/IConnection.h" +#include "sdbus-c++/Error.h" #include #include #include @@ -35,7 +35,7 @@ namespace sdbus { namespace internal { -ObjectProxy::ObjectProxy(sdbus::internal::IConnection& connection, std::string destination, std::string objectPath) +Proxy::Proxy(sdbus::internal::IConnection& connection, std::string destination, std::string objectPath) : connection_(&connection, [](sdbus::internal::IConnection *){ /* Intentionally left empty */ }) , destination_(std::move(destination)) , objectPath_(std::move(objectPath)) @@ -44,9 +44,9 @@ ObjectProxy::ObjectProxy(sdbus::internal::IConnection& connection, std::string d // so we expect the client to manage the event loop upon this connection themselves. } -ObjectProxy::ObjectProxy( std::unique_ptr&& connection - , std::string destination - , std::string objectPath ) +Proxy::Proxy( std::unique_ptr&& connection + , std::string destination + , std::string objectPath ) : connection_(std::move(connection)) , destination_(std::move(destination)) , objectPath_(std::move(objectPath)) @@ -56,33 +56,33 @@ ObjectProxy::ObjectProxy( std::unique_ptr&& connec connection_->enterProcessingLoopAsync(); } -MethodCall ObjectProxy::createMethodCall(const std::string& interfaceName, const std::string& methodName) +MethodCall Proxy::createMethodCall(const std::string& interfaceName, const std::string& methodName) { return connection_->createMethodCall(destination_, objectPath_, interfaceName, methodName); } -AsyncMethodCall ObjectProxy::createAsyncMethodCall(const std::string& interfaceName, const std::string& methodName) +AsyncMethodCall Proxy::createAsyncMethodCall(const std::string& interfaceName, const std::string& methodName) { - return AsyncMethodCall{ObjectProxy::createMethodCall(interfaceName, methodName)}; + return AsyncMethodCall{Proxy::createMethodCall(interfaceName, methodName)}; } -MethodReply ObjectProxy::callMethod(const MethodCall& message) +MethodReply Proxy::callMethod(const MethodCall& message) { return message.send(); } -void ObjectProxy::callMethod(const AsyncMethodCall& message, async_reply_handler asyncReplyCallback) +void Proxy::callMethod(const AsyncMethodCall& message, async_reply_handler asyncReplyCallback) { - auto callback = (void*)&ObjectProxy::sdbus_async_reply_handler; + auto callback = (void*)&Proxy::sdbus_async_reply_handler; // Allocated userData gets deleted in the sdbus_async_reply_handler auto userData = new AsyncReplyUserData{*this, std::move(asyncReplyCallback)}; message.send(callback, userData); } -void ObjectProxy::registerSignalHandler( const std::string& interfaceName - , const std::string& signalName - , signal_handler signalHandler ) +void Proxy::registerSignalHandler( const std::string& interfaceName + , const std::string& signalName + , signal_handler signalHandler ) { SDBUS_THROW_ERROR_IF(!signalHandler, "Invalid signal handler provided", EINVAL); @@ -95,12 +95,12 @@ void ObjectProxy::registerSignalHandler( const std::string& interfaceName SDBUS_THROW_ERROR_IF(!inserted, "Failed to register signal handler: handler already exists", EINVAL); } -void ObjectProxy::finishRegistration() +void Proxy::finishRegistration() { registerSignalHandlers(*connection_); } -void ObjectProxy::registerSignalHandlers(sdbus::internal::IConnection& connection) +void Proxy::registerSignalHandlers(sdbus::internal::IConnection& connection) { for (auto& interfaceItem : interfaces_) { @@ -114,7 +114,7 @@ void ObjectProxy::registerSignalHandlers(sdbus::internal::IConnection& connectio auto* rawSlotPtr = connection.registerSignalHandler( objectPath_ , interfaceName , signalName - , &ObjectProxy::sdbus_signal_callback + , &Proxy::sdbus_signal_callback , this ); slot.reset(rawSlotPtr); slot.get_deleter() = [&connection](sd_bus_slot *slot){ connection.unregisterSignalHandler(slot); }; @@ -122,7 +122,7 @@ void ObjectProxy::registerSignalHandlers(sdbus::internal::IConnection& connectio } } -int ObjectProxy::sdbus_async_reply_handler(sd_bus_message *sdbusMessage, void *userData, sd_bus_error *retError) +int Proxy::sdbus_async_reply_handler(sd_bus_message *sdbusMessage, void *userData, sd_bus_error *retError) { // We are assuming the ownership of the async reply handler pointer passed here std::unique_ptr asyncReplyUserData{static_cast(userData)}; @@ -143,9 +143,9 @@ int ObjectProxy::sdbus_async_reply_handler(sd_bus_message *sdbusMessage, void *u } } -int ObjectProxy::sdbus_signal_callback(sd_bus_message *sdbusMessage, void *userData, sd_bus_error */*retError*/) +int Proxy::sdbus_signal_callback(sd_bus_message *sdbusMessage, void *userData, sd_bus_error */*retError*/) { - auto* proxy = static_cast(userData); + auto* proxy = static_cast(userData); assert(proxy != nullptr); Signal message{sdbusMessage, &proxy->connection_->getSdBusInterface()}; @@ -163,43 +163,43 @@ int ObjectProxy::sdbus_signal_callback(sd_bus_message *sdbusMessage, void *userD namespace sdbus { -std::unique_ptr createObjectProxy( IConnection& connection - , std::string destination - , std::string objectPath ) +std::unique_ptr createProxy( IConnection& connection + , std::string destination + , std::string objectPath ) { auto* sdbusConnection = dynamic_cast(&connection); SDBUS_THROW_ERROR_IF(!sdbusConnection, "Connection is not a real sdbus-c++ connection", EINVAL); - return std::make_unique( *sdbusConnection - , std::move(destination) - , std::move(objectPath) ); + return std::make_unique( *sdbusConnection + , std::move(destination) + , std::move(objectPath) ); } -std::unique_ptr createObjectProxy( std::unique_ptr&& connection - , std::string destination - , std::string objectPath ) +std::unique_ptr createProxy( std::unique_ptr&& connection + , std::string destination + , std::string objectPath ) { auto* sdbusConnection = dynamic_cast(connection.get()); SDBUS_THROW_ERROR_IF(!sdbusConnection, "Connection is not a real sdbus-c++ connection", EINVAL); connection.release(); - return std::make_unique( std::unique_ptr(sdbusConnection) - , std::move(destination) - , std::move(objectPath) ); + return std::make_unique( std::unique_ptr(sdbusConnection) + , std::move(destination) + , std::move(objectPath) ); } -std::unique_ptr createObjectProxy( std::string destination - , std::string objectPath ) +std::unique_ptr createProxy( std::string destination + , std::string objectPath ) { auto connection = sdbus::createConnection(); auto sdbusConnection = std::unique_ptr(dynamic_cast(connection.release())); assert(sdbusConnection != nullptr); - return std::make_unique( std::move(sdbusConnection) - , std::move(destination) - , std::move(objectPath) ); + return std::make_unique( std::move(sdbusConnection) + , std::move(destination) + , std::move(objectPath) ); } } diff --git a/src/ObjectProxy.h b/src/Proxy.h similarity index 82% rename from src/ObjectProxy.h rename to src/Proxy.h index 14b1665..20cdcb1 100644 --- a/src/ObjectProxy.h +++ b/src/Proxy.h @@ -1,7 +1,7 @@ /** * (C) 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland * - * @file ObjectProxy.h + * @file Proxy.h * * Created on: Nov 8, 2016 * Project: sdbus-c++ @@ -23,10 +23,10 @@ * along with sdbus-c++. If not, see . */ -#ifndef SDBUS_CXX_INTERNAL_OBJECTPROXY_H_ -#define SDBUS_CXX_INTERNAL_OBJECTPROXY_H_ +#ifndef SDBUS_CXX_INTERNAL_PROXY_H_ +#define SDBUS_CXX_INTERNAL_PROXY_H_ -#include +#include #include #include #include @@ -40,16 +40,16 @@ namespace sdbus { namespace internal { namespace sdbus { namespace internal { - class ObjectProxy - : public IObjectProxy + class Proxy + : public IProxy { public: - ObjectProxy( sdbus::internal::IConnection& connection - , std::string destination - , std::string objectPath ); - ObjectProxy( std::unique_ptr&& connection - , std::string destination - , std::string objectPath ); + Proxy( sdbus::internal::IConnection& connection + , std::string destination + , std::string objectPath ); + Proxy( std::unique_ptr&& connection + , std::string destination + , std::string objectPath ); MethodCall createMethodCall(const std::string& interfaceName, const std::string& methodName) override; AsyncMethodCall createAsyncMethodCall(const std::string& interfaceName, const std::string& methodName) override; @@ -64,7 +64,7 @@ namespace internal { private: struct AsyncReplyUserData { - ObjectProxy& proxy; + Proxy& proxy; async_reply_handler callback; }; @@ -95,4 +95,4 @@ namespace internal { }} -#endif /* SDBUS_CXX_INTERNAL_OBJECTPROXY_H_ */ +#endif /* SDBUS_CXX_INTERNAL_PROXY_H_ */ diff --git a/stub-generator/ProxyGenerator.cpp b/stub-generator/ProxyGenerator.cpp index 58c1dcb..2c5f572 100644 --- a/stub-generator/ProxyGenerator.cpp +++ b/stub-generator/ProxyGenerator.cpp @@ -82,8 +82,8 @@ std::string ProxyGenerator::processInterface(Node& interface) const << "public:" << endl << tab << "static constexpr const char* interfaceName = \"" << ifaceName << "\";" << endl << endl << "protected:" << endl - << tab << className << "(sdbus::IObjectProxy& object)" << endl - << tab << tab << ": object_(object)" << endl; + << tab << className << "(sdbus::IProxy& proxy)" << endl + << tab << tab << ": proxy_(proxy)" << endl; Nodes methods = interface["method"]; Nodes signals = interface["signal"]; @@ -118,7 +118,7 @@ std::string ProxyGenerator::processInterface(Node& interface) const } body << "private:" << endl - << tab << "sdbus::IObjectProxy& object_;" << endl + << tab << "sdbus::IProxy& proxy_;" << endl << "};" << endl << endl << std::string(namespacesCount, '}') << " // namespaces" << endl << endl; @@ -168,7 +168,7 @@ std::tuple ProxyGenerator::processMethods(const Nodes& definitionSS << tab << tab << retType << " result;" << endl; } - definitionSS << tab << tab << "object_.callMethod" << (async ? "Async" : "") << "(\"" << name << "\")" + definitionSS << tab << tab << "proxy_.callMethod" << (async ? "Async" : "") << "(\"" << name << "\")" ".onInterface(interfaceName)"; if (inArgs.size() > 0) @@ -218,7 +218,7 @@ std::tuple ProxyGenerator::processSignals(const Nodes& std::string argStr, argTypeStr; std::tie(argStr, argTypeStr, std::ignore) = argsToNamesAndTypes(args); - registrationSS << tab << tab << "object_" + registrationSS << tab << tab << "proxy_" ".uponSignal(\"" << name << "\")" ".onInterface(interfaceName)" ".call([this](" << argTypeStr << ")" @@ -247,7 +247,7 @@ std::string ProxyGenerator::processProperties(const Nodes& properties) const { propertySS << tab << propertyType << " " << propertyName << "()" << endl << tab << "{" << endl; - propertySS << tab << tab << "return object_.getProperty(\"" << propertyName << "\")" + propertySS << tab << tab << "return proxy_.getProperty(\"" << propertyName << "\")" ".onInterface(interfaceName)"; propertySS << ";" << endl << tab << "}" << endl << endl; } @@ -256,7 +256,7 @@ std::string ProxyGenerator::processProperties(const Nodes& properties) const { propertySS << tab << "void " << propertyName << "(" << propertyTypeArg << ")" << endl << tab << "{" << endl; - propertySS << tab << tab << "object_.setProperty(\"" << propertyName << "\")" + propertySS << tab << tab << "proxy_.setProperty(\"" << propertyName << "\")" ".onInterface(interfaceName)" ".toValue(" << propertyArg << ")"; propertySS << ";" << endl << tab << "}" << endl << endl; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ea7f97b..0df5df8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -54,10 +54,10 @@ set(INTEGRATIONTESTS_SRCS set(PERFTESTS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/perftests) set(STRESSTESTS_CLIENT_SRCS ${PERFTESTS_SOURCE_DIR}/client.cpp - ${PERFTESTS_SOURCE_DIR}/perftest-proxy.h) + ${PERFTESTS_SOURCE_DIR}/perftests-proxy.h) set(STRESSTESTS_SERVER_SRCS ${PERFTESTS_SOURCE_DIR}/server.cpp - ${PERFTESTS_SOURCE_DIR}/perftest-adaptor.h) + ${PERFTESTS_SOURCE_DIR}/perftests-adaptor.h) set(STRESSTESTS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/stresstests) set(STRESSTESTS_SRCS diff --git a/test/integrationtests/TestingAdaptor.h b/test/integrationtests/TestingAdaptor.h index d328321..7dd0e59 100644 --- a/test/integrationtests/TestingAdaptor.h +++ b/test/integrationtests/TestingAdaptor.h @@ -31,11 +31,11 @@ #include #include -class TestingAdaptor : public sdbus::Interfaces +class TestingAdaptor : public sdbus::AdaptorInterfaces { public: TestingAdaptor(sdbus::IConnection& connection) : - sdbus::Interfaces<::testing_adaptor>(connection, OBJECT_PATH) { } + sdbus::AdaptorInterfaces<::testing_adaptor>(connection, OBJECT_PATH) { } virtual ~TestingAdaptor() { } diff --git a/test/integrationtests/proxy-glue.h b/test/integrationtests/proxy-glue.h index 74203ae..1d8d5a7 100644 --- a/test/integrationtests/proxy-glue.h +++ b/test/integrationtests/proxy-glue.h @@ -34,7 +34,7 @@ class testing_proxy { protected: - testing_proxy(sdbus::IObjectProxy& object) : + testing_proxy(sdbus::IProxy& object) : object_(object) { object_.uponSignal("simpleSignal").onInterface(INTERFACE_NAME).call([this](){ this->onSimpleSignal(); }); @@ -231,7 +231,7 @@ public: private: - sdbus::IObjectProxy& object_; + sdbus::IProxy& object_; }; diff --git a/test/perftests/client.cpp b/test/perftests/client.cpp index d4455a0..4116007 100644 --- a/test/perftests/client.cpp +++ b/test/perftests/client.cpp @@ -23,7 +23,7 @@ * along with sdbus-c++. If not, see . */ -#include "perftest-proxy.h" +#include "perftests-proxy.h" #include #include #include @@ -36,11 +36,11 @@ using namespace std::chrono_literals; -class PerftestClient : public sdbus::ProxyInterfaces +class PerftestClient : public sdbus::ProxyInterfaces { public: PerftestClient(std::string destination, std::string objectPath) - : sdbus::ProxyInterfaces(std::move(destination), std::move(objectPath)) + : sdbus::ProxyInterfaces(std::move(destination), std::move(objectPath)) { } diff --git a/test/perftests/org.sdbuscpp.perftests.xml b/test/perftests/org.sdbuscpp.perftests.xml index cb0f363..34d1455 100644 --- a/test/perftests/org.sdbuscpp.perftests.xml +++ b/test/perftests/org.sdbuscpp.perftests.xml @@ -1,7 +1,7 @@ - + diff --git a/test/perftests/perftest-adaptor.h b/test/perftests/perftests-adaptor.h similarity index 90% rename from test/perftests/perftest-adaptor.h rename to test/perftests/perftests-adaptor.h index 35e886b..3370481 100644 --- a/test/perftests/perftest-adaptor.h +++ b/test/perftests/perftests-adaptor.h @@ -1,6 +1,6 @@ /* - * This file was automatically generated by sdbuscpp-xml2cpp; DO NOT EDIT! + * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT! */ #ifndef __sdbuscpp__perftest_adaptor_h__adaptor__H__ @@ -13,13 +13,13 @@ namespace org { namespace sdbuscpp { -class perftest_adaptor +class perftests_adaptor { public: static constexpr const char* interfaceName = "org.sdbuscpp.perftests"; protected: - perftest_adaptor(sdbus::IObject& object) + perftests_adaptor(sdbus::IObject& object) : object_(object) { object_.registerMethod("sendDataSignals").onInterface(interfaceName).implementedAs([this](const uint32_t& numberOfSignals, const uint32_t& signalMsgSize){ return this->sendDataSignals(numberOfSignals, signalMsgSize); }); diff --git a/test/perftests/perftest-proxy.h b/test/perftests/perftests-proxy.h similarity index 53% rename from test/perftests/perftest-proxy.h rename to test/perftests/perftests-proxy.h index 96edea4..bbbde8f 100644 --- a/test/perftests/perftest-proxy.h +++ b/test/perftests/perftests-proxy.h @@ -1,6 +1,6 @@ /* - * This file was automatically generated by sdbuscpp-xml2cpp; DO NOT EDIT! + * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT! */ #ifndef __sdbuscpp__perftest_proxy_h__proxy__H__ @@ -13,16 +13,16 @@ namespace org { namespace sdbuscpp { -class perftest_proxy +class perftests_proxy { public: static constexpr const char* interfaceName = "org.sdbuscpp.perftests"; protected: - perftest_proxy(sdbus::IObjectProxy& object) - : object_(object) + perftests_proxy(sdbus::IProxy& proxy) + : proxy_(proxy) { - object_.uponSignal("dataSignal").onInterface(interfaceName).call([this](const std::string& data){ this->onDataSignal(data); }); + proxy_.uponSignal("dataSignal").onInterface(interfaceName).call([this](const std::string& data){ this->onDataSignal(data); }); } virtual void onDataSignal(const std::string& data) = 0; @@ -30,18 +30,18 @@ protected: public: void sendDataSignals(const uint32_t& numberOfSignals, const uint32_t& signalMsgSize) { - object_.callMethod("sendDataSignals").onInterface(interfaceName).withArguments(numberOfSignals, signalMsgSize); + proxy_.callMethod("sendDataSignals").onInterface(interfaceName).withArguments(numberOfSignals, signalMsgSize); } std::string concatenateTwoStrings(const std::string& string1, const std::string& string2) { std::string result; - object_.callMethod("concatenateTwoStrings").onInterface(interfaceName).withArguments(string1, string2).storeResultsTo(result); + proxy_.callMethod("concatenateTwoStrings").onInterface(interfaceName).withArguments(string1, string2).storeResultsTo(result); return result; } private: - sdbus::IObjectProxy& object_; + sdbus::IProxy& proxy_; }; }} // namespaces diff --git a/test/perftests/server.cpp b/test/perftests/server.cpp index c705b32..551cfe0 100644 --- a/test/perftests/server.cpp +++ b/test/perftests/server.cpp @@ -23,7 +23,7 @@ * along with sdbus-c++. If not, see . */ -#include "perftest-adaptor.h" +#include "perftests-adaptor.h" #include #include #include @@ -35,11 +35,11 @@ using namespace std::chrono_literals; std::string createRandomString(size_t length); -class PerftestServer : public sdbus::Interfaces +class PerftestServer : public sdbus::AdaptorInterfaces { public: PerftestServer(sdbus::IConnection& connection, std::string objectPath) - : sdbus::Interfaces(connection, std::move(objectPath)) + : sdbus::AdaptorInterfaces(connection, std::move(objectPath)) { } diff --git a/test/stresstests/celsius-thermometer-proxy.h b/test/stresstests/celsius-thermometer-proxy.h index dcfb25c..39850f7 100644 --- a/test/stresstests/celsius-thermometer-proxy.h +++ b/test/stresstests/celsius-thermometer-proxy.h @@ -21,8 +21,8 @@ public: static constexpr const char* interfaceName = "org.sdbuscpp.stresstests.celsius.thermometer"; protected: - thermometer_proxy(sdbus::IObjectProxy& object) - : object_(object) + thermometer_proxy(sdbus::IProxy& proxy) + : proxy_(proxy) { } @@ -30,12 +30,12 @@ public: uint32_t getCurrentTemperature() { uint32_t result; - object_.callMethod("getCurrentTemperature").onInterface(interfaceName).storeResultsTo(result); + proxy_.callMethod("getCurrentTemperature").onInterface(interfaceName).storeResultsTo(result); return result; } private: - sdbus::IObjectProxy& object_; + sdbus::IProxy& proxy_; }; }}}} // namespaces diff --git a/test/stresstests/concatenator-proxy.h b/test/stresstests/concatenator-proxy.h index bc76bef..9b60e04 100644 --- a/test/stresstests/concatenator-proxy.h +++ b/test/stresstests/concatenator-proxy.h @@ -20,10 +20,10 @@ public: static constexpr const char* interfaceName = "org.sdbuscpp.stresstests.concatenator"; protected: - concatenator_proxy(sdbus::IObjectProxy& object) - : object_(object) + concatenator_proxy(sdbus::IProxy& proxy) + : proxy_(proxy) { - object_.uponSignal("concatenatedSignal").onInterface(interfaceName).call([this](const std::string& concatenatedString){ this->onConcatenatedSignal(concatenatedString); }); + proxy_.uponSignal("concatenatedSignal").onInterface(interfaceName).call([this](const std::string& concatenatedString){ this->onConcatenatedSignal(concatenatedString); }); } virtual void onConcatenatedSignal(const std::string& concatenatedString) = 0; @@ -33,11 +33,11 @@ protected: public: void concatenate(const std::map& params) { - object_.callMethodAsync("concatenate").onInterface(interfaceName).withArguments(params).uponReplyInvoke([this](const sdbus::Error* error, const std::string& result){ this->onConcatenateReply(result, error); }); + proxy_.callMethodAsync("concatenate").onInterface(interfaceName).withArguments(params).uponReplyInvoke([this](const sdbus::Error* error, const std::string& result){ this->onConcatenateReply(result, error); }); } private: - sdbus::IObjectProxy& object_; + sdbus::IProxy& proxy_; }; }}} // namespaces diff --git a/test/stresstests/fahrenheit-thermometer-proxy.h b/test/stresstests/fahrenheit-thermometer-proxy.h index feb25d6..f8af47f 100644 --- a/test/stresstests/fahrenheit-thermometer-proxy.h +++ b/test/stresstests/fahrenheit-thermometer-proxy.h @@ -21,8 +21,8 @@ public: static constexpr const char* interfaceName = "org.sdbuscpp.stresstests.fahrenheit.thermometer"; protected: - thermometer_proxy(sdbus::IObjectProxy& object) - : object_(object) + thermometer_proxy(sdbus::IProxy& proxy) + : proxy_(proxy) { } @@ -30,12 +30,12 @@ public: uint32_t getCurrentTemperature() { uint32_t result; - object_.callMethod("getCurrentTemperature").onInterface(interfaceName).storeResultsTo(result); + proxy_.callMethod("getCurrentTemperature").onInterface(interfaceName).storeResultsTo(result); return result; } private: - sdbus::IObjectProxy& object_; + sdbus::IProxy& proxy_; }; }}}} // namespaces @@ -52,8 +52,8 @@ public: static constexpr const char* interfaceName = "org.sdbuscpp.stresstests.fahrenheit.thermometer.factory"; protected: - factory_proxy(sdbus::IObjectProxy& object) - : object_(object) + factory_proxy(sdbus::IProxy& proxy) + : proxy_(proxy) { } @@ -61,17 +61,17 @@ public: sdbus::ObjectPath createDelegateObject() { sdbus::ObjectPath result; - object_.callMethod("createDelegateObject").onInterface(interfaceName).storeResultsTo(result); + proxy_.callMethod("createDelegateObject").onInterface(interfaceName).storeResultsTo(result); return result; } void destroyDelegateObject(const sdbus::ObjectPath& delegate) { - object_.callMethod("destroyDelegateObject").onInterface(interfaceName).withArguments(delegate).dontExpectReply(); + proxy_.callMethod("destroyDelegateObject").onInterface(interfaceName).withArguments(delegate).dontExpectReply(); } private: - sdbus::IObjectProxy& object_; + sdbus::IProxy& proxy_; }; }}}}} // namespaces diff --git a/test/stresstests/sdbus-c++-stress-tests.cpp b/test/stresstests/sdbus-c++-stress-tests.cpp index 0e5c2f0..d606514 100644 --- a/test/stresstests/sdbus-c++-stress-tests.cpp +++ b/test/stresstests/sdbus-c++-stress-tests.cpp @@ -52,10 +52,10 @@ using namespace std::string_literals; #define FAHRENHEIT_THERMOMETER_OBJECT_PATH "/org/sdbuscpp/stresstests/fahrenheit/thermometer"s #define CONCATENATOR_OBJECT_PATH "/org/sdbuscpp/stresstests/concatenator"s -class CelsiusThermometerAdaptor : public sdbus::Interfaces +class CelsiusThermometerAdaptor : public sdbus::AdaptorInterfaces { public: - using sdbus::Interfaces::Interfaces; + using sdbus::AdaptorInterfaces::AdaptorInterfaces; protected: virtual uint32_t getCurrentTemperature() override @@ -73,13 +73,13 @@ public: using sdbus::ProxyInterfaces::ProxyInterfaces; }; -class FahrenheitThermometerAdaptor : public sdbus::Interfaces< org::sdbuscpp::stresstests::fahrenheit::thermometer_adaptor - , org::sdbuscpp::stresstests::fahrenheit::thermometer::factory_adaptor > +class FahrenheitThermometerAdaptor : public sdbus::AdaptorInterfaces< org::sdbuscpp::stresstests::fahrenheit::thermometer_adaptor + , org::sdbuscpp::stresstests::fahrenheit::thermometer::factory_adaptor > { public: FahrenheitThermometerAdaptor(sdbus::IConnection& connection, std::string objectPath) - : sdbus::Interfaces< org::sdbuscpp::stresstests::fahrenheit::thermometer_adaptor - , org::sdbuscpp::stresstests::fahrenheit::thermometer::factory_adaptor >(connection, std::move(objectPath)) + : sdbus::AdaptorInterfaces< org::sdbuscpp::stresstests::fahrenheit::thermometer_adaptor + , org::sdbuscpp::stresstests::fahrenheit::thermometer::factory_adaptor >(connection, std::move(objectPath)) , celsiusProxy_(connection, SERVICE_2_BUS_NAME, CELSIUS_THERMOMETER_OBJECT_PATH) { unsigned int workers = std::thread::hardware_concurrency(); @@ -189,11 +189,11 @@ public: , org::sdbuscpp::stresstests::fahrenheit::thermometer::factory_proxy >::ProxyInterfaces; }; -class ConcatenatorAdaptor : public sdbus::Interfaces +class ConcatenatorAdaptor : public sdbus::AdaptorInterfaces { public: ConcatenatorAdaptor(sdbus::IConnection& connection, std::string objectPath) - : sdbus::Interfaces(connection, std::move(objectPath)) + : sdbus::AdaptorInterfaces(connection, std::move(objectPath)) { unsigned int workers = std::thread::hardware_concurrency(); if (workers < 4)