mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 19:40:18 +00:00
257 lines
8.5 KiB
C++
257 lines
8.5 KiB
C++
#pragma once
|
|
|
|
#include "kernel.h"
|
|
|
|
namespace pybind11 {
|
|
class handle;
|
|
class object;
|
|
class attr_accessor;
|
|
class item_accessor;
|
|
class iterator;
|
|
class str;
|
|
class bytes;
|
|
class iterable;
|
|
class tuple;
|
|
class dict;
|
|
class list;
|
|
class set;
|
|
class function;
|
|
class module;
|
|
class type;
|
|
class bool_;
|
|
class int_;
|
|
class float_;
|
|
class str;
|
|
class bytes;
|
|
|
|
template <typename T>
|
|
T& _builtin_cast(const handle& obj);
|
|
|
|
template <typename T>
|
|
T reinterpret_borrow(const handle& h);
|
|
|
|
template <typename T>
|
|
T reinterpret_steal(const handle& h);
|
|
|
|
class handle {
|
|
protected:
|
|
pkpy::PyVar m_ptr = nullptr;
|
|
mutable int* ref_count = nullptr;
|
|
|
|
public:
|
|
handle() = default;
|
|
handle(const handle& h) = default;
|
|
handle& operator= (const handle& other) = default;
|
|
|
|
handle(pkpy::PyVar ptr) : m_ptr(ptr) {}
|
|
|
|
pkpy::PyVar ptr() const { return m_ptr; }
|
|
|
|
int reference_count() const { return ref_count == nullptr ? 0 : *ref_count; }
|
|
|
|
const handle& inc_ref() const {
|
|
PK_DEBUG_ASSERT(m_ptr != nullptr);
|
|
if(ref_count == nullptr) {
|
|
auto iter = _ref_counts_map->find(m_ptr);
|
|
if(iter == _ref_counts_map->end()) {
|
|
ref_count = ::new int(1);
|
|
_ref_counts_map->insert({m_ptr, ref_count});
|
|
} else {
|
|
ref_count = iter->second;
|
|
*ref_count += 1;
|
|
}
|
|
} else {
|
|
*ref_count += 1;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
const handle& dec_ref() const {
|
|
PK_DEBUG_ASSERT(m_ptr != nullptr);
|
|
PK_DEBUG_ASSERT(ref_count != nullptr);
|
|
|
|
*ref_count -= 1;
|
|
try {
|
|
if(*ref_count == 0) {
|
|
_ref_counts_map->erase(m_ptr);
|
|
::delete ref_count;
|
|
ref_count = nullptr;
|
|
}
|
|
} catch(std::exception& e) { std::cerr << "Error: " << e.what() << std::endl; }
|
|
|
|
return *this;
|
|
}
|
|
|
|
public:
|
|
template <typename T>
|
|
T cast() const;
|
|
|
|
explicit operator bool () const { return m_ptr.operator bool (); }
|
|
|
|
bool is(const handle& other) const { return m_ptr == other.m_ptr; }
|
|
|
|
bool is_none() const { return m_ptr == vm->None; }
|
|
|
|
bool in(const handle& other) const {
|
|
return pkpy::py_cast<bool>(vm, vm->call(vm->py_op("contains"), other.m_ptr, m_ptr));
|
|
}
|
|
|
|
bool contains(const handle& other) const {
|
|
return pkpy::py_cast<bool>(vm, vm->call(vm->py_op("contains"), m_ptr, other.m_ptr));
|
|
}
|
|
|
|
iterator begin() const;
|
|
iterator end() const;
|
|
|
|
str doc() const;
|
|
|
|
attr_accessor attr(const char* name) const;
|
|
attr_accessor attr(const handle& name) const;
|
|
attr_accessor attr(object&& name) const;
|
|
|
|
item_accessor operator[] (int64_t key) const;
|
|
item_accessor operator[] (const char* key) const;
|
|
item_accessor operator[] (const handle& key) const;
|
|
item_accessor operator[] (object&& key) const;
|
|
|
|
object operator- () const;
|
|
object operator~() const;
|
|
|
|
template <return_value_policy policy = return_value_policy::automatic, typename... Args>
|
|
object operator() (Args&&... args) const;
|
|
|
|
private:
|
|
friend object operator+ (const handle& lhs, const handle& rhs);
|
|
friend object operator- (const handle& lhs, const handle& rhs);
|
|
friend object operator* (const handle& lhs, const handle& rhs);
|
|
friend object operator% (const handle& lhs, const handle& rhs);
|
|
friend object operator/ (const handle& lhs, const handle& rhs);
|
|
friend object operator| (const handle& lhs, const handle& rhs);
|
|
friend object operator& (const handle& lhs, const handle& rhs);
|
|
friend object operator^ (const handle& lhs, const handle& rhs);
|
|
friend object operator<< (const handle& lhs, const handle& rhs);
|
|
friend object operator>> (const handle& lhs, const handle& rhs);
|
|
|
|
friend object operator+= (const handle& lhs, const handle& rhs);
|
|
friend object operator-= (const handle& lhs, const handle& rhs);
|
|
friend object operator*= (const handle& lhs, const handle& rhs);
|
|
friend object operator/= (const handle& lhs, const handle& rhs);
|
|
friend object operator%= (const handle& lhs, const handle& rhs);
|
|
friend object operator|= (const handle& lhs, const handle& rhs);
|
|
friend object operator&= (const handle& lhs, const handle& rhs);
|
|
friend object operator^= (const handle& lhs, const handle& rhs);
|
|
friend object operator<<= (const handle& lhs, const handle& rhs);
|
|
friend object operator>>= (const handle& lhs, const handle& rhs);
|
|
|
|
friend object operator== (const handle& lhs, const handle& rhs);
|
|
friend object operator!= (const handle& lhs, const handle& rhs);
|
|
friend object operator< (const handle& lhs, const handle& rhs);
|
|
friend object operator> (const handle& lhs, const handle& rhs);
|
|
friend object operator<= (const handle& lhs, const handle& rhs);
|
|
friend object operator>= (const handle& lhs, const handle& rhs);
|
|
|
|
template <typename T>
|
|
friend T& _builtin_cast(const handle& obj) {
|
|
// FIXME: 2.0 does not use Py_<T> anymore
|
|
static_assert(!std::is_reference_v<T>, "T must not be a reference type.");
|
|
return obj.ptr().obj_get<T>();
|
|
}
|
|
};
|
|
|
|
static_assert(std::is_trivially_copyable_v<handle>);
|
|
|
|
class object : public handle {
|
|
public:
|
|
object(const object& other) : handle(other) { inc_ref(); }
|
|
|
|
object(object&& other) noexcept : handle(other) {
|
|
other.m_ptr = nullptr;
|
|
other.ref_count = nullptr;
|
|
}
|
|
|
|
object& operator= (const object& other) {
|
|
if(this != &other) {
|
|
dec_ref();
|
|
m_ptr = other.m_ptr;
|
|
ref_count = other.ref_count;
|
|
inc_ref();
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
object& operator= (object&& other) noexcept {
|
|
if(this != &other) {
|
|
dec_ref();
|
|
m_ptr = other.m_ptr;
|
|
ref_count = other.ref_count;
|
|
other.m_ptr = nullptr;
|
|
other.ref_count = nullptr;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
~object() {
|
|
if(m_ptr != nullptr) {
|
|
dec_ref();
|
|
}
|
|
}
|
|
|
|
protected:
|
|
object(const handle& h, bool borrow) : handle(h) {
|
|
if(borrow) {
|
|
inc_ref();
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
friend T reinterpret_borrow(const handle& h) {
|
|
return {h, true};
|
|
}
|
|
|
|
template <typename T>
|
|
friend T reinterpret_steal(const handle& h) {
|
|
return {h, false};
|
|
}
|
|
};
|
|
|
|
inline void setattr(const handle& obj, const handle& name, const handle& value);
|
|
inline void setitem(const handle& obj, const handle& key, const handle& value);
|
|
|
|
#define PYBIND11_BINARY_OPERATOR(OP, NAME) \
|
|
inline object operator OP (const handle& lhs, const handle& rhs) { \
|
|
return reinterpret_borrow<object>(vm->call(vm->py_op(NAME), lhs.m_ptr, rhs.m_ptr)); \
|
|
}
|
|
|
|
PYBIND11_BINARY_OPERATOR(+, "add");
|
|
PYBIND11_BINARY_OPERATOR(-, "sub");
|
|
PYBIND11_BINARY_OPERATOR(*, "mul");
|
|
PYBIND11_BINARY_OPERATOR(/, "truediv");
|
|
PYBIND11_BINARY_OPERATOR(%, "mod");
|
|
PYBIND11_BINARY_OPERATOR(|, "or_");
|
|
PYBIND11_BINARY_OPERATOR(&, "and_");
|
|
PYBIND11_BINARY_OPERATOR(^, "xor");
|
|
PYBIND11_BINARY_OPERATOR(<<, "lshift");
|
|
PYBIND11_BINARY_OPERATOR(>>, "rshift");
|
|
|
|
PYBIND11_BINARY_OPERATOR(+=, "iadd");
|
|
PYBIND11_BINARY_OPERATOR(-=, "isub");
|
|
PYBIND11_BINARY_OPERATOR(*=, "imul");
|
|
PYBIND11_BINARY_OPERATOR(/=, "itruediv");
|
|
PYBIND11_BINARY_OPERATOR(%=, "imod");
|
|
PYBIND11_BINARY_OPERATOR(|=, "ior");
|
|
PYBIND11_BINARY_OPERATOR(&=, "iand");
|
|
PYBIND11_BINARY_OPERATOR(^=, "ixor");
|
|
PYBIND11_BINARY_OPERATOR(<<=, "ilshift");
|
|
PYBIND11_BINARY_OPERATOR(>>=, "irshift");
|
|
|
|
PYBIND11_BINARY_OPERATOR(==, "eq");
|
|
PYBIND11_BINARY_OPERATOR(!=, "ne");
|
|
PYBIND11_BINARY_OPERATOR(<, "lt");
|
|
PYBIND11_BINARY_OPERATOR(>, "gt");
|
|
PYBIND11_BINARY_OPERATOR(<=, "le");
|
|
PYBIND11_BINARY_OPERATOR(>=, "ge");
|
|
|
|
#undef PYBIND11_BINARY_OPERATOR
|
|
|
|
} // namespace pybind11
|