builtins.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #pragma once
  2. #include "types.h"
  3. namespace pybind11 {
  4. inline void exec(const char* code, handle global = {}, handle local = {}) {
  5. vm->py_exec(code, global.ptr(), local.ptr());
  6. }
  7. // wrapper for builtin functions in Python
  8. inline bool hasattr(const handle& obj, const handle& name) {
  9. auto& key = _builtin_cast<pkpy::Str>(name);
  10. return vm->getattr(obj.ptr(), key, false) != nullptr;
  11. }
  12. inline bool hasattr(const handle& obj, const char* name) { return vm->getattr(obj.ptr(), name, false) != nullptr; }
  13. inline void delattr(const handle& obj, const handle& name) {
  14. auto& key = _builtin_cast<pkpy::Str>(name);
  15. vm->delattr(obj.ptr(), key);
  16. }
  17. inline void delattr(const handle& obj, const char* name) { vm->delattr(obj.ptr(), name); }
  18. inline object getattr(const handle& obj, const handle& name) {
  19. auto& key = _builtin_cast<pkpy::Str>(name);
  20. return reinterpret_borrow<object>(vm->getattr(obj.ptr(), key));
  21. }
  22. inline object getattr(const handle& obj, const char* name) {
  23. return reinterpret_borrow<object>(vm->getattr(obj.ptr(), name));
  24. }
  25. inline object getattr(const handle& obj, const handle& name, const handle& default_) {
  26. if(!hasattr(obj, name)) { return reinterpret_borrow<object>(default_); }
  27. return getattr(obj, name);
  28. }
  29. inline object getattr(const handle& obj, const char* name, const handle& default_) {
  30. if(!hasattr(obj, name)) { return reinterpret_borrow<object>(default_); }
  31. return getattr(obj, name);
  32. }
  33. inline void setattr(const handle& obj, const handle& name, const handle& value) {
  34. auto& key = _builtin_cast<pkpy::Str>(name);
  35. vm->setattr(obj.ptr(), key, value.ptr());
  36. }
  37. inline void setattr(const handle& obj, const char* name, const handle& value) {
  38. vm->setattr(obj.ptr(), name, value.ptr());
  39. }
  40. template <typename T>
  41. inline bool isinstance(const handle& obj) {
  42. pkpy::Type cls = _builtin_cast<pkpy::Type>(type::handle_of<T>().ptr());
  43. return vm->isinstance(obj.ptr(), cls);
  44. }
  45. template <>
  46. inline bool isinstance<handle>(const handle&) = delete;
  47. template <>
  48. inline bool isinstance<iterable>(const handle& obj) {
  49. return hasattr(obj, "__iter__");
  50. }
  51. template <>
  52. inline bool isinstance<iterator>(const handle& obj) {
  53. return hasattr(obj, "__iter__") && hasattr(obj, "__next__");
  54. }
  55. inline bool isinstance(const handle& obj, const handle& type) {
  56. return vm->isinstance(obj.ptr(), _builtin_cast<pkpy::Type>(type));
  57. }
  58. inline int64_t hash(const handle& obj) { return vm->py_hash(obj.ptr()); }
  59. template <typename T, typename SFINAE = void>
  60. struct type_caster;
  61. template <typename T>
  62. handle
  63. _cast(T&& value, return_value_policy policy = return_value_policy::automatic_reference, handle parent = handle()) {
  64. using U = std::remove_pointer_t<std::remove_cv_t<std::remove_reference_t<T>>>;
  65. return type_caster<U>::cast(std::forward<T>(value), policy, parent);
  66. }
  67. template <typename T>
  68. object
  69. cast(T&& value, return_value_policy policy = return_value_policy::automatic_reference, handle parent = handle()) {
  70. return reinterpret_borrow<object>(_cast(std::forward<T>(value), policy, parent));
  71. }
  72. template <typename T>
  73. T cast(handle obj, bool convert = false) {
  74. using Caster = type_caster<std::remove_pointer_t<std::remove_cv_t<std::remove_reference_t<T>>>>;
  75. Caster caster;
  76. if(caster.load(obj, convert)) {
  77. if constexpr(std::is_rvalue_reference_v<T>) {
  78. return std::move(caster.value);
  79. } else {
  80. return caster.value;
  81. }
  82. }
  83. throw std::runtime_error("Unable to cast Python instance to C++ type");
  84. }
  85. } // namespace pybind11