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


    1. // 将可调用对象转换为 c 风格指针,主要用于 c++ 类函数/bind 作为 c library 回调
    2. // 原理通过 Tag 构建特定类,静态成员存储 c++ 调用对象,静态函数可直接转化成 c 函数指针
    3. template <typename ParamsList /* 参数列表 */, typename Tag>
    4. struct CFuncPointorBuilder {
    5. template <typename Callable>
    6. static auto invoke(Callable&& call) {
    7. // 类函数/bind 不能通过 template 直接推导出 std::function,需要做一层转化,
    8. // 构造指定类型的 function
    9. return extract(std::function(std::forward(call)));
    10. }
    11. template <typename Ret, typename... Params>
    12. static auto extract(const std::function& call) {
    13. // 通过参数列表获取 c 函数指针类型
    14. using CallPointor = Ret(*)(Params...);
    15. // 构建特定类 Wrapper
    16. Wrapper<Ret(Params...), Tag>::callstore = call;
    17. // 将静态函数转化为 c 函数指针
    18. return static_cast(Wrapper<Ret(Params...), Tag>::convert);
    19. }
    20. template <typename T, typename WTag>
    21. struct Wrapper;
    22. template <typename Ret, typename... Params, typename WTag>
    23. struct Wrapper<Ret(Params...), WTag> {
    24. template <typename... Args>
    25. static Ret convert(Args... args) { return callstore(args...); }
    26. static std::function callstore;
    27. };
    28. };
    29. template <typename RetParams, typename Tag>
    30. template <typename Ret, typename... Params, typename WTag>
    31. std::function CFuncPointorBuilder
    32. ::Wrapper<Ret(Params...), WTag>::callstore;
    33. // 针对 bind 方式方便调用
    34. template <typename Tag>
    35. struct BindToCFPointor {
    36. template <typename Ret, typename... Params, typename F, typename... Args>
    37. static void build( Ret(**p)(Params...), F&& f, Args&&... args) {
    38. *p = CFuncPointorBuilder<Ret(Params...), Tag>
    39. ::invoke(std::bind(std::forward(f),
    40. std::forward(args)...));
    41. }
    42. };
    43. // 使用
    44. // 生成 Tag
    45. template <unsigned int N>
    46. using ZKTransferTag = std::integral_constant<unsigned int, N>;
    47. 利用 gcc __COUNTER__ 宏生成一个唯一的 Tag
    48. 把 ZKTransfer::on_conn_event 类内函数转化成 c 函数指针 赋值给 deliver_conn
    49. void(*deliver_conn)(Ptr<zhandle_t>, int, int, const Ptr<char>, Ptr<void>);
    50. BindToCFPointor>::build(
    51. &deliver_conn,
    52. &ZKTransfer::on_conn_event,
    53. shared_from_this(),
    54. std::placeholders::_1,
    55. std::placeholders::_2,
    56. std::placeholders::_3,
    57. std::placeholders::_4,
    58. std::placeholders::_5);

  • 相关阅读:
    测试饱和了? 大数据测试就业薪资和前景究竟怎么样?
    《分析模式》漫谈06-实例不是“一种”隔壁老王
    5分钟教会你如何在生产环境debug代码
    IIC总线
    贝茄莱(B&R)实时以太网通讯测试
    活动贴 Java社区征集开发者调查(微软联合csdn活动)
    【Python】基础知识
    小程序红包服务端请求一直是签名错误如何解决
    基于Ubuntu20.04安装ROS系统
    java计算机毕业设计高校科研信息管理系统源码+mysql数据库+系统+lw文档+部署
  • 原文地址:https://blog.csdn.net/letterwuyu/article/details/126293083