Advertisement
dan-masek

Property Collection for boost python - V1

Mar 13th, 2019
304
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.76 KB | None | 0 0
  1. // https://stackoverflow.com/questions/55052416/how-to-store-class-members-to-be-exposed-to-boost-python
  2. // Version 1
  3. // ============================================================================
  4. #include <boost/format.hpp>
  5. #include <boost/python.hpp>
  6.  
  7. namespace bp = boost::python;
  8. // ============================================================================
  9. template <class W>
  10. class property_def
  11. {
  12. public:
  13.     using wrapper_type = bp::class_<W>;
  14.  
  15.     explicit property_def(std::string name)
  16.         : name_(std::move(name))
  17.     {
  18.     }
  19.     virtual ~property_def() = default;
  20.  
  21.     void apply(wrapper_type& cls)
  22.     {
  23.         apply_impl(cls, name_);
  24.     }
  25.  
  26. private:
  27.     virtual void apply_impl(wrapper_type& cls, std::string const& name) = 0;
  28.  
  29. private:
  30.     std::string name_;
  31. };
  32. // ----------------------------------------------------------------------------
  33. template <class W, class D>
  34. class property_def_impl
  35.     : public property_def<W>
  36. {
  37. public:
  38.     using base = property_def<W>;
  39.     using wrapper_type = typename base::wrapper_type;
  40.  
  41.     property_def_impl(std::string name, D const& d)
  42.         : base(std::move(name))
  43.         , d_(d)
  44.     {
  45.     }
  46.  
  47. private:
  48.     void apply_impl(wrapper_type& cls, std::string const& name) override
  49.     {
  50.         cls.def_readonly(name.c_str(), d_);
  51.     }
  52.  
  53. private:
  54.     D const& d_;
  55. };
  56. // ----------------------------------------------------------------------------
  57. template <class W>
  58. class property_collection
  59. {
  60. public:
  61.     using class_type = W;
  62.     using property_base = property_def<W>;
  63.     using wrapper_type = typename property_base::wrapper_type;
  64.     using property_base_ptr = std::unique_ptr<property_base>;
  65.  
  66.     property_collection() = default;
  67.  
  68.     template <class D>
  69.     void add_readonly(std::string name, D const& d)
  70.     {
  71.         properties_.push_back(std::make_unique<property_def_impl<class_type, D>>(name, d));
  72.     }
  73.  
  74.     void apply(wrapper_type& cls)
  75.     {
  76.         for (auto& prop : properties_) {
  77.             prop->apply(cls);
  78.         }
  79.     }
  80.  
  81. private:
  82.     std::vector<property_base_ptr> properties_;
  83. };
  84. // ============================================================================
  85. struct test_ds
  86. {
  87.     uint8_t prop0{0};
  88.     uint16_t prop1{1};
  89.     uint32_t prop2{2};
  90.     uint64_t prop3{3};
  91.     float prop4{4.0f};
  92.     double prop5{5.0};
  93.     std::string prop6{"six"};
  94.  
  95.     static uint8_t prop7;
  96. };
  97.  
  98. uint8_t test_ds::prop7{7};
  99. // ============================================================================
  100. BOOST_PYTHON_MODULE(test)
  101. {
  102.     property_collection<test_ds> p;
  103.     p.add_readonly("prop0", &test_ds::prop0);
  104.     p.add_readonly("prop1", &test_ds::prop1);
  105.     p.add_readonly("prop2", &test_ds::prop2);
  106.     p.add_readonly("prop3", &test_ds::prop3);
  107.     p.add_readonly("prop4", &test_ds::prop4);
  108.     p.add_readonly("prop5", &test_ds::prop5);
  109.     p.add_readonly("prop6", &test_ds::prop6);
  110.     p.add_readonly("prop7", test_ds::prop7);
  111.    
  112.     bp::class_<test_ds> c("test_ds");
  113.     p.apply(c);
  114. }
  115. // ============================================================================
  116. int main()
  117. {
  118.     Py_Initialize();
  119.     inittest();
  120.  
  121.     try {
  122.         bp::object main_module = bp::import("__main__");
  123.         bp::object main_namespace = main_module.attr("__dict__");
  124.  
  125.         exec(
  126.             "import test\n"
  127.             "o = test.test_ds()\n"
  128.             "print dir(o)\n"
  129.             , main_namespace);
  130.         for (int i(0); i < 8; ++i) {
  131.             exec(str(boost::format("print 'prop%d: ', o.prop%d\n") % i % i).c_str()
  132.                 , main_namespace);
  133.         }
  134.  
  135.     } catch (bp::error_already_set &) {
  136.         PyErr_Print();
  137.     }
  138.  
  139.     Py_Finalize();
  140.     return 0;
  141. }
  142. // ============================================================================
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement