cast.h 4.6 KB

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