#pragma once #include "cpp_function.h" namespace pybind11 { class module : public object { public: using object::object; static module import(const char* name) { if(name == std::string_view{"__main__"}) { return module{vm->_main, true}; } else { return module{vm->py_import(name, false), true}; } } }; // TODO: // 1. inheritance // 2. virtual function // 3. factory function template class class_ : public type { public: using type::type; template class_(const handle& scope, const char* name, Args&&... args) : type(vm->new_type_object(scope.ptr(), name, vm->tp_object, false, pkpy::PyTypeInfo::Vt::get()), true) { pkpy::PyVar mod = scope.ptr(); mod->attr().set(name, m_ptr); vm->_cxx_typeid_map[typeid(T)] = _builtin_cast(m_ptr); vm->bind_func(m_ptr, "__new__", -1, [](pkpy::VM* vm, pkpy::ArgsView args) { auto cls = _builtin_cast(args[0]); return instance::create(cls); }); } /// bind constructor template class_& def(init, const Extra&... extra) { if constexpr(!std::is_constructible_v) { static_assert(std::is_constructible_v, "Invalid constructor arguments"); } else { bind_function( *this, "__init__", [](T* self, Args... args) { new (self) T(args...); }, pkpy::BindType::DEFAULT, extra...); return *this; } } /// bind member function template class_& def(const char* name, Fn&& f, const Extra&... extra) { using first = std::tuple_element_t<0, callable_args_t>>; constexpr bool is_first_base_of_v = std::is_reference_v && std::is_base_of_v>; if constexpr(!is_first_base_of_v) { static_assert(is_first_base_of_v, "If you want to bind member function, the first argument must be the base class"); } else { bind_function(*this, name, std::forward(f), pkpy::BindType::DEFAULT, extra...); } return *this; } /// bind operators template class_& def(Operator op, const Extras&... extras) { op.execute(*this, extras...); return *this; } // TODO: factory function /// bind static function template class_& def_static(const char* name, Fn&& f, const Extra&... extra) { bind_function(*this, name, std::forward(f), pkpy::BindType::STATICMETHOD, extra...); return *this; } template class_& def_readwrite(const char* name, MP mp, const Extras&... extras) { if constexpr(!std::is_member_object_pointer_v) { static_assert(std::is_member_object_pointer_v, "def_readwrite only supports pointer to data member"); } else { bind_property(*this, name, mp, mp, extras...); } return *this; } template class_& def_readonly(const char* name, MP mp, const Extras&... extras) { if constexpr(!std::is_member_object_pointer_v) { static_assert(std::is_member_object_pointer_v, "def_readonly only supports pointer to data member"); } else { bind_property(*this, name, mp, nullptr, extras...); } return *this; } template class_& def_property(const char* name, Getter&& g, Setter&& s, const Extras&... extras) { bind_property(*this, name, std::forward(g), std::forward(s), extras...); return *this; } template class_& def_property_readonly(const char* name, Getter&& mp, const Extras&... extras) { bind_property(*this, name, std::forward(mp), nullptr, extras...); return *this; } template class_& def_readwrite_static(const char* name, Var& mp, const Extras&... extras) { static_assert( dependent_false, "define static properties requires metaclass. This is a complex feature with few use cases, so it may never be implemented."); return *this; } template class_& def_readonly_static(const char* name, Var& mp, const Extras&... extras) { static_assert( dependent_false, "define static properties requires metaclass. This is a complex feature with few use cases, so it may never be implemented."); return *this; } template class_& def_property_static(const char* name, Getter&& g, Setter&& s, const Extras&... extras) { static_assert( dependent_false, "define static properties requires metaclass. This is a complex feature with few use cases, so it may never be implemented."); return *this; } }; template class enum_ : public class_ { std::map m_values; public: using class_::class_; template enum_(const handle& scope, const char* name, Args&&... args) : class_(scope, name, std::forward(args)...) {} enum_& value(const char* name, T value) { handle var = type_caster::cast(value, return_value_policy::copy); this->m_ptr->attr().set(name, var.ptr()); m_values[name] = var.ptr(); return *this; } enum_& export_values() { pkpy::PyVar mod = this->m_ptr->attr("__module__"); for(auto& [name, value]: m_values) { mod->attr().set(name, value); } return *this; } }; } // namespace pybind11