https://github.com/gilzoide/functor2c
Single header templates for wrapping C++ functors as opaque userdata plus function pointers for C interop
https://github.com/gilzoide/functor2c
c-interop cpp cpp11 cpp17 function-pointer function-pointers functor single-file single-file-library single-header single-header-library
Last synced: 2 months ago
JSON representation
Single header templates for wrapping C++ functors as opaque userdata plus function pointers for C interop
- Host: GitHub
- URL: https://github.com/gilzoide/functor2c
- Owner: gilzoide
- License: unlicense
- Created: 2025-04-26T16:16:09.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2025-04-26T16:33:09.000Z (5 months ago)
- Last Synced: 2025-07-30T01:48:15.679Z (2 months ago)
- Topics: c-interop, cpp, cpp11, cpp17, function-pointer, function-pointers, functor, single-file, single-file-library, single-header, single-header-library
- Language: C++
- Homepage: https://gilzoide.github.io/functor2c/
- Size: 171 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
Awesome Lists containing this project
README
# functor2c
Single header templates for wrapping C++ functors as opaque userdata plus function pointers for C interop.## Features
- Easily wrap functors such as `std::function` or lambdas as function pointers to use in C APIs
- Supports functors with parameters and return values of any type
- Provides deleter functionality to avoid memory leaks, including overloads that return smart pointers
- Requires C++11 or newer
- Automatic arguments / return type deduction when used in C++17## Example usage
```cpp
#include "functor2c.hpp"// Let's use as an example Lua's allocator function `lua_Alloc`
// Note that it accepts an opaque userdata as the first parameter (prefix)
typedef void *(*lua_Alloc)(void *ud, void *ptr, size_t osize, size_t nsize);// 1. Define the functor for it
auto alloc_func = [](void *ptr, size_t osize, size_t nsize) {
ptr = /* implementation ... */;
return ptr;
};// 2. Now create the opaque userdata + function pointers for it
// 2.a) C++17 supports type deduction and structured bindings
auto [userdata, invoke_fptr, delete_fptr] = functor2c::prefix_invoker_deleter(alloc_func);
// 2.b) C++11 requires specifying functor type as
void *userdata;
lua_Alloc invoke_fptr;
void (*delete_fptr)(void*);
std::tie(userdata, invoke_fptr, delete_fptr) = functor2c::prefix_invoker_deleter(alloc_func);// 3. Pass the invoke function pointer + opaque userdata to C APIs
lua_setallocf(L, invoke_fptr, userdata);// 4. Delete userdata to avoid memory leaks.
// Note: optionally use `prefix_invoker_unique` to get userdata as a unique_ptr
// and `prefix_invoker_shared` to get userdata as a shared_ptr.
delete_fptr(userdata);
```In case the C API expects the opaque userdata as last argument instead of first, use `suffix_invoker_*` functions instead of `prefix_invoker_*`.
```cpp
// For example Box2D 3.1.0 custom filter callback.
// Note that it accepts an opaque userdata as the last parameter (suffix)
typedef bool b2CustomFilterFcn(b2ShapeId shapeIdA, b2ShapeId shapeIdB, void* context);auto filter_callback = [](b2ShapeId shapeIdA, b2ShapeId shapeIdB) {
/* implementation ... */
return true;
};
auto [userdata, invoke_fptr] = functor2c::suffix_invoker_unique(filter_callback);
b2World_SetCustomFilterCallback(world_id, invoke_fptr, userdata.get());
```## Integrating with CMake
You can integrate functor2c with CMake targets by adding a copy of this repository and linking with the `functor2c` target:
```cmake
add_subdirectory(path/to/functor2c)
target_link_libraries(my_awesome_target functor2c)
```