# cimpl
`cimpl` is a crate that ensures that the signatures of the functions in C you're implementing matches what C expects.
## Why is this useful?
Lets say you have a library in C that requires you to write primitives for it to build up on,
```c
#pragma once
void foo(uint64_t* fill_me);
```
Now this can be implemented in Rust using your usual C-FFI `#[no_mangle]` way although it doesn't guarantee any signature changes that may happen in the libraries requirements tomorrow. This results in complete undefined behavior (example: if it changes to `void foo(uint32_t* fill_me)` tomorrow you could be overflowing buffers 🚨🚨🚨). To ensure against C library fragility at compiletime, `cimpl` guarantees signature safety as long as the header files for the implementation can be generated at compile-time.
## How to use?
### `build.rs` changes
At build time it's required to add the `cimpl` post-processing step to ensure type definitions can be added into your autogenerated file.
```rust
std::fs::write_all(cimpl::derive("<bindgen_output>")).unwrap();
```
#### Before
```rust
extern "C" {
pub fn foo() -> i32;
}
```
#### After
```rust
pub type __cimpl_foo = fn() -> i32;
extern "C" {
pub fn foo() -> i32;
}
```
### Implementation
```rust
#[cimpl::bind(bindgen::foo)]
#[no_mangle]
pub extern "C" fn foo() -> i32 {
42_i32
}
```
This generates the following:
```rust
mod bindgen {
const _: __cimpl_foo = foo; // Guarantees typeck verified signatures at compile-time
#[no_mangle]
pub extern "C" fn foo() -> i32 {
42_i32
}
}
```
## TODOs
- Create a nicer macro like `derive` to match with `bind`,
this allows extern "C" function implementations to not be done at compile
time, however this is likely a bug and requires design reconsiderations
- Tests! I'm not too familiar with `proc-macros` to know how to do this without