cast.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #pragma once
  2. #include "instance.h"
  3. #include "builtins.h"
  4. #include "type_traits.h"
  5. namespace pybind11 {
  6. using pkpy::is_floating_point_v;
  7. using pkpy::is_integral_v;
  8. template <typename T>
  9. constexpr inline bool is_string_v =
  10. std::is_same_v<T, char*> || std::is_same_v<T, const char*> ||
  11. std::is_same_v<T, std::string> || std::is_same_v<T, std::string_view>;
  12. template <typename T>
  13. constexpr bool is_pyobject_v = std::is_base_of_v<handle, T>;
  14. template <typename T, typename>
  15. struct type_caster;
  16. template <>
  17. struct type_caster<bool> {
  18. bool value;
  19. bool load(const handle& src, bool) {
  20. if(isinstance<pybind11::bool_>(src)) {
  21. value = pkpy::_py_cast<bool>(vm, src.ptr());
  22. return true;
  23. }
  24. return false;
  25. }
  26. static handle cast(bool src, return_value_policy, handle) {
  27. return src ? vm->True : vm->False;
  28. }
  29. };
  30. template <typename T>
  31. struct type_caster<T, std::enable_if_t<is_integral_v<T>>> {
  32. T value;
  33. bool load(const handle& src, bool convert) {
  34. if(isinstance<pybind11::int_>(src)) {
  35. value = pkpy::_py_cast<T>(vm, src.ptr());
  36. return true;
  37. }
  38. return false;
  39. }
  40. static handle cast(T src, return_value_policy, handle) { return pkpy::py_var(vm, src); }
  41. };
  42. template <typename T>
  43. struct type_caster<T, std::enable_if_t<is_floating_point_v<T>>> {
  44. T value;
  45. bool load(const handle& src, bool convert) {
  46. if(isinstance<pybind11::float_>(src)) {
  47. value = pkpy::_py_cast<T>(vm, src.ptr());
  48. return true;
  49. }
  50. if(convert && isinstance<pybind11::int_>(src)) {
  51. value = pkpy::_py_cast<int64_t>(vm, src.ptr());
  52. return true;
  53. }
  54. return false;
  55. }
  56. static handle cast(T src, return_value_policy, handle) { return pkpy::py_var(vm, src); }
  57. };
  58. template <typename T>
  59. struct type_caster<T, std::enable_if_t<is_string_v<T>>> {
  60. T value;
  61. bool load(const handle& src, bool) {
  62. if(isinstance<pybind11::str>(src)) {
  63. // FIXME: support other kinds of string
  64. value = pkpy::_py_cast<std::string>(vm, src.ptr());
  65. return true;
  66. }
  67. return false;
  68. }
  69. static handle cast(const std::string& src, return_value_policy, handle) {
  70. return pkpy::py_var(vm, src);
  71. }
  72. };
  73. template <typename T>
  74. struct type_caster<T, std::enable_if_t<is_pyobject_v<T>>> {
  75. T value;
  76. bool load(const handle& src, bool) {
  77. if(isinstance<T>(src)) {
  78. value = reinterpret_borrow<T>(src);
  79. return true;
  80. }
  81. return false;
  82. }
  83. template <typename U>
  84. static handle cast(U&& src, return_value_policy, handle) {
  85. return std::forward<U>(src);
  86. }
  87. };
  88. template <typename T, typename>
  89. struct type_caster {
  90. value_wrapper<T> value;
  91. using underlying_type = std::remove_pointer_t<decltype(value.pointer)>;
  92. bool load(handle src, bool convert) {
  93. if(isinstance<underlying_type>(src)) {
  94. auto& i = _builtin_cast<instance>(src);
  95. value.pointer = &i.cast<underlying_type>();
  96. return true;
  97. }
  98. return false;
  99. }
  100. template <typename U>
  101. static handle cast(U&& value, return_value_policy policy, const handle& parent = handle()) {
  102. // TODO: support implicit cast
  103. const auto& info = typeid(underlying_type);
  104. bool existed = vm->_cxx_typeid_map.find(info) != vm->_cxx_typeid_map.end();
  105. if(existed) {
  106. auto type = vm->_cxx_typeid_map[info];
  107. return instance::create(std::forward<U>(value), type, policy, parent.ptr());
  108. }
  109. vm->TypeError("type not registered");
  110. }
  111. };
  112. template <typename T>
  113. struct type_caster<T, std::enable_if_t<std::is_pointer_v<T> || std::is_reference_v<T>>> {
  114. using underlying = std::conditional_t<std::is_pointer_v<T>,
  115. std::remove_pointer_t<T>,
  116. std::remove_reference_t<T>>;
  117. struct wrapper {
  118. type_caster<underlying> caster;
  119. operator T () {
  120. if constexpr(std::is_pointer_v<T>) {
  121. return caster.value.pointer;
  122. } else {
  123. return caster.value;
  124. }
  125. }
  126. };
  127. wrapper value;
  128. bool load(const handle& src, bool convert) { return value.caster.load(src, convert); }
  129. template <typename U>
  130. static handle cast(U&& value, return_value_policy policy, const handle& parent) {
  131. return type_caster<underlying>::cast(std::forward<U>(value), policy, parent);
  132. }
  133. };
  134. } // namespace pybind11