I have a several structs in C and I want to write the following three functions:
get_field_list(...)
get_value_by_name(...)
set_value_by_name(...)
The first should return the list of fields defined in the struct. The second and third should get and set to the appropriate field by it's name.
I'm writing the structs. I'm willing to use any macro magic if required. It's OK if ill have a triplet of functions per each struct, but generic structures are better. Function pointers are also fine...
Basically I want some elementary reflections for structs....
Relevent: https://natecraun.net/articles/struct-iteration-through-abuse-of-the-c-preprocessor.html
I'm trying to build a DAL (Data Access Layer) for a native app written in C. I'm using SQLite as a DB. I need to store various structures, and to be able to insert\ update\ get(select by key)\ search (select by query), and also to create\ drop the required table.
Basicly I want something like Hibernate for C ...
My best idea so far is to use MACROs, or some code generation utility, or a script, to create my structs together with meta-data I could use to dynamically build all my SQL commands. And also to have a small 'generic' module to implement all the basic procedures i need...
Different or better ideas to solve my actual problem will also be appreciated!
It can be done with "macro magic" as you suggested:
For each struct, create a header file (mystruct-fields.h
) like this:
FIELD(int, field1)
FIELD(int*, field2)
FIELD(char*, string1)
Then, in another header (mystruct.h
) you include that as many times as you need:
#define FIELD(T,N) T N;
struct mystruct {
#include "mystruct-fields.h"
};
#undef FIELD
#define FIELD(T,N) { STRINGIFY(T), STRINGIFY(N), offsetof(mystruct, N) },
#define STRINGIFY1(S) #S
#define STRINGIFY(S) STRINGIFY1(S)
struct mystruct_table {
struct {
const char *type, *name;
size_t offset;
} field[];
} table = {
#include "mystruct-fields.h"
{NULL, NULL, 0}
};
#undef FIELD
You can then implement your reflection functions, using the table, however you choose.
It might be possible, using another layer of header file includes, to reuse the above code for any struct without rewriting it, so your top-level code might only have to say something like:
#define STRUCT_NAME mystruct
#include "reflectable-struct.h"
#undef STRUCT_NAME
Honestly though, it's easier for the people who come after you if you just write the struct normally, and then write out the table by hand; it's much easier to read, your IDE will be able to auto-complete your types, and prominent warnings in the comments should help prevent people breaking it in future (and anyway, you do have tests for this right?)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With