What is CMagic?
CMagic is a portable no-exception C library with C++ bindings. It contains utilities and containers which are not included in C Standard Library. CMagic is purely written in C11 (with possible fallback to C99) and C++11. It doesn't depend on any other library and doesn't require custom compiler extensions. Works both on PC and embedded systems.
Click here for the full documentation.
Features
- Custom memory allocation (cmagic/memory.h)
- Utilities (cmagic/utils.h)
- Provides macros for common C expressions like
CMAGIC_UTILS_ARRAY_SIZE
for checking size of an array
- Containers
- Vector (cmagic/vector.h and cmagic/vector.hpp)
- Map (cmagic/map.h and cmagic/map.hpp)
- Set (cmagic/set.h and cmagic/set.hpp)
- The containers behave similarly as their equivalents known from C++ STL.
- Allow to specify allocators: standard
malloc()
/free()
or custom CMagic allocation.
- Can hold any primitive or custom type elements. Special macros provide basic type checking when using C API.
- Never throw exceptions. Allocation failures are indicated by return values of functions.
Dependencies
To use CMagic you will need:
- C compiler supporting at least C99 standard
- C++ compiler supporting at least C++11 standard
- CMake 3.16
- Optionally Doxygen if you want do build the documentation locally
- Local unit tests use Unity Test framework. It's already included here as a Git submodule, so you only need to ensure the submodule is updated.
Quickstart
Prepare a directory for your project:
> mkdir cmagic_helloworld
> cd cmagic_helloworld
> git clone --recurse-submodules https://github.com/mateusz-olczyk/CMagic.git cmagic
Prepare sources hello.c and hello.cpp and put them in cmagic_helloworld directory:
#include <stdio.h>
int main(void) {
static uint8_t memory_pool[1000];
for (int i = 1; i <= 10; i++) {
fputs("Insufficient memory!\n", stderr);
return -1;
}
}
for (int i = 0; i < 10; i++) {
}
puts("");
return 0;
}
{c++}
// hello.cpp
#include <iostream>
#include "cmagic/memory.h"
#include "cmagic/vector.hpp"
int main() {
static uint8_t memory_pool[1000];
cmagic_memory_init(memory_pool, sizeof(memory_pool));
cmagic::vector<int> vector {cmagic::vector<int>::custom_allocation_vector()};
for (int i = 1; i <= 10; i++) {
if (!vector.push_back(i)) {
std::cerr << "Insufficient memory!\n";
return -1;
}
}
std::cout << "Vector size is " << vector.size() << "\nElements:";
for (int e : vector) {
std::cout << " " << e;
}
std::cout << "\n";
}
Eventually prepare a CMakeLists.txt file and compile the sources:
cmake_minimum_required(VERSION 3.16)
project(cmagic_helloworld)
add_subdirectory(cmagic)
add_executable(hello_c hello.c)
add_executable(hello_cpp hello.cpp)
target_link_libraries(hello_c PRIVATE cmagic)
target_link_libraries(hello_cpp PRIVATE cmagic)
cmake -S . -B build
cmake --build build
Both programs should generate the same output:
Vector size is 10
Elements: 1 2 3 4 5 6 7 8 9 10