C语言通用字典模块,支持任意数据类型的键值对存取。
- 多类型支持:STRING、NUMBER(int/uint)、BINARY 三种键类型
- 自动内存管理:用户无需关心键值生命周期
- 高效哈希算法:采用 MurmurHash3(效率高,分布均匀,抗碰撞能力强),对 NUMBER 类型整数键进一步优化,效率更高
- 跨平台支持:专为 RT-Thread 设计,代码也可运行于 PC 端
- 嵌入式友好:代码量小(~600行)、内存占用可控
- 迭代器支持:安全遍历所有键值对
| 函数 |
说明 |
dict_create(config) |
创建字典 |
dict_clear(handle) |
清空所有键值对 |
dict_size(handle) |
获取元素数量 |
dict_capacity(handle) |
获取当前容量 |
dict_destroy(handle) |
销毁字典,释放所有内存 |
| 函数 |
说明 |
dict_set(handle, key, value, len) |
设置键值对(插入或更新) |
dict_get(handle, key, buf, len) |
获取值,buf 为 NULL 时只检查键是否存在 |
dict_get_size(handle, key, size_out) |
获取值的数据大小 |
dict_delete(handle, key) |
删除键值对 |
dict_exists(handle, key) |
检查键是否存在 |
| 函数 |
说明 |
dict_shrink(handle) |
收缩容量至最小 2^n,释放多余内存 |
| 函数 |
说明 |
dict_iter_create(handle) |
创建迭代器 |
dict_iter_get(iter, ...) |
获取当前元素(键、值、长度) |
dict_iter_next(iter) |
移动到下一个元素 |
dict_iter_destroy(iter) |
销毁迭代器 |
#include "dict.h"
dict_config_t config = {
.capacity = 64,
.key_type = DICT_KEY_STRING
};
dict_handle_t dict = dict_create(&config);
// 存储字符串值
const char *json_data = "{\"temp\":25.5}";
dict_set(dict, "sensor_1", json_data, strlen(json_data) + 1);
// 存储整数
int temp = 25;
dict_set(dict, "temperature", &temp, sizeof(temp));
char buf[256];
dict_get(dict, "sensor_1", buf, sizeof(buf));
int temp_out;
dict_get(dict, "temperature", &temp_out, sizeof(temp_out));
dict_iter_t iter = dict_iter_create(dict);
char key[64];
char value[256];
size_t klen, vlen;
while (dict_iter_is_valid(iter)) {
dict_iter_get(iter, key, &klen, value, &vlen);
printf("%s = %s\n", key, value);
dict_iter_next(iter);
}
dict_iter_destroy(iter);
# 进入应用目录
cd applications
# 清理并编译(默认启用 ASAN 内存泄漏检测)
scons -c && scons
# 运行所有测试
./build/bin/dict_test
# 运行基准测试
./build/bin/dict_benchmark
# 运行示例程序
./build/bin/fibonacci
├── SConscript # RT-Thread 软件包构建配置
├── inc/
│ └── dict.h # 公共API + 平台抽象
├── src/
│ ├── dict_core.c # 核心实现
│ ├── dict_core.h # 内部数据结构
│ ├── dict_hash.c # 哈希算法
│ └── dict_hash.h # 哈希算法内部头文件
├── applications/ # PC 端测试与示例(独立构建)
│ ├── SConstruct # 构建入口
│ ├── test/ # 单元测试
│ └── examples/ # 使用示例
└── README.md
dict 软件包位于 RT-Thread 软件包仓库的 tools 分类下。
# 使用 env 工具进入 menuconfig
menuconfig
导航到:
RT-Thread online packages → tools packages → dict: A general-purpose dictionary module
#include "dict.h"
static dict_handle_t fib_get_cache(void)
{
static dict_handle_t fib_cache = NULL;
if (NULL == fib_cache) {
dict_config_t config = {
.capacity = 128,
.key_type = DICT_KEY_NUMBER,
.key_size = sizeof(int)
};
fib_cache = dict_create(&config);
}
return fib_cache;
}
uint64_t fib_memoized(int n)
{
if (n <= 1) {
return n;
}
uint64_t value = 0;
dict_handle_t cache = fib_get_cache();
if (DICT_OK == dict_get(cache, &n, &value, sizeof(value))) {
return value;
}
value = fib_memoized(n - 1) + fib_memoized(n - 2);
dict_set(cache, key, &value, sizeof(value));
return value;
}
int main(void)
{
int test_cases[] = {20, 25, 30, 40, 50, 60, 90};
size_t test_count = sizeof(test_cases) / sizeof(test_cases[0]);
for (size_t i = 0; i < test_count; i++) {
uint64_t value = fib_memoized(test_cases[i]);
printf("Fib(%d) = %llu\n", test_cases[i], value);
}
}
- 键值对存储时,键值内存由字典模块管理,用户无需管理
- 数据键(key)使用整数类型时,哈希算法做了针对性优化,存取效率更高
- 一个字典实例存储的键值对,数据键(key)类型须保持一致,否则会导致未定义行为
- 迭代器基于快照策略,创建时深拷贝数据,遍历过程中字典的增删改不影响已创建的迭代器
- 考虑到嵌入式系统复杂性不会特别高,因此键和值的长度设置了上限(最大 65535 字节)
- 模块仅支持手动缩容,建议在合适的时机(如数据处理阶段结束)调用
dict_shrink()进行容量缩减
- 模块本身不是线程安全的。如果在多线程环境中使用,需要外部同步机制