diff --git a/include/pybind11/internal/function.h b/include/pybind11/internal/function.h index 00dffa01..3138fec0 100644 --- a/include/pybind11/internal/function.h +++ b/include/pybind11/internal/function.h @@ -515,20 +515,18 @@ struct template_parser tp_function_record = +[](py_Type& type) { + type = py_newtype("function_record", tp_object, nullptr, [](void* data) { static_cast(data)->~function_record(); }); - } + }; static bool is_function_record(handle h) { if(isinstance(h)) { auto slot = py_getslot(h.ptr(), 0); - if(slot) { return py_typeof(slot) == m_type; } + if(slot) { return py_typeof(slot) == tp_function_record; } } return false; } @@ -539,47 +537,42 @@ class cpp_function : public function { // bind the function std::string sig = name; sig += is_method ? "(self, *args, **kwargs)" : "(*args, **kwargs)"; - auto call = [](int argc, py_Ref stack) { - handle func = py_inspect_currentfunction(); - auto data = py_touserdata(py_getslot(func.ptr(), 0)); - auto& record = *static_cast(data); - try { - record(argc, stack); - return true; - } catch(std::domain_error& e) { - py_exception(tp_ValueError, e.what()); - } catch(std::invalid_argument& e) { - py_exception(tp_ValueError, e.what()); - } catch(std::length_error& e) { - py_exception(tp_ValueError, e.what()); - } catch(std::out_of_range& e) { - py_exception(tp_IndexError, e.what()); - } catch(std::range_error& e) { - py_exception(tp_ValueError, e.what()); - } catch(stop_iteration&) { StopIteration(); } catch(index_error& e) { - py_exception(tp_IndexError, e.what()); - } catch(key_error& e) { py_exception(tp_KeyError, e.what()); } catch(value_error& e) { - py_exception(tp_ValueError, e.what()); - } catch(type_error& e) { - py_exception(tp_TypeError, e.what()); - } catch(import_error& e) { - py_exception(tp_ImportError, e.what()); - } catch(attribute_error& e) { - py_exception(tp_AttributeError, e.what()); - } catch(std::exception& e) { py_exception(tp_RuntimeError, e.what()); } - return false; - }; - py_newfunction(m_ptr, sig.c_str(), call, nullptr, 1); - assert(m_type != 0 && "function record type not registered"); + py_newfunction(m_ptr, sig.c_str(), call, nullptr, 1); auto slot = py_getslot(m_ptr, 0); - void* data = py_newobject(slot, m_type, 0, sizeof(impl::function_record)); + void* data = py_newobject(slot, tp_function_record, 0, sizeof(impl::function_record)); new (data) impl::function_record(std::forward(fn), extras...); } - template - cpp_function(Fn&& fn, const Extras&... extras) : - cpp_function("lambda", std::forward(fn), extras...) {} +private: + static bool call(int argc, py_Ref stack) { + handle func = py_inspect_currentfunction(); + auto data = py_touserdata(py_getslot(func.ptr(), 0)); + auto& record = *static_cast(data); + try { + record(argc, stack); + return true; + } catch(std::domain_error& e) { + py_exception(tp_ValueError, e.what()); + } catch(std::invalid_argument& e) { + py_exception(tp_ValueError, e.what()); + } catch(std::length_error& e) { + py_exception(tp_ValueError, e.what()); + } catch(std::out_of_range& e) { + py_exception(tp_IndexError, e.what()); + } catch(std::range_error& e) { + py_exception(tp_ValueError, e.what()); + } catch(stop_iteration&) { StopIteration(); } catch(index_error& e) { + py_exception(tp_IndexError, e.what()); + } catch(key_error& e) { py_exception(tp_KeyError, e.what()); } catch(value_error& e) { + py_exception(tp_ValueError, e.what()); + } catch(type_error& e) { py_exception(tp_TypeError, e.what()); } catch(import_error& e) { + py_exception(tp_ImportError, e.what()); + } catch(attribute_error& e) { + py_exception(tp_AttributeError, e.what()); + } catch(std::exception& e) { py_exception(tp_RuntimeError, e.what()); } + return false; + }; }; class property : public object { diff --git a/include/pybind11/internal/kernel.h b/include/pybind11/internal/kernel.h index 340da4e0..f9b1d92c 100644 --- a/include/pybind11/internal/kernel.h +++ b/include/pybind11/internal/kernel.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -17,27 +18,6 @@ namespace pkbind { class handle; -/// hold the object temporarily -template -struct reg_t { - py_Ref value; - - void operator= (py_Ref ref) & { py_setreg(N, ref); } - - operator py_Ref () & { - assert(value && "register is not initialized"); - return value; - } - - void operator= (handle value) &; - - operator handle () &; - - // pkpy provide user 8 registers. - // 8th register is used for object pool, so N is limited to [0, 7). - static_assert(N >= 0 && N <= 6, "N must be in [0, 7)"); -}; - struct retv_t { py_Ref value; @@ -140,8 +120,28 @@ struct action { static void register_start(function func) { starts.push_back(func); } }; -template -inline reg_t reg; +template +class lazy { +public: + lazy(void (*init)(T&)) : init(init) {} + + operator T& () { + if(!initialized) { + if(init) { init(value); } + initialized = true; + } + return value; + } + + T& operator* () { return static_cast(*this); } + + void reset() { initialized = false; } + +private: + T value; + bool initialized = false; + void (*init)(T&) = nullptr; +}; inline retv_t retv; diff --git a/include/pybind11/internal/object.h b/include/pybind11/internal/object.h index db90fcd9..dd1b6502 100644 --- a/include/pybind11/internal/object.h +++ b/include/pybind11/internal/object.h @@ -281,17 +281,6 @@ T borrow(handle h) { return T(h, object::realloc_t{}); } -template -void reg_t::operator= (handle h) & { - py_setreg(N, h.ptr()); -} - -template -reg_t::operator handle () & { - assert(value && "register is not initialized"); - return value; -} - inline void retv_t::operator= (handle h) & { py_assign(value, h.ptr()); } inline retv_t::operator handle () & { diff --git a/include/pybind11/internal/types.h b/include/pybind11/internal/types.h index f71821b7..38e2de7e 100644 --- a/include/pybind11/internal/types.h +++ b/include/pybind11/internal/types.h @@ -330,24 +330,22 @@ class kwargs : public dict { // TODO: class capsule : public object { + PKBIND_TYPE_IMPL(object, capsule, *tp_capsule); + struct capsule_impl { void* data; void (*destructor)(void*); }; - inline static py_Type m_type = 0; - - PKBIND_TYPE_IMPL(object, capsule, m_type); - - static void register_() { - m_type = py_newtype("capsule", tp_object, nullptr, [](void* data) { + inline static lazy tp_capsule = +[](py_Type& type) { + type = py_newtype("capsule", tp_object, nullptr, [](void* data) { auto impl = static_cast(data); if(impl->data && impl->destructor) { impl->destructor(impl->data); } }); - } + }; capsule(void* data, void (*destructor)(void*) = nullptr) : object(alloc_t{}) { - void* impl = py_newobject(m_ptr, m_type, 0, sizeof(capsule_impl)); + void* impl = py_newobject(m_ptr, tp_capsule, 0, sizeof(capsule_impl)); new (impl) capsule_impl{data, destructor}; } diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 1593c2c7..40ca61b9 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -1,6 +1,8 @@ #pragma once #include "internal/class.h" +#include "internal/function.h" +#include "internal/types.h" namespace pkbind { @@ -14,15 +16,6 @@ inline bool initialized = false; inline void initialize(int object_pool_size = 1024) { if(!initialized) { py_initialize(); } - // initialize all registers. - reg<0>.value = py_getreg(0); - reg<1>.value = py_getreg(1); - reg<2>.value = py_getreg(2); - reg<3>.value = py_getreg(3); - reg<4>.value = py_getreg(4); - reg<5>.value = py_getreg(5); - reg<6>.value = py_getreg(6); - // initialize ret. retv.value = py_retval(); @@ -31,10 +24,6 @@ inline void initialize(int object_pool_size = 1024) { m_type_map = new std::unordered_map(); - // register types. - capsule::register_(); - cpp_function::register_(); - action::initialize(); initialized = true; } @@ -46,6 +35,8 @@ inline void finalize(bool test = false) { m_type_map = nullptr; object_pool::finalize(); if(test) { + capsule::tp_capsule.reset(); + cpp_function::tp_function_record.reset(); py_resetvm(); } else { py_finalize();