cast.h 4.5 KB

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