How to call a D-Bus interface from Qt with struct argument - c++

I'm trying to ask polkit for authorization but I can't seem to find out how to provide a struct as an argument.
QDBusArgument subject;
subject.beginStructure();
subject << "unix-process";
subject << QMap<QString, QVariant>{
{"pid", static_cast<uint32_t>(QCoreApplication::applicationPid())},
{"start-time", static_cast<uint64_t>(0)},
};
subject.endStructure();
QDBusInterface polkit("org.freedesktop.PolicyKit1", "/org/freedesktop/PolicyKit1/Authority", "org.freedesktop.PolicyKit1.Authority");
auto result = polkit.callWithArgumentList(
QDBus::CallMode::AutoDetect,
"CheckAuthorization",
{
// how to provide the subject here?
}
);
The QDBusArgument shows what the argument should look like and I somehow need to translate this to a format that can be used in callWithArgumentList.
FreeDesktop specifies the struct as such:
{
String subject_kind,
Dict<String,Variant> subject_details
}
More specifically, I'm trying to replace this with a dbus call:
// checkProcess is *QProcess
checkProcess->start("pkcheck", {
"--process",
QString::number(QCoreApplication::applicationPid()),
"--action-id",
"my-custom-action-id",
"--allow-user-interaction"
});

I'm not too familiar with D-Bus or its Qt interface, but I do happen to have a linux system I could test this on. It seems that you were already well on your way, I was able to get a response from the polkit service after some small adjustments:
#include <QtDBus>
int main() {
// Not all Qt types are compatible with the D-Bus interface by default:
// QMap<QString, QVariant> is, but QMap<QString, QString> is not.
// If you need such a type, even if only to pass an empty
// Dict<String, String>, it must first be registered like so:
qDBusRegisterMetaType<QMap<QString, QString>>();
// Subject kind should be provided as a QString, integers as Qt types
QDBusArgument subject;
subject.beginStructure();
subject << QString("unix-process");
subject << QMap<QString, QVariant>{
{"pid", static_cast<quint32>(QCoreApplication::applicationPid())},
{"start-time", static_cast<quint64>(0)},
};
subject.endStructure();
// PolicyKit1 is on the system bus
QDBusInterface polkit(
"org.freedesktop.PolicyKit1",
"/org/freedesktop/PolicyKit1/Authority",
"org.freedesktop.PolicyKit1.Authority",
QDBusConnection::systemBus()
);
// callWithArgumentList only takes actual QVariantLists as the arguments,
// call is a more convenient variadic function template
auto result = polkit.call(
QDBus::CallMode::AutoDetect,
"CheckAuthorization",
QVariant::fromValue(subject),
"org.freedesktop.login1.set-user-linger",
QVariant::fromValue(QMap<QString, QString>{}),
0x1u, // AllowUserInteraction = 0x00000001
""
);
qInfo() << result;
}
This resulted in the following output:
QDBusMessage(type=MethodReturn, service=":1.1", signature="(bba{ss})", contents=([Argument: (bba{ss}) false, true, [Argument: a{ss} {"polkit.retains_authorization_after_challenge" = "1"}]]) )
Some further remarks:
Types registered with the D-Bus type system must be convertible to and from QDBusArgument by the << and >> operators, which is why you can run into issues when using those with non-Qt types. You can implement these operators for other types to allow registering them;
Types passed to a D-Bus call must be implicitly convertible to QVariant. If they are not, you can convert them explicitly using QVariant::fromValue().
Once these requirements are met, you should be able to get meaningful output from D-Bus, even if you pass the wrong arguments. For example, leaving out the last string argument to CheckAuthorization leads to an InvalidArgs error response with the message
Type of message, “((sa{sv})sa{ss}u)”, does not match expected type “((sa{sv})sa{ss}us)”
The string encodes the expected types
{
{
String,
Dict<String, Variant>
},
String,
Dict<String, String>,
Uint32,
String
}

Related

typeid, how to get just type name only

Example code:
MainWindow::MainWindow(QWidget *parent) {
QString strTemp = typeid(this).name();
qDebug() << strTemp;
}
I want to get just the class name, in the above example I'm after just "MainWindow", what I get is:
class MainWindow *
Of course I can write a routine that takes this string and then strips out the class and pointer parts isolating just the class name. Is there anything that does this already?
In the absence of any standard routine, this is what I have done:
QString strTemp = typeid(this).name();
qDebug() << strTemp;
QStringList lstParts = strTemp.split(" ");
if ( lstParts.length > 1 ) {
strTemp = lstParts[1];
}
qDebug() << strTemp;
The above results in only the type name. In the end I just needed
__FUNCTION__ which gives the classname and method its being called from which will give:
MainWindow::MainWindow
cppreference says the following about std::type_info::name():
Returns an implementation defined null-terminated character string containing the name of the type. No guarantees are given; in particular, the returned string can be identical for several types and change between invocations of the same program.
So the fact that you got class MainWindow as output here under one compiler does not mean that you will get the same output under different compiler (or even the same one but newer version).
Why not use boost::typeindex::type_id_with_cvr plus using some type traits, for example remove_pointer_t to get desired result ?
#include <iostream>
#include <sstream>
#include <string>
#include <boost/type_index.hpp>
class MainWindow {
public:
void test()
{
std::ostringstream os;
os <<
boost::typeindex::type_id_with_cvr<std::remove_pointer_t<decltype(this)>>().pretty_name()
;
std::string s = os.str(); // easy transform to QString
std::cout << s << std::endl;
}
};
int main()
{
MainWindow{}.test(); // as output MainWindow
return 0;
}
Full demo
You really should not rely on std::typeid, nor on boost or any other C++-only-library. None of them guarantee you will get the typename, especially with mangled types, on different compilers. Using virtual function even RTTI can influence the name of the type. Nothing prevents your compiler from renaming "MainWindow" to "CellarDoor". The only way to go so far is by using some sort of Reflection (which is not (yet) part of C++) or some preprocessor. ComicSansMS provided a nice answer, where you roll your own simple reflection implementation.
However, since you are using QT you can use QT Metaobjects for this. It actually has a method dedicated for this exact purpose; className.
QMetaObject::className() returns the class name as a string at run-time, without requiring native run-time type information (RTTI) support through the C++ compiler.
Simply call metaObject()->className():
MainWindow::MainWindow(QWidget *parent) {
qDebug() << metaObject()->className();
}
moc runs before any compiler and bakes the class name into the code. Looking into the moc generated code you will see something like:
static const qt_meta_stringdata_MainWindow_t qt_meta_stringdata_MainWindow = {
{
QT_MOC_LITERAL(0, 0, 10), // "MainWindow"
QT_MOC_LITERAL(1, 11, 13), // "buttonClicked"
QT_MOC_LITERAL(2, 25, 0) // ""
},
"MainWindow\0buttonClicked\0"
};
std::type_info::name() is a bad match for this kind of task. As pointed out by #pkrysiak's answer the return value of this function is implementation-defined, so it is not possible to strip it down to the type name as it appears in the source code in a portable way.
A better approach in this case would be to roll your own reflection mechanism, which will give you full control over the type string. Unfortunately, the language does not offer a lot of support for this at the moment, so the resulting mechanism will be a bit of a hack. For example, you could do something like this:
#define ENABLE_REFLECTION_TYPE_NAME(class_name) \
inline constexpr char const* type_name(class_name const&) { \
return #class_name; \
}
class Foo {};
ENABLE_REFLECTION_TYPE_NAME(Foo)
ENABLE_REFLECTION_TYPE_NAME(MainWindow)
MainWindow::MainWindow(QWidget *parent) {
QString strTemp = type_name(*this);
qDebug() << strTemp; // prints "MainWindow"
Foo f;
QString strTemp2 = type_name(f);
qDebug() << strTemp2; // prints "Foo"
}

Is there have a way to delay type binding at code level in C++?

I'm going to request some user configuration via json from the server that contains two types of data like (usrID, bool), and (usrID, int). so, I created two map to classify and reload two functions with the same name to put the data into the corresponding map after parsed.
For the sake of refinement, I used the auto keyword of C++11 to initialize a variable without assign and determined its type whether bool or int mentioned above through assigned by parse function, so as to call the overloaded function directly to store them.
But it causes compiler error that cannot use a auto variable without assign.
bool fromStringtoBool() {……}
int fromStringtoInt() {……}
void setAppidConfig(int,bool);
void setAppidConfig(int,int);
……
……
void main func()
{
……
int usrId;
auto value;
if(isBool())
{
value = fromStringtoBool();
}
else
{
value = fromStringtoInt();
}
setAppidConfig(usrId,value)
……
}
Is it possible to implement the above logic in C++ ?
No. In C++ auto variable type resolution and also function overload resolution has to happen compile time. The isBool() of yours is presumably runtime value. So all you can do is something like:
if(isBool())
{
setAppidConfig(usrId,fromStringtoBool());
}
else
{
setAppidConfig(usrId,fromStringtoInt());
}
auto allows you to omit the type name and let the compiler deduce the type. There is no type to deduce from in your case, since there's no assignment, so nothing can be deduced.
For your use case, you need some kind of variant type that can store one of several types. The Qt library has QVariant, and other libraries usually offer something like that as well. As of C++17 however, such a type is offered directly by the standard library: std::variant.
int usrId;
std::variant<bool, int> value;
if (isBool()) {
value = fromStringtoBool();
} else {
value = fromStringtoInt();
}
setAppidConfig(usrId, value);
The setAppidConfig() function would need to accept an appropriate variant parameter:
void setAppidConfig(int usrId, std::variant<bool, int> value)
{
// ...
if (std::holds_alternative<int>(value)) {
// It's a int.
int i = std::get<int>(value);
} else {
// It's a bool.
bool b = std::get<bool>(value);
}
}
Note that variants can hold more than just two types (you can have an std::variant<bool, int, std::string> for example.)
If you need something that can hold anything, then you can use an std::any. This type does not need to know the types in advance (it takes no template arguments.)

Processing ASCII commands in a more robust and type safe way

I have a module which receives ASCII commands and then reacts to them accordingly. I am wondering if it is possible, to have a more robust and typesafe way of calling handler functions.
In the past, I had code like the following, which is also very similar to this answer: Processing ASCII commands via RS232 in embedded c
struct Command commands[] = {
{"command1", command1Handler}
{"command2", command2Handler}
...
};
//gets called when a new string has been received
void parseCmd(const char *input) {
//find the fitting command entry and call function pointer
}
bool command1Handler(const char *input) { }
bool command2Handler(const char *input) { }
I don't like that all handler functions have to do their own parsing. This seems needlessly repetitive and error prone.
It would be cool, if instead we could have it the following way, where all parsing is done in the the parseCmd function:
struct Command commands[] = {
{"command1", command1HandlerSafe}
{"command2", command2HandlerSafe}
...
};
void parseCmd(const char *input) {
//1. find fitting command entry
//2. check that parameter number fits the expected number for the target function
//3. parse parameters and validate the types
//4. call function with parameters in their correct types
}
bool command1HandlerSafe(bool param1, const char *param2) { }
bool command2HandlerSafe(int param1) {}
I think with old C-style varargs it would be possible to do the parsing in a central function, but that would not bring type safety.
Edit:
Meanwhile I came up with the following solution, which I thought somewhat balances the hackiness and modularization:
class ParameterSet{
struct Param{
const char *paramString;
bool isInt();
int toInt();
float toFloat();
..
}
ParameterSet(const char *input);
Param at(size_t index);
size_t length();
char m_buffer[100];
Param m_params[10];
}
bool command1HandlerMoreSafe(const ParameterSet *paramSet);
Building an abstraction layer around this might make things more complex and thereby bug prone. I wouldn't do that unless the amount of commands you are supposed to handle is vast, needs to be maintained, and this is one of the main tasks of your application.
With the pre-requisites to keep type safe and keep parsing separate from algorithms, you could build something similar to the following C-like pseudo code:
typedef enum
{
INT,
STR
} type_t; // for marking which type that is supported by the command
typedef struct
{
type_t type;
const char* text; // what kind of text that is expected in case of strings
} arg_t;
typedef struct
{
const char* name; // the name of the command
arg_t* args; // list of allowed arguments
size_t args_n; // size of that list
void (*callback)(void); // placeholder for callback functions of different types
} command_t;
You can then make callback handler functions that aren't concerned about parsing, but only about their dedicated task:
void cmd_branch (const char* str);
void cmd_kill (int n);
The array of commands might look something like this:
const command_t commands[] =
{
{ // BRANCH [FAST][SLOW]
.name="BRANCH",
.args=(entry_t[]){ {STR,"FAST"}, {STR,"SLOW"} },
.args_n=2,
.callback= (void(*)(void)) cmd_branch,
},
{ // KILL [7][9]
.name="KILL",
.args=(entry_t[]){ {INT, NULL} },
.args_n=1,
.callback= (void(*)(void)) cmd_kill,
}
};
The parse function will then do:
Find which command that was received by searching the above list (bsearch if large list).
Check what type of arguments the received command supports
Parse arguments accordingly
Call the relevant function with arguments of the appropriate type
Since this example just used some dummy type function pointer (void(*)(void)), you'll have to cast to the correct type. Can be done by for example C11 _Generic:
call(commands[i], int_val);
which expands to:
#define call(command, arg) _Generic((arg), \
int: (void(*)(int)) command.callback, \
const char*: (void(*)(const char*)) command.callback )(arg)
One way to keep the command handling interfaces the same is to fall back on the venerable argv / argc interface that main() receives. Assuming the received commands have some notion of words (perhaps whitespace separated), it could go like this:
Receive the input string.
Parse the input into words where the first word is the name of the command and the remaining words are its arguments.
As the parsing proceeds, place a pointer to the string that contains each word in an array and keep count of the number of elements in the array.
Using the first word, look up a command function pointer. You can use something like bsearch() if the commands are all known at compile time. Perhaps a hash table might also be appropriate. However you implement the mapping, the result is a pointer to a function that takes an array of pointers to the arguments and a count of the number of elements in the pointer array.
Invoke the command function via its pointer and pass the array of parsed words and the count, just like main() is invoked by startup code.
From there, each command function can deal with what its arguments specifically mean, converting strings representations to internal forms as necessary.

Passing arbitrary data to a C++ callback that doesn't accept a "void* userarg"

EDIT:
I have modified the example API so it better reflects the real API I am dealing with. The way the API get's the message argument passed to it is by user input so the message argument cannot be used to pass additional data.
I am dealing with a very frustrating API that uses callback routines that don't take "void* userarg" pointers.
Assuming the function that uses the callback routine as defined by the API expects a string argument (that will be assigned by user input), is there ANY possible way to get more data into my callback routine without using global variables?
Here is a simplified example of what the API might look like:
#include <iostream>
using namespace std;
////////////////////////////////////////////////////////////////////////////////
// ASSUME EVERYTHING IN THIS SECTION IS PART OF AN API AND IS NOT MY OWN CODE...
// I DO NOT HAVE THE SOURCE AND IT CANNOT BE MODIFIED
typedef void (*CALLBACK)(string message);
void call_callback(CALLBACK cb) {
// Gets a message from user input
string message = "hello"; // pretend this is user input
cb(message);
}
////////////////////////////////////////////////////////////////////////////////
int data = 42;
void callback_function(string message) {
// I want to access "data" here WITHOUT it being global
cout << message << ' ' << data << endl;
}
int main(int argc, char** argv) {
call_callback(&callback_function);
}
Typically an API that uses callbacks would also pass a "void* userarg" argument into the callback routine so you could pass additional data of any type, but that is not the case here.
This API is used extensively throughout our whole codebase and it is 100% necessary to pass a lot more data in every case where it is used. The current way we get more data in *prepare to cringe* is by storing practically all of our data in singletons so nearly everything is global and can be accessed from literally anywhere in the program.
This whole concept seems EVIL to me, but without a better API I can't figure out any better way to get the data into the callback. I have already contacted the vendor and asked that they fix their API to make it accept a "void* userarg" argument, but it doesn't look like it will be fixed anytime in the near future...
All I am hoping for is ANY better way of doing things than we are now.
If it is really an std::string which is an argument to the callback (and not something else) and you really have access to the argument (as in your sample code which invokes call_callback with supplied string) you can put an entity-serialized pointer to your allocated object into std::string (which is allowed to have arbitrary data in it) and invoke call_callback with it.
One challenge here would be the fact that you'd than have to manually manage this pointer.
My most straightforward idea would be to provide unique strings in place of the void* you would normally expect. You'd then have one map singleton that maps the strings to your callbacks.
So something like this:
class Dispatcher
{
public:
// TODO: Thread safety etc.
std::string makeCallback(std::function<void()> callback)
{
std::string uid = std::to_string(_index);
_callbacks[uid] = std::move(callback);
_index++;
return uid;
}
void runCallback(std::string uid)
{
_callbacks[uid]();
}
private:
size_t _index = 0;
std::map<std::string, std::function<void()>> _callbacks;
};
void leaveAPI(std::string uid)
{
getSingleton<Dispatcher>()->runCallback(uid);
}
void enterAPI(std::function<void()> userCallback)
{
std::string uid = getSingleton<Dispatcher>()->makeCallback(userCallback);
call_callback(leaveAPI, uid);
}
Demo
You just count up a number every time you call the API and use its string version as the callback parameter. The class also maps each of those strings to the callback you wanted called. You could remove the map entries or do any number of performance optimizations, but this is the gist of it.
(This would work just as well with const char* if you figure out the ownership/lifetime questions that it opens.)
You should really petition the writers of the API to use std::function instead of raw pointers to functions.
Then you can easily use e.g. std::bind or lambda expressions to be able to call functions taking more arguments than the callback takes.
For example:
// The callback is a function taking one string argument, and return nothing
using CALLBACK = std::function<void(std::string)>;
// Do some processing and then call the callback function
void call_callback(CALLBACK cb, std::string message)
{
// ...
cb(message);
}
// Our callback takes a string *and* an integer argument
void callback_function(std::string message, int data)
{
std::cout << message << ' ' << data << '\n';
}
int main()
{
int local_data = 42;
// Using std::bind...
using namespace std::placeholders; // for _1, _2, _3...
call_callback(std::bind(&callback_function, _1, local_data), "Foobar");
// Using lambdas...
call_callback([local_data](std::string message)
{
callback_function(message, local_data);
}, "Foobar");
}
Using std::function also makes it easy to use member functions as callbacks as well, not only non-member functions (or static member functions).
However, if you can't modify the API, or the creator of it won't change it and it have to use C-style plain pointers to non-member functions, you can still solve it with lambdas, but you can't have any captures for the lambda:
call_callback([/*empty!*/](std::string message)
{
// Call the function as defined in the previous snippet
callback_function(message, 42); // Pass the value directly
}, "Foobar");

Dynamic Function Args for Callback / RPC in C++

I need to register functions like the following in a list of functions with arguments.
void func1( int a , char* b ) {}
void func2( vec3f a , std::vector<float> b , double c) {}
...
And call them back when I receive data over network with proper arguments. I imagined va_list would solve, but it doesnt work :
void func1(int a, char* b)
{
printf("%d %s",a,b);
}
void prepare(...)
{
va_list argList;
int args = 2;
va_start(argList, args);
((void (*)(va_list))func1)(argList);
va_end(argList);
}
int main(int argc, char **argv)
{
prepare(1, "huhu");
return 0;
}
What is the most elegant way to solve this ?
I know std::bind / std::function has similar abilities, but the internal data is hidden deep in std I assume. I just need a few basic data types, doesnt have to be for arbitrary types. If preprocessor tricks with ##VA_ARGS or using templates would solve, I am also OK with that. Priority is that it is most simple to use.
Edit1 : I found that assembly can solve ( How do I pass arguments to C++ functions when I call them from inline assembly ) - but I would prefer a more platform independent solution.
If your goal is to create your own, small and ad-hoc "rpc" solution, possibly one of the major drivers for making decisions should be: 1. Minimal amount of code 2. Easy as possible.
Keeping that in mind, it is paying off to ponder, what the difference is between the following 2 scenarios:
"Real" RPC: The handlers shall be as you wrote with rpc-method-specific signature.
"Message passing": The handlers receive messages of either "end point-determined type" or simply of a unified message type.
Now, what has to be done to get a solution of type 1?
Incoming byte streams/network packets need to get parsed to some sort of message with regards to some chosen protocol. Then, using some meta-info (contract), according to { serviceContract, serviceMethod }, a specific set of data items needs to be confirmed in the packet and if present, the respective, registered handler function needs to be called. Somewhere within that infrastructure you typically have a (likely code generated) function which does something like that:
void CallHandlerForRpcXYCallFoo( const RpcMessage*message )
{
uint32_t arg0 = message->getAsUint32(0);
// ...
float argN = message->getAsFloat(N);
Foo( arg0, arg1, ... argN );
}
All that can, of course also be packed into classes and virtual methods with the classes being generated from the service contract meta data. Maybe, there is also a way by means of some excessive template voodoo to avoid generating code and having a more generic meta-implementation. But, all that is work, real work. Way too much work to do it just for fun. Instead of doing that, it would be easier to use one of the dozens technologies which do that already.
Worth noting so far is: Somewhere within that piece of art, there is likely a (code generated) function which looks like the one given above.
Now, what has to be done to get a solution of type 2?
Less than for case 1. Why? Because you simply stop your implementation at calling those handler methods, which all take the RpcMessage as their single argument. As such, you can get away without generating the "make-it-look-like-a-function-call" layer above those methods.
Not only is it less work, it is also more robust in the presence of some scenarios where the contract changes. If one more data item is being added to the "rpc solution", the signature of the "rpc function" MUST change. Code re-generated, application code adapted. And that, whether or not the application needs that new data item. On the other hand, in approach 2, there are no breaking changes in the code. Of course, depending on your choices and the kind of changes in the contract, it still would break.
So, the most elegant solution is: Don't do RPC, do message passing. Preferably in a REST-ful way.
Also, if you prefer a "unified" rpc message over a number of rpc-contract specific message types, you remove another reason for code bloat.
Just in case, what I say seems a bit too abstract, here some mock-up dummy code, sketching solution 2:
#include <cstdio>
#include <cstdint>
#include <map>
#include <vector>
#include <deque>
#include <functional>
// "rpc" infrastructure (could be an API for a dll or a lib or so:
// Just one way to do it. Somehow, your various data types need
// to be handled/represented.
class RpcVariant
{
public:
enum class VariantType
{
RVT_EMPTY,
RVT_UINT,
RVT_SINT,
RVT_FLOAT32,
RVT_BYTES
};
private:
VariantType m_type;
uint64_t m_uintValue;
int64_t m_intValue;
float m_floatValue;
std::vector<uint8_t> m_bytesValue;
explicit RpcVariant(VariantType type)
: m_type(type)
{
}
public:
static RpcVariant MakeEmpty()
{
RpcVariant result(VariantType::RVT_EMPTY);
return result;
}
static RpcVariant MakeUint(uint64_t value)
{
RpcVariant result(VariantType::RVT_UINT);
result.m_uintValue = value;
return result;
}
// ... More make-functions
uint64_t AsUint() const
{
// TODO: check if correct type...
return m_uintValue;
}
// ... More AsXXX() functions
// ... Some ToWire()/FromWire() functions...
};
typedef std::map<uint32_t, RpcVariant> RpcMessage_t;
typedef std::function<void(const RpcMessage_t *)> RpcHandler_t;
void RpcInit();
void RpcUninit();
// application writes handlers and registers them with the infrastructure.
// rpc_context_id can be anything opportune - chose uint32_t, here.
// could as well be a string or a pair of values (service,method) or whatever.
void RpcRegisterHandler(uint32_t rpc_context_id, RpcHandler_t handler);
// Then according to taste/style preferences some receive function which uses the registered information and dispatches to the handlers...
void RpcReceive();
void RpcBeginReceive();
void RpcEndReceive();
// maybe some sending, too...
void RpcSend(uint32_t rpc_context_id, const RpcMessage_t * message);
int main(int argc, const char * argv[])
{
RpcInit();
RpcRegisterHandler(42, [](const RpcMessage_t *message) { puts("message type 42 received."); });
RpcRegisterHandler(43, [](const RpcMessage_t *message) { puts("message type 43 received."); });
while (true)
{
RpcReceive();
}
RpcUninit();
return 0;
}
And if RpcMessage then is traded, while packed in a std::shared_ptr, you can even have multiple handlers or do some forwarding (to other threads) of the same message instance. This is one particularly annoying thing, which needs yet another "serializing" in the rpc approach. Here, you simply forward the message.