class.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #pragma once
  2. #include "module.h"
  3. #include <vector>
  4. namespace pybind11 {
  5. struct dynamic_attr {};
  6. template <typename T, typename Base = void>
  7. class class_ : public type {
  8. protected:
  9. handle m_scope;
  10. public:
  11. using type::type;
  12. using underlying_type = T;
  13. template <typename... Args>
  14. class_(const handle& scope, const char* name, const Args&... args) :
  15. m_scope(scope), type(type_visitor::create<T, Base>(scope, name)) {
  16. auto& info = type_info::of<T>();
  17. info.name = name;
  18. // bind __new__
  19. interpreter::bind_func(m_ptr, pkpy::__new__, -1, [](pkpy::VM* vm, pkpy::ArgsView args) {
  20. auto cls = handle(args[0])._as<pkpy::Type>();
  21. // check if the class has constructor, if not, raise error
  22. if(vm->find_name_in_mro(cls, pkpy::__init__) == nullptr) {
  23. vm->RuntimeError("if you want to create instance of bound class, you must bind constructor for it");
  24. }
  25. auto var = instance::create(cls, &type_info::of<T>());
  26. if constexpr(types_count_v<dynamic_attr, Args...> != 0) {
  27. #if PK_VERSION_MAJOR == 2
  28. var.get()->_attr = new pkpy::NameDict();
  29. #else
  30. var->_enable_instance_dict();
  31. #endif
  32. }
  33. return var;
  34. });
  35. }
  36. /// bind constructor
  37. template <typename... Args, typename... Extra>
  38. class_& def(init<Args...>, const Extra&... extra) {
  39. if constexpr(!std::is_constructible_v<T, Args...>) {
  40. static_assert(std::is_constructible_v<T, Args...>, "Invalid constructor arguments");
  41. } else {
  42. impl::bind_function(
  43. *this,
  44. "__init__",
  45. [](T* self, Args... args) {
  46. new (self) T(args...);
  47. },
  48. pkpy::BindType::DEFAULT,
  49. extra...);
  50. return *this;
  51. }
  52. }
  53. /// bind member function
  54. template <typename Fn, typename... Extra>
  55. class_& def(const char* name, Fn&& f, const Extra&... extra) {
  56. using first = std::tuple_element_t<0, callable_args_t<remove_cvref_t<Fn>>>;
  57. constexpr bool is_first_base_of_v = std::is_base_of_v<remove_cvref_t<first>, T>;
  58. if constexpr(!is_first_base_of_v) {
  59. static_assert(is_first_base_of_v,
  60. "If you want to bind member function, the first argument must be the base class");
  61. } else {
  62. impl::bind_function(*this, name, std::forward<Fn>(f), pkpy::BindType::DEFAULT, extra...);
  63. }
  64. return *this;
  65. }
  66. /// bind operators
  67. template <typename Operator, typename... Extras>
  68. class_& def(Operator op, const Extras&... extras) {
  69. op.execute(*this, extras...);
  70. return *this;
  71. }
  72. // TODO: factory function
  73. /// bind static function
  74. template <typename Fn, typename... Extra>
  75. class_& def_static(const char* name, Fn&& f, const Extra&... extra) {
  76. impl::bind_function(*this, name, std::forward<Fn>(f), pkpy::BindType::STATICMETHOD, extra...);
  77. return *this;
  78. }
  79. template <typename MP, typename... Extras>
  80. class_& def_readwrite(const char* name, MP mp, const Extras&... extras) {
  81. if constexpr(!std::is_member_object_pointer_v<MP>) {
  82. static_assert(std::is_member_object_pointer_v<MP>, "def_readwrite only supports pointer to data member");
  83. } else {
  84. impl::bind_property(*this, name, mp, mp, extras...);
  85. }
  86. return *this;
  87. }
  88. template <typename MP, typename... Extras>
  89. class_& def_readonly(const char* name, MP mp, const Extras&... extras) {
  90. if constexpr(!std::is_member_object_pointer_v<MP>) {
  91. static_assert(std::is_member_object_pointer_v<MP>, "def_readonly only supports pointer to data member");
  92. } else {
  93. impl::bind_property(*this, name, mp, nullptr, extras...);
  94. }
  95. return *this;
  96. }
  97. template <typename Getter, typename Setter, typename... Extras>
  98. class_& def_property(const char* name, Getter&& g, Setter&& s, const Extras&... extras) {
  99. impl::bind_property(*this, name, std::forward<Getter>(g), std::forward<Setter>(s), extras...);
  100. return *this;
  101. }
  102. template <typename Getter, typename... Extras>
  103. class_& def_property_readonly(const char* name, Getter&& mp, const Extras&... extras) {
  104. impl::bind_property(*this, name, std::forward<Getter>(mp), nullptr, extras...);
  105. return *this;
  106. }
  107. template <typename Var, typename... Extras>
  108. class_& def_readwrite_static(const char* name, Var& mp, const Extras&... extras) {
  109. static_assert(
  110. dependent_false<Var>,
  111. "define static properties requires metaclass. This is a complex feature with few use cases, so it may never be implemented.");
  112. return *this;
  113. }
  114. template <typename Var, typename... Extras>
  115. class_& def_readonly_static(const char* name, Var& mp, const Extras&... extras) {
  116. static_assert(
  117. dependent_false<Var>,
  118. "define static properties requires metaclass. This is a complex feature with few use cases, so it may never be implemented.");
  119. return *this;
  120. }
  121. template <typename Getter, typename Setter, typename... Extras>
  122. class_& def_property_static(const char* name, Getter&& g, Setter&& s, const Extras&... extras) {
  123. static_assert(
  124. dependent_false<Getter>,
  125. "define static properties requires metaclass. This is a complex feature with few use cases, so it may never be implemented.");
  126. return *this;
  127. }
  128. };
  129. template <typename T, typename... Others>
  130. class enum_ : public class_<T, Others...> {
  131. std::vector<std::pair<const char*, handle>> m_values;
  132. public:
  133. using Base = class_<T, Others...>;
  134. using class_<T, Others...>::class_;
  135. template <typename... Args>
  136. enum_(const handle& scope, const char* name, Args&&... args) :
  137. class_<T, Others...>(scope, name, std::forward<Args>(args)...) {
  138. Base::def_property_readonly("value", [](T& self) {
  139. return int_(static_cast<std::underlying_type_t<T>>(self));
  140. });
  141. }
  142. enum_& value(const char* name, T value) {
  143. handle var = type_caster<T>::cast(value, return_value_policy::copy);
  144. this->m_ptr->attr().set(name, var.ptr());
  145. m_values.emplace_back(name, var);
  146. return *this;
  147. }
  148. enum_& export_values() {
  149. for(auto& [name, value]: m_values) {
  150. Base::m_scope.ptr()->attr().set(name, value.ptr());
  151. }
  152. return *this;
  153. }
  154. };
  155. } // namespace pybind11