I am currently trying to use Google Protocol Buffers for C language.
I am a little unsure as to how to create a C union using GPB.
For example, with a proto file as follows:
message msgToSend
{
required Type msg_type=1; //Type is a predefined enum to determine message type
optional ReqMsg1 msg1=2;
optional ReqMsg2 msg2=3;
}
I expect above to generate a union upon compilation but a structure is generated as follows:
struct _msgToSend
{
ProtobufCMessage base;
Type msg_type;
ReqMsg1 msg1;
ReqMsg2 msg2;
}
In protobuf there is a dedicated structure for that (I'm using it in C++ though, not sure if it will work in pure C):
message MyUnion {
oneof MyUnionOneof {
bool booleanValue = 1;
string stringValue = 2;
}
}
Check out this link: https://developers.google.com/protocol-buffers/docs/proto#oneof
I don't think you can.
In Protobuf "optional" doesn't mean "it's either this or this other" like with C unions; it means "this might be here". That's why you're getting a C structure that can express both optional fields being present.
At work this alone was enough to make me implement a Protobuf replacement system, since we really wanted unions.
Related
I'm using Flow on a React webapp and I'm currently facing a use-case where I'm asking for the user to input certain time values in a "HH:mm" format. Is there any way to describe what pattern is being followed by the strings?
I've been looking around for a solution but the general consensus which I agree to to a certain point seems to be that you don't need to handle this kind of thing using Flow, favouring using validating functions and relying on the UI code to supply the code following the correct pattern. Still, I was wondering if there is any way to achieve this in order to make the code as descriptive as possible.
You want to create a validator function, but enhanced using Opaque Type Aliases: https://flow.org/en/docs/types/opaque-types/
Or, more specifically, Opaque Type Aliases with Subtyping Constraints: https://flow.org/en/docs/types/opaque-types/#toc-subtyping-constraints
You should write a validator function in the same file where you define the opaque type. It will accept the primitive type as an argument and return a value typed as the opaque type with subtyping constraint.
Now, in a different file, you can type some variables as the opaque type, for example in function arguments. Flow will enforce that you only pass values that go through your validator function, but these could be used just as if they were the primitive type.
Example:
exports.js:
export opaque type ID: string = string;
function validateID(x: string): ID | void {
if ( /* some validity check passes */ ) {
return x;
}
return undefined;
}
import.js:
import type {ID} from './exports';
function formatID(x: ID): string {
return "ID: " + x; // Ok! IDs are strings.
}
function toID(x: string): ID {
return x; // Error: strings are not IDs.
}
I have a process which exposes a method to DBus with one of the arguments taking the following type signature a{sv}:
Dict of {String, Variant}
The libDBus documentation for dbus_message_append_args fails to provide adequate reference for this. Some information appears in the specification under container-types, specifically:
A DICT_ENTRY works exactly like a struct, but rather than parentheses
it uses curly braces, and it has more restrictions. The restrictions
are: it occurs only as an array element type; it has exactly two
single complete types inside the curly braces; the first single
complete type (the "key") must be a basic type rather than a container
type. Implementations must not accept dict entries outside of arrays,
must not accept dict entries with zero, one, or more than two fields,
and must not accept dict entries with non-basic-typed keys. A dict
entry is always a key-value pair.
On attempting to append a dict I receive the following error message:
type dict_entry isn't supported yet in dbus_message_append_args_valist
Although I'm actually using dbus_message_append_args(I guess the error message is somewhat off).
There are two other alternatives to dbus_message_append_args() using either:
dbus_message_iter_append_basic()
and
dbus_message_iter_append_fixed_array()
While I can create an empty Dict container with the following:
const char * container_d_sig = "{sv}";
DBusMessageIter iter, sub;
dbus_message_iter_init_append(msg, &iter);
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, container_d_sig, &sub);
dbus_message_iter_close_container(&iter, &sub);
Neither of the append methods appear to support adding a struct. Not sure what to try here...
First, about D-Bus libraries: you talk about dbus-glib in several places but the functions you refer to are not part of dbus-glib but libdbus. If you are still trying to find the best way to use D-Bus, I suggest you forget both of these: libdbus is very low-level (it's documentation even starts with "If you use this low-level API directly, you're signing up for some pain") and dbus-glib is deprecated. The best D-Bus API currently is GDBus which is part of GLib GIO: it's a far better designed API than either of the other two, well tested and supported.
Now, as for the actual question, documentation for dbus_message_append_args() does say it quite clearly:
To append variable-length basic types, or any more complex value, you
have to use an iterator rather than this function.
In other words you should use dbus_message_iter_open_container() to prepare the iterator until it is pointing to somewhere where you can use dbus_message_iter_append_basic(). Note that in your example the dictionary is a container, the dictionary entry is a container and the variant is a container... In other words it gets pretty complex quite fast. If you really want to do it, look at e.g. Connman code for examples.
As I mentioned, the sane route is GDBus. There creating even much more complex signatures is pretty easy as you can use the GVariantBuilder API:
GVariantBuilder builder;
g_variant_builder_init (&builder, G_VARIANT_TYPE("a{sv}"));
g_variant_builder_add (&builder, "{sv}", "name1", my_variant);
/* Now use the builder results with g_dbus_connection_call()
or g_dbus_proxy_call() */
I know this question was asked awhile ago, but I had a very similar question recently, and after several hours of trial and error this is some code I came up with that works for me. Hopefully it helps someone else...
DBusMessage* testMessage()
{
DBusMessage* mssg = dbus_message_new_signal("/fi/w1/wpa_supplicant1/Interfaces/0", "fi.w1.wpa_supplicant1.Interface", "PropertiesChanged");
DBusMessageIter iter, aIter;
dbus_message_iter_init_append(mssg, &iter);
if (!dbus_message_iter_open_container(&iter, 'a', "{sv}", &aIter))
return nullptr;
DBusMessageIter eIter;
if (!dbus_message_iter_open_container(&aIter, 'e', NULL, &eIter)) {
dbus_message_iter_abandon_container_if_open(&iter, &aIter);
return nullptr;
}
const char* key = "test key";
dbus_message_iter_append_basic(&eIter, 's', static_cast<void*>(&key));
DBusMessageIter vIter;
if (!dbus_message_iter_open_container(&eIter, 'v', "i", &vIter)) {
dbus_message_iter_abandon_container_if_open(&aIter, &eIter);
dbus_message_iter_abandon_container_if_open(&iter, &aIter);
return nullptr;
}
dbus_int32_t val = 42;
dbus_message_iter_append_basic(&vIter, 'i', static_cast<void*>(&val));
dbus_message_iter_close_container(&eIter, &vIter);
dbus_message_iter_close_container(&aIter, &eIter);
dbus_message_iter_close_container(&iter, &aIter);
return mssg;
}
This is C++ but should be pretty easy to adapt for C. The returned message has a signature of a{sv}. The dbus docs are helpful-ish.
The Eclipse <CTRL>+<SPACE> code completion assist feature doesn't work with enums the way I want to. Can anyone tell me how to configure it so that I get the follow:
In my C (not C++) project I'm using typedef enums and would like that Eclipse provides a list of all enum entries on <CTRL>+<SPACE> (or maybe another key combination) if I'm typing an assignment of a variable of this enum type.
Example:
typedef enum {
CONSTANT_A = 0,
CONSTANT_B = 1,
CONSTANT_C = 2,
} myenumtype_t;
void func(void)
{
myenumtype_t myenumvar;
myenumvar = <CTRL>+<SHIFT>
}
It should list CONSTANT_A, CONSTANT_B, CONSTANT_C and allow me to choose one.
If it's list other enum variables of the exact same enum type then this is also ok, but I don't like any other variable in the suggestion list.
However, at the moment my Eclipse is listing basically all global and local variables indendent of their type, which isn't very useful.
PS: My Eclipse variant is Arctic Studio 5.0.0 which is basically Eclipse CDT 8.3.0.
This is not exactly what you asked for, but definitely serves the purpose.
You can type a clue, may be "CON" in your specific case, and then press ctrl + space
enum protocol {
ascii_prot = 3, /* arbitrary value. */
binary_prot,
negotiating_prot = 4 /* Discovering the protocol */
};
Both binary_prot and negotiating_prot equals to 4?
Yes.
Yes; C is not particular about enum values. Why you might do that is another question, unless there's some reason to treat the discovery packet the same as data packets. (Which there might well be when someone else designed the protocol and you want to stick as closely as possible to their documentation.)
Is there any benefit in having never-defined structures in C ?
Example in SQLite source code :
/* struct sqlite3_stmt is never defined */
typedef struct sqlite3_stmt sqlite3_stmt;
And the object is manipulated like so :
typedef struct Vdbe Vdbe;
struct Vdbe {
/* lots of members */
};
int sqlite3_step(sqlite3_stmt *pStmt) {
Vdbe *v = (Vdbe*) pStmt;
/* do stuff with v... */
}
So why not just use a usual abstract type, with the actual structure privately defined in foo.c source and a public typedef in foo.h header ?
It is defined like this to hide the implementation detail of sqlite3_stmt from the user, thus avoiding the internal states from being messed around. See Opaque pointer.
(This also forces the user only to use the type as a pointer since the structure sqlite3_stmt itself has incomplete implementation.)
Edit: VDBE (virtual database engine) is just "a" back-end of the SQLite3 API. I believe the back-end is changeable, thus a sqlite3_stmt* is not necessarily a Vdbe*. Not exposing Vdbe* in the API because the back-end detail should not be exposed.
To clarify: What you're asking is why SQLite does the above instead of doing this:
Header file:
typedef struct sqlite3_stmt sqlite3_stmt;
C file:
struct sqlite3_stmt {
/* lots of members */
};
int sqlite3_step(sqlite3_stmt *pStmt) {
/* do stuff with pStmt... */
}
(This is the canonical form of the "opaque pointer" pattern linked to in KennyTM's answer.)
The only good reason I can think of why SQLite does what it does is the following:
The backend code, I'm speculating, came before the API and used the name Vdbe -- the name probably means something related to the implementation along the lines of "virtual database entry" (guessing wildly here).
When time came to create the API, someone realized that the parameter required by sqlite3_step was a Vdbe but that this was not exactly a name that would convey a lot to the user of the API. Hence, from the user's point of view, a Vdbe is referred to as an sqlite3_stmt.
The point here, then, is to differentiate between two views of the same item: The backend thinks in terms of Vdbes (whatever they are) because that's a name that makes sense in the context of the implementation. The API talks about sqlite3_stmts because that's a name that makes sense in the context of the interface.
Edit: As Amarghosh points out, why not just do this to achieve the same effect?
typedef struct Vdbe sqlite3_stmt;
KennyTM points out a good possible reason (please vote him up, I don't want to siphon off his rep here): VDBE is only one of several possible backends; the interface uses a "generic" sqlite3_stmt, and this is then cast to whatever the backend uses to implement it.