2
0
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:
Dave Abrahams
2002-01-22 19:51:04 +00:00
parent 51a66a3202
commit 0389aab0a3
5 changed files with 90 additions and 65 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 } };

View File

@@ -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