Genconfig
Automatic runtime configuration / settings system for your C/C++ application. Load from TOML configs into a generated C struct and back again with minimal effort.
Install / Use
/learn @mborgerson/GenconfigREADME
GenConfig
Aims to provide less-painful C/C++ app configuration support.

Motivation
Created because all of the config systems I have used (or created) in the past had too many pain points, like:
- Requiring things to be defined in multiple places
- Not using standard, human-friendly configuration formats
- Lacking validation of basic types and structure
- Not supporting hierarchical data structures, arrays, strings very well
- Requiring tedious structure maintenance
- Requiring accessor calls to get at simple data fields
- Not supporting configuration deltas
This system attempts to alleviate those pain points and make configuration suck less:
- Automatically generates structure definition code from an input specification, which is easy to write
- Loads application configuration from TOML format, which is standardized and human-friendly
- Validates user configuration matches expected structure and fields are of expected type
- Support hierarchical structures of basic types:
bool,int,float,enum, strings (UTF-8), and arrays - Minimizes development effort: just define the setting once in a spec file and the rest is handled
- Usable in C/C++, without having to do any lookups or extra validation: just read from a
struct - Supports saving configuration deltas
How it Works
- You define the options you want for your app in a spec file
- You run
gen_config.pyto generate a header file withstruct configdefinition - User runs your app, providing their settings in a
.tomlfile matching your specification- Your code calls a function to load, parse, and store the config file to the
configstructure - Your code accesses the config by just reading from and writing to the
configstruct - Your code changes
configstructure in response to some user action - Your code calls a function to save the config delta to the user's
.tomlconfig file
- Your code calls a function to load, parse, and store the config file to the
- You retain a bit more hair that you might have ripped out using/creating another configuration system
- Your app makes lots of money and you send some my way because you support open-source development. Thanks, that's nice of you.
Requirements
- toml++, which is used to parse config file
- Compiler that supports C++17
Example
This is the specification file that defines your config options:
company:
name: string
headquarters:
state: string
city: string
products:
type: array
items:
name:
type: string
default: New Product
price: float
inventory: int
international_shipping:
type: bool
default: true
suppliers:
type: array
items: string
category:
type: enum
values: ['fruit', 'vegetable', 'beverage', 'explosive']
After running gen_config.py, this C code is generated automatically.
enum CONFIG_COMPANY_PRODUCTS_CATEGORY {
CONFIG_COMPANY_PRODUCTS_CATEGORY_FRUIT,
CONFIG_COMPANY_PRODUCTS_CATEGORY_VEGETABLE,
CONFIG_COMPANY_PRODUCTS_CATEGORY_BEVERAGE,
CONFIG_COMPANY_PRODUCTS_CATEGORY_EXPLOSIVE,
CONFIG_COMPANY_PRODUCTS_CATEGORY__COUNT
};
struct config {
struct company {
const char *name;
struct headquarters {
const char *state;
const char *city;
} headquarters;
struct products {
const char *name;
float price;
int inventory;
bool international_shipping;
const char **suppliers;
unsigned int suppliers_count;
enum CONFIG_COMPANY_PRODUCTS_CATEGORY category;
} *products;
unsigned int products_count;
} company;
};
<details>
<summary>
Additionally, a corresponding `CNode` tree is created, that's used to support everything:
</summary>
CNode config_tree =
ctab("config", {
ctab("company", {
cstring(
offsetof(struct config, company.name),
"name", ""),
ctab("headquarters", {
cstring(
offsetof(struct config, company.headquarters.state),
"state", ""),
cstring(
offsetof(struct config, company.headquarters.city),
"city", "")
}),
carray(
offsetof(struct config, company.products),
offsetof(struct config, company.products_count),
sizeof(struct config::company::products),
"products",
ctab("", {
cstring(
offsetof(struct config::company::products, name),
"name", "New Product"),
cnumber(
offsetof(struct config::company::products, price),
"price", 0.0),
cinteger(
offsetof(struct config::company::products, inventory),
"inventory", 0),
cbool(
offsetof(struct config::company::products, international_shipping),
"international_shipping", true),
carray(
offsetof(struct config::company::products, suppliers),
offsetof(struct config::company::products, suppliers_count),
sizeof(((struct config::company::products *){0})->suppliers[0]),
"suppliers",
cstring(
0, "", "")
),
cenum(
offsetof(struct config::company::products, category),
"category", {"fruit", "vegetable", "beverage", "explosive"}, "fruit")
})
)
})
});
</details>
Config file to be loaded at runtime, in TOML format:
[company]
name = 'Acme Corp'
products = [
{ name = 'Apple', price = 1.2, inventory = 100, suppliers = ['Midwest Orchard', 'Tasty Apples Inc.'], category = 'fruit' },
{ name = 'TNT', price = 50, inventory = 1000, category = 'explosive', international_shipping = false },
]
[company.headquarters]
city = 'Phoenix'
state = 'Arizona'
Loading the config basically looks like:
#include <toml.hpp> // Required for basic parsing
#include <cnode.h> // Required data structure for config mgmt
#define DEFINE_CONFIG_TREE
#include "config.h"
// Load config from user file
struct config s;
auto toml_table = toml::parse_file("config.toml");
config_tree.update_from_table(toml_table);
config_tree.store_to_struct(&s);
Then when you are ready to save the config again:
// Update config tree from structure if you have modified it
config_tree.update_from_struct(&s);
// Save config
FILE *f = fopen("config.toml", "wb");
fprintf(f, "%s", config_tree.generate_delta_toml().c_str());
Related Skills
node-connect
352.2kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
111.1kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
352.2kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
352.2kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
