, , API- API.
struct c_api {
void(*f)(void*);
void* ptr;
};
template<class F>
c_api c_api_wrap( F* f ) {
return {
[](void* pv) { (*static_cast<F*>(pv))(); },
f
};
}
std::function ( lambda, ), void .
void std::function ( ).
:
template<class Sig>
struct c_api;
template<class R, class...Args>
struct c_api<R(Args...)> {
using fptr = R(*)(void*, Args...);
fptr f = nullptr;
void* ptr = nullptr;
template<class F>
explicit c_api( F* pf ):
f([](void* vptr, Args...args)->R {
return (*static_cast<F*>(vptr))(std::forward<Args>(args)...);
}),
ptr(pf)
{}
};
template<class...Args>
struct c_api<void(Args...)> {
using fptr = void(*)(void*, Args...);
fptr f = nullptr;
void* ptr = nullptr;
template<class F>
explicit c_api( F* pf ):
f([](void* vptr, Args...args) {
(*static_cast<F*>(vptr))(std::forward<Args>(args)...);
}),
ptr(pf)
{}
};
template<class Sig, class F>
c_api<Sig> c_wrap( F* f ) {
return c_api<Sig>(f);
}
, c_wrap<void()>(&some_std_function). .ptr .f, API C.
.
You can pass additional arguments or process return values by changing the signature void(); however, it assumes that the void*"self" component is the first argument. The fancier version can support void*anywhere, but it becomes verbose.
If you are interested in how this works, stateless lambda can be converted to a functoin pointer, which we use in the constructor c_apiabove.
source
share