functor2c
Single header templates for wrapping C++ functors as opaque userdata plus function pointers for C interop
 
Loading...
Searching...
No Matches
functor2c.hpp
Go to the documentation of this file.
1
4#ifndef __FUNCTOR2C_HPP__
5#define __FUNCTOR2C_HPP__
6
7#include <functional>
8#include <utility>
9
10namespace functor2c {
11
12namespace detail {
13
18template<bool destroy_on_invoke, typename RetType, typename... Args>
19struct destroyable_function {
24 struct deleter {
25 void operator()(void *userdata) const {
26 destroy(userdata);
27 }
28 };
29
30 template<typename Fn>
31 destroyable_function(Fn&& fn) : function(std::move(fn)) {}
32
33 RetType operator()(Args... args) {
34 std::unique_ptr<destroyable_function> destroyer;
35 if (destroy_on_invoke) {
36 destroyer = std::unique_ptr<destroyable_function>(this);
37 }
38 return function(std::forward<Args>(args)...);
39 }
40
41 std::tuple<void*, RetType (*)(void*, Args...)> prefix_invoker() {
42 return std::make_tuple(static_cast<void*>(this), invoke_prefix);
43 }
44 std::tuple<void*, RetType (*)(void*, Args...), void (*)(void*)> prefix_invoker_deleter() {
45 return std::make_tuple(static_cast<void*>(this), invoke_prefix, destroy);
46 }
47 std::tuple<std::unique_ptr<void, deleter>, RetType (*)(void*, Args...)> prefix_invoker_unique() {
48 return std::make_tuple(std::unique_ptr<void, deleter>(static_cast<void*>(this)), invoke_prefix);
49 }
50 std::tuple<std::shared_ptr<void>, RetType (*)(void*, Args...)> prefix_invoker_shared() {
51 return std::make_tuple(std::shared_ptr<void>(static_cast<void*>(this), destroy), invoke_prefix);
52 }
53
54 std::tuple<RetType (*)(Args..., void*), void*> suffix_invoker() {
55 return std::make_tuple(invoke_suffix, static_cast<void*>(this));
56 }
57 std::tuple<RetType (*)(Args..., void*), void*, void (*)(void*)> suffix_invoker_deleter() {
58 return std::make_tuple(invoke_suffix, static_cast<void*>(this), destroy);
59 }
60 std::tuple<RetType (*)(Args..., void*), std::unique_ptr<void, deleter>> suffix_invoker_unique() {
61 return std::make_tuple(invoke_suffix, std::unique_ptr<void, deleter>(static_cast<void*>(this)));
62 }
63 std::tuple<RetType (*)(Args..., void*), std::shared_ptr<void>> suffix_invoker_shared() {
64 return std::make_tuple(invoke_suffix, std::shared_ptr<void>(static_cast<void*>(this), destroy));
65 }
66
67 static RetType invoke_prefix(void *userdata, Args... args) {
68 auto self = static_cast<destroyable_function*>(userdata);
69 return (*self)(std::forward<Args>(args)...);
70 }
71
72 static RetType invoke_suffix(Args... args, void *userdata) {
73 auto self = static_cast<destroyable_function*>(userdata);
74 return (*self)(std::forward<Args>(args)...);
75 }
76
77 static void destroy(void *userdata) {
78 auto self = static_cast<destroyable_function*>(userdata);
79 delete self;
80 }
81
82private:
83 std::function<RetType(Args...)> function;
84};
85
86}
87
107template<typename RetType, typename... Args, typename Fn>
108std::tuple<void*, RetType (*)(void*, Args...), void (*)(void*)> prefix_invoker_deleter(Fn&& fn) {
109 return (new detail::destroyable_function<false, RetType, Args...>(std::move(fn)))->prefix_invoker_deleter();
110}
111
129template<typename RetType, typename... Args, typename Fn>
130std::tuple<void*, RetType (*)(void*, Args...)> prefix_invoker_oneshot(Fn&& fn) {
131 return (new detail::destroyable_function<true, RetType, Args...>(std::move(fn)))->prefix_invoker();
132}
133
152template<typename RetType, typename... Args, typename Fn>
153std::tuple<std::unique_ptr<void, typename detail::destroyable_function<false, RetType, Args...>::deleter>, RetType (*)(void*, Args...)> prefix_invoker_unique(Fn&& fn) {
154 return (new detail::destroyable_function<false, RetType, Args...>(std::move(fn)))->prefix_invoker_unique();
155}
156
175template<typename RetType, typename... Args, typename Fn>
176std::tuple<std::shared_ptr<void>, RetType (*)(void*, Args...)> prefix_invoker_shared(Fn&& fn) {
177 return (new detail::destroyable_function<false, RetType, Args...>(std::move(fn)))->prefix_invoker_shared();
178}
179
180
194template<typename RetType, typename... Args, typename Fn>
195std::tuple<void*, RetType (*)(Args..., void*), void (*)(void*)> suffix_invoker_deleter(Fn&& fn) {
196 return (new detail::destroyable_function<false, RetType, Args...>(std::move(fn)))->suffix_invoker_deleter();
197}
198
208template<typename RetType, typename... Args, typename Fn>
209std::tuple<void*, RetType (*)(Args..., void*)> suffix_invoker_oneshot(Fn&& fn) {
210 return (new detail::destroyable_function<true, RetType, Args...>(std::move(fn)))->suffix_invoker();
211}
212
225template<typename RetType, typename... Args, typename Fn>
226std::tuple<std::unique_ptr<void, typename detail::destroyable_function<false, RetType, Args...>::deleter>, RetType (*)(Args..., void*)> suffix_invoker_unique(Fn&& fn) {
227 return (new detail::destroyable_function<false, RetType, Args...>(std::move(fn)))->suffix_invoker_unique();
228}
229
242template<typename RetType, typename... Args, typename Fn>
243std::tuple<std::shared_ptr<void>, RetType (*)(Args..., void*)> suffix_invoker_shared(Fn&& fn) {
244 return (new detail::destroyable_function<false, RetType, Args...>(std::move(fn)))->suffix_invoker_shared();
245}
246
247
248#if __cplusplus >= 201703L
249
251template<typename RetType, typename... Args>
252auto prefix_invoker_deleter(std::function<RetType(Args...)>&& fn) {
253 return (new detail::destroyable_function<false, RetType, Args...>(std::move(fn)))->prefix_invoker_deleter();
254}
255
256template<typename Fn>
258 return prefix_invoker_deleter(std::move(std::function(fn)));
259}
260
262template<typename RetType, typename... Args>
263auto prefix_invoker_oneshot(std::function<RetType(Args...)>&& fn) {
264 return (new detail::destroyable_function<true, RetType, Args...>(std::move(fn)))->prefix_invoker();
265}
266
267template<typename Fn>
269 return prefix_invoker_oneshot(std::move(std::function(fn)));
270}
271
273template<typename RetType, typename... Args>
274auto prefix_invoker_unique(std::function<RetType(Args...)>&& fn) {
275 return (new detail::destroyable_function<false, RetType, Args...>(std::move(fn)))->prefix_invoker_unique();
276}
277
278template<typename Fn>
280 return prefix_invoker_unique(std::move(std::function(fn)));
281}
282
284template<typename RetType, typename... Args>
285auto prefix_invoker_shared(std::function<RetType(Args...)>&& fn) {
286 return (new detail::destroyable_function<false, RetType, Args...>(std::move(fn)))->prefix_invoker_shared();
287}
288
289template<typename Fn>
291 return prefix_invoker_shared(std::move(std::function(fn)));
292}
293
295template<typename RetType, typename... Args>
296auto suffix_invoker_deleter(std::function<RetType(Args...)>&& fn) {
297 return (new detail::destroyable_function<false, RetType, Args...>(std::move(fn)))->suffix_invoker_deleter();
298}
299
300template<typename Fn>
302 return suffix_invoker_deleter(std::move(std::function(fn)));
303}
304
306template<typename RetType, typename... Args>
307auto suffix_invoker_oneshot(std::function<RetType(Args...)>&& fn) {
308 return (new detail::destroyable_function<true, RetType, Args...>(std::move(fn)))->suffix_invoker();
309}
310
311template<typename Fn>
313 return suffix_invoker_oneshot(std::move(std::function(fn)));
314}
315
317template<typename RetType, typename... Args>
318auto suffix_invoker_unique(std::function<RetType(Args...)>&& fn) {
319 return (new detail::destroyable_function<false, RetType, Args...>(std::move(fn)))->suffix_invoker_unique();
320}
321
322template<typename Fn>
324 return suffix_invoker_unique(std::move(std::function(fn)));
325}
326
328template<typename RetType, typename... Args>
329auto suffix_invoker_shared(std::function<RetType(Args...)>&& fn) {
330 return (new detail::destroyable_function<false, RetType, Args...>(std::move(fn)))->suffix_invoker_shared();
331}
332
333template<typename Fn>
335 return prefix_invoker_shared(std::move(std::function(fn)));
336}
337
338#endif
339
340}
341
342#endif // __FUNCTOR2C_HPP__
Definition functor2c.hpp:12
Definition functor2c.hpp:10
std::tuple< void *, RetType(*)(void *, Args...)> prefix_invoker_oneshot(Fn &&fn)
Definition functor2c.hpp:130
std::tuple< std::shared_ptr< void >, RetType(*)(void *, Args...)> prefix_invoker_shared(Fn &&fn)
Definition functor2c.hpp:176
std::tuple< void *, RetType(*)(Args..., void *)> suffix_invoker_oneshot(Fn &&fn)
Definition functor2c.hpp:209
std::tuple< std::unique_ptr< void, typename detail::destroyable_function< false, RetType, Args... >::deleter >, RetType(*)(void *, Args...)> prefix_invoker_unique(Fn &&fn)
Definition functor2c.hpp:153
std::tuple< void *, RetType(*)(Args..., void *), void(*)(void *)> suffix_invoker_deleter(Fn &&fn)
Definition functor2c.hpp:195
std::tuple< std::shared_ptr< void >, RetType(*)(Args..., void *)> suffix_invoker_shared(Fn &&fn)
Definition functor2c.hpp:243
std::tuple< std::unique_ptr< void, typename detail::destroyable_function< false, RetType, Args... >::deleter >, RetType(*)(Args..., void *)> suffix_invoker_unique(Fn &&fn)
Definition functor2c.hpp:226
std::tuple< void *, RetType(*)(void *, Args...), void(*)(void *)> prefix_invoker_deleter(Fn &&fn)
Definition functor2c.hpp:108