// 将可调用对象转换为 c 风格指针,主要用于 c++ 类函数/bind 作为 c library 回调
// 原理通过 Tag 构建特定类,静态成员存储 c++ 调用对象,静态函数可直接转化成 c 函数指针
template <typename ParamsList /* 参数列表 */, typename Tag>
struct CFuncPointorBuilder {
template <typename Callable>
static auto invoke(Callable&& call) {
// 类函数/bind 不能通过 template 直接推导出 std::function,需要做一层转化,
// 构造指定类型的 function
return extract(std::function<ParamsList>(std::forward<Callable>(call)));
}
template <typename Ret, typename... Params>
static auto extract(const std::function<Ret(Params...)>& call) {
// 通过参数列表获取 c 函数指针类型
using CallPointor = Ret(*)(Params...);
// 构建特定类 Wrapper
Wrapper<Ret(Params...), Tag>::callstore = call;
// 将静态函数转化为 c 函数指针
return static_cast<CallPointor>(Wrapper<Ret(Params...), Tag>::convert);
}
template <typename T, typename WTag>
struct Wrapper;
template <typename Ret, typename... Params, typename WTag>
struct Wrapper<Ret(Params...), WTag> {
template <typename... Args>
static Ret convert(Args... args) { return callstore(args...); }
static std::function<Ret(Params...)> callstore;
};
};
template <typename RetParams, typename Tag>
template <typename Ret, typename... Params, typename WTag>
std::function<Ret(Params...)> CFuncPointorBuilder<RetParams, Tag>
::Wrapper<Ret(Params...), WTag>::callstore;
// 针对 bind 方式方便调用
template <typename Tag>
struct BindToCFPointor {
template <typename Ret, typename... Params, typename F, typename... Args>
static void build( Ret(**p)(Params...), F&& f, Args&&... args) {
*p = CFuncPointorBuilder<Ret(Params...), Tag>
::invoke(std::bind(std::forward<F>(f),
std::forward<Args>(args)...));
}
};
// 使用
// 生成 Tag
template <unsigned int N>
using ZKTransferTag = std::integral_constant<unsigned int, N>;
利用 gcc __COUNTER__ 宏生成一个唯一的 Tag
把 ZKTransfer::on_conn_event 类内函数转化成 c 函数指针 赋值给 deliver_conn
void(*deliver_conn)(Ptr<zhandle_t>, int, int, const Ptr<char>, Ptr<void>);
BindToCFPointor<ZKTransferTag<__COUNTER__>>::build(
&deliver_conn,
&ZKTransfer::on_conn_event,
shared_from_this(),
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5);
将可调用对象转换为 c 风格指针
最新推荐文章于 2023-01-06 17:38:35 发布