A library that adds reflection capabilities to C structs through code generation.
- Zero runtime overhead with metadata generated at compile time
- Struct field introspection and manipulation
- Support for nested structs, unions, and enums
- Pointer handling with automatic dereferencing
- Field type validation and safety
- Support for field decorators (qualifiers, pointers, arrays)
- Compatible with C89/ANSI C
- No external dependencies
- Easily integrate with JSON serialization/deserialization
Clone the repository:
git clone https://github.com/lcsmuller/reflect-c.git
cd reflect-c
The library is header-only, so you can simply include it in your project.
- Define your structures with reflection capabilities using the
PUBLIC
orPRIVATE
macros:
// my_types.PRE.h
#ifdef REFLECTC_DEFINITIONS
/*#!
#include <stdbool.h>
*/
#endif
PUBLIC(struct, person, 4, (
(_, _, char, *, name, _),
(_, _, int, _, age, _),
(_, _, bool, _, active, _),
(_, _, char, *, email, _)
))
- Generate the reflection code:
# Using your preferred method to run the code generator
./reflect-c-gen my_types.PRE.h
- Include the generated headers in your code:
#include "reflect-c.h"
#include "reflect-c_GENERATED.h"
int main() {
struct person p = {"John Doe", 30, true, "[email protected]"};
// Create a reflection wrapper for the person struct
struct reflectc *r_person = reflectc_from_person(&p, NULL);
// Access fields statically (fast access)
char *name_field = (char *)reflectc_get_fast(person, name, r_person);
printf("Name: %s\n", name_field);
// Access fields dynamically (using string names)
char *email_field = (char *)reflectc_get(r_person, "email", strlen("email"));
printf("Email: %s\n", name_field);
// Clean up
reflectc_free(r_person);
return 0;
}
The library can be easily used for JSON serialization, as demonstrated in the test code:
#include <stdio.h>
#include <stdbool.h>
#include "json-build/json-build.h"
#include "reflect-c.h"
#include "reflect-c_GENERATED.h"
void json_stringify(struct jsonb *jb, const struct reflectc *field,
char buf[], const size_t bufsize)
{
if (field->decorator.len && field->ptr_value == NULL) {
jsonb_null(jb, buf, bufsize);
return;
}
switch (field->type) {
case REFLECTC_TYPES__char:
jsonb_string(jb, buf, bufsize, field->ptr_value, strlen(field->ptr_value));
break;
case REFLECTC_TYPES__int:
jsonb_number(jb, buf, bufsize, *(int *)field->ptr_value);
break;
case REFLECTC_TYPES__bool:
jsonb_bool(jb, buf, bufsize, *(bool *)field->ptr_value);
break;
case REFLECTC_TYPES__float:
jsonb_number(jb, buf, bufsize, *(float *)field->ptr_value);
break;
case REFLECTC_TYPES__struct: {
jsonb_object(jb, buf, bufsize);
for (size_t i = 0; i < field->fields.len; ++i) {
const struct reflectc *f = &field->fields.array[i];
jsonb_key(jb, buf, bufsize, f->name.buf, f->name.len);
json_stringify(jb, f, buf, bufsize);
}
jsonb_object_pop(jb, buf, bufsize);
} break;
default:
break;
}
}
int main() {
// Create a sample struct
struct bar a = { true, 42, "hello world" }, *aa = &a, **aaa = &aa;
struct baz baz = { &a, &a, &aaa, "hello world" };
// Create a reflection wrapper
struct reflectc *wrapped_baz = reflectc_from_baz(&baz, NULL);
// Serialize to JSON
char json[1024] = {0};
struct jsonb jb;
jsonb_init(&jb);
json_stringify(&jb, wrapped_baz, json, sizeof(json));
printf("JSON: %s\n", json);
// Output: {"a":{"boolean":true,"number":42,"string":"hello world"},...}
// Clean up
reflectc_free(wrapped_baz);
return 0;
}
PUBLIC(container_type, name, field_count, fields_tuple)
: Defines a public struct/enum/union with reflectionPRIVATE(container_type, name, field_count, fields_tuple)
: Defines a private struct/enum/union with reflection
Fields are defined as tuples with the following format:
- For struct/union fields:
(qualifier, container, type, decorator, name, dimensions)
- For enum fields:
(enumerator, assignment_op, value)
For each reflected type foo
, these functions are generated:
reflectc_from_foo(foo *self, struct reflectc *root)
: Creates reflection data for a foo instance
struct reflectc
: Holds reflection metadata for a struct fieldsize_t size
: Size of the type in bytesstruct { const char *buf; size_t len } qualifier
: Field qualifierstruct { const char *buf; size_t len } decorator
: Field decorator (* for pointers)struct { const char *buf; size_t len } name
: Field namestruct { const char *buf; size_t len } dimensions
: Field dimensions (for arrays)enum reflectc_types type
: Field typevoid *ptr_value
: Pointer to the actual valuestruct { struct reflectc *array; size_t len } fields
: Nested fields (for structs/unions)reflectc_from_cb from_cb
: Callback for generating child reflectc objects
This project is licensed under the MIT License - see the LICENSE file for details.