将可调用对象转换为 c 风格指针

// 将可调用对象转换为 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);

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值