A MISRA C compliant wrapper for LMDB (Lightning Memory-Mapped Database).
This library provides a safe, validated API layer over LMDB that enforces MISRA C coding standards. It serves as a base component for systems that require reliable key-value storage with strict error handling — such as blockchain-like block management architectures.
- Full MISRA C parameter validation on every function call
- Specific error codes for null parameters, invalid parameters, and LMDB errors
- All return values validated (no unchecked calls)
- Read API copies values into caller-owned buffers
- Simple API: create environment, put/get/delete records, close
- Automatic LMDB download via CMake (no manual dependency setup)
| Function | Description |
|---|---|
lmdbWrapperEnvCreate() |
Create and open a database environment |
lmdbWrapperEnvClose() |
Close and destroy an environment |
lmdbWrapperPut() |
Store a key-value record |
lmdbWrapperGet() |
Copy a value by key into a caller buffer |
lmdbWrapperDel() |
Delete a record by key |
lmdbWrapperStrerror() |
Convert error code to string |
LMDB is an ultra-fast embedded key-value database with memory-mapped I/O. This MISRA C wrapper adds the safety layer required for critical environments:
- Blockchain & cryptocurrency — Monero uses LMDB for its entire blockchain storage. The zero-copy reads and lock-free concurrent readers make it ideal for distributed ledger systems.
- Safety-critical embedded systems — Automotive (AUTOSAR), medical devices (IEC 62304), and industrial controllers (IEC 61508) that need persistent key-value storage with MISRA C guarantees.
- IoT & firmware — Persistent configuration, structured logs, and state management on resource-constrained devices. LMDB's minimal footprint (~30KB) is well-suited for embedded targets.
- Infrastructure & servers — OpenLDAP (LMDB's origin), Postfix mail maps, and session/cache storage in server applications.
- AI/ML pipelines — Caffe and Caffe2 use LMDB to store image datasets for deep learning training, leveraging zero-copy reads for high throughput.
- Desktop & mobile apps — Local key-value cache as a lightweight alternative to SQLite when relational queries are not needed.
This library is available as an official vcpkg port:
vcpkg install ddtdanilo-lmdb-wrapperThen in your CMakeLists.txt:
find_package(lmdb_wrapper CONFIG REQUIRED)
target_link_libraries(your_target PRIVATE lmdb_wrapper::lmdb_wrapper)- C compiler (GCC or Clang)
- CMake >= 3.14
- Git (for LMDB download)
cmake -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build buildcd build && ctest --output-on-failureOr run the test executable directly for verbose output:
./build/test_lmdb_wrapper#include "lmdb_wrapper.h"
#include <sys/stat.h>
#include <string.h>
int main(void) {
lmdbWrapperEnv_t *env = NULL;
lmdbWrapperConfig_t config = {
.path = "./my_database",
.mapSize = 0, /* wrapper default 10MB */
.maxDbs = 0 /* default 1 */
};
char readVal[64] = {0};
size_t readSize = 0;
(void)mkdir("./my_database", 0755);
lmdbWrapperErr_t err = lmdbWrapperEnvCreate(&env, &config);
if (err != LMDB_WRAPPER_SUCCESS) {
return 1;
}
/* Write */
const char *key = "block_001";
const char *val = "data...";
err = lmdbWrapperPut(env, key, strlen(key), val, strlen(val));
/* Read */
err = lmdbWrapperGet(env, key, strlen(key),
readVal, sizeof(readVal), &readSize);
/* Delete */
err = lmdbWrapperDel(env, key, strlen(key));
lmdbWrapperEnvClose(env);
return 0;
}├── CLAUDE.md # AI/development rules
├── CMakeLists.txt # Build configuration
├── README.md # This file
├── LICENSE # MIT License
├── CONTRIBUTING.md # Contribution guidelines
├── cmake/ # CMake modules
│ └── FetchLMDB.cmake
├── docs/ # Documentation
│ ├── architecture.md
│ └── context.md
├── examples/ # Example programs
│ └── basic_usage.c
├── include/ # Public headers
│ └── lmdb_wrapper.h
├── src/ # Implementation
│ └── lmdb_wrapper.c
├── tests/ # Tests
│ └── test_lmdb_wrapper.c
├── vcpkg-port/ # vcpkg port files (reference copy)
│ ├── portfile.cmake
│ └── vcpkg.json
└── todo/ # Task tracking
└── plan.md
| Code | Meaning |
|---|---|
LMDB_WRAPPER_SUCCESS |
Operation succeeded |
LMDB_WRAPPER_ERR_NULL_PARAM |
A required parameter was NULL |
LMDB_WRAPPER_ERR_INVALID_PARAM |
A parameter had an invalid value |
LMDB_WRAPPER_ERR_NOT_FOUND |
Record not found |
LMDB_WRAPPER_ERR_ENV_CREATE |
Failed to create LMDB environment |
LMDB_WRAPPER_ERR_ENV_OPEN |
Failed to open LMDB environment |
LMDB_WRAPPER_ERR_TXN_BEGIN |
Failed to begin transaction |
LMDB_WRAPPER_ERR_DBI_OPEN |
Failed to open database handle |
LMDB_WRAPPER_ERR_PUT |
Failed to write record |
LMDB_WRAPPER_ERR_GET |
Failed to read record |
LMDB_WRAPPER_ERR_DEL |
Failed to delete record |
LMDB_WRAPPER_ERR_TXN_COMMIT |
Failed to commit transaction |
LMDB_WRAPPER_ERR_MAP_FULL |
Database map is full |
LMDB_WRAPPER_ERR_BUFFER_TOO_SMALL |
Output buffer is too small |
Contributions are welcome! Please see CONTRIBUTING.md for guidelines on how to build, test, and submit changes.
This project is licensed under the MIT License.