builtins.h 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. #pragma once
  2. #include "types.h"
  3. #include "type_traits.h"
  4. namespace pybind11 {
  5. inline object eval(std::string_view code, const handle& global = none{}, handle local = none{}) {
  6. return vm->py_eval(code, global.ptr(), local.ptr());
  7. }
  8. inline void exec(std::string_view code, const handle& global = none{}, handle local = none{}) {
  9. vm->py_exec(code, global.ptr(), local.ptr());
  10. }
  11. /// globas() in pkpy is immutable, your changes will not be reflected in the Python interpreter
  12. inline dict globals() {
  13. auto& proxy = eval("globals()")._as<pkpy::MappingProxy>().attr();
  14. dict result;
  15. #if PK_VERSION_MAJOR == 2
  16. proxy.apply(
  17. [](pkpy::StrName key, pkpy::PyVar value, void* data) {
  18. auto& dict = static_cast<pybind11::dict*>(data)->_as<pkpy::Dict>();
  19. auto key_ = pybind11::str(key.sv()).ptr();
  20. dict.set(vm, key_, value);
  21. },
  22. &result);
  23. #else
  24. proxy.apply([&](pkpy::StrName key, pkpy::PyVar value) {
  25. result.setitem(str(key.sv()), value);
  26. });
  27. #endif
  28. return result;
  29. }
  30. // wrapper for builtin functions in Python
  31. inline bool hasattr(const handle& obj, const handle& name) {
  32. return vm->getattr(obj.ptr(), name._as<pkpy::Str>(), false) != nullptr;
  33. }
  34. inline bool hasattr(const handle& obj, const char* name) { return vm->getattr(obj.ptr(), name, false) != nullptr; }
  35. inline void delattr(const handle& obj, const handle& name) { vm->delattr(obj.ptr(), name._as<pkpy::Str>()); }
  36. inline void delattr(const handle& obj, const char* name) { vm->delattr(obj.ptr(), name); }
  37. inline object getattr(const handle& obj, const handle& name) { return vm->getattr(obj.ptr(), name._as<pkpy::Str>()); }
  38. inline object getattr(const handle& obj, const char* name) { return vm->getattr(obj.ptr(), name); }
  39. inline object getattr(const handle& obj, const handle& name, const handle& default_) {
  40. auto attr = vm->getattr(obj.ptr(), name._as<pkpy::Str>(), false);
  41. if(attr) { return attr; }
  42. return default_;
  43. }
  44. inline object getattr(const handle& obj, const char* name, const handle& default_) {
  45. auto attr = vm->getattr(obj.ptr(), name, false);
  46. if(attr) { return attr; }
  47. return default_;
  48. }
  49. inline void setattr(const handle& obj, const handle& name, const handle& value) {
  50. vm->setattr(obj.ptr(), name._as<pkpy::Str>(), value.ptr());
  51. }
  52. inline void setattr(const handle& obj, const char* name, const handle& value) {
  53. vm->setattr(obj.ptr(), name, value.ptr());
  54. }
  55. template <typename T>
  56. inline bool isinstance(const handle& obj) {
  57. return type_visitor::check<T>(obj);
  58. }
  59. template <>
  60. inline bool isinstance<handle>(const handle&) = delete;
  61. inline bool isinstance(const handle& obj, const handle& type) {
  62. return vm->isinstance(obj.ptr(), type._as<pkpy::Type>());
  63. }
  64. inline int64_t hash(const handle& obj) { return vm->py_hash(obj.ptr()); }
  65. namespace impl {
  66. template <typename T, typename SFINAE = void>
  67. struct type_caster;
  68. }
  69. template <typename T>
  70. handle cast(T&& value, return_value_policy policy, handle parent) {
  71. // decay_t can resolve c-array type, but remove_cv_ref_t can't.
  72. using underlying_type = std::decay_t<T>;
  73. if constexpr(std::is_convertible_v<underlying_type, handle>) {
  74. return std::forward<T>(value);
  75. } else if constexpr(is_unique_ptr_v<underlying_type>) {
  76. return impl::type_caster<typename underlying_type::pointer>::cast(value.release(),
  77. return_value_policy::take_ownership,
  78. parent);
  79. } else {
  80. static_assert(!is_multiple_pointer_v<underlying_type>, "multiple pointer is not supported.");
  81. static_assert(!std::is_void_v<std::remove_pointer_t<underlying_type>>,
  82. "void* is not supported, consider using py::capsule.");
  83. // resolve for automatic policy.
  84. if(policy == return_value_policy::automatic) {
  85. policy = std::is_pointer_v<underlying_type> ? return_value_policy::take_ownership
  86. : std::is_lvalue_reference_v<T&&> ? return_value_policy::copy
  87. : return_value_policy::move;
  88. } else if(policy == return_value_policy::automatic_reference) {
  89. policy = std::is_pointer_v<underlying_type> ? return_value_policy::reference
  90. : std::is_lvalue_reference_v<T&&> ? return_value_policy::copy
  91. : return_value_policy::move;
  92. }
  93. return impl::type_caster<underlying_type>::cast(std::forward<T>(value), policy, parent);
  94. }
  95. }
  96. template <typename T>
  97. T cast(const handle& obj, bool convert) {
  98. assert(obj.ptr() != nullptr);
  99. impl::type_caster<T> caster = {};
  100. if(caster.load(obj, convert)) {
  101. return caster.value;
  102. } else {
  103. std::string msg = "cast python instance to c++ failed, ";
  104. msg += "obj type is: {";
  105. msg += type::of(obj).name();
  106. msg += "}, target type is: {";
  107. msg += type_name<T>();
  108. msg += "}.";
  109. vm->TypeError(msg);
  110. PK_UNREACHABLE();
  111. }
  112. }
  113. struct kwargs_proxy {
  114. handle value;
  115. };
  116. struct args_proxy {
  117. handle value;
  118. kwargs_proxy operator* () { return kwargs_proxy{value}; }
  119. };
  120. template <typename Derived>
  121. args_proxy interface<Derived>::operator* () const {
  122. return args_proxy{ptr()};
  123. }
  124. template <typename... Args>
  125. handle interpreter::vectorcall(const handle& callable, const handle& self, const Args&... args) {
  126. vm->s_data.push(callable.ptr());
  127. #if PK_VERSION_MAJOR == 2
  128. vm->s_data.push(self ? self.ptr() : PY_NULL);
  129. #else
  130. vm->s_data.push(self ? self.ptr() : pkpy::PY_NULL);
  131. #endif
  132. int argc = 0;
  133. int kwargsc = 0;
  134. auto push_arg = [&](const handle& value) {
  135. assert(value);
  136. vm->s_data.push(value.ptr());
  137. argc++;
  138. };
  139. auto push_named_arg = [&](std::string_view name, const handle& value) {
  140. assert(value);
  141. vm->s_data.push(int_(pkpy::StrName(name).index).ptr());
  142. vm->s_data.push(value.ptr());
  143. kwargsc++;
  144. };
  145. auto foreach_ = [&](const auto& arg) {
  146. using T = std::decay_t<decltype(arg)>;
  147. if constexpr(std::is_convertible_v<T, handle>) {
  148. push_arg(arg);
  149. } else if constexpr(std::is_same_v<T, args_proxy>) {
  150. pybind11::tuple args = arg.value.template cast<pybind11::tuple>();
  151. for(auto item: args) {
  152. push_arg(item);
  153. }
  154. } else if constexpr(std::is_same_v<T, pybind11::arg>) {
  155. push_named_arg(arg.name, arg.default_);
  156. } else if constexpr(std::is_same_v<T, kwargs_proxy>) {
  157. pybind11::dict kwargs = arg.value.template cast<pybind11::dict>();
  158. for(auto item: kwargs) {
  159. str name = item.first.template cast<str>();
  160. push_named_arg(name, item.second);
  161. }
  162. } else {
  163. static_assert(dependent_false<T>, "unsupported type");
  164. }
  165. };
  166. (foreach_(args), ...);
  167. return vm->vectorcall(argc, kwargsc);
  168. }
  169. template <typename Derived>
  170. template <return_value_policy policy, typename... Args>
  171. inline object interface<Derived>::operator() (Args&&... args) const {
  172. auto _cast = [&](auto&& arg) {
  173. using T = std::decay_t<decltype(arg)>;
  174. if constexpr(std::is_same_v<T, pybind11::arg> || std::is_same_v<T, kwargs_proxy> ||
  175. std::is_same_v<T, args_proxy> || std::is_convertible_v<T, handle>) {
  176. return arg;
  177. } else {
  178. return pybind11::cast(std::forward<decltype(arg)>(arg), policy);
  179. }
  180. };
  181. return interpreter::vectorcall(ptr(), handle(), _cast(std::forward<Args>(args))...);
  182. }
  183. template <typename... Args>
  184. void print(Args&&... args) {
  185. handle print = getattr(vm->builtins, "print");
  186. print(std::forward<Args>(args)...);
  187. }
  188. } // namespace pybind11