refactor: add strong types to public API (#414)

This introduces strong types for `std::string`-based D-Bus types. This facilitates safer, less error-prone and more expressive API.

What previously was `auto proxy = createProxy("org.sdbuscpp.concatenator", "/org/sdbuscpp/concatenator");` is now written like `auto proxy = createProxy(ServiceName{"org.sdbuscpp.concatenator"}, ObjectPath{"/org/sdbuscpp/concatenator"});`.

These types are:
  * `ObjectPath` type for the object path (the type has been around already but now is also used consistently in sdbus-c++ API for object path strings),
  * `InterfaceName` type for D-Bus interface names,
  * `BusName` (and its aliases `ServiceName` and `ConnectionName`) type for bus/service/connection names,
  * `MemberName` (and its aliases `MethodName`, `SignalName` and `PropertyName`) type for D-Bus method, signal and property names,
  * `Signature` type for the D-Bus signature (the type has been around already but now is also used consistently in sdbus-c++ API for signature strings),
  * `Error::Name` type for D-Bus error names.
This commit is contained in:
Stanislav Angelovič
2024-03-29 13:23:44 +01:00
parent fe21ee9656
commit 42f0bd07c0
60 changed files with 1085 additions and 621 deletions

View File

@ -184,7 +184,7 @@ The following diagram illustrates the major entities in sdbus-c++.
![class](sdbus-c++-class-diagram.png)
`IConnection` represents the concept of a D-Bus connection. You can connect to either the system bus or a session bus. Services can assign unique service names to those connections. An I/O event loop should be run on the bus connection.
`IConnection` represents the concept of a D-Bus connection. You can connect to either the system bus or a session bus. Services can assign well-known service names to those connections. An I/O event loop should be run on the bus connection.
`IObject` represents the concept of an object that exposes its methods, signals and properties. Its responsibilities are:
@ -238,7 +238,7 @@ Let's have an object `/org/sdbuscpp/concatenator` that implements the `org.sdbus
In the following sections, we will elaborate on the ways of implementing such an object on both the server and the client side.
> **Before running Concatenator example in your system:** In order for your service to be allowed to provide a D-Bus API on system bus, a D-Bus security policy file has to be put in place for that service. Otherwise the service will fail to start (you'll get `[org.freedesktop.DBus.Error.AccessDenied] Failed to request bus name (Permission denied)`, for example). To make the Concatenator example work in your system, [look in this section of systemd configuration](systemd-dbus-config.md#dbus-configuration) for how to name the file, where to place it, how to populate it. For further information, consult [dbus-daemon documentation](https://dbus.freedesktop.org/doc/dbus-daemon.1.html), sections *INTEGRATING SYSTEM SERVICES* and *CONFIGURATION FILE*. As an example used for sdbus-c++ integration tests, you may look at the [policy file for sdbus-c++ integration tests](/tests/integrationtests/files/org.sdbuscpp.integrationtests.conf).
> **Before running Concatenator example in your system:** In order for your service to be allowed to provide a D-Bus API on ** the system bus**, a D-Bus security policy file has to be put in place for that service. Otherwise the service will fail to start (you'll get `[org.freedesktop.DBus.Error.AccessDenied] Failed to request bus name (Permission denied)`, for example). To make the Concatenator example work in your system, [look in this section of systemd configuration](systemd-dbus-config.md#dbus-configuration) for how to name the file, where to place it, how to populate it. For further information, consult [dbus-daemon documentation](https://dbus.freedesktop.org/doc/dbus-daemon.1.html), sections *INTEGRATING SYSTEM SERVICES* and *CONFIGURATION FILE*. As an example used for sdbus-c++ integration tests, you may look at the [policy file for sdbus-c++ integration tests](/tests/integrationtests/files/org.sdbuscpp.integrationtests.conf).
Implementing the Concatenator example using basic sdbus-c++ API layer
---------------------------------------------------------------------
@ -289,28 +289,29 @@ void concatenate(sdbus::MethodCall call)
reply.send();
// Emit 'concatenated' signal
const char* interfaceName = "org.sdbuscpp.Concatenator";
auto signal = g_concatenator->createSignal(interfaceName, "concatenated");
sdbus::InterfaceName interfaceName{"org.sdbuscpp.Concatenator"};
sdbus::SignalName signalName{"concatenated"};
auto signal = g_concatenator->createSignal(interfaceName, signalName);
signal << result;
g_concatenator->emitSignal(signal);
}
int main(int argc, char *argv[])
{
// Create D-Bus connection to the system bus and requests name on it.
const char* serviceName = "org.sdbuscpp.concatenator";
auto connection = sdbus::createSystemBusConnection(serviceName);
// Create D-Bus connection to (either the session or system) bus and requests a well-known name on it.
sdbus::ServiceName serviceName{"org.sdbuscpp.concatenator"};
auto connection = sdbus::createBusConnection(serviceName);
// Create concatenator D-Bus object.
const char* objectPath = "/org/sdbuscpp/concatenator";
auto concatenator = sdbus::createObject(*connection, objectPath);
sdbus::ObjectPath objectPath{"/org/sdbuscpp/concatenator"};
auto concatenator = sdbus::createObject(*connection, std::move(objectPath));
g_concatenator = concatenator.get();
// Register D-Bus methods and signals on the concatenator object, and exports the object.
const char* interfaceName = "org.sdbuscpp.Concatenator";
concatenator->addVTable( sdbus::MethodVTableItem{"concatenate", "ais", {}, "s", {}, &concatenate, {}}
, sdbus::SignalVTableItem{"concatenated", "s", {}, {}} )
sdbus::InterfaceName interfaceName{"org.sdbuscpp.Concatenator"};
concatenator->addVTable( sdbus::MethodVTableItem{"concatenate", sdbus::Signature{"ais"}, {}, sdbus::Signature{"s"}, {}, &concatenate, {}}
, sdbus::SignalVTableItem{"concatenated", sdbus::Signature{"s"}, {}, {}} )
.forInterface(interfaceName);
// Run the I/O event loop on the bus connection.
@ -349,21 +350,24 @@ int main(int argc, char *argv[])
{
// Create proxy object for the concatenator object on the server side. Since here
// we are creating the proxy instance without passing connection to it, the proxy
// 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::createProxy(destinationName, objectPath);
// will create its own connection automatically (to either system bus or session bus,
// depending on the context).
sdbus::ServiceName destination{"org.sdbuscpp.concatenator"};
sdbus::ObjectPath objectPath{"/org/sdbuscpp/concatenator"};
auto concatenatorProxy = sdbus::createProxy(std::move(destination), std::move(objectPath));
// Let's subscribe for the 'concatenated' signals
const char* interfaceName = "org.sdbuscpp.Concatenator";
concatenatorProxy->registerSignalHandler(interfaceName, "concatenated", &onConcatenated);
sdbus::InterfaceName interfaceName{"org.sdbuscpp.Concatenator"};
sdbus::SignalName signalName{"concatenated"};
concatenatorProxy->registerSignalHandler(interfaceName, signalName, &onConcatenated);
std::vector<int> numbers = {1, 2, 3};
std::string separator = ":";
MethodName concatenate{"concatenate"};
// Invoke concatenate on given interface of the object
{
auto method = concatenatorProxy->createMethodCall(interfaceName, "concatenate");
auto method = concatenatorProxy->createMethodCall(interfaceName, concatenate);
method << numbers << separator;
auto reply = concatenatorProxy->callMethod(method);
std::string result;
@ -373,7 +377,7 @@ int main(int argc, char *argv[])
/ // Invoke concatenate again, this time with no numbers and we shall get an error
{
auto method = concatenatorProxy->createMethodCall(interfaceName, "concatenate");
auto method = concatenatorProxy->createMethodCall(interfaceName, concatenate);
method << std::vector<int>() << separator;
try
{
@ -408,11 +412,11 @@ Please note that we can create and destroy D-Bus object proxies dynamically, at
There are several factory methods to create a bus connection object in sdbus-c++:
* `createBusConnection()` - opens a connection to the session bus when in a user context, and a connection to the system bus, otherwise
* `createBusConnection(const std::string& name)` - opens a connection with the given name to the session bus when in a user context, and a connection with the given name to the system bus, otherwise
* `createBusConnection(const sdbus::ServiceName& name)` - opens a connection to the session bus when in a user context, and a connection with the given name to the system bus, otherwise, and requests the given well-known service name on the bus
* `createSystemBusConnection()` - opens a connection to the system bus
* `createSystemBusConnection(const std::string& name)` - opens a connection with the given name to the system bus
* `createSystemBusConnection(const sdbus::ServiceName& name)` - opens a connection to the system bus, and requests the given well-known service name on the bus
* `createSessionBusConnection()` - opens a connection to the session bus
* `createSessionBusConnection(const std::string& name)` - opens a connection with the given name to the session bus
* `createSessionBusConnection(const sdbus::ServiceName& name)` - opens a connection to the session bus, and requests the given well-known service name on the bus.
* `createSessionBusConnectionWithAddress(const std::string& address)` - opens a connection to the session bus at a custom address
* `createRemoteSystemBusConnection(const std::string& host)` - opens a connection to the system bus on a remote host using ssh
* `createDirectBusConnection(const std::string& address)` - opens direct D-Bus connection at a custom address (see [Using direct (peer-to-peer) D-Bus connections](#using-direct-peer-to-peer-d-bus-connections))
@ -503,13 +507,13 @@ The code written using this layer expresses in a declarative way *what* it does,
int main(int argc, char *argv[])
{
// Create D-Bus connection to the system bus and requests name on it.
const char* serviceName = "org.sdbuscpp.concatenator";
auto connection = sdbus::createSystemBusConnection(serviceName);
// Create D-Bus connection to the (either system or session) bus and requests a well-known name on it.
sdbus::ServiceName serviceName{"org.sdbuscpp.concatenator"};
auto connection = sdbus::createBusConnection(serviceName);
// Create concatenator D-Bus object.
const char* objectPath = "/org/sdbuscpp/concatenator";
auto concatenator = sdbus::createObject(*connection, objectPath);
sdbus::ObjectPath objectPath{"/org/sdbuscpp/concatenator"};
auto concatenator = sdbus::createObject(*connection, std::move(objectPath));
auto concatenate = [&concatenator](const std::vector<int> numbers, const std::string& separator)
{
@ -524,17 +528,15 @@ int main(int argc, char *argv[])
}
// Emit 'concatenated' signal
const char* interfaceName = "org.sdbuscpp.Concatenator";
concatenator->emitSignal("concatenated").onInterface(interfaceName).withArguments(result);
concatenator->emitSignal("concatenated").onInterface("org.sdbuscpp.Concatenator").withArguments(result);
return result;
};
// Register D-Bus methods and signals on the concatenator object, and exports the object.
const char* interfaceName = "org.sdbuscpp.Concatenator";
concatenator->addVTable( sdbus::registerMethod("concatenate").implementedAs(std::move(concatenate))
, sdbus::registerSignal{"concatenated").withParameters<std::string>() )
.forInterface(interfaceName);
.forInterface("org.sdbuscpp.Concatenator");
// Run the loop on the connection.
connection->enterEventLoop();
@ -562,12 +564,12 @@ void onConcatenated(const std::string& concatenatedString)
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::createProxy(destinationName, objectPath);
sdbus::ServiceName destination{"org.sdbuscpp.concatenator"};
sdbus::ObjectPath objectPath{"/org/sdbuscpp/concatenator"};
auto concatenatorProxy = sdbus::createProxy(std::move(destination), std::move(objectPath));
// Let's subscribe for the 'concatenated' signals
const char* interfaceName = "org.sdbuscpp.Concatenator";
sdbus::InterfaceName interfaceName{"org.sdbuscpp.Concatenator"};
concatenatorProxy->uponSignal("concatenated").onInterface(interfaceName).call([](const std::string& str){ onConcatenated(str); });
std::vector<int> numbers = {1, 2, 3};
@ -712,7 +714,7 @@ namespace sdbuscpp {
class Concatenator_adaptor
{
public:
static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.Concatenator";
static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.Concatenator"};
protected:
Concatenator_adaptor(sdbus::IObject& object)
@ -771,7 +773,7 @@ namespace sdbuscpp {
class Concatenator_proxy
{
public:
static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.Concatenator";
static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.Concatenator"};
protected:
Concatenator_proxy(sdbus::IProxy& proxy)
@ -827,7 +829,7 @@ Calling `registerAdaptor()` and `unregisterAdaptor()` was not necessary in previ
class Concatenator : public sdbus::AdaptorInterfaces<org::sdbuscpp::Concatenator_adaptor /*, more adaptor classes if there are more interfaces*/>
{
public:
Concatenator(sdbus::IConnection& connection, std::string objectPath)
Concatenator(sdbus::IConnection& connection, sdbus::ObjectPath objectPath)
: AdaptorInterfaces(connection, std::move(objectPath))
{
registerAdaptor();
@ -870,13 +872,13 @@ That's it. We now have an implementation of a D-Bus object implementing `org.sdb
int main(int argc, char *argv[])
{
// Create D-Bus connection to the system bus and requests name on it.
const char* serviceName = "org.sdbuscpp.concatenator";
auto connection = sdbus::createSystemBusConnection(serviceName);
// Create D-Bus connection to (either the system or session) bus and request a well-known name on it.
sdbus::ServiceName serviceName{"org.sdbuscpp.concatenator"};
auto connection = sdbus::createBusConnection(serviceName);
// Create concatenator D-Bus object.
const char* objectPath = "/org/sdbuscpp/concatenator";
Concatenator concatenator(*connection, objectPath);
sdbus::ObjectPath objectPath{"/org/sdbuscpp/concatenator"};
Concatenator concatenator(*connection, std::move(objectPath));
// Run the loop on the connection.
connection->enterEventLoop();
@ -906,7 +908,7 @@ Calling `registerProxy()` and `unregisterProxy()` was not necessary in previous
class ConcatenatorProxy : public sdbus::ProxyInterfaces<org::sdbuscpp::Concatenator_proxy /*, more proxy classes if there are more interfaces*/>
{
public:
ConcatenatorProxy(std::string destination, std::string objectPath)
ConcatenatorProxy(sdbus::ServiceName destination, sdbus::ObjectPath objectPath)
: ProxyInterfaces(std::move(destination), std::move(objectPath))
{
registerProxy();
@ -940,9 +942,9 @@ Now let's use this proxy to make remote calls and listen to signals in a real ap
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";
ConcatenatorProxy concatenatorProxy(destinationName, objectPath);
sdbus::ServiceName destination{"org.sdbuscpp.concatenator"};
sdbus::ObjectPath objectPath{"/org/sdbuscpp/concatenator"};
ConcatenatorProxy concatenatorProxy(std::move(destination), std::move(objectPath));
std::vector<int> numbers = {1, 2, 3};
std::string separator = ":";
@ -1034,8 +1036,9 @@ void concatenate(sdbus::MethodCall call)
reply.send();
// Emit 'concatenated' signal (creating and emitting signals is thread-safe)
const char* interfaceName = "org.sdbuscpp.Concatenator";
auto signal = g_concatenator->createSignal(interfaceName, "concatenated");
sdbus::InterfaceName interfaceName{"org.sdbuscpp.Concatenator"};
sdbus::SignalName signalName{"concatenated"};
auto signal = g_concatenator->createSignal(interfaceName, signalName);
signal << result;
g_concatenator->emitSignal(signal);
}).detach();
@ -1144,7 +1147,7 @@ int main(int argc, char *argv[])
// Invoke concatenate on given interface of the object
{
auto method = concatenatorProxy->createMethodCall(interfaceName, "concatenate");
auto method = concatenatorProxy->createMethodCall(interfaceName, concatenate);
method << numbers << separator;
concatenatorProxy->callMethod(method, callback);
// When the reply comes, we shall get "Got concatenate result 1:2:3" on the standard output
@ -1152,7 +1155,7 @@ int main(int argc, char *argv[])
// Invoke concatenate again, this time with no numbers and we shall get an error
{
auto method = concatenatorProxy->createMethodCall(interfaceName, "concatenate");
auto method = concatenatorProxy->createMethodCall(interfaceName, concatenate);
method << std::vector<int>() << separator;
concatenatorProxy->callMethod(method, callback);
// When the reply comes, we shall get concatenation error message on the standard error output
@ -1174,7 +1177,7 @@ Another option is to use `std::future`-based overload of the `IProxy::callMethod
...
// Invoke concatenate on given interface of the object
{
auto method = concatenatorProxy->createMethodCall(interfaceName, "concatenate");
auto method = concatenatorProxy->createMethodCall(interfaceName, concatenate);
method << numbers << separator;
auto future = concatenatorProxy->callMethod(method, sdbus::with_future);
try
@ -1702,10 +1705,9 @@ int main(int argc, char *argv[])
// We can now use connection objects in a familiar way, e.g. create adaptor and proxy objects on them, and exchange messages.
// Here, using Concatenator IDL-generated bindings example from chapters above:
const char* objectPath = "/org/sdbuscpp/concatenator";
Concatenator concatenator(*serverConnection, objectPath);
const char* emptyDestinationName = ""; // Destination may be empty in case of direct connections
ConcatenatorProxy concatenatorProxy(*clientConnection, emptyDestinationName, objectPath);
Concatenator concatenator(*serverConnection, sdbus::ObjectPath{"/org/sdbuscpp/concatenator"});
sdbus::ServiceName emptyDestination; // Destination may be empty in case of direct connections
ConcatenatorProxy concatenatorProxy(*clientConnection, std::move(emptyDestination), sdbus::ObjectPath{"/org/sdbuscpp/concatenator"});
// Perform call of concatenate D-Bus method
std::vector<int> numbers = {1, 2, 3};
@ -1750,6 +1752,13 @@ sdbus-c++ v2 is a major release that comes with a number of breaking API/ABI/beh
* Change in behavior: In *synchronous* D-Bus calls, the proxy object now keeps the connection instance blocked for the entire duration of the method call. Incoming messages like signals will be queued and processed after the call. Access to the connection from other threads is blocked. To avoid this (in case this hurts you):
* either use short-lived, light-weight proxies for such synchronous calls,
* or call the method in an asynchronous way.
* Strong types were introduced for safer, less error-prone and more expressive API. What previously was `auto proxy = createProxy("org.sdbuscpp.concatenator", "/org/sdbuscpp/concatenator");` is now written like `auto proxy = createProxy(ServiceName{"org.sdbuscpp.concatenator"}, ObjectPath{"/org/sdbuscpp/concatenator"});`. These types are:
* `ObjectPath` type for the object path (the type has been around already but now is also used consistently in sdbus-c++ API for object path strings)
* `InterfaceName` type for D-Bus interface names
* `BusName` (and its aliases `ServiceName` and `ConnectionName`) type for bus/service/connection names
* `MemberName` (and its aliases `MethodName`, `SignalName` and `PropertyName`) type for D-Bus method, signal and property names
* `Signature` type for the D-Bus signature (the type has been around already but now is also used consistently in sdbus-c++ API for signature strings)
* `Error::Name` type for D-Bus error names
* Signatures of callbacks `async_reply_handler`, `signal_handler`, `message_handler` and `property_set_callback` were modified to take input message objects by value instead of non-const ref to a message. The callback handler assumes ownership of the message. This API is cleaner and more self-explaining.
* The `PollData` struct has been extended with a new data member: `eventFd`. All hooks with external event loops shall be modified to poll on this `eventFd` in addition to the `fd`.
* `PollData::timeout_usec` was renamed to `PollData::timeout` and its type has been changed to `std::chrono::microseconds`. This member now holds directly what before had to be obtained through `PollData::getAbsoluteTimeout()` call.

View File

@ -17,7 +17,7 @@ namespace ExampleManager {
class Planet1_proxy
{
public:
static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.ExampleManager.Planet1";
static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.ExampleManager.Planet1"};
protected:
Planet1_proxy(sdbus::IProxy& proxy)

View File

@ -17,7 +17,7 @@ namespace ExampleManager {
class Planet1_adaptor
{
public:
static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.ExampleManager.Planet1";
static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.ExampleManager.Planet1"};
protected:
Planet1_adaptor(sdbus::IObject& object)

View File

@ -17,7 +17,7 @@
class PlanetProxy final : public sdbus::ProxyInterfaces< org::sdbuscpp::ExampleManager::Planet1_proxy >
{
public:
PlanetProxy(sdbus::IConnection& connection, std::string destination, std::string path)
PlanetProxy(sdbus::IConnection& connection, sdbus::ServiceName destination, sdbus::ObjectPath path)
: ProxyInterfaces(connection, std::move(destination), std::move(path))
{
registerProxy();
@ -29,13 +29,13 @@ public:
}
};
class ManagerProxy final : public sdbus::ProxyInterfaces< sdbus::ObjectManager_proxy >
class ManagerProxy final : public sdbus::ProxyInterfaces<sdbus::ObjectManager_proxy>
{
public:
ManagerProxy(sdbus::IConnection& connection, const std::string& destination, std::string path)
: ProxyInterfaces(connection, destination, std::move(path))
, m_connection(connection)
, m_destination(destination)
ManagerProxy(sdbus::IConnection& connection, sdbus::ServiceName destination, sdbus::ObjectPath path)
: ProxyInterfaces(connection, destination, std::move(path))
, m_connection(connection)
, m_destination(destination)
{
registerProxy();
}
@ -47,8 +47,7 @@ public:
void handleExistingObjects()
{
std::map<sdbus::ObjectPath, std::map<std::string, std::map<std::string, sdbus::Variant>>> objectsInterfacesAndProperties;
objectsInterfacesAndProperties = GetManagedObjects();
auto objectsInterfacesAndProperties = GetManagedObjects();
for (const auto& [object, interfacesAndProperties] : objectsInterfacesAndProperties) {
onInterfacesAdded(object, interfacesAndProperties);
}
@ -56,7 +55,7 @@ public:
private:
void onInterfacesAdded( const sdbus::ObjectPath& objectPath
, const std::map<std::string, std::map<std::string, sdbus::Variant>>& interfacesAndProperties) override
, const std::map<sdbus::InterfaceName, std::map<sdbus::PropertyName, sdbus::Variant>>& interfacesAndProperties) override
{
std::cout << objectPath << " added:\t";
for (const auto& [interface, _] : interfacesAndProperties) {
@ -71,14 +70,14 @@ private:
}
const auto& properties = planetInterface->second;
// get a property which was passed as part of the signal.
const auto& name = properties.at("Name").get<std::string>();
const auto& name = properties.at(sdbus::PropertyName{"Name"}).get<std::string>();
// or create a proxy instance to the newly added object.
PlanetProxy planet(m_connection, m_destination, objectPath);
std::cout << name << " has a population of " << planet.GetPopulation() << ".\n" << std::endl;
}
void onInterfacesRemoved( const sdbus::ObjectPath& objectPath
, const std::vector<std::string>& interfaces) override
, const std::vector<sdbus::InterfaceName>& interfaces) override
{
std::cout << objectPath << " removed:\t";
for (const auto& interface : interfaces) {
@ -88,14 +87,16 @@ private:
}
sdbus::IConnection& m_connection;
std::string m_destination;
sdbus::ServiceName m_destination;
};
int main()
{
auto connection = sdbus::createSessionBusConnection();
auto managerProxy = std::make_unique<ManagerProxy>(*connection, "org.sdbuscpp.examplemanager", "/org/sdbuscpp/examplemanager");
sdbus::ServiceName destination{"org.sdbuscpp.examplemanager"};
sdbus::ObjectPath objectPath{"/org/sdbuscpp/examplemanager"};
auto managerProxy = std::make_unique<ManagerProxy>(*connection, std::move(destination), std::move(objectPath));
try {
managerProxy->handleExistingObjects();
}
@ -107,4 +108,4 @@ int main()
connection->enterEventLoop();
return 0;
}
}

View File

@ -19,10 +19,12 @@
#include <thread>
#include <chrono>
using sdbus::ObjectPath;
class ManagerAdaptor : public sdbus::AdaptorInterfaces<sdbus::ObjectManager_adaptor>
{
public:
ManagerAdaptor(sdbus::IConnection& connection, std::string path)
ManagerAdaptor(sdbus::IConnection& connection, sdbus::ObjectPath path)
: AdaptorInterfaces(connection, std::move(path))
{
registerAdaptor();
@ -39,7 +41,7 @@ class PlanetAdaptor final : public sdbus::AdaptorInterfaces< org::sdbuscpp::Exam
, sdbus::Properties_adaptor >
{
public:
PlanetAdaptor(sdbus::IConnection& connection, std::string path, std::string name, uint64_t population)
PlanetAdaptor(sdbus::IConnection& connection, sdbus::ObjectPath path, std::string name, uint64_t population)
: AdaptorInterfaces(connection, std::move(path))
, m_name(std::move(name))
, m_population(population)
@ -82,18 +84,19 @@ void printCountDown(const std::string& message, int seconds)
int main()
{
auto connection = sdbus::createSessionBusConnection();
connection->requestName("org.sdbuscpp.examplemanager");
sdbus::ServiceName serviceName{"org.sdbuscpp.examplemanager"};
connection->requestName(serviceName);
connection->enterEventLoopAsync();
auto manager = std::make_unique<ManagerAdaptor>(*connection, "/org/sdbuscpp/examplemanager");
auto manager = std::make_unique<ManagerAdaptor>(*connection, ObjectPath{"/org/sdbuscpp/examplemanager"});
while (true)
{
printCountDown("Creating PlanetAdaptor in ", 5);
auto earth = std::make_unique<PlanetAdaptor>(*connection, "/org/sdbuscpp/examplemanager/Planet1/Earth", "Earth", 7'874'965'825);
auto earth = std::make_unique<PlanetAdaptor>(*connection, ObjectPath{"/org/sdbuscpp/examplemanager/Planet1/Earth"}, "Earth", 7'874'965'825);
printCountDown("Creating PlanetAdaptor in ", 5);
auto trantor = std::make_unique<PlanetAdaptor>(*connection, "/org/sdbuscpp/examplemanager/Planet1/Trantor", "Trantor", 40'000'000'000);
auto trantor = std::make_unique<PlanetAdaptor>(*connection, ObjectPath{"/org/sdbuscpp/examplemanager/Planet1/Trantor"}, "Trantor", 40'000'000'000);
printCountDown("Creating PlanetAdaptor in ", 5);
auto laconia = std::make_unique<PlanetAdaptor>(*connection, "/org/sdbuscpp/examplemanager/Planet1/Laconia", "Laconia", 231'721);
auto laconia = std::make_unique<PlanetAdaptor>(*connection, ObjectPath{"/org/sdbuscpp/examplemanager/Planet1/Laconia"}, "Laconia", 231'721);
printCountDown("Removing PlanetAdaptor in ", 5);
earth.reset();
printCountDown("Removing PlanetAdaptor in ", 5);
@ -102,7 +105,7 @@ int main()
laconia.reset();
}
connection->releaseName("org.sdbuscpp.examplemanager");
connection->releaseName(serviceName);
connection->leaveEventLoop();
return 0;
}

View File

@ -102,7 +102,7 @@ namespace sdbus {
*
* For more information, consult @ref createObject(sdbus::IConnection&,std::string)
*/
AdaptorInterfaces(IConnection& connection, std::string objectPath)
AdaptorInterfaces(IConnection& connection, ObjectPath objectPath)
: ObjectHolder(createObject(connection, std::move(objectPath)))
, _Interfaces(getObject())...
{

View File

@ -53,7 +53,9 @@ namespace sdbus {
{
public:
VTableAdder(IObject& object, std::vector<VTableItem> vtable);
void forInterface(InterfaceName interfaceName);
void forInterface(std::string interfaceName);
[[nodiscard]] Slot forInterface(InterfaceName interfaceName, return_slot_t);
[[nodiscard]] Slot forInterface(std::string interfaceName, return_slot_t);
private:
@ -64,15 +66,16 @@ namespace sdbus {
class SignalEmitter
{
public:
SignalEmitter(IObject& object, const std::string& signalName);
SignalEmitter(IObject& object, const SignalName& signalName);
SignalEmitter(SignalEmitter&& other) = default;
~SignalEmitter() noexcept(false);
SignalEmitter& onInterface(const InterfaceName& interfaceName);
SignalEmitter& onInterface(const std::string& interfaceName);
template <typename... _Args> void withArguments(_Args&&... args);
private:
IObject& object_;
const std::string& signalName_;
const SignalName& signalName_;
Signal signal_;
int exceptions_{}; // Number of active exceptions when SignalEmitter is constructed
};
@ -80,10 +83,11 @@ namespace sdbus {
class MethodInvoker
{
public:
MethodInvoker(IProxy& proxy, const std::string& methodName);
MethodInvoker(IProxy& proxy, const MethodName& methodName);
MethodInvoker(MethodInvoker&& other) = default;
~MethodInvoker() noexcept(false);
MethodInvoker& onInterface(const InterfaceName& interfaceName);
MethodInvoker& onInterface(const std::string& interfaceName);
MethodInvoker& withTimeout(uint64_t usec);
template <typename _Rep, typename _Period>
@ -95,7 +99,7 @@ namespace sdbus {
private:
IProxy& proxy_;
const std::string& methodName_;
const MethodName& methodName_;
uint64_t timeout_{};
MethodCall method_;
int exceptions_{}; // Number of active exceptions when MethodInvoker is constructed
@ -105,7 +109,8 @@ namespace sdbus {
class AsyncMethodInvoker
{
public:
AsyncMethodInvoker(IProxy& proxy, const std::string& methodName);
AsyncMethodInvoker(IProxy& proxy, const MethodName& methodName);
AsyncMethodInvoker& onInterface(const InterfaceName& interfaceName);
AsyncMethodInvoker& onInterface(const std::string& interfaceName);
AsyncMethodInvoker& withTimeout(uint64_t usec);
template <typename _Rep, typename _Period>
@ -119,7 +124,7 @@ namespace sdbus {
private:
IProxy& proxy_;
const std::string& methodName_;
const MethodName& methodName_;
uint64_t timeout_{};
MethodCall method_;
};
@ -127,7 +132,8 @@ namespace sdbus {
class SignalSubscriber
{
public:
SignalSubscriber(IProxy& proxy, const std::string& signalName);
SignalSubscriber(IProxy& proxy, const SignalName& signalName);
SignalSubscriber& onInterface(InterfaceName interfaceName);
SignalSubscriber& onInterface(std::string interfaceName);
template <typename _Function> void call(_Function&& callback);
template <typename _Function> [[nodiscard]] Slot call(_Function&& callback, return_slot_t);
@ -137,65 +143,81 @@ namespace sdbus {
private:
IProxy& proxy_;
const std::string& signalName_;
std::string interfaceName_;
const SignalName& signalName_;
InterfaceName interfaceName_;
};
class PropertyGetter
{
public:
PropertyGetter(IProxy& proxy, const std::string& propertyName);
PropertyGetter(IProxy& proxy, const PropertyName& propertyName);
Variant onInterface(const InterfaceName& interfaceName);
Variant onInterface(const std::string& interfaceName);
private:
static inline const InterfaceName DBUS_PROPERTIES_INTERFACE_NAME{"org.freedesktop.DBus.Properties"};
private:
IProxy& proxy_;
const std::string& propertyName_;
const PropertyName& propertyName_;
};
class AsyncPropertyGetter
{
public:
AsyncPropertyGetter(IProxy& proxy, const std::string& propertyName);
AsyncPropertyGetter(IProxy& proxy, const PropertyName& propertyName);
AsyncPropertyGetter& onInterface(const InterfaceName& interfaceName);
AsyncPropertyGetter& onInterface(const std::string& interfaceName);
template <typename _Function> PendingAsyncCall uponReplyInvoke(_Function&& callback);
std::future<Variant> getResultAsFuture();
private:
static inline const InterfaceName DBUS_PROPERTIES_INTERFACE_NAME{"org.freedesktop.DBus.Properties"};
private:
IProxy& proxy_;
const std::string& propertyName_;
const std::string* interfaceName_{};
const PropertyName& propertyName_;
const InterfaceName* interfaceName_{};
};
class PropertySetter
{
public:
PropertySetter(IProxy& proxy, const std::string& propertyName);
PropertySetter(IProxy& proxy, const PropertyName& propertyName);
PropertySetter& onInterface(const InterfaceName& interfaceName);
PropertySetter& onInterface(const std::string& interfaceName);
template <typename _Value> void toValue(const _Value& value);
template <typename _Value> void toValue(const _Value& value, dont_expect_reply_t);
void toValue(const Variant& value);
void toValue(const Variant& value, dont_expect_reply_t);
private:
static inline const InterfaceName DBUS_PROPERTIES_INTERFACE_NAME{"org.freedesktop.DBus.Properties"};
private:
IProxy& proxy_;
const std::string& propertyName_;
const std::string* interfaceName_{};
const PropertyName& propertyName_;
const InterfaceName* interfaceName_{};
};
class AsyncPropertySetter
{
public:
AsyncPropertySetter(IProxy& proxy, const std::string& propertyName);
AsyncPropertySetter(IProxy& proxy, const PropertyName& propertyName);
AsyncPropertySetter& onInterface(const InterfaceName& interfaceName);
AsyncPropertySetter& onInterface(const std::string& interfaceName);
template <typename _Value> AsyncPropertySetter& toValue(_Value&& value);
AsyncPropertySetter& toValue(Variant value);
template <typename _Function> PendingAsyncCall uponReplyInvoke(_Function&& callback);
std::future<void> getResultAsFuture();
private:
static inline const InterfaceName DBUS_PROPERTIES_INTERFACE_NAME{"org.freedesktop.DBus.Properties"};
private:
IProxy& proxy_;
const std::string& propertyName_;
const std::string* interfaceName_{};
const PropertyName& propertyName_;
const InterfaceName* interfaceName_{};
Variant value_;
};
@ -203,7 +225,11 @@ namespace sdbus {
{
public:
AllPropertiesGetter(IProxy& proxy);
std::map<std::string, Variant> onInterface(const std::string& interfaceName);
std::map<PropertyName, Variant> onInterface(const InterfaceName& interfaceName);
std::map<PropertyName, Variant> onInterface(const std::string& interfaceName);
private:
static inline const InterfaceName DBUS_PROPERTIES_INTERFACE_NAME{"org.freedesktop.DBus.Properties"};
private:
IProxy& proxy_;
@ -213,13 +239,17 @@ namespace sdbus {
{
public:
AsyncAllPropertiesGetter(IProxy& proxy);
AsyncAllPropertiesGetter& onInterface(const InterfaceName& interfaceName);
AsyncAllPropertiesGetter& onInterface(const std::string& interfaceName);
template <typename _Function> PendingAsyncCall uponReplyInvoke(_Function&& callback);
std::future<std::map<std::string, Variant>> getResultAsFuture();
std::future<std::map<PropertyName, Variant>> getResultAsFuture();
private:
static inline const InterfaceName DBUS_PROPERTIES_INTERFACE_NAME{"org.freedesktop.DBus.Properties"};
private:
IProxy& proxy_;
const std::string* interfaceName_{};
const InterfaceName* interfaceName_{};
};
} // namespace sdbus

View File

@ -53,21 +53,31 @@ namespace sdbus {
{
}
inline void VTableAdder::forInterface(std::string interfaceName)
inline void VTableAdder::forInterface(InterfaceName interfaceName)
{
object_.addVTable(std::move(interfaceName), std::move(vtable_));
}
[[nodiscard]] inline Slot VTableAdder::forInterface(std::string interfaceName, return_slot_t)
inline void VTableAdder::forInterface(std::string interfaceName)
{
forInterface(InterfaceName{std::move(interfaceName)});
}
[[nodiscard]] inline Slot VTableAdder::forInterface(InterfaceName interfaceName, return_slot_t)
{
return object_.addVTable(std::move(interfaceName), std::move(vtable_), return_slot);
}
[[nodiscard]] inline Slot VTableAdder::forInterface(std::string interfaceName, return_slot_t)
{
return forInterface(InterfaceName{std::move(interfaceName)}, return_slot);
}
/*** ------------- ***/
/*** SignalEmitter ***/
/*** ------------- ***/
inline SignalEmitter::SignalEmitter(IObject& object, const std::string& signalName)
inline SignalEmitter::SignalEmitter(IObject& object, const SignalName& signalName)
: object_(object)
, signalName_(signalName)
, exceptions_(std::uncaught_exceptions())
@ -92,13 +102,20 @@ namespace sdbus {
object_.emitSignal(signal_);
}
inline SignalEmitter& SignalEmitter::onInterface(const std::string& interfaceName)
inline SignalEmitter& SignalEmitter::onInterface(const InterfaceName& interfaceName)
{
signal_ = object_.createSignal(interfaceName, signalName_);
return *this;
}
inline SignalEmitter& SignalEmitter::onInterface(const std::string& interfaceName)
{
// Down-cast through static cast for performance reasons (no extra copy and object construction needed)
static_assert(sizeof(interfaceName) == sizeof(InterfaceName));
return onInterface(static_cast<const InterfaceName&>(interfaceName));
}
template <typename... _Args>
inline void SignalEmitter::withArguments(_Args&&... args)
{
@ -111,7 +128,7 @@ namespace sdbus {
/*** MethodInvoker ***/
/*** ------------- ***/
inline MethodInvoker::MethodInvoker(IProxy& proxy, const std::string& methodName)
inline MethodInvoker::MethodInvoker(IProxy& proxy, const MethodName& methodName)
: proxy_(proxy)
, methodName_(methodName)
, exceptions_(std::uncaught_exceptions())
@ -137,13 +154,20 @@ namespace sdbus {
proxy_.callMethod(method_, timeout_);
}
inline MethodInvoker& MethodInvoker::onInterface(const std::string& interfaceName)
inline MethodInvoker& MethodInvoker::onInterface(const InterfaceName& interfaceName)
{
method_ = proxy_.createMethodCall(interfaceName, methodName_);
return *this;
}
inline MethodInvoker& MethodInvoker::onInterface(const std::string& interfaceName)
{
// Down-cast through static cast for performance reasons (no extra copy and object construction needed)
static_assert(sizeof(interfaceName) == sizeof(InterfaceName));
return onInterface(static_cast<const InterfaceName&>(interfaceName));
}
inline MethodInvoker& MethodInvoker::withTimeout(uint64_t usec)
{
timeout_ = usec;
@ -190,19 +214,26 @@ namespace sdbus {
/*** AsyncMethodInvoker ***/
/*** ------------------ ***/
inline AsyncMethodInvoker::AsyncMethodInvoker(IProxy& proxy, const std::string& methodName)
inline AsyncMethodInvoker::AsyncMethodInvoker(IProxy& proxy, const MethodName& methodName)
: proxy_(proxy)
, methodName_(methodName)
{
}
inline AsyncMethodInvoker& AsyncMethodInvoker::onInterface(const std::string& interfaceName)
inline AsyncMethodInvoker& AsyncMethodInvoker::onInterface(const InterfaceName& interfaceName)
{
method_ = proxy_.createMethodCall(interfaceName, methodName_);
return *this;
}
inline AsyncMethodInvoker& AsyncMethodInvoker::onInterface(const std::string& interfaceName)
{
// Down-cast through static cast for performance reasons (no extra copy and object construction needed)
static_assert(sizeof(interfaceName) == sizeof(InterfaceName));
return onInterface(static_cast<const InterfaceName&>(interfaceName));
}
inline AsyncMethodInvoker& AsyncMethodInvoker::withTimeout(uint64_t usec)
{
timeout_ = usec;
@ -288,13 +319,18 @@ namespace sdbus {
/*** SignalSubscriber ***/
/*** ---------------- ***/
inline SignalSubscriber::SignalSubscriber(IProxy& proxy, const std::string& signalName)
inline SignalSubscriber::SignalSubscriber(IProxy& proxy, const SignalName& signalName)
: proxy_(proxy)
, signalName_(signalName)
{
}
inline SignalSubscriber& SignalSubscriber::onInterface(std::string interfaceName)
{
return onInterface(InterfaceName{std::move(interfaceName)});
}
inline SignalSubscriber& SignalSubscriber::onInterface(InterfaceName interfaceName)
{
interfaceName_ = std::move(interfaceName);
@ -368,39 +404,53 @@ namespace sdbus {
/*** PropertyGetter ***/
/*** -------------- ***/
inline PropertyGetter::PropertyGetter(IProxy& proxy, const std::string& propertyName)
inline PropertyGetter::PropertyGetter(IProxy& proxy, const PropertyName& propertyName)
: proxy_(proxy)
, propertyName_(propertyName)
{
}
inline Variant PropertyGetter::onInterface(const std::string& interfaceName)
inline Variant PropertyGetter::onInterface(const InterfaceName& interfaceName)
{
Variant var;
proxy_.callMethod("Get")
.onInterface("org.freedesktop.DBus.Properties")
.onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
.withArguments(interfaceName, propertyName_)
.storeResultsTo(var);
return var;
}
inline Variant PropertyGetter::onInterface(const std::string& interfaceName)
{
// Down-cast through static cast for performance reasons (no extra copy and object construction needed)
static_assert(sizeof(interfaceName) == sizeof(InterfaceName));
return onInterface(static_cast<const InterfaceName&>(interfaceName));
}
/*** ------------------- ***/
/*** AsyncPropertyGetter ***/
/*** ------------------- ***/
inline AsyncPropertyGetter::AsyncPropertyGetter(IProxy& proxy, const std::string& propertyName)
inline AsyncPropertyGetter::AsyncPropertyGetter(IProxy& proxy, const PropertyName& propertyName)
: proxy_(proxy)
, propertyName_(propertyName)
{
}
inline AsyncPropertyGetter& AsyncPropertyGetter::onInterface(const std::string& interfaceName)
inline AsyncPropertyGetter& AsyncPropertyGetter::onInterface(const InterfaceName& interfaceName)
{
interfaceName_ = &interfaceName;
return *this;
}
inline AsyncPropertyGetter& AsyncPropertyGetter::onInterface(const std::string& interfaceName)
{
// Down-cast through static cast for performance reasons (no extra copy and object construction needed)
static_assert(sizeof(interfaceName) == sizeof(InterfaceName));
return onInterface(static_cast<const InterfaceName&>(interfaceName));
}
template <typename _Function>
PendingAsyncCall AsyncPropertyGetter::uponReplyInvoke(_Function&& callback)
{
@ -409,7 +459,7 @@ namespace sdbus {
assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function
return proxy_.callMethodAsync("Get")
.onInterface("org.freedesktop.DBus.Properties")
.onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
.withArguments(*interfaceName_, propertyName_)
.uponReplyInvoke(std::forward<_Function>(callback));
}
@ -419,7 +469,7 @@ namespace sdbus {
assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function
return proxy_.callMethodAsync("Get")
.onInterface("org.freedesktop.DBus.Properties")
.onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
.withArguments(*interfaceName_, propertyName_)
.getResultAsFuture<Variant>();
}
@ -428,19 +478,26 @@ namespace sdbus {
/*** PropertySetter ***/
/*** -------------- ***/
inline PropertySetter::PropertySetter(IProxy& proxy, const std::string& propertyName)
inline PropertySetter::PropertySetter(IProxy& proxy, const PropertyName& propertyName)
: proxy_(proxy)
, propertyName_(propertyName)
{
}
inline PropertySetter& PropertySetter::onInterface(const std::string& interfaceName)
inline PropertySetter& PropertySetter::onInterface(const InterfaceName& interfaceName)
{
interfaceName_ = &interfaceName;
return *this;
}
inline PropertySetter& PropertySetter::onInterface(const std::string& interfaceName)
{
// Down-cast through static cast for performance reasons (no extra copy and object construction needed)
static_assert(sizeof(interfaceName) == sizeof(InterfaceName));
return onInterface(static_cast<const InterfaceName&>(interfaceName));
}
template <typename _Value>
inline void PropertySetter::toValue(const _Value& value)
{
@ -458,7 +515,7 @@ namespace sdbus {
assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function
proxy_.callMethod("Set")
.onInterface("org.freedesktop.DBus.Properties")
.onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
.withArguments(*interfaceName_, propertyName_, value);
}
@ -467,7 +524,7 @@ namespace sdbus {
assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function
proxy_.callMethod("Set")
.onInterface("org.freedesktop.DBus.Properties")
.onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
.withArguments(*interfaceName_, propertyName_, value)
.dontExpectReply();
}
@ -476,19 +533,26 @@ namespace sdbus {
/*** AsyncPropertySetter ***/
/*** ------------------- ***/
inline AsyncPropertySetter::AsyncPropertySetter(IProxy& proxy, const std::string& propertyName)
inline AsyncPropertySetter::AsyncPropertySetter(IProxy& proxy, const PropertyName& propertyName)
: proxy_(proxy)
, propertyName_(propertyName)
{
}
inline AsyncPropertySetter& AsyncPropertySetter::onInterface(const std::string& interfaceName)
inline AsyncPropertySetter& AsyncPropertySetter::onInterface(const InterfaceName& interfaceName)
{
interfaceName_ = &interfaceName;
return *this;
}
inline AsyncPropertySetter& AsyncPropertySetter::onInterface(const std::string& interfaceName)
{
// Down-cast through static cast for performance reasons (no extra copy and object construction needed)
static_assert(sizeof(interfaceName) == sizeof(InterfaceName));
return onInterface(static_cast<const InterfaceName&>(interfaceName));
}
template <typename _Value>
inline AsyncPropertySetter& AsyncPropertySetter::toValue(_Value&& value)
{
@ -510,7 +574,7 @@ namespace sdbus {
assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function
return proxy_.callMethodAsync("Set")
.onInterface("org.freedesktop.DBus.Properties")
.onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
.withArguments(*interfaceName_, propertyName_, std::move(value_))
.uponReplyInvoke(std::forward<_Function>(callback));
}
@ -520,7 +584,7 @@ namespace sdbus {
assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function
return proxy_.callMethodAsync("Set")
.onInterface("org.freedesktop.DBus.Properties")
.onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
.withArguments(*interfaceName_, propertyName_, std::move(value_))
.getResultAsFuture<>();
}
@ -534,16 +598,23 @@ namespace sdbus {
{
}
inline std::map<std::string, Variant> AllPropertiesGetter::onInterface(const std::string& interfaceName)
inline std::map<PropertyName, Variant> AllPropertiesGetter::onInterface(const InterfaceName& interfaceName)
{
std::map<std::string, Variant> props;
std::map<PropertyName, Variant> props;
proxy_.callMethod("GetAll")
.onInterface("org.freedesktop.DBus.Properties")
.onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
.withArguments(interfaceName)
.storeResultsTo(props);
return props;
}
inline std::map<PropertyName, Variant> AllPropertiesGetter::onInterface(const std::string& interfaceName)
{
// Down-cast through static cast for performance reasons (no extra copy and object construction needed)
static_assert(sizeof(interfaceName) == sizeof(InterfaceName));
return onInterface(static_cast<const InterfaceName&>(interfaceName));
}
/*** ------------------------ ***/
/*** AsyncAllPropertiesGetter ***/
/*** ------------------------ ***/
@ -553,35 +624,42 @@ namespace sdbus {
{
}
inline AsyncAllPropertiesGetter& AsyncAllPropertiesGetter::onInterface(const std::string& interfaceName)
inline AsyncAllPropertiesGetter& AsyncAllPropertiesGetter::onInterface(const InterfaceName& interfaceName)
{
interfaceName_ = &interfaceName;
return *this;
}
inline AsyncAllPropertiesGetter& AsyncAllPropertiesGetter::onInterface(const std::string& interfaceName)
{
// Down-cast through static cast for performance reasons (no extra copy and object construction needed)
static_assert(sizeof(interfaceName) == sizeof(InterfaceName));
return onInterface(static_cast<const InterfaceName&>(interfaceName));
}
template <typename _Function>
PendingAsyncCall AsyncAllPropertiesGetter::uponReplyInvoke(_Function&& callback)
{
static_assert( std::is_invocable_r_v<void, _Function, std::optional<Error>, std::map<std::string, Variant>>
, "All properties get callback function must accept std::optional<Error< and a map of property names to their values" );
static_assert( std::is_invocable_r_v<void, _Function, std::optional<Error>, std::map<PropertyName, Variant>>
, "All properties get callback function must accept std::optional<Error> and a map of property names to their values" );
assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function
return proxy_.callMethodAsync("GetAll")
.onInterface("org.freedesktop.DBus.Properties")
.onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
.withArguments(*interfaceName_)
.uponReplyInvoke(std::forward<_Function>(callback));
}
inline std::future<std::map<std::string, Variant>> AsyncAllPropertiesGetter::getResultAsFuture()
inline std::future<std::map<PropertyName, Variant>> AsyncAllPropertiesGetter::getResultAsFuture()
{
assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function
return proxy_.callMethodAsync("GetAll")
.onInterface("org.freedesktop.DBus.Properties")
.onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
.withArguments(*interfaceName_)
.getResultAsFuture<std::map<std::string, Variant>>();
.getResultAsFuture<std::map<PropertyName, Variant>>();
}
} // namespace sdbus

View File

@ -43,19 +43,34 @@ namespace sdbus {
: public std::runtime_error
{
public:
explicit Error(const std::string& name, const char* message = nullptr)
: Error(name, std::string(message ? message : ""))
// Strong type representing the D-Bus error name
class Name : public std::string
{
public:
Name() = default;
explicit Name(std::string value)
: std::string(std::move(value))
{}
explicit Name(const char* value)
: std::string(value)
{}
using std::string::operator=;
};
explicit Error(Name name, const char* message = nullptr)
: Error(std::move(name), std::string(message ? message : ""))
{
}
Error(const std::string& name, const std::string& message)
Error(Name name, std::string message)
: std::runtime_error("[" + name + "] " + message)
, name_(name)
, message_(message)
, name_(std::move(name))
, message_(std::move(message))
{
}
[[nodiscard]] const std::string& getName() const
[[nodiscard]] const Name& getName() const
{
return name_;
}
@ -71,13 +86,13 @@ namespace sdbus {
}
private:
std::string name_;
Name name_;
std::string message_;
};
sdbus::Error createError(int errNo, const std::string& customMsg);
Error createError(int errNo, std::string customMsg);
inline const char* SDBUSCPP_ERROR_NAME = "org.sdbuscpp.Error";
inline const Error::Name SDBUSCPP_ERROR_NAME{"org.sdbuscpp.Error"};
}
#define SDBUS_THROW_ERROR(_MSG, _ERRNO) \

View File

@ -35,10 +35,14 @@
#include <optional>
#include <string>
// Forward declarations
struct sd_bus;
struct sd_event;
namespace sdbus {
class Message;
class Message;
class ObjectPath;
class BusName;
using ServiceName = BusName;
}
namespace sdbus {
@ -61,29 +65,29 @@ namespace sdbus {
virtual ~IConnection() = default;
/*!
* @brief Requests D-Bus name on the connection
* @brief Requests a well-known D-Bus service name on a bus
*
* @param[in] name Name to request
*
* @throws sdbus::Error in case of failure
*/
virtual void requestName(const std::string& name) = 0;
virtual void requestName(const ServiceName& name) = 0;
/*!
* @brief Releases D-Bus name on the connection
* @brief Releases an acquired well-known D-Bus service name on a bus
*
* @param[in] name Name to release
*
* @throws sdbus::Error in case of failure
*/
virtual void releaseName(const std::string& name) = 0;
virtual void releaseName(const ServiceName& name) = 0;
/*!
* @brief Retrieves the unique name of a connection. E.g. ":1.xx"
*
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] virtual std::string getUniqueName() const = 0;
[[nodiscard]] virtual BusName getUniqueName() const = 0;
/*!
* @brief Enters I/O event loop on this bus connection
@ -257,7 +261,7 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
virtual void addObjectManager(const std::string& objectPath, floating_slot_t) = 0;
virtual void addObjectManager(const ObjectPath& objectPath, floating_slot_t) = 0;
/*!
* @brief Installs a match rule for messages received on this bus connection
@ -412,7 +416,7 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] std::unique_ptr<sdbus::IConnection> createBusConnection(const std::string& name);
[[nodiscard]] std::unique_ptr<sdbus::IConnection> createBusConnection(const ServiceName& name);
/*!
* @brief Creates/opens D-Bus system bus connection
@ -431,7 +435,7 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] std::unique_ptr<sdbus::IConnection> createSystemBusConnection(const std::string& name);
[[nodiscard]] std::unique_ptr<sdbus::IConnection> createSystemBusConnection(const ServiceName& name);
/*!
* @brief Creates/opens D-Bus session bus connection
@ -450,7 +454,7 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] std::unique_ptr<sdbus::IConnection> createSessionBusConnection(const std::string& name);
[[nodiscard]] std::unique_ptr<sdbus::IConnection> createSessionBusConnection(const ServiceName& name);
/*!
* @brief Creates/opens D-Bus session bus connection at a custom address

View File

@ -41,6 +41,7 @@
namespace sdbus {
class Signal;
class IConnection;
class ObjectPath;
}
namespace sdbus {
@ -89,7 +90,7 @@ namespace sdbus {
*/
template < typename... VTableItems
, typename = std::enable_if_t<(is_one_of_variants_types<VTableItem, std::decay_t<VTableItems>> && ...)> >
void addVTable(std::string interfaceName, VTableItems&&... items);
void addVTable(InterfaceName interfaceName, VTableItems&&... items);
/*!
* @brief Adds a declaration of methods, properties and signals of the object at a given interface
@ -114,7 +115,7 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
virtual void addVTable(std::string interfaceName, std::vector<VTableItem> vtable) = 0;
virtual void addVTable(InterfaceName interfaceName, std::vector<VTableItem> vtable) = 0;
/*!
* @brief Adds a declaration of methods, properties and signals of the object at a given interface
@ -141,7 +142,7 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] virtual Slot addVTable(std::string interfaceName, std::vector<VTableItem> vtable, return_slot_t) = 0;
[[nodiscard]] virtual Slot addVTable(InterfaceName interfaceName, std::vector<VTableItem> vtable, return_slot_t) = 0;
/*!
* @brief A little more convenient overload of addVTable() above
@ -188,7 +189,7 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] virtual Signal createSignal(const std::string& interfaceName, const std::string& signalName) = 0;
[[nodiscard]] virtual Signal createSignal(const InterfaceName& interfaceName, const SignalName& signalName) = 0;
/*!
* @brief Emits signal for this object path
@ -201,6 +202,28 @@ namespace sdbus {
*/
virtual void emitSignal(const sdbus::Signal& message) = 0;
/*!
* @brief Emits signal on D-Bus
*
* @param[in] signalName Name of the signal
* @return A helper object for convenient emission of signals
*
* This is a high-level, convenience way of emitting D-Bus signals that abstracts
* from the D-Bus message concept. Signal arguments are automatically serialized
* in a message and D-Bus signatures automatically deduced from the provided native arguments.
*
* Example of use:
* @code
* int arg1 = ...;
* double arg2 = ...;
* SignalName fooSignal{"fooSignal"};
* object_.emitSignal(fooSignal).onInterface("com.kistler.foo").withArguments(arg1, arg2);
* @endcode
*
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] SignalEmitter emitSignal(const SignalName& signalName);
/*!
* @brief Emits signal on D-Bus
*
@ -230,7 +253,7 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
virtual void emitPropertiesChangedSignal(const std::string& interfaceName, const std::vector<std::string>& propNames) = 0;
virtual void emitPropertiesChangedSignal(const InterfaceName& interfaceName, const std::vector<PropertyName>& propNames) = 0;
/*!
* @brief Emits PropertyChanged signal for all properties on a given interface of this object path
@ -239,7 +262,7 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
virtual void emitPropertiesChangedSignal(const std::string& interfaceName) = 0;
virtual void emitPropertiesChangedSignal(const InterfaceName& interfaceName) = 0;
/*!
* @brief Emits InterfacesAdded signal on this object path
@ -264,7 +287,7 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
virtual void emitInterfacesAddedSignal(const std::vector<std::string>& interfaces) = 0;
virtual void emitInterfacesAddedSignal(const std::vector<InterfaceName>& interfaces) = 0;
/*!
* @brief Emits InterfacesRemoved signal on this object path
@ -286,7 +309,7 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
virtual void emitInterfacesRemovedSignal(const std::vector<std::string>& interfaces) = 0;
virtual void emitInterfacesRemovedSignal(const std::vector<InterfaceName>& interfaces) = 0;
/*!
* @brief Adds an ObjectManager interface at the path of this D-Bus object
@ -322,7 +345,7 @@ namespace sdbus {
/*!
* @brief Returns object path of the underlying DBus object
*/
[[nodiscard]] virtual const std::string& getObjectPath() const = 0;
[[nodiscard]] virtual const ObjectPath& getObjectPath() const = 0;
/*!
* @brief Provides access to the currently processed D-Bus message
@ -342,13 +365,20 @@ namespace sdbus {
// Out-of-line member definitions
inline SignalEmitter IObject::emitSignal(const std::string& signalName)
inline SignalEmitter IObject::emitSignal(const SignalName& signalName)
{
return SignalEmitter(*this, signalName);
}
inline SignalEmitter IObject::emitSignal(const std::string& signalName)
{
// Down-cast through static cast for performance reasons (no extra copy and object construction needed)
static_assert(sizeof(signalName) == sizeof(SignalName));
return emitSignal(static_cast<const SignalName&>(signalName));
}
template <typename... VTableItems, typename>
void IObject::addVTable(std::string interfaceName, VTableItems&&... items)
void IObject::addVTable(InterfaceName interfaceName, VTableItems&&... items)
{
addVTable(std::move(interfaceName), {std::forward<VTableItems>(items)...});
}
@ -382,7 +412,7 @@ namespace sdbus {
* auto proxy = sdbus::createObject(connection, "/com/kistler/foo");
* @endcode
*/
[[nodiscard]] std::unique_ptr<sdbus::IObject> createObject(sdbus::IConnection& connection, std::string objectPath);
[[nodiscard]] std::unique_ptr<sdbus::IObject> createObject(sdbus::IConnection& connection, ObjectPath objectPath);
}

View File

@ -41,6 +41,7 @@ namespace sdbus {
class MethodCall;
class MethodReply;
class IConnection;
class ObjectPath;
class PendingAsyncCall;
namespace internal {
class Proxy;
@ -81,7 +82,7 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] virtual MethodCall createMethodCall(const std::string& interfaceName, const std::string& methodName) = 0;
[[nodiscard]] virtual MethodCall createMethodCall(const InterfaceName& interfaceName, const MethodName& methodName) = 0;
/*!
* @brief Calls method on the remote D-Bus object
@ -211,11 +212,17 @@ namespace sdbus {
* Example of use:
* @code
* int result, a = ..., b = ...;
* object_.callMethod("multiply").onInterface(INTERFACE_NAME).withArguments(a, b).storeResultsTo(result);
* MethodName multiply{"multiply"};
* object_.callMethod(multiply).onInterface(INTERFACE_NAME).withArguments(a, b).storeResultsTo(result);
* @endcode
*
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] MethodInvoker callMethod(const MethodName& methodName);
/*!
* @copydoc IProxy::callMethod(const MethodName&)
*/
[[nodiscard]] MethodInvoker callMethod(const std::string& methodName);
/*!
@ -232,7 +239,8 @@ namespace sdbus {
* Example of use:
* @code
* int a = ..., b = ...;
* object_.callMethodAsync("multiply").onInterface(INTERFACE_NAME).withArguments(a, b).uponReplyInvoke([](int result)
* MethodName multiply{"multiply"};
* object_.callMethodAsync(multiply).onInterface(INTERFACE_NAME).withArguments(a, b).uponReplyInvoke([](int result)
* {
* std::cout << "Got result of multiplying " << a << " and " << b << ": " << result << std::endl;
* });
@ -240,6 +248,11 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] AsyncMethodInvoker callMethodAsync(const MethodName& methodName);
/*!
* @copydoc IProxy::callMethodAsync(const MethodName&)
*/
[[nodiscard]] AsyncMethodInvoker callMethodAsync(const std::string& methodName);
/*!
@ -254,8 +267,8 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
virtual void registerSignalHandler( const std::string& interfaceName
, const std::string& signalName
virtual void registerSignalHandler( const InterfaceName& interfaceName
, const SignalName& signalName
, signal_handler signalHandler ) = 0;
/*!
@ -273,8 +286,8 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] virtual Slot registerSignalHandler( const std::string& interfaceName
, const std::string& signalName
[[nodiscard]] virtual Slot registerSignalHandler( const InterfaceName& interfaceName
, const SignalName& signalName
, signal_handler signalHandler
, return_slot_t ) = 0;
@ -294,11 +307,19 @@ namespace sdbus {
*
* Example of use:
* @code
* object_.uponSignal("fooSignal").onInterface("com.kistler.foo").call([this](int arg1, double arg2){ this->onFooSignal(arg1, arg2); });
* object_.uponSignal("stateChanged").onInterface("com.kistler.foo").call([this](int arg1, double arg2){ this->onStateChanged(arg1, arg2); });
* sdbus::InterfaceName foo{"com.kistler.foo"};
* sdbus::SignalName levelChanged{"levelChanged"};
* object_.uponSignal(levelChanged).onInterface(foo).call([this](uint16_t level){ this->onLevelChanged(level); });
* @endcode
*
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] SignalSubscriber uponSignal(const SignalName& signalName);
/*!
* @copydoc IProxy::uponSignal(const SignalName&)
*/
[[nodiscard]] SignalSubscriber uponSignal(const std::string& signalName);
/*!
@ -325,10 +346,18 @@ namespace sdbus {
* Example of use:
* @code
* int state = object.getProperty("state").onInterface("com.kistler.foo");
* sdbus::InterfaceName foo{"com.kistler.foo"};
* sdbus::PropertyName level{"level"};
* int level = object.getProperty(level).onInterface(foo);
* @endcode
*
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] PropertyGetter getProperty(const PropertyName& propertyName);
/*!
* @copydoc IProxy::getProperty(const PropertyName&)
*/
[[nodiscard]] PropertyGetter getProperty(const std::string& propertyName);
/*!
@ -349,6 +378,11 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] AsyncPropertyGetter getPropertyAsync(const PropertyName& propertyName);
/*!
* @copydoc IProxy::getPropertyAsync(const PropertyName&)
*/
[[nodiscard]] AsyncPropertyGetter getPropertyAsync(const std::string& propertyName);
/*!
@ -371,6 +405,11 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] PropertySetter setProperty(const PropertyName& propertyName);
/*!
* @copydoc IProxy::setProperty(const PropertyName&)
*/
[[nodiscard]] PropertySetter setProperty(const std::string& propertyName);
/*!
@ -391,6 +430,11 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] AsyncPropertySetter setPropertyAsync(const PropertyName& propertyName);
/*!
* @copydoc IProxy::setPropertyAsync(const PropertyName&)
*/
[[nodiscard]] AsyncPropertySetter setPropertyAsync(const std::string& propertyName);
/*!
@ -420,7 +464,7 @@ namespace sdbus {
*
* Example of use:
* @code
* auto callback = [](std::optional<sdbus::Error> err, const std::map<std::string, Variant>>& properties){ ... };
* auto callback = [](std::optional<sdbus::Error> err, const std::map<PropertyName, Variant>>& properties){ ... };
* auto props = object.getAllPropertiesAsync().onInterface("com.kistler.foo").uponReplyInvoke(std::move(callback));
* @endcode
*
@ -438,7 +482,7 @@ namespace sdbus {
/*!
* @brief Returns object path of the underlying DBus object
*/
[[nodiscard]] virtual const std::string& getObjectPath() const = 0;
[[nodiscard]] virtual const ObjectPath& getObjectPath() const = 0;
/*!
* @brief Provides access to the currently processed D-Bus message
@ -525,41 +569,90 @@ namespace sdbus {
return callMethodAsync(message, microsecs.count(), with_future);
}
inline MethodInvoker IProxy::callMethod(const std::string& methodName)
inline MethodInvoker IProxy::callMethod(const MethodName& methodName)
{
return MethodInvoker(*this, methodName);
}
inline AsyncMethodInvoker IProxy::callMethodAsync(const std::string& methodName)
inline MethodInvoker IProxy::callMethod(const std::string& methodName)
{
// Down-cast through static cast for performance reasons (no extra copy and object construction needed)
static_assert(sizeof(methodName) == sizeof(MethodName));
return callMethod(static_cast<const MethodName&>(methodName));
}
inline AsyncMethodInvoker IProxy::callMethodAsync(const MethodName& methodName)
{
return AsyncMethodInvoker(*this, methodName);
}
inline SignalSubscriber IProxy::uponSignal(const std::string& signalName)
inline AsyncMethodInvoker IProxy::callMethodAsync(const std::string& methodName)
{
// Down-cast through static cast for performance reasons (no extra copy and object construction needed)
static_assert(sizeof(methodName) == sizeof(MethodName));
return callMethodAsync(static_cast<const MethodName&>(methodName));
}
inline SignalSubscriber IProxy::uponSignal(const SignalName& signalName)
{
return SignalSubscriber(*this, signalName);
}
inline PropertyGetter IProxy::getProperty(const std::string& propertyName)
inline SignalSubscriber IProxy::uponSignal(const std::string& signalName)
{
// Down-cast through static cast for performance reasons (no extra copy and object construction needed)
static_assert(sizeof(signalName) == sizeof(SignalName));
return uponSignal(static_cast<const SignalName&>(signalName));
}
inline PropertyGetter IProxy::getProperty(const PropertyName& propertyName)
{
return PropertyGetter(*this, propertyName);
}
inline AsyncPropertyGetter IProxy::getPropertyAsync(const std::string& propertyName)
inline PropertyGetter IProxy::getProperty(const std::string& propertyName)
{
// Down-cast through static cast for performance reasons (no extra copy and object construction needed)
static_assert(sizeof(propertyName) == sizeof(PropertyName));
return getProperty(static_cast<const PropertyName&>(propertyName));
}
inline AsyncPropertyGetter IProxy::getPropertyAsync(const PropertyName& propertyName)
{
return AsyncPropertyGetter(*this, propertyName);
}
inline PropertySetter IProxy::setProperty(const std::string& propertyName)
inline AsyncPropertyGetter IProxy::getPropertyAsync(const std::string& propertyName)
{
// Down-cast through static cast for performance reasons (no extra copy and object construction needed)
static_assert(sizeof(propertyName) == sizeof(PropertyName));
return getPropertyAsync(static_cast<const PropertyName&>(propertyName));
}
inline PropertySetter IProxy::setProperty(const PropertyName& propertyName)
{
return PropertySetter(*this, propertyName);
}
inline AsyncPropertySetter IProxy::setPropertyAsync(const std::string& propertyName)
inline PropertySetter IProxy::setProperty(const std::string& propertyName)
{
// Down-cast through static cast for performance reasons (no extra copy and object construction needed)
static_assert(sizeof(propertyName) == sizeof(PropertyName));
return setProperty(static_cast<const PropertyName&>(propertyName));
}
inline AsyncPropertySetter IProxy::setPropertyAsync(const PropertyName& propertyName)
{
return AsyncPropertySetter(*this, propertyName);
}
inline AsyncPropertySetter IProxy::setPropertyAsync(const std::string& propertyName)
{
// Down-cast through static cast for performance reasons (no extra copy and object construction needed)
static_assert(sizeof(propertyName) == sizeof(PropertyName));
return setPropertyAsync(static_cast<const PropertyName&>(propertyName));
}
inline AllPropertiesGetter IProxy::getAllProperties()
{
return AllPropertiesGetter(*this);
@ -593,8 +686,8 @@ namespace sdbus {
* @endcode
*/
[[nodiscard]] std::unique_ptr<sdbus::IProxy> createProxy( sdbus::IConnection& connection
, std::string destination
, std::string objectPath );
, ServiceName destination
, ObjectPath objectPath );
/*!
* @brief Creates a proxy object for a specific remote D-Bus object
@ -619,8 +712,8 @@ namespace sdbus {
* @endcode
*/
[[nodiscard]] std::unique_ptr<sdbus::IProxy> createProxy( std::unique_ptr<sdbus::IConnection>&& connection
, std::string destination
, std::string objectPath );
, ServiceName destination
, ObjectPath objectPath );
/*!
* @brief Creates a proxy object for a specific remote D-Bus object
@ -646,8 +739,8 @@ namespace sdbus {
* @endcode
*/
[[nodiscard]] std::unique_ptr<sdbus::IProxy> createProxy( std::unique_ptr<sdbus::IConnection>&& connection
, std::string destination
, std::string objectPath
, ServiceName destination
, ObjectPath objectPath
, dont_run_event_loop_thread_t );
/*!
@ -667,8 +760,8 @@ namespace sdbus {
* auto proxy = sdbus::createProxy("com.kistler.foo", "/com/kistler/foo");
* @endcode
*/
[[nodiscard]] std::unique_ptr<sdbus::IProxy> createProxy( std::string destination
, std::string objectPath );
[[nodiscard]] std::unique_ptr<sdbus::IProxy> createProxy( ServiceName destination
, ObjectPath objectPath );
/*!
* @brief Creates a proxy object for a specific remote D-Bus object
@ -688,8 +781,8 @@ namespace sdbus {
* auto proxy = sdbus::createProxy("com.kistler.foo", "/com/kistler/foo", sdbus::dont_run_event_loop_thread );
* @endcode
*/
[[nodiscard]] std::unique_ptr<sdbus::IProxy> createProxy( std::string destination
, std::string objectPath
[[nodiscard]] std::unique_ptr<sdbus::IProxy> createProxy( ServiceName destination
, ObjectPath objectPath
, dont_run_event_loop_thread_t );
}

View File

@ -52,10 +52,14 @@
namespace sdbus {
class Variant;
class ObjectPath;
class InterfaceName;
class MemberName;
class Signature;
template <typename... _ValueTypes> class Struct;
class UnixFd;
class MethodReply;
class BusName;
using ConnectionName = BusName;
namespace internal {
class ISdBus;
}
@ -181,11 +185,11 @@ namespace sdbus {
explicit operator bool() const;
void clearFlags();
std::string getInterfaceName() const;
std::string getMemberName() const;
std::string getSender() const;
std::string getPath() const;
std::string getDestination() const;
InterfaceName getInterfaceName() const;
MemberName getMemberName() const;
ConnectionName getSender() const;
ObjectPath getPath() const;
ConnectionName getDestination() const;
void peekType(std::string& type, std::string& contents) const;
bool isValid() const;
bool isEmpty() const;
@ -281,7 +285,7 @@ namespace sdbus {
public:
Signal() = default;
void setDestination(const std::string& destination);
void setDestination(const ConnectionName& destination);
void send() const;
};

View File

@ -104,7 +104,7 @@ namespace sdbus {
* This constructor overload creates a proxy that manages its own D-Bus connection(s).
* For more information on its behavior, consult @ref createProxy(std::string,std::string)
*/
ProxyInterfaces(std::string destination, std::string objectPath)
ProxyInterfaces(ServiceName destination, ObjectPath objectPath)
: ProxyObjectHolder(createProxy(std::move(destination), std::move(objectPath)))
, _Interfaces(getProxy())...
{
@ -119,7 +119,7 @@ namespace sdbus {
* This constructor overload creates a proxy that manages its own D-Bus connection(s).
* For more information on its behavior, consult @ref createProxy(std::string,std::string,sdbus::dont_run_event_loop_thread_t)
*/
ProxyInterfaces(std::string destination, std::string objectPath, dont_run_event_loop_thread_t)
ProxyInterfaces(ServiceName destination, ObjectPath objectPath, dont_run_event_loop_thread_t)
: ProxyObjectHolder(createProxy(std::move(destination), std::move(objectPath), dont_run_event_loop_thread))
, _Interfaces(getProxy())...
{
@ -135,7 +135,7 @@ namespace sdbus {
* 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 createProxy(IConnection&,std::string,std::string)
*/
ProxyInterfaces(IConnection& connection, std::string destination, std::string objectPath)
ProxyInterfaces(IConnection& connection, ServiceName destination, ObjectPath objectPath)
: ProxyObjectHolder(createProxy(connection, std::move(destination), std::move(objectPath)))
, _Interfaces(getProxy())...
{
@ -151,7 +151,7 @@ namespace sdbus {
* The proxy created this way becomes an owner of the connection.
* For more information on its behavior, consult @ref createProxy(std::unique_ptr<sdbus::IConnection>&&,std::string,std::string)
*/
ProxyInterfaces(std::unique_ptr<sdbus::IConnection>&& connection, std::string destination, std::string objectPath)
ProxyInterfaces(std::unique_ptr<sdbus::IConnection>&& connection, ServiceName destination, ObjectPath objectPath)
: ProxyObjectHolder(createProxy(std::move(connection), std::move(destination), std::move(objectPath)))
, _Interfaces(getProxy())...
{
@ -167,7 +167,7 @@ namespace sdbus {
* The proxy created this way becomes an owner of the connection.
* For more information on its behavior, consult @ref createProxy(std::unique_ptr<sdbus::IConnection>&&,std::string,std::string,sdbus::dont_run_event_loop_thread_t)
*/
ProxyInterfaces(std::unique_ptr<sdbus::IConnection>&& connection, std::string destination, std::string objectPath, dont_run_event_loop_thread_t)
ProxyInterfaces(std::unique_ptr<sdbus::IConnection>&& connection, ServiceName destination, ObjectPath objectPath, dont_run_event_loop_thread_t)
: ProxyObjectHolder(createProxy(std::move(connection), std::move(destination), std::move(objectPath), dont_run_event_loop_thread))
, _Interfaces(getProxy())...
{

View File

@ -39,7 +39,7 @@ namespace sdbus {
// Proxy for peer
class Peer_proxy
{
static constexpr const char* INTERFACE_NAME = "org.freedesktop.DBus.Peer";
static inline const InterfaceName INTERFACE_NAME{"org.freedesktop.DBus.Peer"};
protected:
Peer_proxy(sdbus::IProxy& proxy)
@ -78,7 +78,7 @@ namespace sdbus {
// Proxy for introspection
class Introspectable_proxy
{
static constexpr const char* INTERFACE_NAME = "org.freedesktop.DBus.Introspectable";
static inline const InterfaceName INTERFACE_NAME{"org.freedesktop.DBus.Introspectable"};
protected:
Introspectable_proxy(sdbus::IProxy& proxy)
@ -112,7 +112,7 @@ namespace sdbus {
// Proxy for properties
class Properties_proxy
{
static constexpr const char* INTERFACE_NAME = "org.freedesktop.DBus.Properties";
static inline const InterfaceName INTERFACE_NAME{"org.freedesktop.DBus.Properties"};
protected:
Properties_proxy(sdbus::IProxy& proxy)
@ -132,68 +132,106 @@ namespace sdbus {
proxy_
->uponSignal("PropertiesChanged")
.onInterface(INTERFACE_NAME)
.call([this]( const std::string& interfaceName
, const std::map<std::string, sdbus::Variant>& changedProperties
, const std::vector<std::string>& invalidatedProperties )
.call([this]( const InterfaceName& interfaceName
, const std::map<PropertyName, sdbus::Variant>& changedProperties
, const std::vector<PropertyName>& invalidatedProperties )
{
this->onPropertiesChanged(interfaceName, changedProperties, invalidatedProperties);
});
}
virtual void onPropertiesChanged( const std::string& interfaceName
, const std::map<std::string, sdbus::Variant>& changedProperties
, const std::vector<std::string>& invalidatedProperties ) = 0;
virtual void onPropertiesChanged( const InterfaceName& interfaceName
, const std::map<PropertyName, sdbus::Variant>& changedProperties
, const std::vector<PropertyName>& invalidatedProperties ) = 0;
public:
sdbus::Variant Get(const std::string& interfaceName, const std::string& propertyName)
sdbus::Variant Get(const InterfaceName& interfaceName, const PropertyName& propertyName)
{
return proxy_->getProperty(propertyName).onInterface(interfaceName);
}
// TODO: Refactor from std::string to std::string_view before release/v2.0 !!!
sdbus::Variant Get(const InterfaceName& interfaceName, const std::string& propertyName)
{
return proxy_->getProperty(propertyName).onInterface(interfaceName);
}
template <typename _Function>
PendingAsyncCall GetAsync(const std::string& interfaceName, const std::string& propertyName, _Function&& callback)
PendingAsyncCall GetAsync(const InterfaceName& interfaceName, const PropertyName& propertyName, _Function&& callback)
{
return proxy_->getPropertyAsync(propertyName).onInterface(interfaceName).uponReplyInvoke(std::forward<_Function>(callback));
}
std::future<sdbus::Variant> GetAsync(const std::string& interfaceName, const std::string& propertyName, with_future_t)
template <typename _Function>
PendingAsyncCall GetAsync(const InterfaceName& interfaceName, const std::string& propertyName, _Function&& callback)
{
return proxy_->getPropertyAsync(propertyName).onInterface(interfaceName).uponReplyInvoke(std::forward<_Function>(callback));
}
std::future<sdbus::Variant> GetAsync(const InterfaceName& interfaceName, const PropertyName& propertyName, with_future_t)
{
return proxy_->getPropertyAsync(propertyName).onInterface(interfaceName).getResultAsFuture();
}
void Set(const std::string& interfaceName, const std::string& propertyName, const sdbus::Variant& value)
std::future<sdbus::Variant> GetAsync(const InterfaceName& interfaceName, const std::string& propertyName, with_future_t)
{
return proxy_->getPropertyAsync(propertyName).onInterface(interfaceName).getResultAsFuture();
}
void Set(const InterfaceName& interfaceName, const PropertyName& propertyName, const sdbus::Variant& value)
{
proxy_->setProperty(propertyName).onInterface(interfaceName).toValue(value);
}
void Set(const std::string& interfaceName, const std::string& propertyName, const sdbus::Variant& value, dont_expect_reply_t)
void Set(const InterfaceName& interfaceName, const std::string& propertyName, const sdbus::Variant& value)
{
proxy_->setProperty(propertyName).onInterface(interfaceName).toValue(value);
}
void Set(const InterfaceName& interfaceName, const PropertyName& propertyName, const sdbus::Variant& value, dont_expect_reply_t)
{
proxy_->setProperty(propertyName).onInterface(interfaceName).toValue(value, dont_expect_reply);
}
void Set(const InterfaceName& interfaceName, const std::string& propertyName, const sdbus::Variant& value, dont_expect_reply_t)
{
proxy_->setProperty(propertyName).onInterface(interfaceName).toValue(value, dont_expect_reply);
}
template <typename _Function>
PendingAsyncCall SetAsync(const std::string& interfaceName, const std::string& propertyName, const sdbus::Variant& value, _Function&& callback)
PendingAsyncCall SetAsync(const InterfaceName& interfaceName, const PropertyName& propertyName, const sdbus::Variant& value, _Function&& callback)
{
return proxy_->setPropertyAsync(propertyName).onInterface(interfaceName).toValue(value).uponReplyInvoke(std::forward<_Function>(callback));
}
std::future<void> SetAsync(const std::string& interfaceName, const std::string& propertyName, const sdbus::Variant& value, with_future_t)
template <typename _Function>
PendingAsyncCall SetAsync(const InterfaceName& interfaceName, const std::string& propertyName, const sdbus::Variant& value, _Function&& callback)
{
return proxy_->setPropertyAsync(propertyName).onInterface(interfaceName).toValue(value).uponReplyInvoke(std::forward<_Function>(callback));
}
std::future<void> SetAsync(const InterfaceName& interfaceName, const PropertyName& propertyName, const sdbus::Variant& value, with_future_t)
{
return proxy_->setPropertyAsync(propertyName).onInterface(interfaceName).toValue(value).getResultAsFuture();
}
std::map<std::string, sdbus::Variant> GetAll(const std::string& interfaceName)
std::future<void> SetAsync(const InterfaceName& interfaceName, const std::string& propertyName, const sdbus::Variant& value, with_future_t)
{
return proxy_->setPropertyAsync(propertyName).onInterface(interfaceName).toValue(value).getResultAsFuture();
}
std::map<PropertyName, sdbus::Variant> GetAll(const InterfaceName& interfaceName)
{
return proxy_->getAllProperties().onInterface(interfaceName);
}
template <typename _Function>
PendingAsyncCall GetAllAsync(const std::string& interfaceName, _Function&& callback)
PendingAsyncCall GetAllAsync(const InterfaceName& interfaceName, _Function&& callback)
{
return proxy_->getAllPropertiesAsync().onInterface(interfaceName).uponReplyInvoke(std::forward<_Function>(callback));
}
std::future<std::map<std::string, sdbus::Variant>> GetAllAsync(const std::string& interfaceName, with_future_t)
std::future<std::map<PropertyName, sdbus::Variant>> GetAllAsync(const InterfaceName& interfaceName, with_future_t)
{
return proxy_->getAllPropertiesAsync().onInterface(interfaceName).getResultAsFuture();
}
@ -205,7 +243,7 @@ namespace sdbus {
// Proxy for object manager
class ObjectManager_proxy
{
static constexpr const char* INTERFACE_NAME = "org.freedesktop.DBus.ObjectManager";
static inline const InterfaceName INTERFACE_NAME{"org.freedesktop.DBus.ObjectManager"};
protected:
ObjectManager_proxy(sdbus::IProxy& proxy)
@ -226,7 +264,7 @@ namespace sdbus {
->uponSignal("InterfacesAdded")
.onInterface(INTERFACE_NAME)
.call([this]( const sdbus::ObjectPath& objectPath
, const std::map<std::string, std::map<std::string, sdbus::Variant>>& interfacesAndProperties )
, const std::map<sdbus::InterfaceName, std::map<PropertyName, sdbus::Variant>>& interfacesAndProperties )
{
this->onInterfacesAdded(objectPath, interfacesAndProperties);
});
@ -234,21 +272,21 @@ namespace sdbus {
proxy_->uponSignal("InterfacesRemoved")
.onInterface(INTERFACE_NAME)
.call([this]( const sdbus::ObjectPath& objectPath
, const std::vector<std::string>& interfaces )
, const std::vector<sdbus::InterfaceName>& interfaces )
{
this->onInterfacesRemoved(objectPath, interfaces);
});
}
virtual void onInterfacesAdded( const sdbus::ObjectPath& objectPath
, const std::map<std::string, std::map<std::string, sdbus::Variant>>& interfacesAndProperties) = 0;
, const std::map<sdbus::InterfaceName, std::map<PropertyName, sdbus::Variant>>& interfacesAndProperties) = 0;
virtual void onInterfacesRemoved( const sdbus::ObjectPath& objectPath
, const std::vector<std::string>& interfaces) = 0;
, const std::vector<sdbus::InterfaceName>& interfaces) = 0;
public:
std::map<sdbus::ObjectPath, std::map<std::string, std::map<std::string, sdbus::Variant>>> GetManagedObjects()
std::map<sdbus::ObjectPath, std::map<sdbus::InterfaceName, std::map<PropertyName, sdbus::Variant>>> GetManagedObjects()
{
std::map<sdbus::ObjectPath, std::map<std::string, std::map<std::string, sdbus::Variant>>> objectsInterfacesAndProperties;
std::map<sdbus::ObjectPath, std::map<sdbus::InterfaceName, std::map<PropertyName, sdbus::Variant>>> objectsInterfacesAndProperties;
proxy_->callMethod("GetManagedObjects").onInterface(INTERFACE_NAME).storeResultsTo(objectsInterfacesAndProperties);
return objectsInterfacesAndProperties;
}
@ -264,7 +302,7 @@ namespace sdbus {
// Adaptor for properties
class Properties_adaptor
{
static constexpr const char* INTERFACE_NAME = "org.freedesktop.DBus.Properties";
static inline const InterfaceName INTERFACE_NAME{"org.freedesktop.DBus.Properties"};
protected:
Properties_adaptor(sdbus::IObject& object) : object_(&object)
@ -283,12 +321,12 @@ namespace sdbus {
}
public:
void emitPropertiesChangedSignal(const std::string& interfaceName, const std::vector<std::string>& properties)
void emitPropertiesChangedSignal(const InterfaceName& interfaceName, const std::vector<PropertyName>& properties)
{
object_->emitPropertiesChangedSignal(interfaceName, properties);
}
void emitPropertiesChangedSignal(const std::string& interfaceName)
void emitPropertiesChangedSignal(const InterfaceName& interfaceName)
{
object_->emitPropertiesChangedSignal(interfaceName);
}
@ -309,7 +347,7 @@ namespace sdbus {
*/
class ObjectManager_adaptor
{
static constexpr const char* INTERFACE_NAME = "org.freedesktop.DBus.ObjectManager";
static inline const InterfaceName INTERFACE_NAME{"org.freedesktop.DBus.ObjectManager"};
protected:
explicit ObjectManager_adaptor(sdbus::IObject& object) : object_(&object)
@ -378,7 +416,7 @@ namespace sdbus {
*
* See IObject::emitInterfacesAddedSignal().
*/
void emitInterfacesAddedSignal(const std::vector<std::string>& interfaces)
void emitInterfacesAddedSignal(const std::vector<sdbus::InterfaceName>& interfaces)
{
object_->emitInterfacesAddedSignal(interfaces);
}
@ -398,7 +436,7 @@ namespace sdbus {
*
* See IObject::emitInterfacesRemovedSignal().
*/
void emitInterfacesRemovedSignal(const std::vector<std::string>& interfaces)
void emitInterfacesRemovedSignal(const std::vector<InterfaceName>& interfaces)
{
object_->emitInterfacesRemovedSignal(interfaces);
}

View File

@ -54,6 +54,9 @@ namespace sdbus {
class ObjectPath;
class Signature;
class UnixFd;
class BusName;
class InterfaceName;
class MemberName;
class MethodCall;
class MethodReply;
class Signal;
@ -309,6 +312,21 @@ namespace sdbus {
}
};
template <>
struct signature_of<BusName> : signature_of<std::string>
{
};
template <>
struct signature_of<InterfaceName> : signature_of<std::string>
{
};
template <>
struct signature_of<MemberName> : signature_of<std::string>
{
};
template <typename... _ValueTypes>
struct signature_of<Struct<_ValueTypes...>>
{

View File

@ -171,42 +171,107 @@ namespace sdbus {
/********************************************//**
* @class ObjectPath
*
* Representation of object path D-Bus type
* Strong type representing the D-Bus object path
*
***********************************************/
class ObjectPath : public std::string
{
public:
using std::string::string;
ObjectPath() = default; // Fixes gcc 6.3 error (default c-tor is not imported in above using declaration)
ObjectPath(const ObjectPath&) = default; // Fixes gcc 8.3 error (deleted copy constructor)
ObjectPath(ObjectPath&&) = default; // Enable move - user-declared copy ctor prevents implicit creation
ObjectPath& operator = (const ObjectPath&) = default; // Fixes gcc 8.3 error (deleted copy assignment)
ObjectPath& operator = (ObjectPath&&) = default; // Enable move - user-declared copy assign prevents implicit creation
ObjectPath(std::string path)
: std::string(std::move(path))
ObjectPath() = default;
explicit ObjectPath(std::string value)
: std::string(std::move(value))
{}
explicit ObjectPath(const char* value)
: std::string(value)
{}
using std::string::operator=;
};
/********************************************//**
* @class BusName
*
* Strong type representing the D-Bus bus/service/connection name
*
***********************************************/
class BusName : public std::string
{
public:
BusName() = default;
explicit BusName(std::string value)
: std::string(std::move(value))
{}
explicit BusName(const char* value)
: std::string(value)
{}
using std::string::operator=;
};
using ServiceName = BusName;
using ConnectionName = BusName;
/********************************************//**
* @class InterfaceName
*
* Strong type representing the D-Bus interface name
*
***********************************************/
class InterfaceName : public std::string
{
public:
InterfaceName() = default;
explicit InterfaceName(std::string value)
: std::string(std::move(value))
{}
explicit InterfaceName(const char* value)
: std::string(value)
{}
using std::string::operator=;
};
/********************************************//**
* @class MemberName
*
* Strong type representing the D-Bus member name
*
***********************************************/
class MemberName : public std::string
{
public:
MemberName() = default;
explicit MemberName(std::string value)
: std::string(std::move(value))
{}
explicit MemberName(const char* value)
: std::string(value)
{}
using std::string::operator=;
};
using MethodName = MemberName;
using SignalName = MemberName;
using PropertyName = MemberName;
/********************************************//**
* @class Signature
*
* Representation of Signature D-Bus type
* Strong type representing the D-Bus object path
*
***********************************************/
class Signature : public std::string
{
public:
using std::string::string;
Signature() = default; // Fixes gcc 6.3 error (default c-tor is not imported in above using declaration)
Signature(const Signature&) = default; // Fixes gcc 8.3 error (deleted copy constructor)
Signature(Signature&&) = default; // Enable move - user-declared copy ctor prevents implicit creation
Signature& operator = (const Signature&) = default; // Fixes gcc 8.3 error (deleted copy assignment)
Signature& operator = (Signature&&) = default; // Enable move - user-declared copy assign prevents implicit creation
Signature(std::string path)
: std::string(std::move(path))
Signature() = default;
explicit Signature(std::string value)
: std::string(std::move(value))
{}
explicit Signature(const char* value)
: std::string(value)
{}
using std::string::operator=;
};

View File

@ -27,6 +27,7 @@
#define SDBUS_CXX_VTABLEITEMS_H_
#include <sdbus-c++/Flags.h>
#include <sdbus-c++/Types.h>
#include <sdbus-c++/TypeTraits.h>
#include <string>
@ -46,15 +47,16 @@ namespace sdbus {
MethodVTableItem& markAsPrivileged();
MethodVTableItem& withNoReply();
std::string name;
std::string inputSignature;
MethodName name;
Signature inputSignature;
std::vector<std::string> inputParamNames;
std::string outputSignature;
Signature outputSignature;
std::vector<std::string> outputParamNames;
method_callback callbackHandler;
Flags flags;
};
MethodVTableItem registerMethod(MethodName methodName);
MethodVTableItem registerMethod(std::string methodName);
struct SignalVTableItem
@ -64,12 +66,13 @@ namespace sdbus {
template <typename... _Args, typename... _String> SignalVTableItem& withParameters(_String... names);
SignalVTableItem& markAsDeprecated();
std::string name;
std::string signature;
SignalName name;
Signature signature;
std::vector<std::string> paramNames;
Flags flags;
};
SignalVTableItem registerSignal(SignalName signalName);
SignalVTableItem registerSignal(std::string signalName);
struct PropertyVTableItem
@ -80,13 +83,14 @@ namespace sdbus {
PropertyVTableItem& markAsPrivileged();
PropertyVTableItem& withUpdateBehavior(Flags::PropertyUpdateBehaviorFlags behavior);
std::string name;
std::string signature;
PropertyName name;
Signature signature;
property_get_callback getter;
property_set_callback setter;
Flags flags;
};
PropertyVTableItem registerProperty(PropertyName propertyName);
PropertyVTableItem registerProperty(std::string propertyName);
struct InterfaceFlagsVTableItem

View File

@ -125,11 +125,16 @@ namespace sdbus {
return *this;
}
inline MethodVTableItem registerMethod(std::string methodName)
inline MethodVTableItem registerMethod(MethodName methodName)
{
return {std::move(methodName), {}, {}, {}, {}, {}, {}};
}
inline MethodVTableItem registerMethod(std::string methodName)
{
return registerMethod(MethodName{std::move(methodName)});
}
/*** -------------------- ***/
/*** Signal VTable Item ***/
/*** -------------------- ***/
@ -166,11 +171,16 @@ namespace sdbus {
return *this;
}
inline SignalVTableItem registerSignal(std::string signalName)
inline SignalVTableItem registerSignal(SignalName signalName)
{
return {std::move(signalName), {}, {}, {}};
}
inline SignalVTableItem registerSignal(std::string signalName)
{
return registerSignal(SignalName{std::move(signalName)});
}
/*** -------------------- ***/
/*** Property VTable Item ***/
/*** -------------------- ***/
@ -239,11 +249,16 @@ namespace sdbus {
return *this;
}
inline PropertyVTableItem registerProperty(std::string propertyName)
inline PropertyVTableItem registerProperty(PropertyName propertyName)
{
return {std::move(propertyName), {}, {}, {}, {}};
}
inline PropertyVTableItem registerProperty(std::string propertyName)
{
return registerProperty(PropertyName{std::move(propertyName)});
}
/*** --------------------------- ***/
/*** Interface Flags VTable Item ***/
/*** --------------------------- ***/

View File

@ -28,6 +28,7 @@
#include "sdbus-c++/Error.h"
#include "sdbus-c++/Message.h"
#include "sdbus-c++/Types.h"
#include "MessageUtils.h"
#include "ScopeGuard.h"
@ -108,7 +109,7 @@ Connection::~Connection()
Connection::leaveEventLoop();
}
void Connection::requestName(const std::string& name)
void Connection::requestName(const ServiceName& name)
{
SDBUS_CHECK_SERVICE_NAME(name);
@ -120,7 +121,7 @@ void Connection::requestName(const std::string& name)
wakeUpEventLoopIfMessagesInQueue();
}
void Connection::releaseName(const std::string& name)
void Connection::releaseName(const ServiceName& name)
{
auto r = sdbus_->sd_bus_release_name(bus_.get(), name.c_str());
SDBUS_THROW_ERROR_IF(r < 0, "Failed to release bus name", -r);
@ -130,12 +131,12 @@ void Connection::releaseName(const std::string& name)
wakeUpEventLoopIfMessagesInQueue();
}
std::string Connection::getUniqueName() const
BusName Connection::getUniqueName() const
{
const char* unique = nullptr;
auto r = sdbus_->sd_bus_get_unique_name(bus_.get(), &unique);
SDBUS_THROW_ERROR_IF(r < 0 || unique == nullptr, "Failed to get unique bus name", -r);
return unique;
const char* name{};
auto r = sdbus_->sd_bus_get_unique_name(bus_.get(), &name);
SDBUS_THROW_ERROR_IF(r < 0 || name == nullptr, "Failed to get unique bus name", -r);
return BusName{name};
}
void Connection::enterEventLoop()
@ -188,14 +189,14 @@ ISdBus& Connection::getSdBusInterface()
return *sdbus_.get();
}
void Connection::addObjectManager(const std::string& objectPath, floating_slot_t)
void Connection::addObjectManager(const ObjectPath& objectPath, floating_slot_t)
{
auto r = sdbus_->sd_bus_add_object_manager(bus_.get(), nullptr, objectPath.c_str());
SDBUS_THROW_ERROR_IF(r < 0, "Failed to add object manager", -r);
}
Slot Connection::addObjectManager(const std::string& objectPath, return_slot_t)
Slot Connection::addObjectManager(const ObjectPath& objectPath, return_slot_t)
{
sd_bus_slot *slot{};
@ -456,8 +457,8 @@ void Connection::deleteSdEventSource(sd_event_source *s)
#endif // SDBUS_basu
Slot Connection::addObjectVTable( const std::string& objectPath
, const std::string& interfaceName
Slot Connection::addObjectVTable( const ObjectPath& objectPath
, const InterfaceName& interfaceName
, const sd_bus_vtable* vtable
, void* userData )
{
@ -486,10 +487,10 @@ PlainMessage Connection::createPlainMessage() const
return Message::Factory::create<PlainMessage>(sdbusMsg, sdbus_.get(), adopt_message);
}
MethodCall Connection::createMethodCall( const std::string& destination
, const std::string& objectPath
, const std::string& interfaceName
, const std::string& methodName ) const
MethodCall Connection::createMethodCall( const ServiceName& destination
, const ObjectPath& objectPath
, const InterfaceName& interfaceName
, const MethodName& methodName ) const
{
sd_bus_message *sdbusMsg{};
@ -505,9 +506,9 @@ MethodCall Connection::createMethodCall( const std::string& destination
return Message::Factory::create<MethodCall>(sdbusMsg, sdbus_.get(), adopt_message);
}
Signal Connection::createSignal( const std::string& objectPath
, const std::string& interfaceName
, const std::string& signalName ) const
Signal Connection::createSignal( const ObjectPath& objectPath
, const InterfaceName& interfaceName
, const SignalName& signalName ) const
{
sd_bus_message *sdbusMsg{};
@ -562,9 +563,9 @@ Slot Connection::callMethod(const MethodCall& message, void* callback, void* use
return slot;
}
void Connection::emitPropertiesChangedSignal( const std::string& objectPath
, const std::string& interfaceName
, const std::vector<std::string>& propNames )
void Connection::emitPropertiesChangedSignal( const ObjectPath& objectPath
, const InterfaceName& interfaceName
, const std::vector<PropertyName>& propNames )
{
auto names = to_strv(propNames);
@ -576,15 +577,15 @@ void Connection::emitPropertiesChangedSignal( const std::string& objectPath
SDBUS_THROW_ERROR_IF(r < 0, "Failed to emit PropertiesChanged signal", -r);
}
void Connection::emitInterfacesAddedSignal(const std::string& objectPath)
void Connection::emitInterfacesAddedSignal(const ObjectPath& objectPath)
{
auto r = sdbus_->sd_bus_emit_object_added(bus_.get(), objectPath.c_str());
SDBUS_THROW_ERROR_IF(r < 0, "Failed to emit InterfacesAdded signal for all registered interfaces", -r);
}
void Connection::emitInterfacesAddedSignal( const std::string& objectPath
, const std::vector<std::string>& interfaces )
void Connection::emitInterfacesAddedSignal( const ObjectPath& objectPath
, const std::vector<InterfaceName>& interfaces )
{
auto names = to_strv(interfaces);
@ -595,15 +596,15 @@ void Connection::emitInterfacesAddedSignal( const std::string& objectPath
SDBUS_THROW_ERROR_IF(r < 0, "Failed to emit InterfacesAdded signal", -r);
}
void Connection::emitInterfacesRemovedSignal(const std::string& objectPath)
void Connection::emitInterfacesRemovedSignal(const ObjectPath& objectPath)
{
auto r = sdbus_->sd_bus_emit_object_removed(bus_.get(), objectPath.c_str());
SDBUS_THROW_ERROR_IF(r < 0, "Failed to emit InterfacesRemoved signal for all registered interfaces", -r);
}
void Connection::emitInterfacesRemovedSignal( const std::string& objectPath
, const std::vector<std::string>& interfaces )
void Connection::emitInterfacesRemovedSignal( const ObjectPath& objectPath
, const std::vector<InterfaceName>& interfaces )
{
auto names = to_strv(interfaces);
@ -614,10 +615,10 @@ void Connection::emitInterfacesRemovedSignal( const std::string& objectPath
SDBUS_THROW_ERROR_IF(r < 0, "Failed to emit InterfacesRemoved signal", -r);
}
Slot Connection::registerSignalHandler( const std::string& sender
, const std::string& objectPath
, const std::string& interfaceName
, const std::string& signalName
Slot Connection::registerSignalHandler( const ServiceName& sender
, const ObjectPath& objectPath
, const InterfaceName& interfaceName
, const SignalName& signalName
, sd_bus_message_handler_t callback
, void* userData )
{
@ -777,7 +778,8 @@ Message Connection::getCurrentlyProcessedMessage() const
return Message::Factory::create<Message>(sdbusMsg, sdbus_.get());
}
std::vector</*const */char*> Connection::to_strv(const std::vector<std::string>& strings)
template <typename StringBasedType>
std::vector</*const */char*> Connection::to_strv(const std::vector<StringBasedType>& strings)
{
std::vector</*const */char*> strv;
for (auto& str : strings)
@ -890,7 +892,7 @@ std::unique_ptr<sdbus::IConnection> createBusConnection()
return std::make_unique<sdbus::internal::Connection>(std::move(interface), Connection::default_bus);
}
std::unique_ptr<sdbus::IConnection> createBusConnection(const std::string& name)
std::unique_ptr<sdbus::IConnection> createBusConnection(const ServiceName& name)
{
auto conn = createBusConnection();
conn->requestName(name);
@ -903,7 +905,7 @@ std::unique_ptr<sdbus::IConnection> createSystemBusConnection()
return std::make_unique<sdbus::internal::Connection>(std::move(interface), Connection::system_bus);
}
std::unique_ptr<sdbus::IConnection> createSystemBusConnection(const std::string& name)
std::unique_ptr<sdbus::IConnection> createSystemBusConnection(const ServiceName& name)
{
auto conn = createSystemBusConnection();
conn->requestName(name);
@ -916,7 +918,7 @@ std::unique_ptr<sdbus::IConnection> createSessionBusConnection()
return std::make_unique<sdbus::internal::Connection>(std::move(interface), Connection::session_bus);
}
std::unique_ptr<sdbus::IConnection> createSessionBusConnection(const std::string& name)
std::unique_ptr<sdbus::IConnection> createSessionBusConnection(const ServiceName& name)
{
auto conn = createSessionBusConnection();
conn->requestName(name);

View File

@ -41,7 +41,18 @@
#include <thread>
#include <vector>
// Forward declarations
struct sd_event_source;
namespace sdbus {
class ObjectPath;
class InterfaceName;
class BusName;
using ServiceName = BusName;
class MemberName;
using MethodName = MemberName;
using SignalName = MemberName;
using PropertyName = MemberName;
}
namespace sdbus::internal {
@ -81,9 +92,9 @@ namespace sdbus::internal {
Connection(std::unique_ptr<ISdBus>&& interface, pseudo_bus_t);
~Connection() override;
void requestName(const std::string& name) override;
void releaseName(const std::string& name) override;
[[nodiscard]] std::string getUniqueName() const override;
void requestName(const ServiceName & name) override;
void releaseName(const ServiceName& name) override;
[[nodiscard]] BusName getUniqueName() const override;
void enterEventLoop() override;
void enterEventLoopAsync() override;
void leaveEventLoop() override;
@ -91,8 +102,8 @@ namespace sdbus::internal {
bool processPendingEvent() override;
Message getCurrentlyProcessedMessage() const override;
void addObjectManager(const std::string& objectPath, floating_slot_t) override;
Slot addObjectManager(const std::string& objectPath, return_slot_t) override;
void addObjectManager(const ObjectPath& objectPath, floating_slot_t) override;
Slot addObjectManager(const ObjectPath& objectPath, return_slot_t) override;
void setMethodCallTimeout(uint64_t timeout) override;
[[nodiscard]] uint64_t getMethodCallTimeout() const override;
@ -109,38 +120,38 @@ namespace sdbus::internal {
[[nodiscard]] const ISdBus& getSdBusInterface() const override;
[[nodiscard]] ISdBus& getSdBusInterface() override;
Slot addObjectVTable( const std::string& objectPath
, const std::string& interfaceName
Slot addObjectVTable( const ObjectPath& objectPath
, const InterfaceName& interfaceName
, const sd_bus_vtable* vtable
, void* userData ) override;
[[nodiscard]] PlainMessage createPlainMessage() const override;
[[nodiscard]] MethodCall createMethodCall( const std::string& destination
, const std::string& objectPath
, const std::string& interfaceName
, const std::string& methodName ) const override;
[[nodiscard]] Signal createSignal( const std::string& objectPath
, const std::string& interfaceName
, const std::string& signalName ) const override;
[[nodiscard]] MethodCall createMethodCall( const ServiceName& destination
, const ObjectPath& objectPath
, const InterfaceName& interfaceName
, const MethodName& methodName ) const override;
[[nodiscard]] Signal createSignal( const ObjectPath& objectPath
, const InterfaceName& interfaceName
, const SignalName& signalName ) const override;
MethodReply callMethod(const MethodCall& message, uint64_t timeout) override;
void callMethod(const MethodCall& message, void* callback, void* userData, uint64_t timeout, floating_slot_t) override;
Slot callMethod(const MethodCall& message, void* callback, void* userData, uint64_t timeout) override;
void emitPropertiesChangedSignal( const std::string& objectPath
, const std::string& interfaceName
, const std::vector<std::string>& propNames ) override;
void emitInterfacesAddedSignal(const std::string& objectPath) override;
void emitInterfacesAddedSignal( const std::string& objectPath
, const std::vector<std::string>& interfaces ) override;
void emitInterfacesRemovedSignal(const std::string& objectPath) override;
void emitInterfacesRemovedSignal( const std::string& objectPath
, const std::vector<std::string>& interfaces ) override;
void emitPropertiesChangedSignal( const ObjectPath& objectPath
, const InterfaceName& interfaceName
, const std::vector<PropertyName>& propNames ) override;
void emitInterfacesAddedSignal(const ObjectPath& objectPath) override;
void emitInterfacesAddedSignal( const ObjectPath& objectPath
, const std::vector<InterfaceName>& interfaces ) override;
void emitInterfacesRemovedSignal(const ObjectPath& objectPath) override;
void emitInterfacesRemovedSignal( const ObjectPath& objectPath
, const std::vector<InterfaceName>& interfaces ) override;
Slot registerSignalHandler( const std::string& sender
, const std::string& objectPath
, const std::string& interfaceName
, const std::string& signalName
Slot registerSignalHandler( const ServiceName& sender
, const ObjectPath& objectPath
, const InterfaceName& interfaceName
, const SignalName& signalName
, sd_bus_message_handler_t callback
, void* userData ) override;
@ -161,7 +172,8 @@ namespace sdbus::internal {
void wakeUpEventLoopIfMessagesInQueue();
void joinWithEventLoop();
static std::vector</*const */char*> to_strv(const std::vector<std::string>& strings);
template <typename StringBasedType>
static std::vector</*const */char*> to_strv(const std::vector<StringBasedType>& strings);
static int sdbus_match_callback(sd_bus_message *sdbusMessage, void *userData, sd_bus_error *retError);
static int sdbus_match_install_callback(sd_bus_message *sdbusMessage, void *userData, sd_bus_error *retError);

View File

@ -32,14 +32,18 @@
namespace sdbus
{
sdbus::Error createError(int errNo, const std::string& customMsg)
sdbus::Error createError(int errNo, std::string customMsg)
{
sd_bus_error sdbusError = SD_BUS_ERROR_NULL;
sd_bus_error_set_errno(&sdbusError, errNo);
SCOPE_EXIT{ sd_bus_error_free(&sdbusError); };
std::string name(sdbusError.name);
std::string message(customMsg + " (" + sdbusError.message + ")");
return sdbus::Error(name, message);
Error::Name name(sdbusError.name);
std::string message(std::move(customMsg));
message.append(" (");
message.append(sdbusError.message);
message.append(")");
return Error(std::move(name), std::move(message));
}
} // namespace sdbus

View File

@ -37,12 +37,20 @@
#include SDBUS_HEADER
#include <vector>
// Forward declaration
// Forward declarations
namespace sdbus {
class MethodCall;
class MethodReply;
class Signal;
class PlainMessage;
class ObjectPath;
class InterfaceName;
class BusName;
using ServiceName = BusName;
class MemberName;
using MethodName = MemberName;
using SignalName = MemberName;
using PropertyName = MemberName;
namespace internal {
class ISdBus;
}
@ -59,41 +67,41 @@ namespace sdbus::internal {
[[nodiscard]] virtual const ISdBus& getSdBusInterface() const = 0;
[[nodiscard]] virtual ISdBus& getSdBusInterface() = 0;
[[nodiscard]] virtual Slot addObjectVTable( const std::string& objectPath
, const std::string& interfaceName
[[nodiscard]] virtual Slot addObjectVTable( const ObjectPath& objectPath
, const InterfaceName& interfaceName
, const sd_bus_vtable* vtable
, void* userData ) = 0;
[[nodiscard]] virtual PlainMessage createPlainMessage() const = 0;
[[nodiscard]] virtual MethodCall createMethodCall( const std::string& destination
, const std::string& objectPath
, const std::string& interfaceName
, const std::string& methodName ) const = 0;
[[nodiscard]] virtual Signal createSignal( const std::string& objectPath
, const std::string& interfaceName
, const std::string& signalName ) const = 0;
[[nodiscard]] virtual MethodCall createMethodCall( const ServiceName& destination
, const ObjectPath& objectPath
, const InterfaceName& interfaceName
, const MethodName& methodName ) const = 0;
[[nodiscard]] virtual Signal createSignal( const ObjectPath& objectPath
, const InterfaceName& interfaceName
, const SignalName& signalName ) const = 0;
virtual MethodReply callMethod(const MethodCall& message, uint64_t timeout) = 0;
virtual void callMethod(const MethodCall& message, void* callback, void* userData, uint64_t timeout, floating_slot_t) = 0;
[[nodiscard]] virtual Slot callMethod(const MethodCall& message, void* callback, void* userData, uint64_t timeout) = 0;
virtual void emitPropertiesChangedSignal( const std::string& objectPath
, const std::string& interfaceName
, const std::vector<std::string>& propNames ) = 0;
virtual void emitInterfacesAddedSignal(const std::string& objectPath) = 0;
virtual void emitInterfacesAddedSignal( const std::string& objectPath
, const std::vector<std::string>& interfaces ) = 0;
virtual void emitInterfacesRemovedSignal(const std::string& objectPath) = 0;
virtual void emitInterfacesRemovedSignal( const std::string& objectPath
, const std::vector<std::string>& interfaces ) = 0;
virtual void emitPropertiesChangedSignal( const ObjectPath& objectPath
, const InterfaceName& interfaceName
, const std::vector<PropertyName>& propNames ) = 0;
virtual void emitInterfacesAddedSignal(const ObjectPath& objectPath) = 0;
virtual void emitInterfacesAddedSignal( const ObjectPath& objectPath
, const std::vector<InterfaceName>& interfaces ) = 0;
virtual void emitInterfacesRemovedSignal(const ObjectPath& objectPath) = 0;
virtual void emitInterfacesRemovedSignal( const ObjectPath& objectPath
, const std::vector<InterfaceName>& interfaces ) = 0;
using sdbus::IConnection::addObjectManager;
[[nodiscard]] virtual Slot addObjectManager(const std::string& objectPath, return_slot_t) = 0;
[[nodiscard]] virtual Slot addObjectManager(const ObjectPath& objectPath, return_slot_t) = 0;
[[nodiscard]] virtual Slot registerSignalHandler( const std::string& sender
, const std::string& objectPath
, const std::string& interfaceName
, const std::string& signalName
[[nodiscard]] virtual Slot registerSignalHandler( const ServiceName& sender
, const ObjectPath& objectPath
, const InterfaceName& interfaceName
, const SignalName& signalName
, sd_bus_message_handler_t callback
, void* userData ) = 0;
};

View File

@ -602,33 +602,34 @@ void Message::rewind(bool complete)
SDBUS_THROW_ERROR_IF(r < 0, "Failed to rewind the message", -r);
}
std::string Message::getInterfaceName() const
InterfaceName Message::getInterfaceName() const
{
auto interface = sd_bus_message_get_interface((sd_bus_message*)msg_);
return interface != nullptr ? interface : "";
const auto* interface = sd_bus_message_get_interface((sd_bus_message*)msg_);
return interface != nullptr ? InterfaceName{interface} : InterfaceName{};
}
std::string Message::getMemberName() const
MemberName Message::getMemberName() const
{
auto member = sd_bus_message_get_member((sd_bus_message*)msg_);
return member != nullptr ? member : "";
const auto* member = sd_bus_message_get_member((sd_bus_message*)msg_);
return member != nullptr ? MemberName{member} : MemberName{};
}
std::string Message::getSender() const
ConnectionName Message::getSender() const
{
return sd_bus_message_get_sender((sd_bus_message*)msg_);
const auto* sender = sd_bus_message_get_sender((sd_bus_message*)msg_);
return ConnectionName{sender};
}
std::string Message::getPath() const
ObjectPath Message::getPath() const
{
auto path = sd_bus_message_get_path((sd_bus_message*)msg_);
return path != nullptr ? path : "";
const auto* path = sd_bus_message_get_path((sd_bus_message*)msg_);
return path != nullptr ? ObjectPath{path} : ObjectPath{};
}
std::string Message::getDestination() const
ConnectionName Message::getDestination() const
{
auto destination = sd_bus_message_get_destination((sd_bus_message*)msg_);
return destination != nullptr ? destination : "";
const auto* destination = sd_bus_message_get_destination((sd_bus_message*)msg_);
return destination != nullptr ? ConnectionName{destination} : ConnectionName{};
}
void Message::peekType(std::string& type, std::string& contents) const
@ -801,7 +802,7 @@ MethodReply MethodCall::sendWithReply(uint64_t timeout) const
auto r = sdbus_->sd_bus_call(nullptr, (sd_bus_message*)msg_, timeout, &sdbusError, &sdbusReply);
if (sd_bus_error_is_set(&sdbusError))
throw sdbus::Error(sdbusError.name, sdbusError.message);
throw Error(Error::Name{sdbusError.name}, sdbusError.message);
SDBUS_THROW_ERROR_IF(r < 0, "Failed to call method", -r);
@ -866,7 +867,7 @@ void Signal::send() const
SDBUS_THROW_ERROR_IF(r < 0, "Failed to emit signal", -r);
}
void Signal::setDestination(const std::string& destination)
void Signal::setDestination(const ConnectionName& destination)
{
auto r = sdbus_->sd_bus_message_set_destination((sd_bus_message*)msg_, destination.c_str());
SDBUS_THROW_ERROR_IF(r < 0, "Failed to set signal destination", -r);

View File

@ -43,20 +43,20 @@
namespace sdbus::internal {
Object::Object(sdbus::internal::IConnection& connection, std::string objectPath)
Object::Object(sdbus::internal::IConnection& connection, ObjectPath objectPath)
: connection_(connection), objectPath_(std::move(objectPath))
{
SDBUS_CHECK_OBJECT_PATH(objectPath_);
}
void Object::addVTable(std::string interfaceName, std::vector<VTableItem> vtable)
void Object::addVTable(InterfaceName interfaceName, std::vector<VTableItem> vtable)
{
auto slot = Object::addVTable(std::move(interfaceName), std::move(vtable), return_slot);
vtables_.push_back(std::move(slot));
}
Slot Object::addVTable(std::string interfaceName, std::vector<VTableItem> vtable, return_slot_t)
Slot Object::addVTable(InterfaceName interfaceName, std::vector<VTableItem> vtable, return_slot_t)
{
SDBUS_CHECK_INTERFACE_NAME(interfaceName);
@ -79,7 +79,7 @@ void Object::unregister()
removeObjectManager();
}
sdbus::Signal Object::createSignal(const std::string& interfaceName, const std::string& signalName)
sdbus::Signal Object::createSignal(const InterfaceName& interfaceName, const SignalName& signalName)
{
return connection_.createSignal(objectPath_, interfaceName, signalName);
}
@ -91,12 +91,12 @@ void Object::emitSignal(const sdbus::Signal& message)
message.send();
}
void Object::emitPropertiesChangedSignal(const std::string& interfaceName, const std::vector<std::string>& propNames)
void Object::emitPropertiesChangedSignal(const InterfaceName& interfaceName, const std::vector<PropertyName>& propNames)
{
connection_.emitPropertiesChangedSignal(objectPath_, interfaceName, propNames);
}
void Object::emitPropertiesChangedSignal(const std::string& interfaceName)
void Object::emitPropertiesChangedSignal(const InterfaceName& interfaceName)
{
Object::emitPropertiesChangedSignal(interfaceName, {});
}
@ -106,7 +106,7 @@ void Object::emitInterfacesAddedSignal()
connection_.emitInterfacesAddedSignal(objectPath_);
}
void Object::emitInterfacesAddedSignal(const std::vector<std::string>& interfaces)
void Object::emitInterfacesAddedSignal(const std::vector<InterfaceName>& interfaces)
{
connection_.emitInterfacesAddedSignal(objectPath_, interfaces);
}
@ -116,7 +116,7 @@ void Object::emitInterfacesRemovedSignal()
connection_.emitInterfacesRemovedSignal(objectPath_);
}
void Object::emitInterfacesRemovedSignal(const std::vector<std::string>& interfaces)
void Object::emitInterfacesRemovedSignal(const std::vector<InterfaceName>& interfaces)
{
connection_.emitInterfacesRemovedSignal(objectPath_, interfaces);
}
@ -141,7 +141,7 @@ sdbus::IConnection& Object::getConnection() const
return connection_;
}
const std::string& Object::getObjectPath() const
const ObjectPath& Object::getObjectPath() const
{
return objectPath_;
}
@ -151,7 +151,7 @@ Message Object::getCurrentlyProcessedMessage() const
return connection_.getCurrentlyProcessedMessage();
}
Object::VTable Object::createInternalVTable(std::string interfaceName, std::vector<VTableItem> vtable)
Object::VTable Object::createInternalVTable(InterfaceName interfaceName, std::vector<VTableItem> vtable)
{
VTable internalVTable;
@ -241,8 +241,8 @@ void Object::startSdBusVTable(const Flags& interfaceFlags, std::vector<sd_bus_vt
void Object::writeMethodRecordToSdBusVTable(const VTable::MethodItem& method, std::vector<sd_bus_vtable>& vtable)
{
auto vtableItem = createSdBusVTableMethodItem( method.name.c_str()
, method.inputArgs.c_str()
, method.outputArgs.c_str()
, method.inputSignature.c_str()
, method.outputSignature.c_str()
, method.paramNames.c_str()
, &Object::sdbus_method_callback
, method.flags.toSdBusMethodFlags() );
@ -278,23 +278,27 @@ void Object::finalizeSdBusVTable(std::vector<sd_bus_vtable>& vtable)
vtable.push_back(createSdBusVTableEndItem());
}
const Object::VTable::MethodItem* Object::findMethod(const VTable& vtable, const std::string& methodName)
const Object::VTable::MethodItem* Object::findMethod(const VTable& vtable, std::string_view methodName)
{
auto it = std::lower_bound(vtable.methods.begin(), vtable.methods.end(), methodName, [](const auto& methodItem, const auto& methodName)
{
return methodItem.name < methodName;
});
(void)it;
return it != vtable.methods.end() && it->name == methodName ? &*it : nullptr;
}
const Object::VTable::PropertyItem* Object::findProperty(const VTable& vtable, const std::string& propertyName)
const Object::VTable::PropertyItem* Object::findProperty(const VTable& vtable, std::string_view propertyName)
{
auto it = std::lower_bound(vtable.properties.begin(), vtable.properties.end(), propertyName, [](const auto& propertyItem, const auto& propertyName)
{
return propertyItem.name < propertyName;
});
(void)it;
return it != vtable.properties.end() && it->name == propertyName ? &*it : nullptr;
}
@ -314,7 +318,7 @@ int Object::sdbus_method_callback(sd_bus_message *sdbusMessage, void *userData,
auto message = Message::Factory::create<MethodCall>(sdbusMessage, &vtable->object->connection_.getSdBusInterface());
const auto* methodItem = findMethod(*vtable, message.getMemberName());
const auto* methodItem = findMethod(*vtable, message.getMemberName()); // TODO: optimize the situation around getMemberName()
assert(methodItem != nullptr);
assert(methodItem->callback);
@ -379,7 +383,7 @@ int Object::sdbus_property_set_callback( sd_bus */*bus*/
namespace sdbus {
std::unique_ptr<sdbus::IObject> createObject(sdbus::IConnection& connection, std::string objectPath)
std::unique_ptr<sdbus::IObject> createObject(sdbus::IConnection& connection, ObjectPath objectPath)
{
auto* sdbusConnection = dynamic_cast<sdbus::internal::IConnection*>(&connection);
SDBUS_THROW_ERROR_IF(!sdbusConnection, "Connection is not a real sdbus-c++ connection", EINVAL);

View File

@ -30,12 +30,14 @@
#include "sdbus-c++/IObject.h"
#include "IConnection.h"
#include "sdbus-c++/Types.h"
#include <cassert>
#include <functional>
#include <list>
#include <memory>
#include <string>
#include <string_view>
#include SDBUS_HEADER
#include <vector>
@ -45,27 +47,27 @@ namespace sdbus::internal {
: public IObject
{
public:
Object(sdbus::internal::IConnection& connection, std::string objectPath);
Object(sdbus::internal::IConnection& connection, ObjectPath objectPath);
void addVTable(std::string interfaceName, std::vector<VTableItem> vtable) override;
Slot addVTable(std::string interfaceName, std::vector<VTableItem> vtable, return_slot_t) override;
void addVTable(InterfaceName interfaceName, std::vector<VTableItem> vtable) override;
Slot addVTable(InterfaceName interfaceName, std::vector<VTableItem> vtable, return_slot_t) override;
void unregister() override;
sdbus::Signal createSignal(const std::string& interfaceName, const std::string& signalName) override;
sdbus::Signal createSignal(const InterfaceName& interfaceName, const SignalName& signalName) override;
void emitSignal(const sdbus::Signal& message) override;
void emitPropertiesChangedSignal(const std::string& interfaceName, const std::vector<std::string>& propNames) override;
void emitPropertiesChangedSignal(const std::string& interfaceName) override;
void emitPropertiesChangedSignal(const InterfaceName& interfaceName, const std::vector<PropertyName>& propNames) override;
void emitPropertiesChangedSignal(const InterfaceName& interfaceName) override;
void emitInterfacesAddedSignal() override;
void emitInterfacesAddedSignal(const std::vector<std::string>& interfaces) override;
void emitInterfacesAddedSignal(const std::vector<InterfaceName>& interfaces) override;
void emitInterfacesRemovedSignal() override;
void emitInterfacesRemovedSignal(const std::vector<std::string>& interfaces) override;
void emitInterfacesRemovedSignal(const std::vector<InterfaceName>& interfaces) override;
void addObjectManager() override;
void removeObjectManager() override;
[[nodiscard]] bool hasObjectManager() const override;
[[nodiscard]] sdbus::IConnection& getConnection() const override;
[[nodiscard]] const std::string& getObjectPath() const override;
[[nodiscard]] const ObjectPath& getObjectPath() const override;
[[nodiscard]] Message getCurrentlyProcessedMessage() const override;
private:
@ -74,14 +76,14 @@ namespace sdbus::internal {
// An interface can have any number of vtables attached to it, not only one.
struct VTable
{
std::string interfaceName;
InterfaceName interfaceName;
Flags interfaceFlags;
struct MethodItem
{
std::string name;
std::string inputArgs;
std::string outputArgs;
MethodName name;
Signature inputSignature;
Signature outputSignature;
std::string paramNames;
method_callback callback;
Flags flags;
@ -91,8 +93,8 @@ namespace sdbus::internal {
struct SignalItem
{
std::string name;
std::string signature;
SignalName name;
Signature signature;
std::string paramNames;
Flags flags;
};
@ -101,8 +103,8 @@ namespace sdbus::internal {
struct PropertyItem
{
std::string name;
std::string signature;
PropertyName name;
Signature signature;
property_get_callback getCallback;
property_set_callback setCallback;
Flags flags;
@ -121,7 +123,7 @@ namespace sdbus::internal {
Slot slot;
};
VTable createInternalVTable(std::string interfaceName, std::vector<VTableItem> vtable);
VTable createInternalVTable(InterfaceName interfaceName, std::vector<VTableItem> vtable);
void writeInterfaceFlagsToVTable(InterfaceFlagsVTableItem flags, VTable& vtable);
void writeMethodRecordToVTable(MethodVTableItem method, VTable& vtable);
void writeSignalRecordToVTable(SignalVTableItem signal, VTable& vtable);
@ -134,8 +136,8 @@ namespace sdbus::internal {
static void writePropertyRecordToSdBusVTable(const VTable::PropertyItem& property, std::vector<sd_bus_vtable>& vtable);
static void finalizeSdBusVTable(std::vector<sd_bus_vtable>& vtable);
static const VTable::MethodItem* findMethod(const VTable& vtable, const std::string& methodName);
static const VTable::PropertyItem* findProperty(const VTable& vtable, const std::string& propertyName);
static const VTable::MethodItem* findMethod(const VTable& vtable, std::string_view methodName);
static const VTable::PropertyItem* findProperty(const VTable& vtable, std::string_view propertyName);
static std::string paramNamesToString(const std::vector<std::string>& paramNames);
@ -157,7 +159,7 @@ namespace sdbus::internal {
private:
sdbus::internal::IConnection& connection_;
std::string objectPath_;
ObjectPath objectPath_;
std::vector<Slot> vtables_;
Slot objectManagerSlot_;
};

View File

@ -41,7 +41,7 @@
namespace sdbus::internal {
Proxy::Proxy(sdbus::internal::IConnection& connection, std::string destination, std::string objectPath)
Proxy::Proxy(sdbus::internal::IConnection& connection, ServiceName destination, ObjectPath objectPath)
: connection_(&connection, [](sdbus::internal::IConnection *){ /* Intentionally left empty */ })
, destination_(std::move(destination))
, objectPath_(std::move(objectPath))
@ -54,8 +54,8 @@ Proxy::Proxy(sdbus::internal::IConnection& connection, std::string destination,
}
Proxy::Proxy( std::unique_ptr<sdbus::internal::IConnection>&& connection
, std::string destination
, std::string objectPath )
, ServiceName destination
, ObjectPath objectPath )
: connection_(std::move(connection))
, destination_(std::move(destination))
, objectPath_(std::move(objectPath))
@ -69,8 +69,8 @@ Proxy::Proxy( std::unique_ptr<sdbus::internal::IConnection>&& connection
}
Proxy::Proxy( std::unique_ptr<sdbus::internal::IConnection>&& connection
, std::string destination
, std::string objectPath
, ServiceName destination
, ObjectPath objectPath
, dont_run_event_loop_thread_t )
: connection_(std::move(connection))
, destination_(std::move(destination))
@ -83,7 +83,7 @@ Proxy::Proxy( std::unique_ptr<sdbus::internal::IConnection>&& connection
// This proxy is meant to be created, used for simple synchronous D-Bus call(s) and then dismissed.
}
MethodCall Proxy::createMethodCall(const std::string& interfaceName, const std::string& methodName)
MethodCall Proxy::createMethodCall(const InterfaceName& interfaceName, const MethodName& methodName)
{
return connection_->createMethodCall(destination_, objectPath_, interfaceName, methodName);
}
@ -134,8 +134,8 @@ std::future<MethodReply> Proxy::callMethodAsync(const MethodCall& message, uint6
return future;
}
void Proxy::registerSignalHandler( const std::string& interfaceName
, const std::string& signalName
void Proxy::registerSignalHandler( const InterfaceName& interfaceName
, const SignalName& signalName
, signal_handler signalHandler )
{
auto slot = Proxy::registerSignalHandler(interfaceName, signalName, std::move(signalHandler), return_slot);
@ -143,8 +143,8 @@ void Proxy::registerSignalHandler( const std::string& interfaceName
floatingSignalSlots_.push_back(std::move(slot));
}
Slot Proxy::registerSignalHandler( const std::string& interfaceName
, const std::string& signalName
Slot Proxy::registerSignalHandler( const InterfaceName& interfaceName
, const SignalName& signalName
, signal_handler signalHandler
, return_slot_t )
{
@ -175,7 +175,7 @@ sdbus::IConnection& Proxy::getConnection() const
return *connection_;
}
const std::string& Proxy::getObjectPath() const
const ObjectPath& Proxy::getObjectPath() const
{
return objectPath_;
}
@ -211,7 +211,7 @@ int Proxy::sdbus_async_reply_handler(sd_bus_message *sdbusMessage, void *userDat
}
else
{
Error exception(error->name, error->message);
Error exception(Error::Name{error->name}, error->message);
asyncCallData->callback(std::move(message), std::move(exception));
}
}, retError);
@ -266,8 +266,8 @@ bool PendingAsyncCall::isPending() const
namespace sdbus {
std::unique_ptr<sdbus::IProxy> createProxy( IConnection& connection
, std::string destination
, std::string objectPath )
, ServiceName destination
, ObjectPath objectPath )
{
auto* sdbusConnection = dynamic_cast<sdbus::internal::IConnection*>(&connection);
SDBUS_THROW_ERROR_IF(!sdbusConnection, "Connection is not a real sdbus-c++ connection", EINVAL);
@ -278,8 +278,8 @@ std::unique_ptr<sdbus::IProxy> createProxy( IConnection& connection
}
std::unique_ptr<sdbus::IProxy> createProxy( std::unique_ptr<IConnection>&& connection
, std::string destination
, std::string objectPath )
, ServiceName destination
, ObjectPath objectPath )
{
auto* sdbusConnection = dynamic_cast<sdbus::internal::IConnection*>(connection.get());
SDBUS_THROW_ERROR_IF(!sdbusConnection, "Connection is not a real sdbus-c++ connection", EINVAL);
@ -292,8 +292,8 @@ std::unique_ptr<sdbus::IProxy> createProxy( std::unique_ptr<IConnection>&& conne
}
std::unique_ptr<sdbus::IProxy> createProxy( std::unique_ptr<IConnection>&& connection
, std::string destination
, std::string objectPath
, ServiceName destination
, ObjectPath objectPath
, dont_run_event_loop_thread_t )
{
auto* sdbusConnection = dynamic_cast<sdbus::internal::IConnection*>(connection.get());
@ -307,8 +307,8 @@ std::unique_ptr<sdbus::IProxy> createProxy( std::unique_ptr<IConnection>&& conne
, dont_run_event_loop_thread );
}
std::unique_ptr<sdbus::IProxy> createProxy( std::string destination
, std::string objectPath )
std::unique_ptr<sdbus::IProxy> createProxy( ServiceName destination
, ObjectPath objectPath )
{
auto connection = sdbus::createBusConnection();
@ -320,8 +320,8 @@ std::unique_ptr<sdbus::IProxy> createProxy( std::string destination
, std::move(objectPath) );
}
std::unique_ptr<sdbus::IProxy> createProxy( std::string destination
, std::string objectPath
std::unique_ptr<sdbus::IProxy> createProxy( ServiceName destination
, ObjectPath objectPath
, dont_run_event_loop_thread_t )
{
auto connection = sdbus::createBusConnection();

View File

@ -30,6 +30,7 @@
#include "sdbus-c++/IProxy.h"
#include "IConnection.h"
#include "sdbus-c++/Types.h"
#include <deque>
#include <memory>
@ -45,33 +46,33 @@ namespace sdbus::internal {
{
public:
Proxy( sdbus::internal::IConnection& connection
, std::string destination
, std::string objectPath );
, ServiceName destination
, ObjectPath objectPath );
Proxy( std::unique_ptr<sdbus::internal::IConnection>&& connection
, std::string destination
, std::string objectPath );
, ServiceName destination
, ObjectPath objectPath );
Proxy( std::unique_ptr<sdbus::internal::IConnection>&& connection
, std::string destination
, std::string objectPath
, ServiceName destination
, ObjectPath objectPath
, dont_run_event_loop_thread_t );
MethodCall createMethodCall(const std::string& interfaceName, const std::string& methodName) override;
MethodCall createMethodCall(const InterfaceName& interfaceName, const MethodName& methodName) override;
MethodReply callMethod(const MethodCall& message, uint64_t timeout) override;
PendingAsyncCall callMethodAsync(const MethodCall& message, async_reply_handler asyncReplyCallback, uint64_t timeout) override;
std::future<MethodReply> callMethodAsync(const MethodCall& message, with_future_t) override;
std::future<MethodReply> callMethodAsync(const MethodCall& message, uint64_t timeout, with_future_t) override;
void registerSignalHandler( const std::string& interfaceName
, const std::string& signalName
void registerSignalHandler( const InterfaceName& interfaceName
, const SignalName& signalName
, signal_handler signalHandler ) override;
Slot registerSignalHandler( const std::string& interfaceName
, const std::string& signalName
Slot registerSignalHandler( const InterfaceName& interfaceName
, const SignalName& signalName
, signal_handler signalHandler
, return_slot_t ) override;
void unregister() override;
[[nodiscard]] sdbus::IConnection& getConnection() const override;
[[nodiscard]] const std::string& getObjectPath() const override;
[[nodiscard]] const ObjectPath& getObjectPath() const override;
[[nodiscard]] Message getCurrentlyProcessedMessage() const override;
private:
@ -84,8 +85,8 @@ namespace sdbus::internal {
std::unique_ptr< sdbus::internal::IConnection
, std::function<void(sdbus::internal::IConnection*)>
> connection_;
std::string destination_;
std::string objectPath_;
ServiceName destination_;
ObjectPath objectPath_;
std::vector<Slot> floatingSignalSlots_;

View File

@ -41,7 +41,7 @@
SDBUS_THROW_ERROR_IF(!_NAME.empty() && !sd_bus_service_name_is_valid(_NAME.c_str()), "Invalid service name '" + _NAME + "' provided", EINVAL) \
/**/
#define SDBUS_CHECK_MEMBER_NAME(_NAME) \
SDBUS_THROW_ERROR_IF(!sd_bus_member_name_is_valid(_NAME.c_str()), "Invalid member name '" + _NAME + "' provided", EINVAL) \
SDBUS_THROW_ERROR_IF(!sd_bus_member_name_is_valid(_NAME.c_str()), std::string("Invalid member name '") + _NAME.c_str() + "' provided", EINVAL) \
/**/
#else
#define SDBUS_CHECK_OBJECT_PATH(_PATH)
@ -66,12 +66,12 @@ namespace sdbus::internal {
}
catch (const std::exception& e)
{
sd_bus_error_set(retError, SDBUSCPP_ERROR_NAME, e.what());
sd_bus_error_set(retError, SDBUSCPP_ERROR_NAME.c_str(), e.what());
return false;
}
catch (...)
{
sd_bus_error_set(retError, SDBUSCPP_ERROR_NAME, "Unknown error occurred");
sd_bus_error_set(retError, SDBUSCPP_ERROR_NAME.c_str(), "Unknown error occurred");
return false;
}

View File

@ -96,7 +96,7 @@ TYPED_TEST(AsyncSdbusTestObject, RunsServerSideAsynchoronousMethodAsynchronously
std::atomic<int> startedCount{};
auto call = [&](uint32_t param)
{
TestProxy proxy{BUS_NAME, OBJECT_PATH};
TestProxy proxy{SERVICE_NAME, OBJECT_PATH};
++startedCount;
while (!invoke) ;
auto result = proxy.doOperationAsync(param);
@ -119,7 +119,7 @@ TYPED_TEST(AsyncSdbusTestObject, HandlesCorrectlyABulkOfParallelServerSideAsyncM
std::atomic<int> startedCount{};
auto call = [&]()
{
TestProxy proxy{BUS_NAME, OBJECT_PATH};
TestProxy proxy{SERVICE_NAME, OBJECT_PATH};
++startedCount;
while (!invoke) ;

View File

@ -51,38 +51,43 @@ TEST(Connection, CanBeDefaultConstructed)
ASSERT_NO_THROW(auto con = sdbus::createBusConnection());
}
TEST(SystemBusConnection, CanRequestRegisteredDbusName)
TEST(Connection, CanRequestName)
{
auto connection = sdbus::createSystemBusConnection();
auto connection = sdbus::createBusConnection();
ASSERT_NO_THROW(connection->requestName(BUS_NAME))
// In case of system bus connection, requesting may throw as we need to allow that first through a config file in /etc/dbus-1/system.d
ASSERT_NO_THROW(connection->requestName(SERVICE_NAME))
<< "Perhaps you've forgotten to copy `org.sdbuscpp.integrationtests.conf` file to `/etc/dbus-1/system.d` directory before running the tests?";
}
TEST(SystemBusConnection, CannotRequestNonregisteredDbusName)
{
auto connection = sdbus::createSystemBusConnection();
ASSERT_THROW(connection->requestName("some.random.not.supported.dbus.name"), sdbus::Error);
sdbus::ServiceName notSupportedBusName{"some.random.not.supported.dbus.name"};
ASSERT_THROW(connection->requestName(notSupportedBusName), sdbus::Error);
}
TEST(Connection, CanReleasedRequestedName)
TEST(Connection, CanReleaseRequestedName)
{
auto connection = sdbus::createBusConnection();
connection->requestName(SERVICE_NAME);
connection->requestName(BUS_NAME);
ASSERT_NO_THROW(connection->releaseName(BUS_NAME));
ASSERT_NO_THROW(connection->releaseName(SERVICE_NAME));
}
TEST(Connection, CannotReleaseNonrequestedName)
{
auto connection = sdbus::createBusConnection();
ASSERT_THROW(connection->releaseName("some.random.nonrequested.name"), sdbus::Error);
sdbus::ServiceName notAcquiredBusName{"some.random.unacquired.name"};
ASSERT_THROW(connection->releaseName(notAcquiredBusName), sdbus::Error);
}
TEST(Connection, CanEnterAndLeaveInternalEventLoop)
{
auto connection = sdbus::createBusConnection();
connection->requestName(BUS_NAME);
connection->requestName(SERVICE_NAME);
std::thread t([&](){ connection->enterEventLoop(); });
connection->leaveEventLoop();

View File

@ -54,12 +54,12 @@ using ADirectConnection = TestFixtureWithDirectConnection;
TEST(AdaptorAndProxy, CanBeConstructedSuccesfully)
{
auto connection = sdbus::createBusConnection();
connection->requestName(BUS_NAME);
connection->requestName(SERVICE_NAME);
ASSERT_NO_THROW(TestAdaptor adaptor(*connection, OBJECT_PATH));
ASSERT_NO_THROW(TestProxy proxy(BUS_NAME, OBJECT_PATH));
ASSERT_NO_THROW(TestProxy proxy(SERVICE_NAME, OBJECT_PATH));
connection->releaseName(BUS_NAME);
connection->releaseName(SERVICE_NAME);
}
TEST(AProxy, SupportsMoveSemantics)
@ -76,7 +76,7 @@ TEST(AnAdaptor, SupportsMoveSemantics)
TYPED_TEST(AConnection, WillCallCallbackHandlerForIncomingMessageMatchingMatchRule)
{
auto matchRule = "sender='" + BUS_NAME + "',path='" + OBJECT_PATH + "'";
auto matchRule = "sender='" + SERVICE_NAME + "',path='" + OBJECT_PATH + "'";
std::atomic<bool> matchingMessageReceived{false};
auto slot = this->s_proxyConnection->addMatch(matchRule, [&](sdbus::Message msg)
{
@ -91,7 +91,7 @@ TYPED_TEST(AConnection, WillCallCallbackHandlerForIncomingMessageMatchingMatchRu
TYPED_TEST(AConnection, CanInstallMatchRuleAsynchronously)
{
auto matchRule = "sender='" + BUS_NAME + "',path='" + OBJECT_PATH + "'";
auto matchRule = "sender='" + SERVICE_NAME + "',path='" + OBJECT_PATH + "'";
std::atomic<bool> matchingMessageReceived{false};
std::atomic<bool> matchRuleInstalled{false};
auto slot = this->s_proxyConnection->addMatchAsync( matchRule
@ -114,7 +114,7 @@ TYPED_TEST(AConnection, CanInstallMatchRuleAsynchronously)
TYPED_TEST(AConnection, WillUnsubscribeMatchRuleWhenClientDestroysTheAssociatedSlot)
{
auto matchRule = "sender='" + BUS_NAME + "',path='" + OBJECT_PATH + "'";
auto matchRule = "sender='" + SERVICE_NAME + "',path='" + OBJECT_PATH + "'";
std::atomic<bool> matchingMessageReceived{false};
auto slot = this->s_proxyConnection->addMatch(matchRule, [&](sdbus::Message msg)
{
@ -130,7 +130,7 @@ TYPED_TEST(AConnection, WillUnsubscribeMatchRuleWhenClientDestroysTheAssociatedS
TYPED_TEST(AConnection, CanAddFloatingMatchRule)
{
auto matchRule = "sender='" + BUS_NAME + "',path='" + OBJECT_PATH + "'";
auto matchRule = "sender='" + SERVICE_NAME + "',path='" + OBJECT_PATH + "'";
std::atomic<bool> matchingMessageReceived{false};
auto con = sdbus::createBusConnection();
con->enterEventLoopAsync();

View File

@ -231,13 +231,13 @@ TYPED_TEST(SdbusTestObject, FailsCallingMethodOnNonexistentInterface)
TYPED_TEST(SdbusTestObject, FailsCallingMethodOnNonexistentDestination)
{
TestProxy proxy("sdbuscpp.destination.that.does.not.exist", OBJECT_PATH);
TestProxy proxy(sdbus::ServiceName{"sdbuscpp.destination.that.does.not.exist"}, OBJECT_PATH);
ASSERT_THROW(proxy.getInt(), sdbus::Error);
}
TYPED_TEST(SdbusTestObject, FailsCallingMethodOnNonexistentObject)
{
TestProxy proxy(BUS_NAME, "/sdbuscpp/path/that/does/not/exist");
TestProxy proxy(SERVICE_NAME, sdbus::ObjectPath{"/sdbuscpp/path/that/does/not/exist"});
ASSERT_THROW(proxy.getInt(), sdbus::Error);
}
@ -254,7 +254,7 @@ TYPED_TEST(SdbusTestObject, CanAccessAssociatedMethodCallMessageInMethodCallHand
this->m_proxy->doOperation(10); // This will save pointer to method call message on server side
ASSERT_THAT(this->m_adaptor->m_methodCallMsg, NotNull());
ASSERT_THAT(this->m_adaptor->m_methodCallMemberName, Eq("doOperation"));
ASSERT_THAT(this->m_adaptor->m_methodName, Eq("doOperation"));
}
TYPED_TEST(SdbusTestObject, CanAccessAssociatedMethodCallMessageInAsyncMethodCallHandler)
@ -262,7 +262,7 @@ TYPED_TEST(SdbusTestObject, CanAccessAssociatedMethodCallMessageInAsyncMethodCal
this->m_proxy->doOperationAsync(10); // This will save pointer to method call message on server side
ASSERT_THAT(this->m_adaptor->m_methodCallMsg, NotNull());
ASSERT_THAT(this->m_adaptor->m_methodCallMemberName, Eq("doOperationAsync"));
ASSERT_THAT(this->m_adaptor->m_methodName, Eq("doOperationAsync"));
}
#if LIBSYSTEMD_VERSION>=240
@ -281,7 +281,7 @@ TYPED_TEST(SdbusTestObject, CannotSetGeneralMethodTimeoutWithLibsystemdVersionLe
TYPED_TEST(SdbusTestObject, CanCallMethodSynchronouslyWithoutAnEventLoopThread)
{
auto proxy = std::make_unique<TestProxy>(BUS_NAME, OBJECT_PATH, sdbus::dont_run_event_loop_thread);
auto proxy = std::make_unique<TestProxy>(SERVICE_NAME, OBJECT_PATH, sdbus::dont_run_event_loop_thread);
auto multiplyRes = proxy->multiply(INT64_VALUE, DOUBLE_VALUE);
@ -291,15 +291,16 @@ TYPED_TEST(SdbusTestObject, CanCallMethodSynchronouslyWithoutAnEventLoopThread)
TYPED_TEST(SdbusTestObject, CanRegisterAdditionalVTableDynamicallyAtAnyTime)
{
auto& object = this->m_adaptor->getObject();
auto vtableSlot = object.addVTable( "org.sdbuscpp.integrationtests2"
sdbus::InterfaceName interfaceName{"org.sdbuscpp.integrationtests2"};
auto vtableSlot = object.addVTable( interfaceName
, { sdbus::registerMethod("add").implementedAs([](const int64_t& a, const double& b){ return a + b; })
, sdbus::registerMethod("subtract").implementedAs([](const int& a, const int& b){ return a - b; }) }
, sdbus::return_slot );
// The new remote vtable is registered as long as we keep vtableSlot, so remote method calls now should pass
auto proxy = sdbus::createProxy(BUS_NAME, OBJECT_PATH, sdbus::dont_run_event_loop_thread);
auto proxy = sdbus::createProxy(SERVICE_NAME, OBJECT_PATH, sdbus::dont_run_event_loop_thread);
int result{};
proxy->callMethod("subtract").onInterface("org.sdbuscpp.integrationtests2").withArguments(10, 2).storeResultsTo(result);
proxy->callMethod("subtract").onInterface(interfaceName).withArguments(10, 2).storeResultsTo(result);
ASSERT_THAT(result, Eq(8));
}
@ -307,14 +308,15 @@ TYPED_TEST(SdbusTestObject, CanRegisterAdditionalVTableDynamicallyAtAnyTime)
TYPED_TEST(SdbusTestObject, CanUnregisterAdditionallyRegisteredVTableAtAnyTime)
{
auto& object = this->m_adaptor->getObject();
sdbus::InterfaceName interfaceName{"org.sdbuscpp.integrationtests2"};
auto vtableSlot = object.addVTable( "org.sdbuscpp.integrationtests2"
auto vtableSlot = object.addVTable( interfaceName
, { sdbus::registerMethod("add").implementedAs([](const int64_t& a, const double& b){ return a + b; })
, sdbus::registerMethod("subtract").implementedAs([](const int& a, const int& b){ return a - b; }) }
, sdbus::return_slot );
vtableSlot.reset(); // Letting the slot go means letting go the associated vtable registration
// No such remote D-Bus method under given interface exists anymore...
auto proxy = sdbus::createProxy(BUS_NAME, OBJECT_PATH, sdbus::dont_run_event_loop_thread);
ASSERT_THROW(proxy->callMethod("subtract").onInterface("org.sdbuscpp.integrationtests2").withArguments(10, 2), sdbus::Error);
auto proxy = sdbus::createProxy(SERVICE_NAME, OBJECT_PATH, sdbus::dont_run_event_loop_thread);
ASSERT_THROW(proxy->callMethod("subtract").onInterface(interfaceName).withArguments(10, 2), sdbus::Error);
}

View File

@ -57,8 +57,8 @@ TYPED_TEST(SdbusTestObject, EmitsSimpleSignalSuccesfully)
TYPED_TEST(SdbusTestObject, EmitsSimpleSignalToMultipleProxiesSuccesfully)
{
auto proxy1 = std::make_unique<TestProxy>(*this->s_adaptorConnection, BUS_NAME, OBJECT_PATH);
auto proxy2 = std::make_unique<TestProxy>(*this->s_adaptorConnection, BUS_NAME, OBJECT_PATH);
auto proxy1 = std::make_unique<TestProxy>(*this->s_adaptorConnection, SERVICE_NAME, OBJECT_PATH);
auto proxy2 = std::make_unique<TestProxy>(*this->s_adaptorConnection, SERVICE_NAME, OBJECT_PATH);
this->m_adaptor->emitSimpleSignal();
@ -69,7 +69,7 @@ TYPED_TEST(SdbusTestObject, EmitsSimpleSignalToMultipleProxiesSuccesfully)
TYPED_TEST(SdbusTestObject, ProxyDoesNotReceiveSignalFromOtherBusName)
{
auto otherBusName = BUS_NAME + "2";
sdbus::ServiceName otherBusName{SERVICE_NAME + "2"};
auto connection2 = sdbus::createBusConnection(otherBusName);
auto adaptor2 = std::make_unique<TestAdaptor>(*connection2, OBJECT_PATH);
@ -110,10 +110,10 @@ TYPED_TEST(SdbusTestObject, EmitsSignalWithVariantSuccesfully)
TYPED_TEST(SdbusTestObject, EmitsSignalWithoutRegistrationSuccesfully)
{
this->m_adaptor->emitSignalWithoutRegistration({"platform", {"av"}});
this->m_adaptor->emitSignalWithoutRegistration({"platform", sdbus::Signature{"av"}});
ASSERT_TRUE(waitUntil(this->m_proxy->m_gotSignalWithSignature));
ASSERT_THAT(this->m_proxy->m_signatureFromSignal["platform"], Eq("av"));
ASSERT_THAT(this->m_proxy->m_signatureFromSignal["platform"], Eq(sdbus::Signature{"av"}));
}
TYPED_TEST(SdbusTestObject, CanAccessAssociatedSignalMessageInSignalHandler)
@ -123,7 +123,7 @@ TYPED_TEST(SdbusTestObject, CanAccessAssociatedSignalMessageInSignalHandler)
waitUntil(this->m_proxy->m_gotSimpleSignal);
ASSERT_THAT(this->m_proxy->m_signalMsg, NotNull());
ASSERT_THAT(this->m_proxy->m_signalMemberName, Eq("simpleSignal"));
ASSERT_THAT(this->m_proxy->m_signalName, Eq(std::string("simpleSignal")));
}
TYPED_TEST(SdbusTestObject, UnregistersSignalHandler)
@ -137,8 +137,8 @@ TYPED_TEST(SdbusTestObject, UnregistersSignalHandler)
TYPED_TEST(SdbusTestObject, UnregistersSignalHandlerForSomeProxies)
{
auto proxy1 = std::make_unique<TestProxy>(*this->s_adaptorConnection, BUS_NAME, OBJECT_PATH);
auto proxy2 = std::make_unique<TestProxy>(*this->s_adaptorConnection, BUS_NAME, OBJECT_PATH);
auto proxy1 = std::make_unique<TestProxy>(*this->s_adaptorConnection, SERVICE_NAME, OBJECT_PATH);
auto proxy2 = std::make_unique<TestProxy>(*this->s_adaptorConnection, SERVICE_NAME, OBJECT_PATH);
ASSERT_NO_THROW(this->m_proxy->unregisterSimpleSignalHandler());

View File

@ -142,17 +142,17 @@ TYPED_TEST(SdbusTestObject, GetsAllPropertiesViaPropertiesInterface)
const auto properties = this->m_proxy->GetAll(INTERFACE_NAME);
ASSERT_THAT(properties, SizeIs(3));
EXPECT_THAT(properties.at("state").template get<std::string>(), Eq(DEFAULT_STATE_VALUE));
EXPECT_THAT(properties.at("action").template get<uint32_t>(), Eq(DEFAULT_ACTION_VALUE));
EXPECT_THAT(properties.at("blocking").template get<bool>(), Eq(DEFAULT_BLOCKING_VALUE));
EXPECT_THAT(properties.at(STATE_PROPERTY).template get<std::string>(), Eq(DEFAULT_STATE_VALUE));
EXPECT_THAT(properties.at(ACTION_PROPERTY).template get<uint32_t>(), Eq(DEFAULT_ACTION_VALUE));
EXPECT_THAT(properties.at(BLOCKING_PROPERTY).template get<bool>(), Eq(DEFAULT_BLOCKING_VALUE));
}
TYPED_TEST(SdbusTestObject, GetsAllPropertiesAsynchronouslyViaPropertiesInterface)
{
std::promise<std::map<std::string, sdbus::Variant>> promise;
std::promise<std::map<sdbus::PropertyName, sdbus::Variant>> promise;
auto future = promise.get_future();
this->m_proxy->GetAllAsync(INTERFACE_NAME, [&](std::optional<sdbus::Error> err, std::map<std::string, sdbus::Variant> value)
this->m_proxy->GetAllAsync(INTERFACE_NAME, [&](std::optional<sdbus::Error> err, std::map<sdbus::PropertyName, sdbus::Variant> value)
{
if (!err)
promise.set_value(std::move(value));
@ -162,9 +162,9 @@ TYPED_TEST(SdbusTestObject, GetsAllPropertiesAsynchronouslyViaPropertiesInterfac
const auto properties = future.get();
ASSERT_THAT(properties, SizeIs(3));
EXPECT_THAT(properties.at("state").get<std::string>(), Eq(DEFAULT_STATE_VALUE));
EXPECT_THAT(properties.at("action").get<uint32_t>(), Eq(DEFAULT_ACTION_VALUE));
EXPECT_THAT(properties.at("blocking").get<bool>(), Eq(DEFAULT_BLOCKING_VALUE));
EXPECT_THAT(properties.at(STATE_PROPERTY).get<std::string>(), Eq(DEFAULT_STATE_VALUE));
EXPECT_THAT(properties.at(ACTION_PROPERTY).get<uint32_t>(), Eq(DEFAULT_ACTION_VALUE));
EXPECT_THAT(properties.at(BLOCKING_PROPERTY).get<bool>(), Eq(DEFAULT_BLOCKING_VALUE));
}
TYPED_TEST(SdbusTestObject, GetsAllPropertiesAsynchronouslyViaPropertiesInterfaceWithFuture)
@ -174,27 +174,27 @@ TYPED_TEST(SdbusTestObject, GetsAllPropertiesAsynchronouslyViaPropertiesInterfac
auto properties = future.get();
ASSERT_THAT(properties, SizeIs(3));
EXPECT_THAT(properties.at("state").template get<std::string>(), Eq(DEFAULT_STATE_VALUE));
EXPECT_THAT(properties.at("action").template get<uint32_t>(), Eq(DEFAULT_ACTION_VALUE));
EXPECT_THAT(properties.at("blocking").template get<bool>(), Eq(DEFAULT_BLOCKING_VALUE));
EXPECT_THAT(properties.at(STATE_PROPERTY).template get<std::string>(), Eq(DEFAULT_STATE_VALUE));
EXPECT_THAT(properties.at(ACTION_PROPERTY).template get<uint32_t>(), Eq(DEFAULT_ACTION_VALUE));
EXPECT_THAT(properties.at(BLOCKING_PROPERTY).template get<bool>(), Eq(DEFAULT_BLOCKING_VALUE));
}
TYPED_TEST(SdbusTestObject, EmitsPropertyChangedSignalForSelectedProperties)
{
std::atomic<bool> signalReceived{false};
this->m_proxy->m_onPropertiesChangedHandler = [&signalReceived]( const std::string& interfaceName
, const std::map<std::string, sdbus::Variant>& changedProperties
, const std::vector<std::string>& /*invalidatedProperties*/ )
this->m_proxy->m_onPropertiesChangedHandler = [&signalReceived]( const sdbus::InterfaceName& interfaceName
, const std::map<sdbus::PropertyName, sdbus::Variant>& changedProperties
, const std::vector<sdbus::PropertyName>& /*invalidatedProperties*/ )
{
EXPECT_THAT(interfaceName, Eq(INTERFACE_NAME));
EXPECT_THAT(changedProperties, SizeIs(1));
EXPECT_THAT(changedProperties.at("blocking").get<bool>(), Eq(!DEFAULT_BLOCKING_VALUE));
EXPECT_THAT(changedProperties.at(BLOCKING_PROPERTY).get<bool>(), Eq(!DEFAULT_BLOCKING_VALUE));
signalReceived = true;
};
this->m_proxy->blocking(!DEFAULT_BLOCKING_VALUE);
this->m_proxy->action(DEFAULT_ACTION_VALUE*2);
this->m_adaptor->emitPropertiesChangedSignal(INTERFACE_NAME, {"blocking"});
this->m_adaptor->emitPropertiesChangedSignal(INTERFACE_NAME, {BLOCKING_PROPERTY});
ASSERT_TRUE(waitUntil(signalReceived));
}
@ -202,13 +202,13 @@ TYPED_TEST(SdbusTestObject, EmitsPropertyChangedSignalForSelectedProperties)
TYPED_TEST(SdbusTestObject, EmitsPropertyChangedSignalForAllProperties)
{
std::atomic<bool> signalReceived{false};
this->m_proxy->m_onPropertiesChangedHandler = [&signalReceived]( const std::string& interfaceName
, const std::map<std::string, sdbus::Variant>& changedProperties
, const std::vector<std::string>& invalidatedProperties )
this->m_proxy->m_onPropertiesChangedHandler = [&signalReceived]( const sdbus::InterfaceName& interfaceName
, const std::map<sdbus::PropertyName, sdbus::Variant>& changedProperties
, const std::vector<sdbus::PropertyName>& invalidatedProperties )
{
EXPECT_THAT(interfaceName, Eq(INTERFACE_NAME));
EXPECT_THAT(changedProperties, SizeIs(1));
EXPECT_THAT(changedProperties.at("blocking").get<bool>(), Eq(DEFAULT_BLOCKING_VALUE));
EXPECT_THAT(changedProperties.at(BLOCKING_PROPERTY).get<bool>(), Eq(DEFAULT_BLOCKING_VALUE));
ASSERT_THAT(invalidatedProperties, SizeIs(1));
EXPECT_THAT(invalidatedProperties[0], Eq("action"));
signalReceived = true;
@ -235,17 +235,17 @@ TYPED_TEST(SdbusTestObject, GetsManagedObjectsSuccessfully)
ASSERT_THAT(objectsInterfacesAndProperties, SizeIs(2));
EXPECT_THAT(objectsInterfacesAndProperties.at(OBJECT_PATH)
.at(org::sdbuscpp::integrationtests_adaptor::INTERFACE_NAME)
.at("action").template get<uint32_t>(), Eq(DEFAULT_ACTION_VALUE));
.at(ACTION_PROPERTY).template get<uint32_t>(), Eq(DEFAULT_ACTION_VALUE));
EXPECT_THAT(objectsInterfacesAndProperties.at(OBJECT_PATH_2)
.at(org::sdbuscpp::integrationtests_adaptor::INTERFACE_NAME)
.at("action").template get<uint32_t>(), Eq(DEFAULT_ACTION_VALUE));
.at(ACTION_PROPERTY).template get<uint32_t>(), Eq(DEFAULT_ACTION_VALUE));
}
TYPED_TEST(SdbusTestObject, EmitsInterfacesAddedSignalForSelectedObjectInterfaces)
{
std::atomic<bool> signalReceived{false};
this->m_objectManagerProxy->m_onInterfacesAddedHandler = [&signalReceived]( const sdbus::ObjectPath& objectPath
, const std::map<std::string, std::map<std::string, sdbus::Variant>>& interfacesAndProperties )
, const std::map<sdbus::InterfaceName, std::map<sdbus::PropertyName, sdbus::Variant>>& interfacesAndProperties )
{
EXPECT_THAT(objectPath, Eq(OBJECT_PATH));
EXPECT_THAT(interfacesAndProperties, SizeIs(1));
@ -253,16 +253,16 @@ TYPED_TEST(SdbusTestObject, EmitsInterfacesAddedSignalForSelectedObjectInterface
#if LIBSYSTEMD_VERSION<=244
// Up to sd-bus v244, all properties are added to the list, i.e. `state', `action', and `blocking' in this case.
EXPECT_THAT(interfacesAndProperties.at(INTERFACE_NAME), SizeIs(3));
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("state"));
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("action"));
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("blocking"));
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(STATE_PROPERTY));
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(ACTION_PROPERTY));
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(BLOCKING_PROPERTY));
#else
// Since v245 sd-bus does not add to the InterfacesAdded signal message the values of properties marked only
// for invalidation on change, which makes the behavior consistent with the PropertiesChangedSignal.
// So in this specific instance, `action' property is no more added to the list.
EXPECT_THAT(interfacesAndProperties.at(INTERFACE_NAME), SizeIs(2));
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("state"));
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("blocking"));
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(STATE_PROPERTY));
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(BLOCKING_PROPERTY));
#endif
signalReceived = true;
};
@ -276,7 +276,7 @@ TYPED_TEST(SdbusTestObject, EmitsInterfacesAddedSignalForAllObjectInterfaces)
{
std::atomic<bool> signalReceived{false};
this->m_objectManagerProxy->m_onInterfacesAddedHandler = [&signalReceived]( const sdbus::ObjectPath& objectPath
, const std::map<std::string, std::map<std::string, sdbus::Variant>>& interfacesAndProperties )
, const std::map<sdbus::InterfaceName, std::map<sdbus::PropertyName, sdbus::Variant>>& interfacesAndProperties )
{
EXPECT_THAT(objectPath, Eq(OBJECT_PATH));
#if LIBSYSTEMD_VERSION<=250
@ -289,16 +289,16 @@ TYPED_TEST(SdbusTestObject, EmitsInterfacesAddedSignalForAllObjectInterfaces)
#if LIBSYSTEMD_VERSION<=244
// Up to sd-bus v244, all properties are added to the list, i.e. `state', `action', and `blocking' in this case.
EXPECT_THAT(interfacesAndProperties.at(INTERFACE_NAME), SizeIs(3));
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("state"));
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("action"));
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("blocking"));
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(STATE_PROPERTY));
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(ACTION_PROPERTY));
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(BLOCKING_PROPERTY));
#else
// Since v245 sd-bus does not add to the InterfacesAdded signal message the values of properties marked only
// for invalidation on change, which makes the behavior consistent with the PropertiesChangedSignal.
// So in this specific instance, `action' property is no more added to the list.
EXPECT_THAT(interfacesAndProperties.at(INTERFACE_NAME), SizeIs(2));
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("state"));
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("blocking"));
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(STATE_PROPERTY));
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(BLOCKING_PROPERTY));
#endif
signalReceived = true;
};
@ -312,7 +312,7 @@ TYPED_TEST(SdbusTestObject, EmitsInterfacesRemovedSignalForSelectedObjectInterfa
{
std::atomic<bool> signalReceived{false};
this->m_objectManagerProxy->m_onInterfacesRemovedHandler = [&signalReceived]( const sdbus::ObjectPath& objectPath
, const std::vector<std::string>& interfaces )
, const std::vector<sdbus::InterfaceName>& interfaces )
{
EXPECT_THAT(objectPath, Eq(OBJECT_PATH));
ASSERT_THAT(interfaces, SizeIs(1));
@ -329,7 +329,7 @@ TYPED_TEST(SdbusTestObject, EmitsInterfacesRemovedSignalForAllObjectInterfaces)
{
std::atomic<bool> signalReceived{false};
this->m_objectManagerProxy->m_onInterfacesRemovedHandler = [&signalReceived]( const sdbus::ObjectPath& objectPath
, const std::vector<std::string>& interfaces )
, const std::vector<sdbus::InterfaceName>& interfaces )
{
EXPECT_THAT(objectPath, Eq(OBJECT_PATH));
#if LIBSYSTEMD_VERSION<=250

View File

@ -34,12 +34,15 @@
namespace sdbus { namespace test {
const std::string INTERFACE_NAME{"org.sdbuscpp.integrationtests"};
const std::string BUS_NAME = INTERFACE_NAME;
const std::string EMPTY_DESTINATION;
const std::string MANAGER_PATH {"/org/sdbuscpp/integrationtests"};
const std::string OBJECT_PATH {"/org/sdbuscpp/integrationtests/ObjectA1"};
const std::string OBJECT_PATH_2{"/org/sdbuscpp/integrationtests/ObjectB1"};
const InterfaceName INTERFACE_NAME{"org.sdbuscpp.integrationtests"};
const ServiceName SERVICE_NAME{"org.sdbuscpp.integrationtests"};
const ServiceName EMPTY_DESTINATION;
const ObjectPath MANAGER_PATH {"/org/sdbuscpp/integrationtests"};
const ObjectPath OBJECT_PATH {"/org/sdbuscpp/integrationtests/ObjectA1"};
const ObjectPath OBJECT_PATH_2{"/org/sdbuscpp/integrationtests/ObjectB1"};
const PropertyName STATE_PROPERTY{"state"};
const PropertyName ACTION_PROPERTY{"action"};
const PropertyName BLOCKING_PROPERTY{"blocking"};
const std::string DIRECT_CONNECTION_SOCKET_PATH{std::filesystem::temp_directory_path() / "sdbus-cpp-direct-connection-test"};
constexpr const uint8_t UINT8_VALUE{1};
@ -49,8 +52,8 @@ constexpr const int32_t INT32_VALUE{-42};
constexpr const int32_t INT64_VALUE{-1024};
const std::string STRING_VALUE{"sdbus-c++-testing"};
const sdbus::Signature SIGNATURE_VALUE{"a{is}"};
const sdbus::ObjectPath OBJECT_PATH_VALUE{"/"};
const Signature SIGNATURE_VALUE{"a{is}"};
const ObjectPath OBJECT_PATH_VALUE{"/"};
const int UNIX_FD_VALUE = 0;
const std::string DEFAULT_STATE_VALUE{"default-state-value"};

View File

@ -31,8 +31,8 @@
namespace sdbus { namespace test {
TestAdaptor::TestAdaptor(sdbus::IConnection& connection, const std::string& path) :
AdaptorInterfaces(connection, path)
TestAdaptor::TestAdaptor(sdbus::IConnection& connection, sdbus::ObjectPath path) :
AdaptorInterfaces(connection, std::move(path))
{
registerAdaptor();
}
@ -123,7 +123,7 @@ uint32_t TestAdaptor::doOperation(const uint32_t& param)
std::this_thread::sleep_for(std::chrono::milliseconds(param));
m_methodCallMsg = std::make_unique<const Message>(getObject().getCurrentlyProcessedMessage());
m_methodCallMemberName = m_methodCallMsg->getMemberName();
m_methodName = m_methodCallMsg->getMemberName();
return param;
}
@ -131,7 +131,7 @@ uint32_t TestAdaptor::doOperation(const uint32_t& param)
void TestAdaptor::doOperationAsync(sdbus::Result<uint32_t>&& result, uint32_t param)
{
m_methodCallMsg = std::make_unique<const Message>(getObject().getCurrentlyProcessedMessage());
m_methodCallMemberName = m_methodCallMsg->getMemberName();
m_methodName = m_methodCallMsg->getMemberName();
if (param == 0)
{
@ -173,7 +173,7 @@ std::unordered_map<uint64_t, sdbus::Struct<std::map<uint8_t, std::vector<sdbus::
23, // uint8_t
{ // vector
{ // struct
"/object/path", // object path
sdbus::ObjectPath{"/object/path"}, // object path
false,
Variant{3.14},
{ // map
@ -183,7 +183,7 @@ std::unordered_map<uint64_t, sdbus::Struct<std::map<uint8_t, std::vector<sdbus::
}
}
},
"a{t(a{ya(obva{is})}gs)}", // signature
sdbus::Signature{"a{t(a{ya(obva{is})}gs)}"}, // signature
std::string{}
}
}

View File

@ -40,7 +40,7 @@ namespace sdbus { namespace test {
class ObjectManagerTestAdaptor final : public sdbus::AdaptorInterfaces< sdbus::ObjectManager_adaptor >
{
public:
ObjectManagerTestAdaptor(sdbus::IConnection& connection, std::string path) :
ObjectManagerTestAdaptor(sdbus::IConnection& connection, sdbus::ObjectPath path) :
AdaptorInterfaces(connection, std::move(path))
{
registerAdaptor();
@ -57,7 +57,7 @@ class TestAdaptor final : public sdbus::AdaptorInterfaces< org::sdbuscpp::integr
, sdbus::ManagedObject_adaptor >
{
public:
TestAdaptor(sdbus::IConnection& connection, const std::string& path);
TestAdaptor(sdbus::IConnection& connection, sdbus::ObjectPath path);
~TestAdaptor();
protected:
@ -105,7 +105,7 @@ public: // for tests
mutable std::atomic<bool> m_wasThrowErrorCalled{false};
std::unique_ptr<const Message> m_methodCallMsg;
std::string m_methodCallMemberName;
MethodName m_methodName;
std::unique_ptr<const Message> m_propertySetMsg;
std::string m_propertySetSender;
};
@ -115,7 +115,9 @@ class DummyTestAdaptor final : public sdbus::AdaptorInterfaces< org::sdbuscpp::i
, sdbus::ManagedObject_adaptor >
{
public:
DummyTestAdaptor(sdbus::IConnection& connection, const std::string& path) : AdaptorInterfaces(connection, path) {}
DummyTestAdaptor(sdbus::IConnection& connection, sdbus::ObjectPath path)
: AdaptorInterfaces(connection, std::move(path))
{}
protected:
void noArgNoReturn() override {}

View File

@ -55,19 +55,19 @@ class BaseTestFixture : public ::testing::Test
public:
static void SetUpTestCase()
{
s_adaptorConnection->requestName(BUS_NAME);
s_adaptorConnection->requestName(SERVICE_NAME);
}
static void TearDownTestCase()
{
s_adaptorConnection->releaseName(BUS_NAME);
s_adaptorConnection->releaseName(SERVICE_NAME);
}
private:
void SetUp() override
{
m_objectManagerProxy = std::make_unique<ObjectManagerTestProxy>(*s_proxyConnection, BUS_NAME, MANAGER_PATH);
m_proxy = std::make_unique<TestProxy>(*s_proxyConnection, BUS_NAME, OBJECT_PATH);
m_objectManagerProxy = std::make_unique<ObjectManagerTestProxy>(*s_proxyConnection, SERVICE_NAME, MANAGER_PATH);
m_proxy = std::make_unique<TestProxy>(*s_proxyConnection, SERVICE_NAME, OBJECT_PATH);
m_objectManagerAdaptor = std::make_unique<ObjectManagerTestAdaptor>(*s_adaptorConnection, MANAGER_PATH);
m_adaptor = std::make_unique<TestAdaptor>(*s_adaptorConnection, OBJECT_PATH);

View File

@ -31,7 +31,7 @@
namespace sdbus { namespace test {
TestProxy::TestProxy(std::string destination, std::string objectPath)
TestProxy::TestProxy(ServiceName destination, ObjectPath objectPath)
: ProxyInterfaces(std::move(destination), std::move(objectPath))
{
getProxy().uponSignal("signalWithoutRegistration").onInterface(sdbus::test::INTERFACE_NAME).call([this](const sdbus::Struct<std::string, sdbus::Struct<sdbus::Signature>>& s){ this->onSignalWithoutRegistration(s); });
@ -39,14 +39,14 @@ TestProxy::TestProxy(std::string destination, std::string objectPath)
registerProxy();
}
TestProxy::TestProxy(std::string destination, std::string objectPath, dont_run_event_loop_thread_t)
TestProxy::TestProxy(ServiceName destination, ObjectPath objectPath, dont_run_event_loop_thread_t)
: ProxyInterfaces(std::move(destination), std::move(objectPath), dont_run_event_loop_thread)
{
// It doesn't make sense to register any signals here since proxy upon a D-Bus connection with no event loop thread
// will not receive any incoming messages except replies to synchronous D-Bus calls.
}
TestProxy::TestProxy(sdbus::IConnection& connection, std::string destination, std::string objectPath)
TestProxy::TestProxy(sdbus::IConnection& connection, ServiceName destination, ObjectPath objectPath)
: ProxyInterfaces(connection, std::move(destination), std::move(objectPath))
{
getProxy().uponSignal("signalWithoutRegistration").onInterface(sdbus::test::INTERFACE_NAME).call([this](const sdbus::Struct<std::string, sdbus::Struct<sdbus::Signature>>& s){ this->onSignalWithoutRegistration(s); });
@ -62,7 +62,7 @@ TestProxy::~TestProxy()
void TestProxy::onSimpleSignal()
{
m_signalMsg = std::make_unique<sdbus::Message>(getProxy().getCurrentlyProcessedMessage());
m_signalMemberName = m_signalMsg->getMemberName();
m_signalName = m_signalMsg->getMemberName();
m_gotSimpleSignal = true;
}
@ -81,6 +81,7 @@ void TestProxy::onSignalWithVariant(const sdbus::Variant& aVariant)
void TestProxy::onSignalWithoutRegistration(const sdbus::Struct<std::string, sdbus::Struct<sdbus::Signature>>& s)
{
// Static cast to std::string is a workaround for gcc 11.4 false positive warning (which later gcc versions nor Clang emit)
m_signatureFromSignal[std::get<0>(s)] = static_cast<std::string>(std::get<0>(std::get<1>(s)));
m_gotSignalWithSignature = true;
}
@ -91,9 +92,9 @@ void TestProxy::onDoOperationReply(uint32_t returnValue, std::optional<sdbus::Er
m_DoOperationClientSideAsyncReplyHandler(returnValue, error);
}
void TestProxy::onPropertiesChanged( const std::string& interfaceName
, const std::map<std::string, sdbus::Variant>& changedProperties
, const std::vector<std::string>& invalidatedProperties )
void TestProxy::onPropertiesChanged( const sdbus::InterfaceName& interfaceName
, const std::map<PropertyName, sdbus::Variant>& changedProperties
, const std::vector<PropertyName>& invalidatedProperties )
{
if (m_onPropertiesChangedHandler)
m_onPropertiesChangedHandler(interfaceName, changedProperties, invalidatedProperties);
@ -133,7 +134,7 @@ std::future<uint32_t> TestProxy::doOperationClientSideAsync(uint32_t param, with
std::future<MethodReply> TestProxy::doOperationClientSideAsyncOnBasicAPILevel(uint32_t param)
{
auto methodCall = getProxy().createMethodCall(sdbus::test::INTERFACE_NAME, "doOperation");
auto methodCall = getProxy().createMethodCall(sdbus::test::INTERFACE_NAME, sdbus::MethodName{"doOperation"});
methodCall << param;
return getProxy().callMethodAsync(methodCall, sdbus::with_future);
@ -178,8 +179,9 @@ int32_t TestProxy::callNonexistentMethod()
int32_t TestProxy::callMethodOnNonexistentInterface()
{
sdbus::InterfaceName nonexistentInterfaceName{"sdbuscpp.interface.that.does.not.exist"};
int32_t result;
getProxy().callMethod("someMethod").onInterface("sdbuscpp.interface.that.does.not.exist").storeResultsTo(result);
getProxy().callMethod("someMethod").onInterface(nonexistentInterfaceName).storeResultsTo(result);
return result;
}

View File

@ -40,7 +40,7 @@ namespace sdbus { namespace test {
class ObjectManagerTestProxy final : public sdbus::ProxyInterfaces< sdbus::ObjectManager_proxy >
{
public:
ObjectManagerTestProxy(sdbus::IConnection& connection, std::string destination, std::string objectPath)
ObjectManagerTestProxy(sdbus::IConnection& connection, ServiceName destination, ObjectPath objectPath)
: ProxyInterfaces(connection, std::move(destination), std::move(objectPath))
{
registerProxy();
@ -51,21 +51,21 @@ public:
unregisterProxy();
}
protected:
void onInterfacesAdded(const sdbus::ObjectPath& objectPath, const std::map<std::string, std::map<std::string, sdbus::Variant>>& interfacesAndProperties) override
void onInterfacesAdded(const sdbus::ObjectPath& objectPath, const std::map<sdbus::InterfaceName, std::map<PropertyName, sdbus::Variant>>& interfacesAndProperties) override
{
if (m_onInterfacesAddedHandler)
m_onInterfacesAddedHandler(objectPath, interfacesAndProperties);
}
void onInterfacesRemoved(const sdbus::ObjectPath& objectPath, const std::vector<std::string>& interfaces) override
void onInterfacesRemoved(const sdbus::ObjectPath& objectPath, const std::vector<sdbus::InterfaceName>& interfaces) override
{
if (m_onInterfacesRemovedHandler)
m_onInterfacesRemovedHandler(objectPath, interfaces);
}
public: // for tests
std::function<void(const sdbus::ObjectPath&, const std::map<std::string, std::map<std::string, sdbus::Variant>>&)> m_onInterfacesAddedHandler;
std::function<void(const sdbus::ObjectPath&, const std::vector<std::string>&)> m_onInterfacesRemovedHandler;
std::function<void(const sdbus::ObjectPath&, const std::map<sdbus::InterfaceName, std::map<PropertyName, sdbus::Variant>>&)> m_onInterfacesAddedHandler;
std::function<void(const sdbus::ObjectPath&, const std::vector<sdbus::InterfaceName>&)> m_onInterfacesRemovedHandler;
};
class TestProxy final : public sdbus::ProxyInterfaces< org::sdbuscpp::integrationtests_proxy
@ -74,9 +74,9 @@ class TestProxy final : public sdbus::ProxyInterfaces< org::sdbuscpp::integratio
, sdbus::Properties_proxy >
{
public:
TestProxy(std::string destination, std::string objectPath);
TestProxy(std::string destination, std::string objectPath, dont_run_event_loop_thread_t);
TestProxy(sdbus::IConnection& connection, std::string destination, std::string objectPath);
TestProxy(ServiceName destination, ObjectPath objectPath);
TestProxy(ServiceName destination, ObjectPath objectPath, dont_run_event_loop_thread_t);
TestProxy(sdbus::IConnection& connection, ServiceName destination, ObjectPath objectPath);
~TestProxy();
protected:
@ -88,9 +88,9 @@ protected:
void onDoOperationReply(uint32_t returnValue, std::optional<sdbus::Error> error);
// Signals of standard D-Bus interfaces
void onPropertiesChanged( const std::string& interfaceName
, const std::map<std::string, sdbus::Variant>& changedProperties
, const std::vector<std::string>& invalidatedProperties ) override;
void onPropertiesChanged( const sdbus::InterfaceName& interfaceName
, const std::map<PropertyName, sdbus::Variant>& changedProperties
, const std::vector<PropertyName>& invalidatedProperties ) override;
public:
void installDoOperationClientSideAsyncReplyHandler(std::function<void(uint32_t res, std::optional<sdbus::Error> err)> handler);
@ -114,13 +114,13 @@ public: // for tests
std::atomic<bool> m_gotSignalWithVariant{false};
double m_variantFromSignal;
std::atomic<bool> m_gotSignalWithSignature{false};
std::map<std::string, std::string> m_signatureFromSignal;
std::map<std::string, Signature> m_signatureFromSignal;
std::function<void(uint32_t res, std::optional<sdbus::Error> err)> m_DoOperationClientSideAsyncReplyHandler;
std::function<void(const std::string&, const std::map<std::string, sdbus::Variant>&, const std::vector<std::string>&)> m_onPropertiesChangedHandler;
std::function<void(const sdbus::InterfaceName&, const std::map<PropertyName, sdbus::Variant>&, const std::vector<PropertyName>&)> m_onPropertiesChangedHandler;
std::unique_ptr<const Message> m_signalMsg;
std::string m_signalMemberName;
SignalName m_signalName;
};
class DummyTestProxy final : public sdbus::ProxyInterfaces< org::sdbuscpp::integrationtests_proxy
@ -129,7 +129,7 @@ class DummyTestProxy final : public sdbus::ProxyInterfaces< org::sdbuscpp::integ
, sdbus::Properties_proxy >
{
public:
DummyTestProxy(std::string destination, std::string objectPath)
DummyTestProxy(ServiceName destination, ObjectPath objectPath)
: ProxyInterfaces(destination, objectPath)
{
}
@ -143,7 +143,7 @@ protected:
void onDoOperationReply(uint32_t, std::optional<sdbus::Error>) {}
// Signals of standard D-Bus interfaces
void onPropertiesChanged( const std::string&, const std::map<std::string, sdbus::Variant>&, const std::vector<std::string>& ) override {}
void onPropertiesChanged(const InterfaceName&, const std::map<PropertyName, sdbus::Variant>&, const std::vector<PropertyName>&) override {}
};
}}

View File

@ -16,7 +16,7 @@ namespace sdbuscpp {
class integrationtests_adaptor
{
public:
static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.integrationtests";
static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.integrationtests"};
protected:
integrationtests_adaptor(sdbus::IObject& object)

View File

@ -16,7 +16,7 @@ namespace sdbuscpp {
class integrationtests_proxy
{
public:
static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.integrationtests";
static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.integrationtests"};
protected:
integrationtests_proxy(sdbus::IProxy& proxy)

View File

@ -43,7 +43,7 @@ uint64_t totalDuration = 0;
class PerftestProxy final : public sdbus::ProxyInterfaces<org::sdbuscpp::perftests_proxy>
{
public:
PerftestProxy(std::string destination, std::string objectPath)
PerftestProxy(sdbus::ServiceName destination, sdbus::ObjectPath objectPath)
: ProxyInterfaces(std::move(destination), std::move(objectPath))
{
registerProxy();
@ -101,9 +101,9 @@ std::string createRandomString(size_t length)
//-----------------------------------------
int main(int /*argc*/, char */*argv*/[])
{
const char* destinationName = "org.sdbuscpp.perftests";
const char* objectPath = "/org/sdbuscpp/perftests";
PerftestProxy client(destinationName, objectPath);
sdbus::ServiceName destination{"org.sdbuscpp.perftests"};
sdbus::ObjectPath objectPath{"/org/sdbuscpp/perftests"};
PerftestProxy client(std::move(destination), std::move(objectPath));
const unsigned int repetitions{20};
unsigned int msgCount = 1000;

View File

@ -16,7 +16,7 @@ namespace sdbuscpp {
class perftests_adaptor
{
public:
static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.perftests";
static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.perftests"};
protected:
perftests_adaptor(sdbus::IObject& object)

View File

@ -16,7 +16,7 @@ namespace sdbuscpp {
class perftests_proxy
{
public:
static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.perftests";
static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.perftests"};
protected:
perftests_proxy(sdbus::IProxy& proxy)

View File

@ -40,7 +40,7 @@ std::string createRandomString(size_t length);
class PerftestAdaptor final : public sdbus::AdaptorInterfaces<org::sdbuscpp::perftests_adaptor>
{
public:
PerftestAdaptor(sdbus::IConnection& connection, std::string objectPath)
PerftestAdaptor(sdbus::IConnection& connection, sdbus::ObjectPath objectPath)
: AdaptorInterfaces(connection, std::move(objectPath))
{
registerAdaptor();
@ -92,11 +92,11 @@ std::string createRandomString(size_t length)
//-----------------------------------------
int main(int /*argc*/, char */*argv*/[])
{
const char* serviceName = "org.sdbuscpp.perftests";
sdbus::ServiceName serviceName{"org.sdbuscpp.perftests"};
auto connection = sdbus::createSystemBusConnection(serviceName);
const char* objectPath = "/org/sdbuscpp/perftests";
PerftestAdaptor server(*connection, objectPath);
sdbus::ObjectPath objectPath{"/org/sdbuscpp/perftests"};
PerftestAdaptor server(*connection, std::move(objectPath));
connection->enterEventLoop();
}

View File

@ -18,7 +18,7 @@ namespace celsius {
class thermometer_adaptor
{
public:
static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.celsius.thermometer";
static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.stresstests.celsius.thermometer"};
protected:
thermometer_adaptor(sdbus::IObject& object)

View File

@ -18,7 +18,7 @@ namespace celsius {
class thermometer_proxy
{
public:
static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.celsius.thermometer";
static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.stresstests.celsius.thermometer"};
protected:
thermometer_proxy(sdbus::IProxy& proxy)

View File

@ -17,7 +17,7 @@ namespace stresstests {
class concatenator_adaptor
{
public:
static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.concatenator";
static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.stresstests.concatenator"};
protected:
concatenator_adaptor(sdbus::IObject& object)

View File

@ -17,7 +17,7 @@ namespace stresstests {
class concatenator_proxy
{
public:
static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.concatenator";
static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.stresstests.concatenator"};
protected:
concatenator_proxy(sdbus::IProxy& proxy)

View File

@ -18,7 +18,7 @@ namespace fahrenheit {
class thermometer_adaptor
{
public:
static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.fahrenheit.thermometer";
static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.stresstests.fahrenheit.thermometer"};
protected:
thermometer_adaptor(sdbus::IObject& object)
@ -56,7 +56,7 @@ namespace thermometer {
class factory_adaptor
{
public:
static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.fahrenheit.thermometer.factory";
static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.stresstests.fahrenheit.thermometer.factory"};
protected:
factory_adaptor(sdbus::IObject& object)

View File

@ -18,7 +18,7 @@ namespace fahrenheit {
class thermometer_proxy
{
public:
static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.fahrenheit.thermometer";
static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.stresstests.fahrenheit.thermometer"};
protected:
thermometer_proxy(sdbus::IProxy& proxy)
@ -60,7 +60,7 @@ namespace thermometer {
class factory_proxy
{
public:
static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.fahrenheit.thermometer.factory";
static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.stresstests.fahrenheit.thermometer.factory"};
protected:
factory_proxy(sdbus::IProxy& proxy)

View File

@ -46,18 +46,17 @@
#include <queue>
using namespace std::chrono_literals;
using namespace std::string_literals;
#define SERVICE_1_BUS_NAME "org.sdbuscpp.stresstests.service1"s
#define SERVICE_2_BUS_NAME "org.sdbuscpp.stresstests.service2"s
#define CELSIUS_THERMOMETER_OBJECT_PATH "/org/sdbuscpp/stresstests/celsius/thermometer"s
#define FAHRENHEIT_THERMOMETER_OBJECT_PATH "/org/sdbuscpp/stresstests/fahrenheit/thermometer"s
#define CONCATENATOR_OBJECT_PATH "/org/sdbuscpp/stresstests/concatenator"s
const sdbus::ServiceName SERVICE_1_BUS_NAME{"org.sdbuscpp.stresstests.service1"};
const sdbus::ServiceName SERVICE_2_BUS_NAME{"org.sdbuscpp.stresstests.service2"};
const sdbus::ObjectPath CELSIUS_THERMOMETER_OBJECT_PATH{"/org/sdbuscpp/stresstests/celsius/thermometer"};
const sdbus::ObjectPath FAHRENHEIT_THERMOMETER_OBJECT_PATH{"/org/sdbuscpp/stresstests/fahrenheit/thermometer"};
const sdbus::ObjectPath CONCATENATOR_OBJECT_PATH{"/org/sdbuscpp/stresstests/concatenator"};
class CelsiusThermometerAdaptor final : public sdbus::AdaptorInterfaces<org::sdbuscpp::stresstests::celsius::thermometer_adaptor>
{
public:
CelsiusThermometerAdaptor(sdbus::IConnection& connection, std::string objectPath)
CelsiusThermometerAdaptor(sdbus::IConnection& connection, sdbus::ObjectPath objectPath)
: AdaptorInterfaces(connection, std::move(objectPath))
{
registerAdaptor();
@ -81,7 +80,7 @@ private:
class CelsiusThermometerProxy : public sdbus::ProxyInterfaces<org::sdbuscpp::stresstests::celsius::thermometer_proxy>
{
public:
CelsiusThermometerProxy(sdbus::IConnection& connection, std::string destination, std::string objectPath)
CelsiusThermometerProxy(sdbus::IConnection& connection, sdbus::ServiceName destination, sdbus::ObjectPath objectPath)
: ProxyInterfaces(connection, std::move(destination), std::move(objectPath))
{
registerProxy();
@ -97,7 +96,7 @@ class FahrenheitThermometerAdaptor final : public sdbus::AdaptorInterfaces< org:
, org::sdbuscpp::stresstests::fahrenheit::thermometer::factory_adaptor >
{
public:
FahrenheitThermometerAdaptor(sdbus::IConnection& connection, std::string objectPath, bool isDelegate)
FahrenheitThermometerAdaptor(sdbus::IConnection& connection, sdbus::ObjectPath objectPath, bool isDelegate)
: AdaptorInterfaces(connection, std::move(objectPath))
, celsiusProxy_(connection, SERVICE_2_BUS_NAME, CELSIUS_THERMOMETER_OBJECT_PATH)
{
@ -128,7 +127,7 @@ public:
{
// Create new delegate object
auto& connection = getObject().getConnection();
sdbus::ObjectPath newObjectPath = FAHRENHEIT_THERMOMETER_OBJECT_PATH + "/" + std::to_string(request.objectNr);
sdbus::ObjectPath newObjectPath{FAHRENHEIT_THERMOMETER_OBJECT_PATH + "/" + std::to_string(request.objectNr)};
// Here we are testing dynamic creation of a D-Bus object in an async way
auto adaptor = std::make_unique<FahrenheitThermometerAdaptor>(connection, newObjectPath, true);
@ -176,7 +175,7 @@ protected:
objectCounter++;
std::unique_lock<std::mutex> lock(mutex_);
requests_.push(WorkItem{objectCounter, std::string{}, std::move(result)});
requests_.push(WorkItem{objectCounter, {}, std::move(result)});
lock.unlock();
cond_.notify_one();
}
@ -191,7 +190,7 @@ protected:
private:
CelsiusThermometerProxy celsiusProxy_;
std::map<std::string, std::unique_ptr<FahrenheitThermometerAdaptor>> children_;
std::map<sdbus::ObjectPath, std::unique_ptr<FahrenheitThermometerAdaptor>> children_;
std::mutex childrenMutex_;
struct WorkItem
@ -211,7 +210,7 @@ class FahrenheitThermometerProxy : public sdbus::ProxyInterfaces< org::sdbuscpp:
, org::sdbuscpp::stresstests::fahrenheit::thermometer::factory_proxy >
{
public:
FahrenheitThermometerProxy(sdbus::IConnection& connection, std::string destination, std::string objectPath)
FahrenheitThermometerProxy(sdbus::IConnection& connection, sdbus::ServiceName destination, sdbus::ObjectPath objectPath)
: ProxyInterfaces(connection, std::move(destination), std::move(objectPath))
{
registerProxy();
@ -226,7 +225,7 @@ public:
class ConcatenatorAdaptor final : public sdbus::AdaptorInterfaces<org::sdbuscpp::stresstests::concatenator_adaptor>
{
public:
ConcatenatorAdaptor(sdbus::IConnection& connection, std::string objectPath)
ConcatenatorAdaptor(sdbus::IConnection& connection, sdbus::ObjectPath objectPath)
: AdaptorInterfaces(connection, std::move(objectPath))
{
unsigned int workers = std::thread::hardware_concurrency();
@ -298,7 +297,7 @@ private:
class ConcatenatorProxy final : public sdbus::ProxyInterfaces<org::sdbuscpp::stresstests::concatenator_proxy>
{
public:
ConcatenatorProxy(sdbus::IConnection& connection, std::string destination, std::string objectPath)
ConcatenatorProxy(sdbus::IConnection& connection, sdbus::ServiceName destination, sdbus::ObjectPath objectPath)
: ProxyInterfaces(connection, std::move(destination), std::move(objectPath))
{
registerProxy();

View File

@ -26,6 +26,7 @@
*/
#include "Connection.h"
#include "sdbus-c++/Types.h"
#include "unittests/mocks/SdBusMock.h"
#include <gtest/gtest.h>
@ -207,12 +208,16 @@ TYPED_TEST_SUITE(AConnectionNameRequest, BusTypeTags);
TYPED_TEST(AConnectionNameRequest, DoesNotThrowOnSuccess)
{
EXPECT_CALL(*this->sdBusIntfMock_, sd_bus_request_name(_, _, _)).WillOnce(Return(1));
this->con_->requestName("org.sdbuscpp.somename");
sdbus::ConnectionName name{"org.sdbuscpp.somename"};
this->con_->requestName(name);
}
TYPED_TEST(AConnectionNameRequest, ThrowsOnFail)
{
sdbus::ConnectionName name{"org.sdbuscpp.somename"};
EXPECT_CALL(*this->sdBusIntfMock_, sd_bus_request_name(_, _, _)).WillOnce(Return(-1));
ASSERT_THROW(this->con_->requestName("org.sdbuscpp.somename"), sdbus::Error);
ASSERT_THROW(this->con_->requestName(name), sdbus::Error);
}

View File

@ -270,7 +270,7 @@ TEST(AMessage, CanCarryDBusArrayOfNontrivialTypesGivenAsStdVector)
{
auto msg = sdbus::createPlainMessage();
const std::vector<sdbus::Signature> dataWritten{"s", "u", "b"};
const std::vector dataWritten{sdbus::Signature{"s"}, sdbus::Signature{"u"}, sdbus::Signature{"b"}};
msg << dataWritten;
msg.seal();
@ -300,7 +300,7 @@ TEST(AMessage, CanCarryDBusArrayOfNontrivialTypesGivenAsStdArray)
{
auto msg = sdbus::createPlainMessage();
const std::array<sdbus::Signature, 3> dataWritten{"s", "u", "b"};
const std::array dataWritten{sdbus::Signature{"s"}, sdbus::Signature{"u"}, sdbus::Signature{"b"}};
msg << dataWritten;
msg.seal();
@ -333,7 +333,7 @@ TEST(AMessage, CanCarryDBusArrayOfNontrivialTypesGivenAsStdSpan)
{
auto msg = sdbus::createPlainMessage();
const std::array<sdbus::Signature, 3> sourceArray{"s", "u", "b"};
const std::array sourceArray{sdbus::Signature{"s"}, sdbus::Signature{"u"}, sdbus::Signature{"b"}};
const std::span dataWritten{sourceArray};
msg << dataWritten;
@ -433,7 +433,7 @@ TEST(AMessage, CanCarryAComplexType)
>
>;
ComplexType dataWritten = { {1, {{{5, {{"/some/object", true, 45, {{6, "hello"}, {7, "world"}}}}}}, "av", 3.14}}};
ComplexType dataWritten = { {1, {{{5, {{sdbus::ObjectPath{"/some/object"}, true, 45, {{6, "hello"}, {7, "world"}}}}}}, sdbus::Signature{"av"}, 3.14}}};
msg << dataWritten;
msg.seal();

View File

@ -85,6 +85,9 @@ namespace
TYPE(double)HAS_DBUS_TYPE_SIGNATURE("d")
TYPE(const char*)HAS_DBUS_TYPE_SIGNATURE("s")
TYPE(std::string)HAS_DBUS_TYPE_SIGNATURE("s")
TYPE(sdbus::BusName)HAS_DBUS_TYPE_SIGNATURE("s")
TYPE(sdbus::InterfaceName)HAS_DBUS_TYPE_SIGNATURE("s")
TYPE(sdbus::MemberName)HAS_DBUS_TYPE_SIGNATURE("s")
TYPE(sdbus::ObjectPath)HAS_DBUS_TYPE_SIGNATURE("o")
TYPE(sdbus::Signature)HAS_DBUS_TYPE_SIGNATURE("g")
TYPE(sdbus::Variant)HAS_DBUS_TYPE_SIGNATURE("v")
@ -135,6 +138,9 @@ namespace
, double
, const char*
, std::string
, sdbus::BusName
, sdbus::InterfaceName
, sdbus::MemberName
, sdbus::ObjectPath
, sdbus::Signature
, sdbus::Variant

View File

@ -322,7 +322,6 @@ TEST(ASignature, CanBeMovedLikeAStdString)
sdbus::Signature oSignature{aSignature};
ASSERT_THAT(sdbus::Signature{std::move(oSignature)}, Eq(sdbus::Signature(std::move(aSignature))));
ASSERT_THAT(std::string(oSignature), Eq(aSignature));
}
TEST(AUnixFd, DuplicatesAndOwnsFdUponStandardConstruction)
@ -428,17 +427,17 @@ TEST(AUnixFd, TakesOverNewFdAndClosesOriginalFdOnAdoptingReset)
TEST(AnError, CanBeConstructedFromANameAndAMessage)
{
auto error = sdbus::Error("name", "message");
EXPECT_THAT(error.getName(), Eq<std::string>("name"));
auto error = sdbus::Error(sdbus::Error::Name{"org.sdbuscpp.error"}, "message");
EXPECT_THAT(error.getName(), Eq<std::string>("org.sdbuscpp.error"));
EXPECT_THAT(error.getMessage(), Eq<std::string>("message"));
}
TEST(AnError, CanBeConstructedFromANameOnly)
{
auto error1 = sdbus::Error("name");
auto error2 = sdbus::Error("name", nullptr);
EXPECT_THAT(error1.getName(), Eq<std::string>("name"));
EXPECT_THAT(error2.getName(), Eq<std::string>("name"));
auto error1 = sdbus::Error(sdbus::Error::Name{"org.sdbuscpp.error"});
auto error2 = sdbus::Error(sdbus::Error::Name{"org.sdbuscpp.error"}, nullptr);
EXPECT_THAT(error1.getName(), Eq<std::string>("org.sdbuscpp.error"));
EXPECT_THAT(error2.getName(), Eq<std::string>("org.sdbuscpp.error"));
EXPECT_THAT(error1.getMessage(), Eq<std::string>(""));
EXPECT_THAT(error2.getMessage(), Eq<std::string>(""));

View File

@ -82,7 +82,7 @@ std::string AdaptorGenerator::processInterface(Node& interface) const
body << "class " << className << endl
<< "{" << endl
<< "public:" << endl
<< tab << "static constexpr const char* INTERFACE_NAME = \"" << ifaceName << "\";" << endl << endl
<< tab << "static inline const sdbus::InterfaceName INTERFACE_NAME{\"" << ifaceName << "\"};" << endl << endl
<< "protected:" << endl
<< tab << className << "(sdbus::IObject& object)" << endl
<< tab << tab << ": object_(&object)" << endl

View File

@ -81,7 +81,7 @@ std::string ProxyGenerator::processInterface(Node& interface) const
body << "class " << className << endl
<< "{" << endl
<< "public:" << endl
<< tab << "static constexpr const char* INTERFACE_NAME = \"" << ifaceName << "\";" << endl << endl
<< tab << "static inline const sdbus::InterfaceName INTERFACE_NAME{\"" << ifaceName << "\"};" << endl << endl
<< "protected:" << endl
<< tab << className << "(sdbus::IProxy& proxy)" << endl
<< tab << tab << ": proxy_(&proxy)" << endl