mirror of
https://github.com/boostorg/python.git
synced 2026-01-26 18:52:26 +00:00
Nicer syntactic sugar
[SVN r12447]
This commit is contained in:
@@ -6,7 +6,6 @@
|
||||
#ifndef CLASS_DWA200216_HPP
|
||||
# define CLASS_DWA200216_HPP
|
||||
|
||||
# include <boost/python/module.hpp>
|
||||
# include <boost/python/reference.hpp>
|
||||
# include <boost/python/object/class.hpp>
|
||||
# include <boost/python/converter/type_id.hpp>
|
||||
@@ -84,26 +83,26 @@ template <
|
||||
, class Bases = mpl::type_list<>::type
|
||||
, class HolderGenerator = objects::value_holder_generator
|
||||
>
|
||||
class class_ : objects::class_base
|
||||
class class_ : private objects::class_base
|
||||
{
|
||||
typedef class_<T,Bases,HolderGenerator> self;
|
||||
public:
|
||||
|
||||
// Construct with the module and automatically derive the class
|
||||
// name
|
||||
class_(module&);
|
||||
// Automatically derive the class name - only works on some
|
||||
// compilers because type_info::name is sometimes mangled (gcc)
|
||||
class_();
|
||||
|
||||
// Construct with the module and class name. [ Would have used a
|
||||
// default argument but gcc-2.95.2 choked on typeid(T).name() as a
|
||||
// default parameter value]
|
||||
class_(module&, char const* name);
|
||||
// Construct with the class name. [ Would have used a default
|
||||
// argument but gcc-2.95.2 choked on typeid(T).name() as a default
|
||||
// parameter value]
|
||||
class_(char const* name);
|
||||
|
||||
|
||||
// Wrap a member function or a non-member function which can take
|
||||
// a T, T cv&, or T cv* as its first parameter, or a callable
|
||||
// python object.
|
||||
template <class F>
|
||||
self& def(F f, char const* name)
|
||||
self& def(char const* name, F f)
|
||||
{
|
||||
// Use function::add_to_namespace to achieve overloading if
|
||||
// appropriate.
|
||||
@@ -117,7 +116,7 @@ class class_ : objects::class_base
|
||||
template <class Args>
|
||||
self& def_init(Args const& = Args())
|
||||
{
|
||||
def(make_constructor<T,Args,HolderGenerator>(), "__init__");
|
||||
def("__init__", make_constructor<T,Args,HolderGenerator>());
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -128,6 +127,9 @@ class class_ : objects::class_base
|
||||
return *this;
|
||||
}
|
||||
|
||||
// return the underlying object
|
||||
ref object() const;
|
||||
|
||||
private: // types
|
||||
typedef objects::class_id class_id;
|
||||
|
||||
@@ -160,9 +162,8 @@ class class_ : objects::class_base
|
||||
// implementations
|
||||
//
|
||||
template <class T, class Bases, class HolderGenerator>
|
||||
inline class_<T, Bases, HolderGenerator>::class_(
|
||||
module& m)
|
||||
: class_base(m, typeid(T).name(), id_vector::size, id_vector().ids)
|
||||
inline class_<T, Bases, HolderGenerator>::class_()
|
||||
: class_base(typeid(T).name(), id_vector::size, id_vector().ids)
|
||||
{
|
||||
// Bring the class converters into existence. This static object
|
||||
// will survive until the shared library this module lives in is
|
||||
@@ -171,9 +172,8 @@ inline class_<T, Bases, HolderGenerator>::class_(
|
||||
}
|
||||
|
||||
template <class T, class Bases, class HolderGenerator>
|
||||
inline class_<T, Bases, HolderGenerator>::class_(
|
||||
module& m, char const* name)
|
||||
: class_base(m, name, id_vector::size, id_vector().ids)
|
||||
inline class_<T, Bases, HolderGenerator>::class_(char const* name)
|
||||
: class_base(name, id_vector::size, id_vector().ids)
|
||||
{
|
||||
// Bring the class converters into existence. This static object
|
||||
// will survive until the shared library this module lives in is
|
||||
@@ -181,6 +181,12 @@ inline class_<T, Bases, HolderGenerator>::class_(
|
||||
static objects::class_converters<T,Bases> converters(object());
|
||||
}
|
||||
|
||||
template <class T, class Bases, class HolderGenerator>
|
||||
inline ref class_<T, Bases, HolderGenerator>::object() const
|
||||
{
|
||||
return this->class_base::object();
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // CLASS_DWA200216_HPP
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
template <class T, class Bases, class HolderGenerator> class class_;
|
||||
|
||||
class BOOST_PYTHON_DECL module_base
|
||||
{
|
||||
public:
|
||||
@@ -23,18 +25,12 @@ class BOOST_PYTHON_DECL module_base
|
||||
~module_base();
|
||||
|
||||
// Add elements to the module
|
||||
void add(PyObject* x, const char* name);
|
||||
void add(PyTypeObject* x, const char* name = 0);
|
||||
void add(ref const& x, const char*name);
|
||||
|
||||
// Return true iff a module is currently being built.
|
||||
static bool initializing();
|
||||
void setattr(const char* name, PyObject*);
|
||||
void setattr(const char* name, ref const&);
|
||||
void add(PyTypeObject* x); // just use the type's name
|
||||
void add_type(ref);
|
||||
|
||||
// Return the name of the module currently being built.
|
||||
// REQUIRES: initializing() == true
|
||||
static string name();
|
||||
|
||||
// Return a pointer to the Python module object being built
|
||||
// Return a reference to the Python module object being built
|
||||
ref module() const;
|
||||
|
||||
private:
|
||||
@@ -48,17 +44,34 @@ class module : public module_base
|
||||
module(const char* name)
|
||||
: module_base(name) {}
|
||||
|
||||
// Add elements to the module
|
||||
module& setattr(const char* name, PyObject*);
|
||||
module& setattr(const char* name, PyTypeObject*);
|
||||
module& setattr(const char* name, ref const&);
|
||||
module& add(PyTypeObject* x); // just use the type's name
|
||||
|
||||
template <class T, class Bases, class HolderGenerator>
|
||||
module& add(class_<T,Bases,HolderGenerator> const& c)
|
||||
{
|
||||
std::cout << "adding " << typeid(T).name() << " to module" << std::endl << std::flush;
|
||||
Py_INCREF(c.object());
|
||||
this->add_type(c.object());
|
||||
return *this;
|
||||
}
|
||||
|
||||
# if 0
|
||||
template <class Fn>
|
||||
void def_raw(Fn fn, const char* name)
|
||||
void def_raw(char const* name, Fn fn)
|
||||
{
|
||||
add(detail::new_raw_arguments_function(fn), name);
|
||||
}
|
||||
# endif
|
||||
# endif
|
||||
|
||||
template <class Fn>
|
||||
void def(Fn fn, const char* name)
|
||||
module& def(char const* name, Fn fn)
|
||||
{
|
||||
this->add(boost::python::make_function(fn), name);
|
||||
this->setattr(name, boost::python::make_function(fn));
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -70,6 +83,30 @@ inline ref module_base::module() const
|
||||
return m_module;
|
||||
}
|
||||
|
||||
inline module& module::setattr(const char* name, PyObject* x)
|
||||
{
|
||||
this->module_base::setattr(name, x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline module& module::setattr(const char* name, PyTypeObject* x)
|
||||
{
|
||||
this->module_base::setattr(name, (PyObject*)x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline module& module::setattr(const char* name, ref const& x)
|
||||
{
|
||||
this->module_base::setattr(name, x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline module& module::add(PyTypeObject* x)
|
||||
{
|
||||
this->module_base::add(x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // MODULE_DWA20011221_HPP
|
||||
|
||||
@@ -30,8 +30,7 @@ struct BOOST_PYTHON_DECL class_base : noncopyable
|
||||
{
|
||||
// constructor
|
||||
class_base(
|
||||
module& name_space // Which name space the class will live in
|
||||
, char const* name // The name of the class
|
||||
char const* name // The name of the class
|
||||
|
||||
, std::size_t num_types // A list of class_ids. The first is the type
|
||||
, class_id const*const types // this is wrapping. The rest are the types of
|
||||
|
||||
@@ -10,53 +10,38 @@
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace {
|
||||
ref name_holder;
|
||||
}
|
||||
|
||||
bool module_base::initializing()
|
||||
{
|
||||
return name_holder.get() != 0;
|
||||
}
|
||||
|
||||
string module_base::name()
|
||||
{
|
||||
// If this fails, you haven't created a module object
|
||||
assert(initializing());
|
||||
return string(name_holder);
|
||||
}
|
||||
|
||||
module_base::module_base(const char* name)
|
||||
: m_module(
|
||||
Py_InitModule(const_cast<char*>(name), initial_methods)
|
||||
, ref::increment_count)
|
||||
{
|
||||
// If this fails, you've created more than 1 module object in your module
|
||||
assert(name_holder.get() == 0);
|
||||
name_holder = ref(PyObject_GetAttrString(
|
||||
m_module.get() , const_cast<char*>("__name__")));
|
||||
}
|
||||
|
||||
module_base::~module_base()
|
||||
{
|
||||
name_holder.reset();
|
||||
}
|
||||
|
||||
void module_base::add(PyObject* x, const char* name)
|
||||
void module_base::setattr(const char* name, PyObject* x)
|
||||
{
|
||||
add(ref(x), name);
|
||||
setattr(name, ref(x));
|
||||
}
|
||||
|
||||
void module_base::add(ref const& x, const char* name)
|
||||
void module_base::setattr(char const* name, ref const& x)
|
||||
{
|
||||
// Use function::add_to_namespace to achieve overloading if
|
||||
// appropriate.
|
||||
objects::function::add_to_namespace(m_module, name, x);
|
||||
}
|
||||
|
||||
void module_base::add(PyTypeObject* x, const char* name /*= 0*/)
|
||||
void module_base::add(PyTypeObject* x)
|
||||
{
|
||||
this->add((PyObject*)x, name ? name : x->tp_name);
|
||||
this->setattr(x->tp_name, (PyObject*)x);
|
||||
}
|
||||
|
||||
void module_base::add_type(ref x)
|
||||
{
|
||||
assert(PyObject_TypeCheck(x.get(), &PyType_Type));
|
||||
add((PyTypeObject*)x.release());
|
||||
}
|
||||
|
||||
PyMethodDef module_base::initial_methods[] = { { 0, 0, 0, 0 } };
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <boost/python/detail/map_entry.hpp>
|
||||
#include <boost/detail/binary_search.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/python/detail/wrap_python.hpp>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
@@ -190,11 +189,11 @@ namespace
|
||||
|
||||
std::vector<entry>::const_iterator p
|
||||
= boost::detail::lower_bound(start, finish, id);
|
||||
|
||||
|
||||
if (p == finish && p->key != id)
|
||||
{
|
||||
string report("extension class wrapper for base class ");
|
||||
(report += id.name()) += "has not been created yet";
|
||||
(report += id.name()) += " has not been created yet";
|
||||
PyErr_SetObject(PyExc_RuntimeError, report.get());
|
||||
throw error_already_set();
|
||||
}
|
||||
@@ -212,7 +211,7 @@ namespace
|
||||
}
|
||||
|
||||
class_base::class_base(
|
||||
module& m, char const* name, std::size_t num_types, class_id const* const types)
|
||||
char const* name, std::size_t num_types, class_id const* const types)
|
||||
{
|
||||
class_registry& r = registry();
|
||||
assert(num_types >= 1);
|
||||
@@ -234,7 +233,6 @@ class_base::class_base(
|
||||
|
||||
m_object = ref(PyObject_CallObject(class_metatype().get(), args.get()));
|
||||
r.set(types[0], m_object);
|
||||
m.add(m_object, name);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::objects
|
||||
|
||||
Reference in New Issue
Block a user