2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-20 04:42:28 +00:00

Compare commits

..

2 Commits

Author SHA1 Message Date
Dave Abrahams
f8934fa00f Began trying to get 0 pointers to be translated to/from None
[SVN r9374]
2001-03-02 01:14:16 +00:00
nobody
fcf452e24a This commit was manufactured by cvs2svn to create branch
'null_ptr_is_none'.

[SVN r8443]
2000-12-10 03:41:33 +00:00
125 changed files with 907 additions and 7703 deletions

View File

@@ -0,0 +1,907 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
//
// This file automatically generated for 10-argument constructors by
// gen_extclass.python
#ifndef EXTENSION_CLASS_DWA052000_H_
# define EXTENSION_CLASS_DWA052000_H_
# include <boost/python/detail/config.hpp>
# include <boost/python/classes.hpp>
# include <vector>
# include <boost/python/detail/none.hpp>
# include <boost/python/objects.hpp>
# include <boost/python/detail/functions.hpp>
# include <memory>
# include <boost/python/detail/init_function.hpp>
# include <typeinfo>
# include <boost/smart_ptr.hpp>
# include <boost/type_traits.hpp>
namespace boost { namespace python {
// forward declarations
template <long which, class operand> struct operators;
template <class T> struct left_operand;
template <class T> struct right_operand;
enum without_downcast_t { without_downcast };
namespace detail {
// forward declarations
class extension_instance;
class extension_class_base;
template <class T> class instance_holder;
template <class T, class U> class instance_value_holder;
template <class ref, class T> class instance_ptr_holder;
template <class Specified> struct operand_select;
template <long> struct choose_op;
template <long> struct choose_rop;
template <long> struct choose_unary_op;
template <long> struct define_operator;
meta_class<extension_instance>* extension_meta_class();
extension_instance* get_extension_instance(PyObject* p);
void report_missing_instance_data(extension_instance*, class_t<extension_instance>*, const std::type_info&);
void report_missing_ptr_data(extension_instance*, class_t<extension_instance>*, const std::type_info&);
void report_missing_class_object(const std::type_info&);
void report_released_smart_pointer(const std::type_info&);
template <class T>
T* check_non_null(T* p)
{
if (p == 0)
report_released_smart_pointer(typeid(T));
return p;
}
template <class T> class held_instance;
typedef void* (*conversion_function_ptr)(void*);
struct base_class_info
{
base_class_info(extension_class_base* t, conversion_function_ptr f)
:class_object(t), convert(f)
{}
extension_class_base* class_object;
conversion_function_ptr convert;
};
typedef base_class_info derived_class_info;
struct add_operator_base;
class extension_class_base : public class_t<extension_instance>
{
public:
extension_class_base(const char* name);
public:
// the purpose of try_class_conversions() and its related functions
// is explained in extclass.cpp
void* try_class_conversions(instance_holder_base*) const;
void* try_base_class_conversions(instance_holder_base*) const;
void* try_derived_class_conversions(instance_holder_base*) const;
void set_attribute(const char* name, PyObject* x);
void set_attribute(const char* name, ref x);
private:
virtual void* extract_object_from_holder(instance_holder_base* v) const = 0;
virtual std::vector<base_class_info> const& base_classes() const = 0;
virtual std::vector<derived_class_info> const& derived_classes() const = 0;
protected:
friend struct add_operator_base;
void add_method(reference<function> method, const char* name);
void add_method(function* method, const char* name);
void add_constructor_object(function*);
void add_setter_method(function*, const char* name);
void add_getter_method(function*, const char* name);
};
template <class T>
class class_registry
{
public:
static extension_class_base* class_object()
{ return static_class_object; }
// Register/unregister the Python class object corresponding to T
static void register_class(extension_class_base*);
static void unregister_class(extension_class_base*);
// Establish C++ inheritance relationships
static void register_base_class(base_class_info const&);
static void register_derived_class(derived_class_info const&);
// Query the C++ inheritance relationships
static std::vector<base_class_info> const& base_classes();
static std::vector<derived_class_info> const& derived_classes();
private:
static extension_class_base* static_class_object;
static std::vector<base_class_info> static_base_class_info;
static std::vector<derived_class_info> static_derived_class_info;
};
template <bool is_pointer>
struct is_null_helper
{
template <class Ptr>
static bool test(Ptr x) { return x == 0; }
};
template <>
struct is_null_helper<false>
{
template <class Ptr>
static bool test(Ptr x) { return x.get() == 0; }
};
template <class Ptr>
bool is_null(const Ptr& x)
{
return is_null_helper<(is_pointer<Ptr>::value)>::test(x);
};
}}} // namespace boost::python::detail
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
// This class' only job is to define from_python and to_python converters for T
// and U. T is the class the user really intends to wrap. U is a class derived
// from T with some virtual function overriding boilerplate, or if there are no
// virtual functions, U = held_instance<T>.
template <class T, class U = boost::python::detail::held_instance<T> >
class python_extension_class_converters
{
public:
// Get an object which can be used to convert T to/from python. This is used
// as a kind of concept check by the global template
//
// PyObject* to_python(const T& x)
//
// below this class, to prevent the confusing messages that would otherwise
// pop up. Now, if T hasn't been wrapped as an extension class, the user
// will see an error message about the lack of an eligible
// py_extension_class_converters() function.
friend python_extension_class_converters py_extension_class_converters(boost::python::type<T>)
{
return python_extension_class_converters();
}
// This is a member function because in a conforming implementation, friend
// funcitons defined inline in the class body are all instantiated as soon
// as the enclosing class is instantiated. If T is not copyable, that causes
// a compiler error. Instead, we access this function through the global
// template
//
// PyObject* to_python(const T& x)
//
// defined below this class. Since template functions are instantiated only
// on demand, errors will be avoided unless T is noncopyable and the user
// writes code which causes us to try to copy a T.
PyObject* to_python(const T& x) const
{
boost::python::reference<boost::python::detail::extension_instance> result(create_instance());
result->add_implementation(
std::auto_ptr<boost::python::detail::instance_holder_base>(
new boost::python::detail::instance_value_holder<T,U>(result.get(), x)));
return result.release();
}
friend
T* non_null_from_python(PyObject* obj, boost::python::type<T*>)
{
// downcast to an extension_instance, then find the actual T
boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj);
typedef std::vector<boost::python::detail::instance_holder_base*>::const_iterator iterator;
for (iterator p = self->wrapped_objects().begin();
p != self->wrapped_objects().end(); ++p)
{
boost::python::detail::instance_holder<T>* held = dynamic_cast<boost::python::detail::instance_holder<T>*>(*p);
if (held != 0)
return held->target();
// see extclass.cpp for an explanation of try_class_conversions()
void* target = boost::python::detail::class_registry<T>::class_object()->try_class_conversions(*p);
if(target)
return static_cast<T*>(target);
}
boost::python::detail::report_missing_instance_data(self, boost::python::detail::class_registry<T>::class_object(), typeid(T));
throw boost::python::argument_error();
}
// Convert to T*
friend T* from_python(PyObject* obj, boost::python::type<T*>)
{
if (obj == Py_None)
return 0;
else
return non_null_from_python(obj, boost::python::type<T*>());
}
// Convert to PtrType, where PtrType can be dereferenced to obtain a T.
template <class PtrType>
static PtrType& ptr_from_python(PyObject* obj, boost::python::type<PtrType>)
{
// downcast to an extension_instance, then find the actual T
boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj);
typedef std::vector<boost::python::detail::instance_holder_base*>::const_iterator iterator;
for (iterator p = self->wrapped_objects().begin();
p != self->wrapped_objects().end(); ++p)
{
boost::python::detail::instance_ptr_holder<PtrType, T>* held =
dynamic_cast<boost::python::detail::instance_ptr_holder<PtrType, T>*>(*p);
if (held != 0)
return held->ptr();
}
boost::python::detail::report_missing_ptr_data(self, boost::python::detail::class_registry<T>::class_object(), typeid(T));
throw boost::python::argument_error();
}
template <class PtrType>
static const PtrType& ptr_const_ref_from_python(PyObject* obj, boost::python::type<PtrType>)
{
if (obj == Py_None)
{
static PtrType null_ptr;
return null_ptr;
}
return ptr_from_python(obj, boost::python::type<PtrType>());
}
template <class PtrType>
static PyObject* ptr_to_python(PtrType x)
{
if (boost::python::detail::is_null(x))
{
return boost::python::detail::none();
}
boost::python::reference<boost::python::detail::extension_instance> result(create_instance());
result->add_implementation(
std::auto_ptr<boost::python::detail::instance_holder_base>(
new boost::python::detail::instance_ptr_holder<PtrType,T>(x)));
return result.release();
}
static boost::python::reference<boost::python::detail::extension_instance> create_instance()
{
PyTypeObject* class_object = boost::python::detail::class_registry<T>::class_object();
if (class_object == 0)
boost::python::detail::report_missing_class_object(typeid(T));
return boost::python::reference<boost::python::detail::extension_instance>(
new boost::python::detail::extension_instance(class_object));
}
// Convert to const T*
friend const T* from_python(PyObject* p, boost::python::type<const T*>)
{ return from_python(p, boost::python::type<T*>()); }
// Convert to const T* const&
friend const T* from_python(PyObject* p, boost::python::type<const T*const&>)
{ return from_python(p, boost::python::type<const T*>()); }
// Convert to T* const&
friend T* from_python(PyObject* p, boost::python::type<T* const&>)
{ return from_python(p, boost::python::type<T*>()); }
// Convert to T&
friend T& from_python(PyObject* p, boost::python::type<T&>)
{ return *boost::python::detail::check_non_null(non_null_from_python(p, boost::python::type<T*>())); }
// Convert to const T&
friend const T& from_python(PyObject* p, boost::python::type<const T&>)
{ return from_python(p, boost::python::type<T&>()); }
// Convert to T
friend const T& from_python(PyObject* p, boost::python::type<T>)
{ return from_python(p, boost::python::type<T&>()); }
friend std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<std::auto_ptr<T>&>)
{ return ptr_from_python(p, boost::python::type<std::auto_ptr<T> >()); }
friend const std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<std::auto_ptr<T> >)
{ return ptr_const_ref_from_python(p, boost::python::type<std::auto_ptr<T> >()); }
friend const std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<const std::auto_ptr<T>&>)
{ return ptr_const_ref_from_python(p, boost::python::type<std::auto_ptr<T> >()); }
friend PyObject* to_python(std::auto_ptr<T> x)
{ return ptr_to_python(x); }
friend boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T>&>)
{ return ptr_from_python(p, boost::python::type<boost::shared_ptr<T> >()); }
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T> >)
{ return ptr_const_ref_from_python(p, boost::python::type<boost::shared_ptr<T> >()); }
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<const boost::shared_ptr<T>&>)
{ return ptr_const_ref_from_python(p, boost::python::type<boost::shared_ptr<T> >()); }
friend PyObject* to_python(boost::shared_ptr<T> x)
{ return ptr_to_python(x); }
};
// Convert T to_python, instantiated on demand and only if there isn't a
// non-template overload for this function. This version is the one invoked when
// T is a wrapped class. See the first 2 functions declared in
// python_extension_class_converters above for more info.
template <class T>
PyObject* to_python(const T& x)
{
return py_extension_class_converters(boost::python::type<T>()).to_python(x);
}
BOOST_PYTHON_END_CONVERSION_NAMESPACE
namespace boost { namespace python {
BOOST_PYTHON_IMPORT_CONVERSION(python_extension_class_converters);
namespace detail {
template <class T> class instance_holder;
class read_only_setattr_function : public function
{
public:
read_only_setattr_function(const char* name);
PyObject* do_call(PyObject* args, PyObject* keywords) const;
const char* description() const;
private:
string m_name;
};
template <class From, class To>
struct define_conversion
{
static void* upcast_ptr(void* v)
{
return static_cast<To*>(static_cast<From*>(v));
}
static void* downcast_ptr(void* v)
{
return dynamic_cast<To*>(static_cast<From*>(v));
}
};
// An easy way to make an extension base class which wraps T. Note that Python
// subclasses of this class will simply be class_t<extension_instance> objects.
//
// U should be a class derived from T which overrides virtual functions with
// boilerplate code to call back into Python. See extclass_demo.h for examples.
//
// U is optional, but you won't be able to override any member functions in
// Python which are called from C++ if you don't supply it. If you just want to
// be able to use T in python without overriding member functions, you can omit
// U.
template <class T, class U = held_instance<T> >
class extension_class
: public python_extension_class_converters<T, U>, // This generates the to_python/from_python functions
public extension_class_base
{
public:
typedef T wrapped_type;
typedef U callback_type;
// Construct with a name that comes from typeid(T).name(). The name only
// affects the objects of this class are represented through repr()
extension_class();
// Construct with the given name. The name only affects the objects of this
// class are represented through repr()
extension_class(const char* name);
~extension_class();
// define constructors
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
inline void def(constructor<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>)
// The following incantation builds a signature1, signature2,... object. It
// should _all_ get optimized away.
{ add_constructor(
prepend(type<A1>::id(),
prepend(type<A2>::id(),
prepend(type<A3>::id(),
prepend(type<A4>::id(),
prepend(type<A5>::id(),
prepend(type<A6>::id(),
prepend(type<A7>::id(),
prepend(type<A8>::id(),
prepend(type<A9>::id(),
prepend(type<A10>::id(),
signature0())))))))))));
}
// export homogeneous operators (type of both lhs and rhs is 'operator')
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub), Foo>());
// export homogeneous operators (type of both lhs and rhs is 'T const&')
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub)>());
template <long which, class Operand>
inline void def(operators<which,Operand>)
{
typedef typename operand_select<Operand>::template wrapped<T>::type true_operand;
def_operators(operators<which,true_operand>());
}
// export heterogeneous operators (type of lhs: 'left', of rhs: 'right')
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub), Foo>(),
// boost::python::right_operand<int const&>());
// export heterogeneous operators (type of lhs: 'T const&', of rhs: 'right')
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub)>(),
// boost::python::right_operand<int const&>());
template <long which, class Left, class Right>
inline void def(operators<which,Left>, right_operand<Right> r)
{
typedef typename operand_select<Left>::template wrapped<T>::type true_left;
def_operators(operators<which,true_left>(), r);
}
// export heterogeneous reverse-argument operators
// (type of lhs: 'left', of rhs: 'right')
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub), Foo>(),
// boost::python::left_operand<int const&>());
// export heterogeneous reverse-argument operators
// (type of lhs: 'left', of rhs: 'T const&')
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub)>(),
// boost::python::left_operand<int const&>());
template <long which, class Left, class Right>
inline void def(operators<which,Right>, left_operand<Left> l)
{
typedef typename operand_select<Right>::template wrapped<T>::type true_right;
def_operators(operators<which,true_right>(), l);
}
// define a function that passes Python arguments and keywords
// to C++ verbatim (as a 'tuple const&' and 'dictionary const&'
// respectively). This is useful for manual argument passing.
// It's also the only possibility to pass keyword arguments to C++.
// Fn must have a signatur that is compatible to
// PyObject* (*)(PyObject* aTuple, PyObject* aDictionary)
template <class Fn>
inline void def_raw(Fn fn, const char* name)
{
this->add_method(new_raw_arguments_function(fn), name);
}
// define member functions. In fact this works for free functions, too -
// they act like static member functions, or if they start with the
// appropriate self argument (as a pointer), they can be used just like
// ordinary member functions -- just like Python!
template <class Fn>
inline void def(Fn fn, const char* name)
{
this->add_method(new_wrapped_function(fn), name);
}
// Define a virtual member function with a default implementation.
// default_fn should be a function which provides the default implementation.
// Be careful that default_fn does not in fact call fn virtually!
template <class Fn, class DefaultFn>
inline void def(Fn fn, const char* name, DefaultFn default_fn)
{
this->add_method(new_virtual_function(type<T>(), fn, default_fn), name);
}
// Provide a function which implements x.<name>, reading from the given
// member (pm) of the T obj
template <class MemberType>
inline void def_getter(MemberType T::*pm, const char* name)
{
this->add_getter_method(new getter_function<T, MemberType>(pm), name);
}
// Provide a function which implements assignment to x.<name>, writing to
// the given member (pm) of the T obj
template <class MemberType>
inline void def_setter(MemberType T::*pm, const char* name)
{
this->add_setter_method(new setter_function<T, MemberType>(pm), name);
}
// Expose the given member (pm) of the T obj as a read-only attribute
template <class MemberType>
inline void def_readonly(MemberType T::*pm, const char* name)
{
this->add_setter_method(new read_only_setattr_function(name), name);
this->def_getter(pm, name);
}
// Expose the given member (pm) of the T obj as a read/write attribute
template <class MemberType>
inline void def_read_write(MemberType T::*pm, const char* name)
{
this->def_getter(pm, name);
this->def_setter(pm, name);
}
// define the standard coercion needed for operator overloading
void def_standard_coerce();
// declare the given class a base class of this one and register
// up and down conversion functions
template <class S, class V>
void declare_base(extension_class<S, V>* base)
{
// see extclass.cpp for an explanation of why we need to register
// conversion functions
base_class_info baseInfo(base,
&define_conversion<S, T>::downcast_ptr);
class_registry<T>::register_base_class(baseInfo);
add_base(ref(as_object(base), ref::increment_count));
derived_class_info derivedInfo(this,
&define_conversion<T, S>::upcast_ptr);
class_registry<S>::register_derived_class(derivedInfo);
}
// declare the given class a base class of this one and register
// only up conversion function
template <class S, class V>
void declare_base(extension_class<S, V>* base, without_downcast_t)
{
// see extclass.cpp for an explanation of why we need to register
// conversion functions
base_class_info baseInfo(base, 0);
class_registry<T>::register_base_class(baseInfo);
add_base(ref(as_object(base), ref::increment_count));
derived_class_info derivedInfo(this,
&define_conversion<T, S>::upcast_ptr);
class_registry<S>::register_derived_class(derivedInfo);
}
private: // types
typedef instance_value_holder<T,U> holder;
private: // extension_class_base virtual function implementations
std::vector<base_class_info> const& base_classes() const;
std::vector<derived_class_info> const& derived_classes() const;
void* extract_object_from_holder(instance_holder_base* v) const;
private: // Utility functions
template <long which, class Operand>
inline void def_operators(operators<which,Operand>)
{
def_standard_coerce();
// for some strange reason, this prevents MSVC from having an
// "unrecoverable block scoping error"!
typedef choose_op<(which & op_add)> choose_add;
choose_op<(which & op_add)>::template args<Operand>::add(this);
choose_op<(which & op_sub)>::template args<Operand>::add(this);
choose_op<(which & op_mul)>::template args<Operand>::add(this);
choose_op<(which & op_div)>::template args<Operand>::add(this);
choose_op<(which & op_mod)>::template args<Operand>::add(this);
choose_op<(which & op_divmod)>::template args<Operand>::add(this);
choose_op<(which & op_pow)>::template args<Operand>::add(this);
choose_op<(which & op_lshift)>::template args<Operand>::add(this);
choose_op<(which & op_rshift)>::template args<Operand>::add(this);
choose_op<(which & op_and)>::template args<Operand>::add(this);
choose_op<(which & op_xor)>::template args<Operand>::add(this);
choose_op<(which & op_or)>::template args<Operand>::add(this);
choose_unary_op<(which & op_neg)>::template args<Operand>::add(this);
choose_unary_op<(which & op_pos)>::template args<Operand>::add(this);
choose_unary_op<(which & op_abs)>::template args<Operand>::add(this);
choose_unary_op<(which & op_invert)>::template args<Operand>::add(this);
choose_unary_op<(which & op_int)>::template args<Operand>::add(this);
choose_unary_op<(which & op_long)>::template args<Operand>::add(this);
choose_unary_op<(which & op_float)>::template args<Operand>::add(this);
choose_op<(which & op_cmp)>::template args<Operand>::add(this);
choose_unary_op<(which & op_str)>::template args<Operand>::add(this);
}
template <long which, class Left, class Right>
inline void def_operators(operators<which,Left>, right_operand<Right>)
{
def_standard_coerce();
choose_op<(which & op_add)>::template args<Left,Right>::add(this);
choose_op<(which & op_sub)>::template args<Left,Right>::add(this);
choose_op<(which & op_mul)>::template args<Left,Right>::add(this);
choose_op<(which & op_div)>::template args<Left,Right>::add(this);
choose_op<(which & op_mod)>::template args<Left,Right>::add(this);
choose_op<(which & op_divmod)>::template args<Left,Right>::add(this);
choose_op<(which & op_pow)>::template args<Left,Right>::add(this);
choose_op<(which & op_lshift)>::template args<Left,Right>::add(this);
choose_op<(which & op_rshift)>::template args<Left,Right>::add(this);
choose_op<(which & op_and)>::template args<Left,Right>::add(this);
choose_op<(which & op_xor)>::template args<Left,Right>::add(this);
choose_op<(which & op_or)>::template args<Left,Right>::add(this);
choose_op<(which & op_cmp)>::template args<Left,Right>::add(this);
}
template <long which, class Left, class Right>
inline void def_operators(operators<which,Right>, left_operand<Left>)
{
def_standard_coerce();
choose_rop<(which & op_add)>::template args<Left,Right>::add(this);
choose_rop<(which & op_sub)>::template args<Left,Right>::add(this);
choose_rop<(which & op_mul)>::template args<Left,Right>::add(this);
choose_rop<(which & op_div)>::template args<Left,Right>::add(this);
choose_rop<(which & op_mod)>::template args<Left,Right>::add(this);
choose_rop<(which & op_divmod)>::template args<Left,Right>::add(this);
choose_rop<(which & op_pow)>::template args<Left,Right>::add(this);
choose_rop<(which & op_lshift)>::template args<Left,Right>::add(this);
choose_rop<(which & op_rshift)>::template args<Left,Right>::add(this);
choose_rop<(which & op_and)>::template args<Left,Right>::add(this);
choose_rop<(which & op_xor)>::template args<Left,Right>::add(this);
choose_rop<(which & op_or)>::template args<Left,Right>::add(this);
choose_rop<(which & op_cmp)>::template args<Left,Right>::add(this);
}
template <class signature>
void add_constructor(signature sig)
{
this->add_constructor_object(init_function<holder>::create(sig));
}
};
// A simple wrapper over a T which allows us to use extension_class<T> with a
// single template parameter only. See extension_class<T>, above.
template <class T>
class held_instance : public T
{
// There are no member functions: we want to avoid inadvertently overriding
// any virtual functions in T.
public:
held_instance(PyObject*) : T() {}
template <class A1>
held_instance(PyObject*, A1 a1) : T(a1) {}
template <class A1, class A2>
held_instance(PyObject*, A1 a1, A2 a2) : T(a1, a2) {}
template <class A1, class A2, class A3>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3) : T(a1, a2, a3) {}
template <class A1, class A2, class A3, class A4>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) : T(a1, a2, a3, a4) {}
template <class A1, class A2, class A3, class A4, class A5>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : T(a1, a2, a3, a4, a5) {}
template <class A1, class A2, class A3, class A4, class A5, class A6>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) : T(a1, a2, a3, a4, a5, a6) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) : T(a1, a2, a3, a4, a5, a6, a7) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) : T(a1, a2, a3, a4, a5, a6, a7, a8) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) : T(a1, a2, a3, a4, a5, a6, a7, a8, a9) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) : T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {}
};
// Abstract base class for all obj holders. Base for template class
// instance_holder<>, below.
class instance_holder_base
{
public:
virtual ~instance_holder_base() {}
virtual bool held_by_value() = 0;
};
// Abstract base class which holds a Held, somehow. Provides a uniform way to
// get a pointer to the held object
template <class Held>
class instance_holder : public instance_holder_base
{
public:
virtual Held*target() = 0;
};
// Concrete class which holds a Held by way of a wrapper class Wrapper. If Held
// can be constructed with arguments (A1...An), Wrapper must have a
// corresponding constructor for arguments (PyObject*, A1...An). Wrapper is
// neccessary to implement virtual function callbacks (there must be a
// back-pointer to the actual Python object so that we can call any
// overrides). held_instance (above) is used as a default Wrapper class when
// there are no virtual functions.
template <class Held, class Wrapper>
class instance_value_holder : public instance_holder<Held>
{
public:
Held* target() { return &m_held; }
Wrapper* value_target() { return &m_held; }
instance_value_holder(extension_instance* p) :
m_held(p) {}
template <class A1>
instance_value_holder(extension_instance* p, A1 a1) :
m_held(p, a1) {}
template <class A1, class A2>
instance_value_holder(extension_instance* p, A1 a1, A2 a2) :
m_held(p, a1, a2) {}
template <class A1, class A2, class A3>
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3) :
m_held(p, a1, a2, a3) {}
template <class A1, class A2, class A3, class A4>
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4) :
m_held(p, a1, a2, a3, a4) {}
template <class A1, class A2, class A3, class A4, class A5>
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) :
m_held(p, a1, a2, a3, a4, a5) {}
template <class A1, class A2, class A3, class A4, class A5, class A6>
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) :
m_held(p, a1, a2, a3, a4, a5, a6) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) :
m_held(p, a1, a2, a3, a4, a5, a6, a7) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) :
m_held(p, a1, a2, a3, a4, a5, a6, a7, a8) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) :
m_held(p, a1, a2, a3, a4, a5, a6, a7, a8, a9) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) :
m_held(p, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {}
public: // implementation of instance_holder_base required interface
bool held_by_value() { return true; }
private:
Wrapper m_held;
};
// Concrete class which holds a HeldType by way of a (possibly smart) pointer
// PtrType. By default, these are only generated for PtrType ==
// std::auto_ptr<HeldType> and PtrType == boost::shared_ptr<HeldType>.
template <class PtrType, class HeldType>
class instance_ptr_holder : public instance_holder<HeldType>
{
public:
HeldType* target() { return &*m_ptr; }
PtrType& ptr() { return m_ptr; }
instance_ptr_holder(PtrType ptr) : m_ptr(ptr) {}
public: // implementation of instance_holder_base required interface
bool held_by_value() { return false; }
private:
PtrType m_ptr;
};
class extension_instance : public instance
{
public:
extension_instance(PyTypeObject* class_);
~extension_instance();
void add_implementation(std::auto_ptr<instance_holder_base> holder);
typedef std::vector<instance_holder_base*> held_objects;
const held_objects& wrapped_objects() const
{ return m_wrapped_objects; }
private:
held_objects m_wrapped_objects;
};
//
// Template function implementations
//
template <class T, class U>
extension_class<T, U>::extension_class()
: extension_class_base(typeid(T).name())
{
class_registry<T>::register_class(this);
}
template <class T, class U>
extension_class<T, U>::extension_class(const char* name)
: extension_class_base(name)
{
class_registry<T>::register_class(this);
}
template <class T, class U>
void extension_class<T, U>::def_standard_coerce()
{
ref coerce_fct = dict().get_item(string("__coerce__"));
if(coerce_fct.get() == 0) // not yet defined
this->def(&standard_coerce, "__coerce__");
}
template <class T, class U>
inline
std::vector<base_class_info> const&
extension_class<T, U>::base_classes() const
{
return class_registry<T>::base_classes();
}
template <class T, class U>
inline
std::vector<derived_class_info> const&
extension_class<T, U>::derived_classes() const
{
return class_registry<T>::derived_classes();
}
template <class T, class U>
void* extension_class<T, U>::extract_object_from_holder(instance_holder_base* v) const
{
instance_holder<T>* held = dynamic_cast<instance_holder<T>*>(v);
if(held)
return held->target();
return 0;
}
template <class T, class U>
extension_class<T, U>::~extension_class()
{
class_registry<T>::unregister_class(this);
}
template <class T>
inline void class_registry<T>::register_class(extension_class_base* p)
{
// You're not expected to create more than one of these!
assert(static_class_object == 0);
static_class_object = p;
}
template <class T>
inline void class_registry<T>::unregister_class(extension_class_base* p)
{
// The user should be destroying the same object they created.
assert(static_class_object == p);
(void)p; // unused in shipping version
static_class_object = 0;
}
template <class T>
void class_registry<T>::register_base_class(base_class_info const& i)
{
static_base_class_info.push_back(i);
}
template <class T>
void class_registry<T>::register_derived_class(derived_class_info const& i)
{
static_derived_class_info.push_back(i);
}
template <class T>
std::vector<base_class_info> const& class_registry<T>::base_classes()
{
return static_base_class_info;
}
template <class T>
std::vector<derived_class_info> const& class_registry<T>::derived_classes()
{
return static_derived_class_info;
}
//
// Static data member declaration.
//
template <class T>
extension_class_base* class_registry<T>::static_class_object;
template <class T>
std::vector<base_class_info> class_registry<T>::static_base_class_info;
template <class T>
std::vector<derived_class_info> class_registry<T>::static_derived_class_info;
}}} // namespace boost::python::detail
#endif // EXTENSION_CLASS_DWA052000_H_

View File

@@ -1,126 +0,0 @@
16 August 2003
Applied a patch by Gottfried Ganssauge that adds exception specifiers to
wrapper functions and pointer declarations. Thanks a lot Gottfried!!
Applied a patch by Prabhu Ramachandran that fixes ae problem with the
pure virtual method generation. Thanks again Prabhu!
10 August 2003
Support for incremental generation of the code has been added. This changes
how --multiple works; documentation of this new feature will follow. Thanks
to Prabhu Ramachandran, that saw the need for this feature and discussed a
solution.
Automatically convert \ to / in Windows systems before passing the paths to
gccxml.
Fixed a bug reported by Prabhu Ramachandran, where in some classes the virtual
methods were being definied incorrectly. Thanks a lot Prabhu!
7 July 2003
Applied 2 patches by Prabhu Ramachandran: a fix in the new --multiple method,
and two new functions "hold_with_shared_ptr" and its counterpart for auto_ptr.
Thanks a lot Prabhu!
Fixed a bug where the macro BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID was being
called multiple times for the same type.
Thanks to Gottfried Ganßauge for reporting this!
Fixed bug where using AllFromHeader didn't use bases<> when exporting
hierarchies.
Fixed the staticmethod bug.
5 July 2003
Changed how --multiple works: now it generates one cpp file for each pyste
file, makeing easier to integrate Pyste with build systems.
4 July 2003
Applied patch that solved a bug in ClassExporter and added a distutils install
script (install/setup.py), both contributed by Prabhu Ramachandran.
Thanks Prabhu!
2 July 2003
Jim Wilson found a bug where types like "char**" were being interpreted as
"char*". Thanks Jim!
16 June 2003
Thanks to discussions with David Abrahams and Roman Sulzhyk, some behaviours
have changed:
- If you export a derived class without exporting its base classes, the derived
class will explicitly export the bases's methods and attributes. Before, if
you were interested in the bases's methods, you had to export the base
classes too.
- Added a new function, no_override. When a member function is specified as
"no_override", no virtual wrappers are generated for it, improving
performance and letting the code more clean.
- There was a bug in which the policy of virtual member functions was being
ignored (patch by Roman Sulzhyk).
Thanks again to Roman Sulzhyk for the patches and discussion in the c++-sig.
4 June 2003
Major improvements in memory usage.
3 June 2003
Appliced a patch from Giulio Eulisse that allows unnamed enumerations to be
exported with an AllFromHeader construct. Thanks a lot Giulio!
2 June 2003
Added a new construct, add_method. See documentation.
23 May 2003
Support for global variables added.
Various bug fixes.
08 May 2003
Fixed bug where in a certain cases the GCCXMLParser would end up with multiple
declarations of the same class
22 Apr 2003
- Now shows a warning when the user tries to export a forward-declared class.
Forward-declared classes are ignored by the AllFromHeader construct.
- Fixed a bug where classes, functions and enums where being exported, even if
excluded from a AllFromHeader construct.
16 Apr 2003
Added a more generic (but ugly) code to declare the smart pointer converters.
07 Apr 2003
- Removed the warnings about forward declarations: it was not accurate enough.
Another strategy must be thought of.
- Fixed bug in the --multiple mode, where the order of the class instantiations
could end up wrong.
- Lots of fixes in the documentation, pointed out by Dirk Gerrits. Thanks Dirk!
- Fixed support for the return_opaque_pointer policy (the support macro was not
being declared).
06 Apr 2003
Support for the improved static data members support of Boost.Python.
05 Apr 2003
New option for generating the bindings: --multiple.
02 Apr 2003
Forward declarations are now detected and a warning is generated.
24 Mar 2003
Default policy for functions/methods that return const T& is now
return_value_policy<copy_const_reference>().
22 Mar 2003
Exporting virtual methods of the base classes in the derived classes too.
21 Mar 2003
Added manual support for boost::shared_ptr and std::auto_ptr (see doc).
19 Mar 2003
Added support for int, double, float and long operators acting as expected in
python.
14 Mar 2003
Fixed bug: Wrappers for protected and virtual methods were not being generated.

View File

@@ -1,31 +0,0 @@
Pyste - Python Semi-Automatic Exporter
======================================
Pyste is a Boost.Python code generator. The user specifies the classes and
functions to be exported using a simple interface file, which following the
Boost.Python's philosophy, is simple Python code. Pyste then uses GCCXML to
parse all the headers and extract the necessary information to automatically
generate C++ code.
The documentation can be found in the file index.html accompaning this README.
Enjoy!
Bruno da Silva de Oliveira (nicodemus@globalite.com.br)
Thanks
======
- David Abrahams, creator of Boost.Python, for tips on the syntax of the interface
file and support.
- Marcelo Camelo, for design tips, support and inspiration for this project.
Also, the name was his idea. 8)
- Brad King, creator of the excellent GCCXML (http://www.gccxml.org)
- Fredrik Lundh, creator of the elementtree library (http://effbot.org)
Bugs
====
Pyste is a young tool, so please help it to get better! Send bug reports to
nicodemus@globalite.com.br, accompaining the stack trace in case of exceptions.
If possible, run pyste with --debug, and send the resulting xmls too (pyste
will output a xml file with the same of each header it parsed).

View File

@@ -1,12 +0,0 @@
- Make Pyste accept already-generated xml files
- throw() declaration in virtual wrapper's member functions
- Allow protected methods to be overriden in Python
- Expose programmability to the Pyste files (listing members of a class, for
instance)
- Virtual operators
- args() support

View File

@@ -1,2 +0,0 @@
*.zip
*.pyc

View File

@@ -1,51 +0,0 @@
import os
import sys
import shutil
import fnmatch
from zipfile import ZipFile, ZIP_DEFLATED
def findfiles(directory, mask):
def visit(files, dir, names):
for name in names:
if fnmatch.fnmatch(name, mask):
files.append(os.path.join(dir, name))
files = []
os.path.walk(directory, visit, files)
return files
def main():
# test if PyXML is installed
try:
import _xmlplus.parsers.expat
pyxml = '--includes _xmlplus.parsers.expat'
except ImportError:
pyxml = ''
# create exe
status = os.system('python setup.py py2exe %s >& build.log' % pyxml)
if status != 0:
raise RuntimeError, 'Error creating EXE'
# create distribution
import pyste
version = pyste.__VERSION__
zip = ZipFile('pyste-%s.zip' % version, 'w', ZIP_DEFLATED)
# include the base files
dist_dir = 'dist/pyste'
for basefile in os.listdir(dist_dir):
zip.write(os.path.join(dist_dir, basefile), os.path.join('pyste', basefile))
# include documentation
for doc_file in findfiles('../doc', '*.*'):
dest_name = os.path.join('pyste/doc', doc_file[3:])
zip.write(doc_file, dest_name)
zip.write('../index.html', 'pyste/doc/index.html')
zip.close()
# cleanup
os.remove('build.log')
shutil.rmtree('build')
shutil.rmtree('dist')
if __name__ == '__main__':
sys.path.append('../src')
main()

6
pyste/dist/setup.py vendored
View File

@@ -1,6 +0,0 @@
from distutils.core import setup
import py2exe
import sys
sys.path.append('../src')
setup(name='pyste', scripts=['../src/pyste.py'])

View File

@@ -1,79 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Adding New Methods</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="global_variables.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Adding New Methods</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="global_variables.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><img src="theme/r_arr_disabled.gif" border="0"></td>
</tr>
</table>
<p>
Suppose that you want to add a function to a class, turning it into a member
function:</p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>World
</span><span class=special>{
</span><span class=keyword>void </span><span class=identifier>set</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>) { </span><span class=keyword>this</span><span class=special>-&gt;</span><span class=identifier>msg </span><span class=special>= </span><span class=identifier>msg</span><span class=special>; }
</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>;
};
</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>greet</span><span class=special>(</span><span class=identifier>World</span><span class=special>&amp; </span><span class=identifier>w</span><span class=special>)
{
</span><span class=keyword>return </span><span class=identifier>w</span><span class=special>.</span><span class=identifier>msg</span><span class=special>;
}
</span></pre></code>
<p>
Here, we want to make <tt>greet</tt> work as a member function of the class <tt>World</tt>. We do
that using the <tt>add_method</tt> construct:</p>
<code><pre>
<span class=identifier>W </span><span class=special>= </span><span class=identifier>Class</span><span class=special>(</span><span class=string>&quot;World&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
</span><span class=identifier>add_method</span><span class=special>(</span><span class=identifier>W</span><span class=special>, </span><span class=string>&quot;greet&quot;</span><span class=special>)
</span></pre></code>
<p>
Notice also that then you can rename it, set its policy, just like a regular
member function:</p>
<code><pre>
<span class=identifier>rename</span><span class=special>(</span><span class=identifier>W</span><span class=special>.</span><span class=identifier>greet</span><span class=special>, </span><span class=literal>'Greet'</span><span class=special>)
</span></pre></code>
<p>
Now from Python:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>import </span><span class=identifier>hello
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>w </span><span class=special>= </span><span class=identifier>hello</span><span class=special>.</span><span class=identifier>World</span><span class=special>()
&gt;&gt;&gt; </span><span class=identifier>w</span><span class=special>.</span><span class=identifier>set</span><span class=special>(</span><span class=literal>'Ni'</span><span class=special>)
&gt;&gt;&gt; </span><span class=identifier>w</span><span class=special>.</span><span class=identifier>greet</span><span class=special>()
</span><span class=literal>'Ni'
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>print </span><span class=literal>'Oh no! The knights who say Ni!'
</span><span class=identifier>Oh </span><span class=identifier>no</span><span class=special>! </span><span class=identifier>The </span><span class=identifier>knights </span><span class=identifier>who </span><span class=identifier>say </span><span class=identifier>Ni</span><span class=special>!
</span></pre></code>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="global_variables.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><img src="theme/r_arr_disabled.gif" border="0"></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,77 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Exporting An Entire Header</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="wrappers.html">
<link rel="next" href="smart_pointers.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Exporting An Entire Header</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="wrappers.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="smart_pointers.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
Pyste also supports a mechanism to export all declarations found in a header
file. Suppose again our file, <tt>hello.h</tt>:</p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>World
</span><span class=special>{
</span><span class=identifier>World</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>): </span><span class=identifier>msg</span><span class=special>(</span><span class=identifier>msg</span><span class=special>) {}
</span><span class=keyword>void </span><span class=identifier>set</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>) { </span><span class=keyword>this</span><span class=special>-&gt;</span><span class=identifier>msg </span><span class=special>= </span><span class=identifier>msg</span><span class=special>; }
</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>greet</span><span class=special>() { </span><span class=keyword>return </span><span class=identifier>msg</span><span class=special>; }
</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>;
};
</span><span class=keyword>enum </span><span class=identifier>choice </span><span class=special>{ </span><span class=identifier>red</span><span class=special>, </span><span class=identifier>blue </span><span class=special>};
</span><span class=keyword>void </span><span class=identifier>show</span><span class=special>(</span><span class=identifier>choice </span><span class=identifier>c</span><span class=special>) { </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>cout </span><span class=special>&lt;&lt; </span><span class=string>&quot;value: &quot; </span><span class=special>&lt;&lt; (</span><span class=keyword>int</span><span class=special>)</span><span class=identifier>c </span><span class=special>&lt;&lt; </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>; }
</span></pre></code>
<p>
You can just use the <tt>AllFromHeader</tt> construct:</p>
<code><pre>
<span class=identifier>hello </span><span class=special>= </span><span class=identifier>AllFromHeader</span><span class=special>(</span><span class=string>&quot;hello.h&quot;</span><span class=special>)
</span></pre></code>
<p>
this will export all the declarations found in <tt>hello.h</tt>, which is equivalent
to write:</p>
<code><pre>
<span class=identifier>Class</span><span class=special>(</span><span class=string>&quot;World&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
</span><span class=identifier>Enum</span><span class=special>(</span><span class=string>&quot;choice&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
</span><span class=identifier>Function</span><span class=special>(</span><span class=string>&quot;show&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
</span></pre></code>
<p>
Note that you can still use the functions <tt>rename</tt>, <tt>set_policy</tt>, <tt>exclude</tt>, etc. Just access
the members of the header object like this:</p>
<code><pre>
<span class=identifier>rename</span><span class=special>(</span><span class=identifier>hello</span><span class=special>.</span><span class=identifier>World</span><span class=special>.</span><span class=identifier>greet</span><span class=special>, </span><span class=string>&quot;Greet&quot;</span><span class=special>)
</span><span class=identifier>exclude</span><span class=special>(</span><span class=identifier>hello</span><span class=special>.</span><span class=identifier>World</span><span class=special>.</span><span class=identifier>set</span><span class=special>, </span><span class=string>&quot;Set&quot;</span><span class=special>)
</span></pre></code>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="wrappers.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="smart_pointers.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,50 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Global Variables</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="smart_pointers.html">
<link rel="next" href="adding_new_methods.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Global Variables</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="smart_pointers.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="adding_new_methods.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
To export global variables, use the <tt>Var</tt> construct:</p>
<code><pre>
<span class=identifier>Var</span><span class=special>(</span><span class=string>&quot;myglobal&quot;</span><span class=special>, </span><span class=string>&quot;foo.h&quot;</span><span class=special>)
</span></pre></code>
<p>
Beware of non-const global variables: changes in Python won't reflect in C++!
If you really must change them in Python, you will have to write some accessor
functions, and export those.</p>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="smart_pointers.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="adding_new_methods.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,74 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Introduction</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="next" href="running_pyste.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Introduction</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><img src="theme/l_arr_disabled.gif" border="0"></td>
<td width="20"><a href="running_pyste.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<a name="what_is_pyste_"></a><h2>What is Pyste?</h2><p>
Pyste is a <a href="../../index.html">
Boost.Python</a> code generator. The user specifies the classes and
functions to be exported using a simple <i>interface file</i>, which following the
<a href="../../index.html">
Boost.Python</a>'s philosophy, is simple Python code. Pyste then uses <a href="http://www.gccxml.org">
GCCXML</a> to
parse all the headers and extract the necessary information to automatically
generate C++ code.</p>
<a name="example"></a><h2>Example</h2><p>
Let's borrow the class <tt>World</tt> from the <a href="../../doc/tutorial/doc/exposing_classes.html">
tutorial</a>: </p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>World
</span><span class=special>{
</span><span class=keyword>void </span><span class=identifier>set</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>) { </span><span class=keyword>this</span><span class=special>-&gt;</span><span class=identifier>msg </span><span class=special>= </span><span class=identifier>msg</span><span class=special>; }
</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>greet</span><span class=special>() { </span><span class=keyword>return </span><span class=identifier>msg</span><span class=special>; }
</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>;
};
</span></pre></code>
<p>
Here's the interface file for it, named <tt>world.pyste</tt>:</p>
<code><pre>
<span class=identifier>Class</span><span class=special>(</span><span class=string>&quot;World&quot;</span><span class=special>, </span><span class=string>&quot;world.h&quot;</span><span class=special>)
</span></pre></code>
<p>
and that's it!</p>
<p>
The next step is invoke Pyste in the command-line:</p>
<code><pre>python pyste.py --module=hello world.pyste</pre></code><p>
this will create a file &quot;<tt>hello.cpp</tt>&quot; in the directory where the command was
run. </p>
<p>
Pyste supports the following features:</p>
<ul><li>Functions</li><li>Classes</li><li>Class Templates</li><li>Virtual Methods</li><li>Overloading</li><li>Attributes </li><li>Enums (both &quot;free&quot; enums and class enums)</li><li>Nested Classes</li><li>Support for <tt>boost::shared_ptr</tt> and <tt>std::auto_ptr</tt></li><li>Global Variables</li></ul><table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><img src="theme/l_arr_disabled.gif" border="0"></td>
<td width="20"><a href="running_pyste.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,91 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Policies</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="renaming_and_excluding.html">
<link rel="next" href="templates.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Policies</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="renaming_and_excluding.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="templates.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
Even thought Pyste can identify various elements in the C++ code, like virtual
member functions, attributes, and so on, one thing that it can't do is to
guess the semantics of functions that return pointers or references. In this
case, the user must manually specify the policy. Policies are explained in the
<a href="../../doc/tutorial/doc/call_policies.html">
tutorial</a>.</p>
<p>
The policies in Pyste are named exactly as in <a href="../../index.html">
Boost.Python</a>, only the syntax is
slightly different. For instance, this policy:</p>
<code><pre>
<span class=identifier>return_internal_reference</span><span class=special>&lt;</span><span class=number>1</span><span class=special>, </span><span class=identifier>with_custodian_and_ward</span><span class=special>&lt;</span><span class=number>1</span><span class=special>, </span><span class=number>2</span><span class=special>&gt; &gt;()
</span></pre></code>
<p>
becomes in Pyste: </p>
<code><pre>
<span class=identifier>return_internal_reference</span><span class=special>(</span><span class=number>1</span><span class=special>, </span><span class=identifier>with_custodian_and_ward</span><span class=special>(</span><span class=number>1</span><span class=special>, </span><span class=number>2</span><span class=special>))
</span></pre></code>
<p>
The user can specify policies for functions and virtual member functions with
the <tt>set_policy</tt> function:</p>
<code><pre>
<span class=identifier>set_policy</span><span class=special>(</span><span class=identifier>f</span><span class=special>, </span><span class=identifier>return_internal_reference</span><span class=special>())
</span><span class=identifier>set_policy</span><span class=special>(</span><span class=identifier>C</span><span class=special>.</span><span class=identifier>foo</span><span class=special>, </span><span class=identifier>return_value_policy</span><span class=special>(</span><span class=identifier>manage_new_object</span><span class=special>))
</span></pre></code>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/note.gif"></img> <b>What if a function or member function needs a policy and
the user doesn't set one?</b><br><br> If a function needs a policy and one
was not set, Pyste will issue a error. The user should then go in the
interface file and set the policy for it, otherwise the generated cpp won't
compile.
</td>
</tr>
</table>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/note.gif"></img>
Note that, for functions that return <tt>const T&amp;</tt>, the policy
<tt>return_value_policy&lt;copy_const_reference&gt;()</tt> wil be used by default, because
that's normally what you want. You can change it to something else if you need
to, though.
</td>
</tr>
</table>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="renaming_and_excluding.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="templates.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,541 +0,0 @@
[doc Pyste Documentation]
[def GCCXML [@http://www.gccxml.org GCCXML]]
[def Boost.Python [@../../index.html Boost.Python]]
[page Introduction]
[h2 What is Pyste?]
Pyste is a Boost.Python code generator. The user specifies the classes and
functions to be exported using a simple ['interface file], which following the
Boost.Python's philosophy, is simple Python code. Pyste then uses GCCXML to
parse all the headers and extract the necessary information to automatically
generate C++ code.
[h2 Example]
Let's borrow the class [^World] from the [@../../doc/tutorial/doc/exposing_classes.html tutorial]:
struct World
{
void set(std::string msg) { this->msg = msg; }
std::string greet() { return msg; }
std::string msg;
};
Here's the interface file for it, named [^world.pyste]:
Class("World", "world.h")
and that's it!
The next step is invoke Pyste in the command-line:
[pre python pyste.py --module=hello world.pyste]
this will create a file "[^hello.cpp]" in the directory where the command was
run.
Pyste supports the following features:
* Functions
* Classes
* Class Templates
* Virtual Methods
* Overloading
* Attributes
* Enums (both "free" enums and class enums)
* Nested Classes
* Support for [^boost::shared_ptr] and [^std::auto_ptr]
* Global Variables
[page Running Pyste]
To run Pyste, you will need:
* Python 2.2, available at [@http://www.python.org python's website].
* The great [@http://effbot.org elementtree] library, from Fredrik Lundh.
* The excellent GCCXML, from Brad King.
Installation for the tools is available in their respective webpages.
[blurb
[$theme/note.gif] GCCXML must be accessible in the PATH environment variable, so
that Pyste can call it. How to do this varies from platform to platform.
]
[h2 Ok, now what?]
Well, now let's fire it up:
[pre
'''
>python pyste.py
Pyste version 0.6.5
Usage:
pyste [options] --module=<name> interface-files
where options are:
-I <path> add an include path
-D <symbol> define symbol
--multiple create various cpps (one for each pyste file), instead
of only one (useful during development)
--out specify output filename (default: <module>.cpp)
in --multiple mode, this will be a directory
--no-using do not declare "using namespace boost";
use explicit declarations instead
--pyste-ns=<name> set the namespace where new types will be declared;
default is the empty namespace
--debug writes the xml for each file parsed in the current
directory
-h, --help print this help and exit
-v, --version print version information
'''
]
Options explained:
The [^-I] and [^-D] are preprocessor flags, which are needed by GCCXML to parse
the header files correctly and by Pyste to find the header files declared in the
interface files.
[^--multiple] tells Pyste to generate multiple cpps for this module (one for
each header parsed) in the directory named by [^--out], instead of the usual
single cpp file. This mode is useful during development of a binding, because
you are constantly changing source files, re-generating the bindings and
recompiling. This saves a lot of time in compiling.
[^--out] names the output file (default: [^<module>.cpp]), or in multiple mode,
names a output directory for the files (default: [^<module>]).
[^--no-using] tells Pyste to don't declare "[^using namespace boost;]" in the
generated cpp, using the namespace boost::python explicitly in all declarations.
Use only if you're having a name conflict in one of the files.
Use [^--pyste-ns] to change the namespace where new types are declared (for
instance, the virtual wrappers). Use only if you are having any problems. By
default, Pyste uses the empty namespace.
[^--debug] will write in the current directory a xml file as outputted by GCCXML
for each header parsed. Useful for bug reports.
[^-h, --help, -v, --version] are self-explaining, I believe. ;)
So, the usage is simple enough:
[pre >python pyste.py --module=mymodule file.pyste file2.pyste ...]
will generate a file [^mymodule.cpp] in the same dir where the command was
executed. Now you can compile the file using the same instructions of the
[@../../doc/tutorial/doc/building_hello_world.html tutorial]. Or, if you prefer:
[pre >python pyste.py --module=mymodule --multiple file.pyste file2.pyste ...]
will create a directory named "mymodule" in the current directory, and will
generate a bunch of cpp files, one for each header exported. You can then
compile them all into a single shared library (or dll).
[h2 Wait... how do I set those I and D flags?]
Don't worry: normally GCCXML is already configured correctly for your plataform,
so the search path to the standard libraries and the standard defines should
already be set. You only have to set the paths to other libraries that your code
needs, like Boost, for example.
Plus, Pyste automatically uses the contents of the environment variable
[^INCLUDE] if it exists. Visual C++ users should run the [^Vcvars32.bat] file,
which for Visual C++ 6 is normally located at:
C:\Program Files\Microsoft Visual Studio\VC98\bin\Vcvars32.bat
with that, you should have little trouble setting up the flags.
[blurb [$theme/note.gif][*A note about Psyco][br][br]
Although you don't have to install [@http://psyco.sourceforge.net/ Psyco] to use Pyste, if you do, Pyste will make use of it to speed up the wrapper generation. Speed ups of 30% can be achieved, so it's highly recommended.
]
[page The Interface Files]
The interface files are the heart of Pyste. The user creates one or more
interface files declaring the classes and functions he wants to export, and then
invokes Pyste passing the interface files to it. Pyste then generates a single
cpp file with Boost.Python code, with all the classes and functions exported.
Besides declaring the classes and functions, the user has a number of other
options, like renaming e excluding classes and member functionis. Those are
explained later on.
[h2 Basics]
Suppose we have a class and some functions that we want to expose to Python
declared in the header [^hello.h]:
struct World
{
World(std::string msg): msg(msg) {}
void set(std::string msg) { this->msg = msg; }
std::string greet() { return msg; }
std::string msg;
};
enum choice { red, blue };
namespace test {
void show(choice c) { std::cout << "value: " << (int)c << std::endl; }
}
We create a file named [^hello.pyste] and create instances of the classes
[^Function], [^Class] and [^Enum]:
Function("test::show", "hello.h")
Class("World", "hello.h")
Enum("choice", "hello.h")
That will expose the class, the free function and the enum found in [^hello.h].
[page:1 Renaming and Excluding]
You can easily rename functions, classes, member functions, attributes, etc. Just use the
function [^rename], like this:
World = Class("World", "hello.h")
rename(World, "IWorld")
show = Function("choice", "hello.h")
rename(show, "Show")
You can rename member functions and attributes using this syntax:
rename(World.greet, "Greet")
rename(World.set, "Set")
choice = Enum("choice", "hello.h")
rename(choice.red, "Red")
rename(choice.blue, "Blue")
You can exclude functions, classes, member functions, attributes, etc, in the same way,
with the function [^exclude]:
exclude(World.greet)
exclude(World.msg)
To access the operators of a class, access the member [^operator] like this
(supposing that [^C] is a class being exported):
exclude(C.operator['+'])
exclude(C.operator['*'])
exclude(C.operator['<<'])
The string inside the brackets is the same as the name of the operator in C++.[br]
[h2 Virtual Member Functions]
Pyste automatically generates wrappers for virtual member functions, but you
may want to disable this behaviour (for performance reasons, or to let the
code more clean) if you do not plan to override the functions in Python. To do
this, use the function [^final]:
C = Class('C', 'C.h')
final(C.foo) # C::foo is a virtual member function
No virtual wrapper code will be generated for the virtual member function
C::foo that way.
[page:1 Policies]
Even thought Pyste can identify various elements in the C++ code, like virtual
member functions, attributes, and so on, one thing that it can't do is to
guess the semantics of functions that return pointers or references. In this
case, the user must manually specify the policy. Policies are explained in the
[@../../doc/tutorial/doc/call_policies.html tutorial].
The policies in Pyste are named exactly as in Boost.Python, only the syntax is
slightly different. For instance, this policy:
return_internal_reference<1, with_custodian_and_ward<1, 2> >()
becomes in Pyste:
return_internal_reference(1, with_custodian_and_ward(1, 2))
The user can specify policies for functions and virtual member functions with
the [^set_policy] function:
set_policy(f, return_internal_reference())
set_policy(C.foo, return_value_policy(manage_new_object))
[blurb
[$theme/note.gif] [*What if a function or member function needs a policy and
the user doesn't set one?][br][br] If a function needs a policy and one
was not set, Pyste will issue a error. The user should then go in the
interface file and set the policy for it, otherwise the generated cpp won't
compile.
]
[blurb
[$theme/note.gif]
Note that, for functions that return [^const T&], the policy
[^return_value_policy<copy_const_reference>()] wil be used by default, because
that's normally what you want. You can change it to something else if you need
to, though.
]
[page:1 Templates]
Template classes can easily be exported too, but you can't export the template
itself... you have to export instantiations of it! So, if you want to export a
[^std::vector], you will have to export vectors of int, doubles, etc.
Suppose we have this code:
template <class T>
struct Point
{
T x;
T y;
};
And we want to export [^Point]s of int and double:
Point = Template("Point", "point.h")
Point("int")
Point("double")
Pyste will assign default names for each instantiation. In this example, those
would be "[^Point_int]" and "[^Point_double]", but most of the time users will want to
rename the instantiations:
Point("int", "IPoint") // renames the instantiation
double_inst = Point("double") // another way to do the same
rename(double_inst, "DPoint")
Note that you can rename, exclude, set policies, etc, in the [^Template] object
like you would do with a [^Function] or a [^Class]. This changes affect all
[*future] instantiations:
Point = Template("Point", "point.h")
Point("float", "FPoint") // will have x and y as data members
rename(Point.x, "X")
rename(Point.y, "Y")
Point("int", "IPoint") // will have X and Y as data members
Point("double", "DPoint") // also will have X and Y as data member
If you want to change a option of a particular instantiation, you can do so:
Point = Template("Point", "point.h")
Point("int", "IPoint")
d_inst = Point("double", "DPoint")
rename(d_inst.x, "X") // only DPoint is affect by this renames,
rename(d_inst.y, "Y") // IPoint stays intact
[blurb [$theme/note.gif] [*What if my template accepts more than one type?]
[br][br]
When you want to instantiate a template with more than one type, you can pass
either a string with the types separated by whitespace, or a list of strings
'''("int double" or ["int", "double"]''' would both work).
]
[page:1 Wrappers]
Suppose you have this function:
std::vector<std::string> names();
But you don't want to export [^std::vector<std::string>], you want this function
to return a python list of strings. Boost.Python has excellent support for
that:
list names_wrapper()
{
list result;
// call original function
vector<string> v = names();
// put all the strings inside the python list
vector<string>::iterator it;
for (it = v.begin(); it != v.end(); ++it){
result.append(*it);
}
return result;
}
BOOST_PYTHON_MODULE(test)
{
def("names", &names_wrapper);
}
Nice heh? Pyste supports this mechanism too. You declare the [^names_wrapper]
function in a header named "[^test_wrappers.h]" and in the interface file:
Include("test_wrappers.h")
names = Function("names", "test.h")
set_wrapper(names, "names_wrapper")
You can optionally declare the function in the interface file itself:
names_wrapper = Wrapper("names_wrapper",
"""
list names_wrapper()
{
// code to call name() and convert the vector to a list...
}
""")
names = Function("names", "test.h")
set_wrapper(names, names_wrapper)
The same mechanism can be used with member functions too. Just remember that
the first parameter of wrappers for member functions is a pointer to the
class, as in:
struct C
{
std::vector<std::string> names();
}
list names_wrapper(C* c)
{
// same as before, calling c->names() and converting result to a list
}
And then in the interface file:
C = Class("C", "test.h")
set_wrapper(C.names, "names_wrapper")
[blurb
[$theme/note.gif]Even though Boost.Python accepts either a pointer or a
reference to the class in wrappers for member functions as the first parameter,
Pyste expects them to be a [*pointer]. Doing otherwise will prevent your
code to compile when you set a wrapper for a virtual member function.
]
[page:1 Exporting An Entire Header]
Pyste also supports a mechanism to export all declarations found in a header
file. Suppose again our file, [^hello.h]:
struct World
{
World(std::string msg): msg(msg) {}
void set(std::string msg) { this->msg = msg; }
std::string greet() { return msg; }
std::string msg;
};
enum choice { red, blue };
void show(choice c) { std::cout << "value: " << (int)c << std::endl; }
You can just use the [^AllFromHeader] construct:
hello = AllFromHeader("hello.h")
this will export all the declarations found in [^hello.h], which is equivalent
to write:
Class("World", "hello.h")
Enum("choice", "hello.h")
Function("show", "hello.h")
Note that you can still use the functions [^rename], [^set_policy], [^exclude], etc. Just access
the members of the header object like this:
rename(hello.World.greet, "Greet")
exclude(hello.World.set, "Set")
[page:1 Smart Pointers]
Pyste for now has manual support for smart pointers. Suppose:
struct C
{
int value;
};
boost::shared_ptr<C> newC(int value)
{
boost::shared_ptr<C> c( new C() );
c->value = value;
return c;
}
void printC(boost::shared_ptr<C> c)
{
std::cout << c->value << std::endl;
}
To make [^newC] and [^printC] work correctly, you have to tell Pyste that a
convertor for [^boost::shared_ptr<C>] is needed.
C = Class('C', 'C.h')
use_shared_ptr(C)
Function('newC', 'C.h')
Function('printC', 'C.h')
For [^std::auto_ptr]'s, use the function [^use_auto_ptr].
This system is temporary, and in the future the converters will automatically be
exported if needed, without the need to tell Pyste about them explicitly.
[h2 Holders]
If only the converter for the smart pointers is not enough and you need to
specify the smart pointer as the holder for a class, use the functions
[^hold_with_shared_ptr] and [^hold_with_auto_ptr]:
C = Class('C', 'C.h')
hold_with_shared_ptr(C)
Function('newC', 'C.h')
Function('printC', 'C.h')
[page:1 Global Variables]
To export global variables, use the [^Var] construct:
Var("myglobal", "foo.h")
Beware of non-const global variables: changes in Python won't reflect in C++!
If you really must change them in Python, you will have to write some accessor
functions, and export those.
[page:1 Adding New Methods]
Suppose that you want to add a function to a class, turning it into a member
function:
struct World
{
void set(std::string msg) { this->msg = msg; }
std::string msg;
};
std::string greet(World& w)
{
return w.msg;
}
Here, we want to make [^greet] work as a member function of the class [^World]. We do
that using the [^add_method] construct:
W = Class("World", "hello.h")
add_method(W, "greet")
Notice also that then you can rename it, set its policy, just like a regular
member function:
rename(W.greet, 'Greet')
Now from Python:
>>> import hello
>>> w = hello.World()
>>> w.set('Ni')
>>> w.greet()
'Ni'
>>> print 'Oh no! The knights who say Ni!'
Oh no! The knights who say Ni!

View File

@@ -1,88 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Renaming and Excluding</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="the_interface_files.html">
<link rel="next" href="policies.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Renaming and Excluding</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="the_interface_files.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="policies.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
You can easily rename functions, classes, member functions, attributes, etc. Just use the
function <tt>rename</tt>, like this:</p>
<code><pre>
<span class=identifier>World </span><span class=special>= </span><span class=identifier>Class</span><span class=special>(</span><span class=string>&quot;World&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
</span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>World</span><span class=special>, </span><span class=string>&quot;IWorld&quot;</span><span class=special>)
</span><span class=identifier>show </span><span class=special>= </span><span class=identifier>Function</span><span class=special>(</span><span class=string>&quot;choice&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
</span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>show</span><span class=special>, </span><span class=string>&quot;Show&quot;</span><span class=special>)
</span></pre></code>
<p>
You can rename member functions and attributes using this syntax:</p>
<code><pre>
<span class=identifier>rename</span><span class=special>(</span><span class=identifier>World</span><span class=special>.</span><span class=identifier>greet</span><span class=special>, </span><span class=string>&quot;Greet&quot;</span><span class=special>)
</span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>World</span><span class=special>.</span><span class=identifier>set</span><span class=special>, </span><span class=string>&quot;Set&quot;</span><span class=special>)
</span><span class=identifier>choice </span><span class=special>= </span><span class=identifier>Enum</span><span class=special>(</span><span class=string>&quot;choice&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
</span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>choice</span><span class=special>.</span><span class=identifier>red</span><span class=special>, </span><span class=string>&quot;Red&quot;</span><span class=special>)
</span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>choice</span><span class=special>.</span><span class=identifier>blue</span><span class=special>, </span><span class=string>&quot;Blue&quot;</span><span class=special>)
</span></pre></code>
<p>
You can exclude functions, classes, member functions, attributes, etc, in the same way,
with the function <tt>exclude</tt>:</p>
<code><pre>
<span class=identifier>exclude</span><span class=special>(</span><span class=identifier>World</span><span class=special>.</span><span class=identifier>greet</span><span class=special>)
</span><span class=identifier>exclude</span><span class=special>(</span><span class=identifier>World</span><span class=special>.</span><span class=identifier>msg</span><span class=special>)
</span></pre></code>
<p>
To access the operators of a class, access the member <tt>operator</tt> like this
(supposing that <tt>C</tt> is a class being exported):</p>
<code><pre>
<span class=identifier>exclude</span><span class=special>(</span><span class=identifier>C</span><span class=special>.</span><span class=keyword>operator</span><span class=special>[</span><span class=literal>'+'</span><span class=special>])
</span><span class=identifier>exclude</span><span class=special>(</span><span class=identifier>C</span><span class=special>.</span><span class=keyword>operator</span><span class=special>[</span><span class=literal>'*'</span><span class=special>])
</span><span class=identifier>exclude</span><span class=special>(</span><span class=identifier>C</span><span class=special>.</span><span class=keyword>operator</span><span class=special>[</span><span class=literal>'&lt;&lt;'</span><span class=special>])
</span></pre></code>
<p>
The string inside the brackets is the same as the name of the operator in C++.<br></p>
<a name="virtual_member_functions"></a><h2>Virtual Member Functions</h2><p>
Pyste automatically generates wrappers for virtual member functions, but you
may want to disable this behaviour (for performance reasons, or to let the
code more clean) if you do not plan to override the functions in Python. To do
this, use the function <tt>final</tt>:</p>
<code><pre>
<span class=identifier>C </span><span class=special>= </span><span class=identifier>Class</span><span class=special>(</span><span class=literal>'C'</span><span class=special>, </span><span class=literal>'C.h'</span><span class=special>)
</span><span class=identifier>final</span><span class=special>(</span><span class=identifier>C</span><span class=special>.</span><span class=identifier>foo</span><span class=special>) </span>##<span class=identifier>C</span><span class=special>::</span><span class=identifier>foo </span><span class=identifier>is </span><span class=identifier>a </span><span class=keyword>virtual </span><span class=identifier>member </span><span class=identifier>function
</span></pre></code>
<p>
No virtual wrapper code will be generated for the virtual member function
C::foo that way.</p>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="the_interface_files.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="policies.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,150 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Running Pyste</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="introduction.html">
<link rel="next" href="the_interface_files.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Running Pyste</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="introduction.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="the_interface_files.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
To run Pyste, you will need:</p>
<ul><li>Python 2.2, available at <a href="http://www.python.org">
python's website</a>.</li><li>The great <a href="http://effbot.org">
elementtree</a> library, from Fredrik Lundh.</li><li>The excellent <a href="http://www.gccxml.org">
GCCXML</a>, from Brad King.</li></ul><p>
Installation for the tools is available in their respective webpages.</p>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/note.gif"></img> <a href="http://www.gccxml.org">
GCCXML</a> must be accessible in the PATH environment variable, so
that Pyste can call it. How to do this varies from platform to platform.
</td>
</tr>
</table>
<a name="ok__now_what_"></a><h2>Ok, now what?</h2><p>
Well, now let's fire it up:</p>
<code><pre>
&gt;python pyste.py
Pyste version 0.6.5
Usage:
pyste [options] --module=&lt;name&gt; interface-files
where options are:
-I &lt;path&gt; add an include path
-D &lt;symbol&gt; define symbol
--multiple create various cpps (one for each pyste file), instead
of only one (useful during development)
--out specify output filename (default: &lt;module&gt;.cpp)
in --multiple mode, this will be a directory
--no-using do not declare &quot;using namespace boost&quot;;
use explicit declarations instead
--pyste-ns=&lt;name&gt; set the namespace where new types will be declared;
default is the empty namespace
--debug writes the xml for each file parsed in the current
directory
-h, --help print this help and exit
-v, --version print version information
</pre></code><p>
Options explained:</p>
<p>
The <tt>-I</tt> and <tt>-D</tt> are preprocessor flags, which are needed by <a href="http://www.gccxml.org">
GCCXML</a> to parse
the header files correctly and by Pyste to find the header files declared in the
interface files.</p>
<p>
<tt>--multiple</tt> tells Pyste to generate multiple cpps for this module (one for
each header parsed) in the directory named by <tt>--out</tt>, instead of the usual
single cpp file. This mode is useful during development of a binding, because
you are constantly changing source files, re-generating the bindings and
recompiling. This saves a lot of time in compiling.</p>
<p>
<tt>--out</tt> names the output file (default: <tt>&lt;module&gt;.cpp</tt>), or in multiple mode,
names a output directory for the files (default: <tt>&lt;module&gt;</tt>).</p>
<p>
<tt>--no-using</tt> tells Pyste to don't declare &quot;<tt>using namespace boost;</tt>&quot; in the
generated cpp, using the namespace boost::python explicitly in all declarations.
Use only if you're having a name conflict in one of the files.</p>
<p>
Use <tt>--pyste-ns</tt> to change the namespace where new types are declared (for
instance, the virtual wrappers). Use only if you are having any problems. By
default, Pyste uses the empty namespace.</p>
<p>
<tt>--debug</tt> will write in the current directory a xml file as outputted by <a href="http://www.gccxml.org">
GCCXML</a>
for each header parsed. Useful for bug reports.</p>
<p>
<tt>-h, --help, -v, --version</tt> are self-explaining, I believe. ;)</p>
<p>
So, the usage is simple enough:</p>
<code><pre>&gt;python pyste.py --module=mymodule file.pyste file2.pyste ...</pre></code><p>
will generate a file <tt>mymodule.cpp</tt> in the same dir where the command was
executed. Now you can compile the file using the same instructions of the
<a href="../../doc/tutorial/doc/building_hello_world.html">
tutorial</a>. Or, if you prefer:</p>
<code><pre>&gt;python pyste.py --module=mymodule --multiple file.pyste file2.pyste ...</pre></code><p>
will create a directory named &quot;mymodule&quot; in the current directory, and will
generate a bunch of cpp files, one for each header exported. You can then
compile them all into a single shared library (or dll).</p>
<a name="wait____how_do_i_set_those_i_and_d_flags_"></a><h2>Wait... how do I set those I and D flags?</h2><p>
Don't worry: normally <a href="http://www.gccxml.org">
GCCXML</a> is already configured correctly for your plataform,
so the search path to the standard libraries and the standard defines should
already be set. You only have to set the paths to other libraries that your code
needs, like Boost, for example.</p>
<p>
Plus, Pyste automatically uses the contents of the environment variable
<tt>INCLUDE</tt> if it exists. Visual C++ users should run the <tt>Vcvars32.bat</tt> file,
which for Visual C++ 6 is normally located at:</p>
<code><pre>
<span class=identifier>C</span><span class=special>:\</span><span class=identifier>Program </span><span class=identifier>Files</span><span class=special>\</span><span class=identifier>Microsoft </span><span class=identifier>Visual </span><span class=identifier>Studio</span><span class=special>\</span><span class=identifier>VC98</span><span class=special>\</span><span class=identifier>bin</span><span class=special>\</span><span class=identifier>Vcvars32</span><span class=special>.</span><span class=identifier>bat
</span></pre></code>
<p>
with that, you should have little trouble setting up the flags.</p>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/note.gif"></img><b>A note about Psyco</b><br><br>
Although you don't have to install <a href="http://psyco.sourceforge.net/">
Psyco</a> to use Pyste, if you do, Pyste will make use of it to speed up the wrapper generation. Speed ups of 30% can be achieved, so it's highly recommended.
</td>
</tr>
</table>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="introduction.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="the_interface_files.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,85 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Smart Pointers</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="exporting_an_entire_header.html">
<link rel="next" href="global_variables.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Smart Pointers</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="exporting_an_entire_header.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="global_variables.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
Pyste for now has manual support for smart pointers. Suppose:</p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>C
</span><span class=special>{
</span><span class=keyword>int </span><span class=identifier>value</span><span class=special>;
};
</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>shared_ptr</span><span class=special>&lt;</span><span class=identifier>C</span><span class=special>&gt; </span><span class=identifier>newC</span><span class=special>(</span><span class=keyword>int </span><span class=identifier>value</span><span class=special>)
{
</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>shared_ptr</span><span class=special>&lt;</span><span class=identifier>C</span><span class=special>&gt; </span><span class=identifier>c</span><span class=special>( </span><span class=keyword>new </span><span class=identifier>C</span><span class=special>() );
</span><span class=identifier>c</span><span class=special>-&gt;</span><span class=identifier>value </span><span class=special>= </span><span class=identifier>value</span><span class=special>;
</span><span class=keyword>return </span><span class=identifier>c</span><span class=special>;
}
</span><span class=keyword>void </span><span class=identifier>printC</span><span class=special>(</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>shared_ptr</span><span class=special>&lt;</span><span class=identifier>C</span><span class=special>&gt; </span><span class=identifier>c</span><span class=special>)
{
</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>cout </span><span class=special>&lt;&lt; </span><span class=identifier>c</span><span class=special>-&gt;</span><span class=identifier>value </span><span class=special>&lt;&lt; </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>;
}
</span></pre></code>
<p>
To make <tt>newC</tt> and <tt>printC</tt> work correctly, you have to tell Pyste that a
convertor for <tt>boost::shared_ptr&lt;C&gt;</tt> is needed.</p>
<code><pre>
<span class=identifier>C </span><span class=special>= </span><span class=identifier>Class</span><span class=special>(</span><span class=literal>'C'</span><span class=special>, </span><span class=literal>'C.h'</span><span class=special>)
</span><span class=identifier>use_shared_ptr</span><span class=special>(</span><span class=identifier>C</span><span class=special>)
</span><span class=identifier>Function</span><span class=special>(</span><span class=literal>'newC'</span><span class=special>, </span><span class=literal>'C.h'</span><span class=special>)
</span><span class=identifier>Function</span><span class=special>(</span><span class=literal>'printC'</span><span class=special>, </span><span class=literal>'C.h'</span><span class=special>)
</span></pre></code>
<p>
For <tt>std::auto_ptr</tt>'s, use the function <tt>use_auto_ptr</tt>.</p>
<p>
This system is temporary, and in the future the converters will automatically be
exported if needed, without the need to tell Pyste about them explicitly.</p>
<a name="holders"></a><h2>Holders</h2><p>
If only the converter for the smart pointers is not enough and you need to
specify the smart pointer as the holder for a class, use the functions
<tt>hold_with_shared_ptr</tt> and <tt>hold_with_auto_ptr</tt>:</p>
<code><pre>
<span class=identifier>C </span><span class=special>= </span><span class=identifier>Class</span><span class=special>(</span><span class=literal>'C'</span><span class=special>, </span><span class=literal>'C.h'</span><span class=special>)
</span><span class=identifier>hold_with_shared_ptr</span><span class=special>(</span><span class=identifier>C</span><span class=special>)
</span><span class=identifier>Function</span><span class=special>(</span><span class=literal>'newC'</span><span class=special>, </span><span class=literal>'C.h'</span><span class=special>)
</span><span class=identifier>Function</span><span class=special>(</span><span class=literal>'printC'</span><span class=special>, </span><span class=literal>'C.h'</span><span class=special>)
</span></pre></code>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="exporting_an_entire_header.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="global_variables.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,103 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Templates</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="policies.html">
<link rel="next" href="wrappers.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Templates</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="policies.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="wrappers.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
Template classes can easily be exported too, but you can't export the template
itself... you have to export instantiations of it! So, if you want to export a
<tt>std::vector</tt>, you will have to export vectors of int, doubles, etc.</p>
<p>
Suppose we have this code:</p>
<code><pre>
<span class=keyword>template </span><span class=special>&lt;</span><span class=keyword>class </span><span class=identifier>T</span><span class=special>&gt;
</span><span class=keyword>struct </span><span class=identifier>Point
</span><span class=special>{
</span><span class=identifier>T </span><span class=identifier>x</span><span class=special>;
</span><span class=identifier>T </span><span class=identifier>y</span><span class=special>;
};
</span></pre></code>
<p>
And we want to export <tt>Point</tt>s of int and double:</p>
<code><pre>
<span class=identifier>Point </span><span class=special>= </span><span class=identifier>Template</span><span class=special>(</span><span class=string>&quot;Point&quot;</span><span class=special>, </span><span class=string>&quot;point.h&quot;</span><span class=special>)
</span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;int&quot;</span><span class=special>)
</span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;double&quot;</span><span class=special>)
</span></pre></code>
<p>
Pyste will assign default names for each instantiation. In this example, those
would be &quot;<tt>Point_int</tt>&quot; and &quot;<tt>Point_double</tt>&quot;, but most of the time users will want to
rename the instantiations:</p>
<code><pre>
<span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;int&quot;</span><span class=special>, </span><span class=string>&quot;IPoint&quot;</span><span class=special>) // </span><span class=identifier>renames </span><span class=identifier>the </span><span class=identifier>instantiation
</span><span class=identifier>double_inst </span><span class=special>= </span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;double&quot;</span><span class=special>) // </span><span class=identifier>another </span><span class=identifier>way </span><span class=identifier>to </span><span class=keyword>do </span><span class=identifier>the </span><span class=identifier>same
</span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>double_inst</span><span class=special>, </span><span class=string>&quot;DPoint&quot;</span><span class=special>)
</span></pre></code>
<p>
Note that you can rename, exclude, set policies, etc, in the <tt>Template</tt> object
like you would do with a <tt>Function</tt> or a <tt>Class</tt>. This changes affect all
<b>future</b> instantiations:</p>
<code><pre>
<span class=identifier>Point </span><span class=special>= </span><span class=identifier>Template</span><span class=special>(</span><span class=string>&quot;Point&quot;</span><span class=special>, </span><span class=string>&quot;point.h&quot;</span><span class=special>)
</span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;float&quot;</span><span class=special>, </span><span class=string>&quot;FPoint&quot;</span><span class=special>) // </span><span class=identifier>will </span><span class=identifier>have </span><span class=identifier>x </span><span class=keyword>and </span><span class=identifier>y </span><span class=identifier>as </span><span class=identifier>data </span><span class=identifier>members
</span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>Point</span><span class=special>.</span><span class=identifier>x</span><span class=special>, </span><span class=string>&quot;X&quot;</span><span class=special>)
</span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>Point</span><span class=special>.</span><span class=identifier>y</span><span class=special>, </span><span class=string>&quot;Y&quot;</span><span class=special>)
</span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;int&quot;</span><span class=special>, </span><span class=string>&quot;IPoint&quot;</span><span class=special>) // </span><span class=identifier>will </span><span class=identifier>have </span><span class=identifier>X </span><span class=keyword>and </span><span class=identifier>Y </span><span class=identifier>as </span><span class=identifier>data </span><span class=identifier>members
</span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;double&quot;</span><span class=special>, </span><span class=string>&quot;DPoint&quot;</span><span class=special>) // </span><span class=identifier>also </span><span class=identifier>will </span><span class=identifier>have </span><span class=identifier>X </span><span class=keyword>and </span><span class=identifier>Y </span><span class=identifier>as </span><span class=identifier>data </span><span class=identifier>member
</span></pre></code>
<p>
If you want to change a option of a particular instantiation, you can do so:</p>
<code><pre>
<span class=identifier>Point </span><span class=special>= </span><span class=identifier>Template</span><span class=special>(</span><span class=string>&quot;Point&quot;</span><span class=special>, </span><span class=string>&quot;point.h&quot;</span><span class=special>)
</span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;int&quot;</span><span class=special>, </span><span class=string>&quot;IPoint&quot;</span><span class=special>)
</span><span class=identifier>d_inst </span><span class=special>= </span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;double&quot;</span><span class=special>, </span><span class=string>&quot;DPoint&quot;</span><span class=special>)
</span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>d_inst</span><span class=special>.</span><span class=identifier>x</span><span class=special>, </span><span class=string>&quot;X&quot;</span><span class=special>) // </span><span class=identifier>only </span><span class=identifier>DPoint </span><span class=identifier>is </span><span class=identifier>affect </span><span class=identifier>by </span><span class=keyword>this </span><span class=identifier>renames</span><span class=special>,
</span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>d_inst</span><span class=special>.</span><span class=identifier>y</span><span class=special>, </span><span class=string>&quot;Y&quot;</span><span class=special>) // </span><span class=identifier>IPoint </span><span class=identifier>stays </span><span class=identifier>intact
</span></pre></code>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/note.gif"></img> <b>What if my template accepts more than one type?</b>
<br><br>
When you want to instantiate a template with more than one type, you can pass
either a string with the types separated by whitespace, or a list of strings
(&quot;int double&quot; or [&quot;int&quot;, &quot;double&quot;] would both work).
</td>
</tr>
</table>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="policies.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="wrappers.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,81 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>The Interface Files</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="running_pyste.html">
<link rel="next" href="renaming_and_excluding.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>The Interface Files</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="running_pyste.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="renaming_and_excluding.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
The interface files are the heart of Pyste. The user creates one or more
interface files declaring the classes and functions he wants to export, and then
invokes Pyste passing the interface files to it. Pyste then generates a single
cpp file with <a href="../../index.html">
Boost.Python</a> code, with all the classes and functions exported.</p>
<p>
Besides declaring the classes and functions, the user has a number of other
options, like renaming e excluding classes and member functionis. Those are
explained later on.</p>
<a name="basics"></a><h2>Basics</h2><p>
Suppose we have a class and some functions that we want to expose to Python
declared in the header <tt>hello.h</tt>:</p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>World
</span><span class=special>{
</span><span class=identifier>World</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>): </span><span class=identifier>msg</span><span class=special>(</span><span class=identifier>msg</span><span class=special>) {}
</span><span class=keyword>void </span><span class=identifier>set</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>) { </span><span class=keyword>this</span><span class=special>-&gt;</span><span class=identifier>msg </span><span class=special>= </span><span class=identifier>msg</span><span class=special>; }
</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>greet</span><span class=special>() { </span><span class=keyword>return </span><span class=identifier>msg</span><span class=special>; }
</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>;
};
</span><span class=keyword>enum </span><span class=identifier>choice </span><span class=special>{ </span><span class=identifier>red</span><span class=special>, </span><span class=identifier>blue </span><span class=special>};
</span><span class=keyword>namespace </span><span class=identifier>test </span><span class=special>{
</span><span class=keyword>void </span><span class=identifier>show</span><span class=special>(</span><span class=identifier>choice </span><span class=identifier>c</span><span class=special>) { </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>cout </span><span class=special>&lt;&lt; </span><span class=string>&quot;value: &quot; </span><span class=special>&lt;&lt; (</span><span class=keyword>int</span><span class=special>)</span><span class=identifier>c </span><span class=special>&lt;&lt; </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>; }
}
</span></pre></code>
<p>
We create a file named <tt>hello.pyste</tt> and create instances of the classes
<tt>Function</tt>, <tt>Class</tt> and <tt>Enum</tt>:</p>
<code><pre>
<span class=identifier>Function</span><span class=special>(</span><span class=string>&quot;test::show&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
</span><span class=identifier>Class</span><span class=special>(</span><span class=string>&quot;World&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
</span><span class=identifier>Enum</span><span class=special>(</span><span class=string>&quot;choice&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
</span></pre></code>
<p>
That will expose the class, the free function and the enum found in <tt>hello.h</tt>. </p>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="running_pyste.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="renaming_and_excluding.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 577 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 944 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 879 B

View File

@@ -1,170 +0,0 @@
body
{
background-image: url(bkd.gif);
background-color: #FFFFFF;
margin: 1em 2em 1em 2em;
}
h1 { font-family: Verdana, Arial, Helvetica, sans-serif; font-weight: bold; text-align: left; }
h2 { font: 140% sans-serif; font-weight: bold; text-align: left; }
h3 { font: 120% sans-serif; font-weight: bold; text-align: left; }
h4 { font: bold 100% sans-serif; font-weight: bold; text-align: left; }
h5 { font: italic 100% sans-serif; font-weight: bold; text-align: left; }
h6 { font: small-caps 100% sans-serif; font-weight: bold; text-align: left; }
pre
{
border-top: gray 1pt solid;
border-right: gray 1pt solid;
border-left: gray 1pt solid;
border-bottom: gray 1pt solid;
padding-top: 2pt;
padding-right: 2pt;
padding-left: 2pt;
padding-bottom: 2pt;
display: block;
font-family: "courier new", courier, mono;
background-color: #eeeeee; font-size: small
}
code
{
font-family: "Courier New", Courier, mono;
font-size: small
}
tt
{
display: inline;
font-family: "Courier New", Courier, mono;
color: #000099;
font-size: small
}
p
{
text-align: justify;
font-family: Georgia, "Times New Roman", Times, serif
}
ul
{
list-style-image: url(bullet.gif);
font-family: Georgia, "Times New Roman", Times, serif
}
ol
{
font-family: Georgia, "Times New Roman", Times, serif
}
a
{
font-weight: bold;
color: #003366;
text-decoration: none;
}
a:hover { color: #8080FF; }
.literal { color: #666666; font-style: italic}
.keyword { color: #000099}
.identifier {}
.comment { font-style: italic; color: #990000}
.special { color: #800040}
.preprocessor { color: #FF0000}
.string { font-style: italic; color: #666666}
.copyright { color: #666666; font-size: small}
.white_bkd { background-color: #FFFFFF}
.dk_grey_bkd { background-color: #999999}
.quotes { color: #666666; font-style: italic; font-weight: bold}
.note_box
{
display: block;
border-top: gray 1pt solid;
border-right: gray 1pt solid;
border-left: gray 1pt solid;
border-bottom: gray 1pt solid;
padding-right: 12pt;
padding-left: 12pt;
padding-bottom: 12pt;
padding-top: 12pt;
font-family: Arial, Helvetica, sans-serif;
background-color: #E2E9EF;
font-size: small; text-align: justify
}
.table_title
{
background-color: #648CCA;
font-family: Verdana, Arial, Helvetica, sans-serif; color: #FFFFFF;
font-weight: bold
; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px
}
.table_cells
{
background-color: #E2E9EF;
font-family: Geneva, Arial, Helvetica, san-serif;
font-size: small
; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px
}
.toc
{
DISPLAY: block;
background-color: #E2E9EF
font-family: Arial, Helvetica, sans-serif;
border-top: gray 1pt solid;
border-left: gray 1pt solid;
border-bottom: gray 1pt solid;
border-right: gray 1pt solid;
padding-top: 24pt;
padding-right: 24pt;
padding-left: 24pt;
padding-bottom: 24pt;
}
.toc_title
{
background-color: #648CCA;
padding-top: 4px;
padding-right: 4px;
padding-bottom: 4px;
padding-left: 4px;
font-family: Geneva, Arial, Helvetica, san-serif;
color: #FFFFFF;
font-weight: bold
}
.toc_cells
{
background-color: #E2E9EF;
padding-top: 4px;
padding-right: 4px;
padding-bottom: 4px;
padding-left: 4px;
font-family: Geneva, Arial, Helvetica, san-serif;
font-size: small
}
div.logo
{
float: right;
}
.toc_cells_L0 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }
.toc_cells_L1 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 44px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }
.toc_cells_L2 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 88px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }
.toc_cells_L3 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 122px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }
.toc_cells_L4 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 166px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 B

View File

@@ -1,124 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Wrappers</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="templates.html">
<link rel="next" href="exporting_an_entire_header.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Wrappers</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="templates.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="exporting_an_entire_header.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
Suppose you have this function:</p>
<code><pre>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>vector</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt; </span><span class=identifier>names</span><span class=special>();
</span></pre></code>
<p>
But you don't want to export <tt>std::vector&lt;std::string&gt;</tt>, you want this function
to return a python list of strings. <a href="../../index.html">
Boost.Python</a> has excellent support for
that:</p>
<code><pre>
<span class=identifier>list </span><span class=identifier>names_wrapper</span><span class=special>()
{
</span><span class=identifier>list </span><span class=identifier>result</span><span class=special>;
// </span><span class=identifier>call </span><span class=identifier>original </span><span class=identifier>function
</span><span class=identifier>vector</span><span class=special>&lt;</span><span class=identifier>string</span><span class=special>&gt; </span><span class=identifier>v </span><span class=special>= </span><span class=identifier>names</span><span class=special>();
// </span><span class=identifier>put </span><span class=identifier>all </span><span class=identifier>the </span><span class=identifier>strings </span><span class=identifier>inside </span><span class=identifier>the </span><span class=identifier>python </span><span class=identifier>list
</span><span class=identifier>vector</span><span class=special>&lt;</span><span class=identifier>string</span><span class=special>&gt;::</span><span class=identifier>iterator </span><span class=identifier>it</span><span class=special>;
</span><span class=keyword>for </span><span class=special>(</span><span class=identifier>it </span><span class=special>= </span><span class=identifier>v</span><span class=special>.</span><span class=identifier>begin</span><span class=special>(); </span><span class=identifier>it </span><span class=special>!= </span><span class=identifier>v</span><span class=special>.</span><span class=identifier>end</span><span class=special>(); ++</span><span class=identifier>it</span><span class=special>){
</span><span class=identifier>result</span><span class=special>.</span><span class=identifier>append</span><span class=special>(*</span><span class=identifier>it</span><span class=special>);
}
</span><span class=keyword>return </span><span class=identifier>result</span><span class=special>;
}
</span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>test</span><span class=special>)
{
</span><span class=identifier>def</span><span class=special>(</span><span class=string>&quot;names&quot;</span><span class=special>, &amp;</span><span class=identifier>names_wrapper</span><span class=special>);
}
</span></pre></code>
<p>
Nice heh? Pyste supports this mechanism too. You declare the <tt>names_wrapper</tt>
function in a header named &quot;<tt>test_wrappers.h</tt>&quot; and in the interface file:</p>
<code><pre>
<span class=identifier>Include</span><span class=special>(</span><span class=string>&quot;test_wrappers.h&quot;</span><span class=special>)
</span><span class=identifier>names </span><span class=special>= </span><span class=identifier>Function</span><span class=special>(</span><span class=string>&quot;names&quot;</span><span class=special>, </span><span class=string>&quot;test.h&quot;</span><span class=special>)
</span><span class=identifier>set_wrapper</span><span class=special>(</span><span class=identifier>names</span><span class=special>, </span><span class=string>&quot;names_wrapper&quot;</span><span class=special>)
</span></pre></code>
<p>
You can optionally declare the function in the interface file itself:</p>
<code><pre>
<span class=identifier>names_wrapper </span><span class=special>= </span><span class=identifier>Wrapper</span><span class=special>(</span><span class=string>&quot;names_wrapper&quot;</span><span class=special>,
</span><span class=string>&quot;&quot;</span><span class=string>&quot;
list names_wrapper()
{
// code to call name() and convert the vector to a list...
}
&quot;</span><span class=string>&quot;&quot;</span><span class=special>)
</span><span class=identifier>names </span><span class=special>= </span><span class=identifier>Function</span><span class=special>(</span><span class=string>&quot;names&quot;</span><span class=special>, </span><span class=string>&quot;test.h&quot;</span><span class=special>)
</span><span class=identifier>set_wrapper</span><span class=special>(</span><span class=identifier>names</span><span class=special>, </span><span class=identifier>names_wrapper</span><span class=special>)
</span></pre></code>
<p>
The same mechanism can be used with member functions too. Just remember that
the first parameter of wrappers for member functions is a pointer to the
class, as in:</p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>C
</span><span class=special>{
</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>vector</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt; </span><span class=identifier>names</span><span class=special>();
}
</span><span class=identifier>list </span><span class=identifier>names_wrapper</span><span class=special>(</span><span class=identifier>C</span><span class=special>* </span><span class=identifier>c</span><span class=special>)
{
// </span><span class=identifier>same </span><span class=identifier>as </span><span class=identifier>before</span><span class=special>, </span><span class=identifier>calling </span><span class=identifier>c</span><span class=special>-&gt;</span><span class=identifier>names</span><span class=special>() </span><span class=keyword>and </span><span class=identifier>converting </span><span class=identifier>result </span><span class=identifier>to </span><span class=identifier>a </span><span class=identifier>list
</span><span class=special>}
</span></pre></code>
<p>
And then in the interface file:</p>
<code><pre>
<span class=identifier>C </span><span class=special>= </span><span class=identifier>Class</span><span class=special>(</span><span class=string>&quot;C&quot;</span><span class=special>, </span><span class=string>&quot;test.h&quot;</span><span class=special>)
</span><span class=identifier>set_wrapper</span><span class=special>(</span><span class=identifier>C</span><span class=special>.</span><span class=identifier>names</span><span class=special>, </span><span class=string>&quot;names_wrapper&quot;</span><span class=special>)
</span></pre></code>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/note.gif"></img>Even though <a href="../../index.html">
Boost.Python</a> accepts either a pointer or a
reference to the class in wrappers for member functions as the first parameter,
Pyste expects them to be a <b>pointer</b>. Doing otherwise will prevent your
code to compile when you set a wrapper for a virtual member function.
</td>
</tr>
</table>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="templates.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="exporting_an_entire_header.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,86 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Pyste Documentation</title>
<link rel="stylesheet" href="doc/theme/style.css" type="text/css">
<link rel="next" href="introduction.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="doc/theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Pyste Documentation</b></font>
</td>
</tr>
</table>
<br>
<table width="80%" border="0" align="center">
<tr>
<td class="toc_title">Table of contents</td>
</tr>
<tr>
<td class="toc_cells_L0">
<a href="doc/introduction.html">Introduction</a>
</td>
</tr>
<tr>
<td class="toc_cells_L0">
<a href="doc/running_pyste.html">Running Pyste</a>
</td>
</tr>
<tr>
<td class="toc_cells_L0">
<a href="doc/the_interface_files.html">The Interface Files</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/renaming_and_excluding.html">Renaming and Excluding</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/policies.html">Policies</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/templates.html">Templates</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/wrappers.html">Wrappers</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/exporting_an_entire_header.html">Exporting An Entire Header</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/smart_pointers.html">Smart Pointers</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/global_variables.html">Global Variables</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/adding_new_methods.html">Adding New Methods</a>
</td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,4 +0,0 @@
#!/usr/bin/env python
from Pyste import pyste
pyste.main()

View File

@@ -1,18 +0,0 @@
# contributed by Prabhu Ramachandran
from distutils.core import setup
import sys
setup (name = "Pyste",
version = "0.9.10",
description = "Pyste - Python Semi-Automatic Exporter",
maintainer = "Bruno da Silva de Oliveira",
maintainer_email = "nicodemus@globalite.com.br",
licence = "Boost License",
long_description = "Pyste is a Boost.Python code generator",
url = "http://www.boost.org/libs/python/pyste/index.html",
platforms = ['Any'],
packages = ['Pyste'],
scripts = ['pyste.py'],
package_dir = {'Pyste': '../src/Pyste'},
)

View File

@@ -1 +0,0 @@
*.pyc

View File

@@ -1,887 +0,0 @@
import exporters
from Exporter import Exporter
from declarations import *
from settings import *
from policies import *
from SingleCodeUnit import SingleCodeUnit
from EnumExporter import EnumExporter
from utils import makeid, enumerate
import copy
import exporterutils
import re
#==============================================================================
# ClassExporter
#==============================================================================
class ClassExporter(Exporter):
'Generates boost.python code to export a class declaration'
def __init__(self, info, parser_tail=None):
Exporter.__init__(self, info, parser_tail)
# sections of code
self.sections = {}
# template: each item in the list is an item into the class_<...>
# section.
self.sections['template'] = []
# constructor: each item in the list is a parameter to the class_
# constructor, like class_<C>(...)
self.sections['constructor'] = []
# inside: everything within the class_<> statement
self.sections['inside'] = []
# scope: items outside the class statement but within its scope.
# scope* s = new scope(class<>());
# ...
# delete s;
self.sections['scope'] = []
# declarations: outside the BOOST_PYTHON_MODULE macro
self.sections['declaration'] = []
self.sections['declaration-outside'] = []
self.sections['include'] = []
# a list of Constructor instances
self.constructors = []
self.wrapper_generator = None
# a list of code units, generated by nested declarations
self.nested_codeunits = []
def ScopeName(self):
return makeid(self.class_.FullName()) + '_scope'
def Name(self):
return self.info.name
def SetDeclarations(self, declarations):
Exporter.SetDeclarations(self, declarations)
if self.declarations:
decl = self.GetDeclaration(self.info.name)
if isinstance(decl, Typedef):
self.class_ = self.GetDeclaration(decl.type.name)
if not self.info.rename:
self.info.rename = decl.name
else:
self.class_ = decl
self.class_ = copy.deepcopy(self.class_)
else:
self.class_ = None
def ClassBases(self):
all_bases = []
for level in self.class_.hierarchy:
for base in level:
all_bases.append(base)
return [self.GetDeclaration(x.name) for x in all_bases]
def Order(self):
'''Return the TOTAL number of bases that this class has, including the
bases' bases. Do this because base classes must be instantialized
before the derived classes in the module definition.
'''
num_bases = len(self.ClassBases())
return num_bases, self.class_.FullName()
def Export(self, codeunit, exported_names):
self.InheritMethods(exported_names)
self.MakeNonVirtual()
if not self.info.exclude:
self.ExportBasics()
self.ExportBases(exported_names)
self.ExportConstructors()
self.ExportVariables()
self.ExportVirtualMethods()
self.ExportMethods()
self.ExportOperators()
self.ExportNestedClasses(exported_names)
self.ExportNestedEnums(exported_names)
self.ExportSmartPointer()
self.ExportOpaquePointerPolicies()
self.Write(codeunit)
exported_names[self.Name()] = 1
def InheritMethods(self, exported_names):
'''Go up in the class hierarchy looking for classes that were not
exported yet, and then add their public members to this classes
members, as if they were members of this class. This allows the user to
just export one type and automatically get all the members from the
base classes.
'''
valid_members = (Method, ClassVariable, NestedClass, ClassEnumeration)
# these don't work INVESTIGATE!: (ClassOperator, ConverterOperator)
fullnames = [x.FullName() for x in self.class_]
pointers = [x.PointerDeclaration(True) for x in self.class_ if isinstance(x, Method)]
fullnames = dict([(x, None) for x in fullnames])
pointers = dict([(x, None) for x in pointers])
for level in self.class_.hierarchy:
level_exported = False
for base in level:
base = self.GetDeclaration(base.name)
if base.FullName() not in exported_names:
for member in base:
if type(member) in valid_members:
member_copy = copy.deepcopy(member)
member_copy.class_ = self.class_.FullName()
if isinstance(member_copy, Method):
pointer = member_copy.PointerDeclaration(True)
if pointer not in pointers:
self.class_.AddMember(member)
pointers[pointer] = None
elif member_copy.FullName() not in fullnames:
self.class_.AddMember(member)
else:
level_exported = True
if level_exported:
break
def IsValid(member):
return isinstance(member, valid_members) and member.visibility == Scope.public
self.public_members = [x for x in self.class_ if IsValid(x)]
def Write(self, codeunit):
indent = self.INDENT
boost_ns = namespaces.python
pyste_ns = namespaces.pyste
code = ''
# begin a scope for this class if needed
nested_codeunits = self.nested_codeunits
needs_scope = self.sections['scope'] or nested_codeunits
if needs_scope:
scope_name = self.ScopeName()
code += indent + boost_ns + 'scope* %s = new %sscope(\n' %\
(scope_name, boost_ns)
# export the template section
template_params = ', '.join(self.sections['template'])
code += indent + boost_ns + 'class_< %s >' % template_params
# export the constructor section
constructor_params = ', '.join(self.sections['constructor'])
code += '(%s)\n' % constructor_params
# export the inside section
in_indent = indent*2
for line in self.sections['inside']:
code += in_indent + line + '\n'
# write the scope section and end it
if not needs_scope:
code += indent + ';\n'
else:
code += indent + ');\n'
for line in self.sections['scope']:
code += indent + line + '\n'
# write the contents of the nested classes
for nested_unit in nested_codeunits:
code += '\n' + nested_unit.Section('module')
# close the scope
code += indent + 'delete %s;\n' % scope_name
# write the code to the module section in the codeunit
codeunit.Write('module', code + '\n')
# write the declarations to the codeunit
declarations = '\n'.join(self.sections['declaration'])
for nested_unit in nested_codeunits:
declarations += nested_unit.Section('declaration')
if declarations:
codeunit.Write('declaration', declarations + '\n')
declarations_outside = '\n'.join(self.sections['declaration-outside'])
if declarations_outside:
codeunit.Write('declaration-outside', declarations_outside + '\n')
# write the includes to the codeunit
includes = '\n'.join(self.sections['include'])
for nested_unit in nested_codeunits:
includes += nested_unit.Section('include')
if includes:
codeunit.Write('include', includes)
def Add(self, section, item):
'Add the item into the corresponding section'
self.sections[section].append(item)
def ExportBasics(self):
'''Export the name of the class and its class_ statement.'''
class_name = self.class_.FullName()
self.Add('template', class_name)
name = self.info.rename or self.class_.name
self.Add('constructor', '"%s"' % name)
def ExportBases(self, exported_names):
'Expose the bases of the class into the template section'
hierarchy = self.class_.hierarchy
exported = []
for level in hierarchy:
for base in level:
if base.visibility == Scope.public and base.name in exported_names:
exported.append(base.name)
if exported:
code = namespaces.python + 'bases< %s > ' % (', '.join(exported))
self.Add('template', code)
def ExportConstructors(self):
'''Exports all the public contructors of the class, plus indicates if the
class is noncopyable.
'''
py_ns = namespaces.python
indent = self.INDENT
def init_code(cons):
'return the init<>() code for the given contructor'
param_list = [p.FullName() for p in cons.parameters]
min_params_list = param_list[:cons.minArgs]
max_params_list = param_list[cons.minArgs:]
min_params = ', '.join(min_params_list)
max_params = ', '.join(max_params_list)
init = py_ns + 'init< '
init += min_params
if max_params:
if min_params:
init += ', '
init += py_ns + ('optional< %s >' % max_params)
init += ' >()'
return init
constructors = [x for x in self.public_members if isinstance(x, Constructor)]
self.constructors = constructors[:]
# don't export the copy constructor if the class is abstract
if self.class_.abstract:
for cons in constructors:
if cons.IsCopy():
constructors.remove(cons)
break
if not constructors:
# declare no_init
self.Add('constructor', py_ns + 'no_init')
else:
# write the constructor with less parameters to the constructor section
smaller = None
for cons in constructors:
if smaller is None or len(cons.parameters) < len(smaller.parameters):
smaller = cons
assert smaller is not None
self.Add('constructor', init_code(smaller))
constructors.remove(smaller)
# write the rest to the inside section, using def()
for cons in constructors:
code = '.def(%s)' % init_code(cons)
self.Add('inside', code)
# check if the class is copyable
if not self.class_.HasCopyConstructor() or self.class_.abstract:
self.Add('template', namespaces.boost + 'noncopyable')
def ExportVariables(self):
'Export the variables of the class, both static and simple variables'
vars = [x for x in self.public_members if isinstance(x, Variable)]
for var in vars:
if self.info[var.name].exclude:
continue
name = self.info[var.name].rename or var.name
fullname = var.FullName()
if var.type.const:
def_ = '.def_readonly'
else:
def_ = '.def_readwrite'
code = '%s("%s", &%s)' % (def_, name, fullname)
self.Add('inside', code)
def OverloadName(self, method):
'Returns the name of the overloads struct for the given method'
name = makeid(method.FullName())
overloads = '_overloads_%i_%i' % (method.minArgs, method.maxArgs)
return name + overloads
def GetAddedMethods(self):
added_methods = self.info.__added__
result = []
if added_methods:
for name, rename in added_methods:
decl = self.GetDeclaration(name)
self.info[name].rename = rename
result.append(decl)
return result
def ExportMethods(self):
'''Export all the non-virtual methods of this class, plus any function
that is to be exported as a method'''
declared = {}
def DeclareOverloads(m):
'Declares the macro for the generation of the overloads'
if (isinstance(m, Method) and m.static) or type(m) == Function:
func = m.FullName()
macro = 'BOOST_PYTHON_FUNCTION_OVERLOADS'
else:
func = m.name
macro = 'BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS'
code = '%s(%s, %s, %i, %i)\n' % (macro, self.OverloadName(m), func, m.minArgs, m.maxArgs)
if code not in declared:
declared[code] = True
self.Add('declaration', code)
def Pointer(m):
'returns the correct pointer declaration for the method m'
# check if this method has a wrapper set for him
wrapper = self.info[m.name].wrapper
if wrapper:
return '&' + wrapper.FullName()
else:
return m.PointerDeclaration()
def IsExportable(m):
'Returns true if the given method is exportable by this routine'
ignore = (Constructor, ClassOperator, Destructor)
return isinstance(m, Function) and not isinstance(m, ignore) and not m.virtual
methods = [x for x in self.public_members if IsExportable(x)]
methods.extend(self.GetAddedMethods())
staticmethods = {}
for method in methods:
method_info = self.info[method.name]
# skip this method if it was excluded by the user
if method_info.exclude:
continue
# rename the method if the user requested
name = method_info.rename or method.name
# warn the user if this method needs a policy and doesn't have one
method_info.policy = exporterutils.HandlePolicy(method, method_info.policy)
# check for policies
policy = method_info.policy or ''
if policy:
policy = ', %s%s()' % (namespaces.python, policy.Code())
# check for overloads
overload = ''
if method.minArgs != method.maxArgs:
# add the overloads for this method
DeclareOverloads(method)
overload_name = self.OverloadName(method)
overload = ', %s%s()' % (namespaces.pyste, overload_name)
# build the .def string to export the method
pointer = Pointer(method)
code = '.def("%s", %s' % (name, pointer)
code += policy
code += overload
code += ')'
self.Add('inside', code)
# static method
if isinstance(method, Method) and method.static:
staticmethods[name] = 1
# add wrapper code if this method has one
wrapper = method_info.wrapper
if wrapper and wrapper.code:
self.Add('declaration', wrapper.code)
# export staticmethod statements
for name in staticmethods:
code = '.staticmethod("%s")' % name
self.Add('inside', code)
def MakeNonVirtual(self):
'''Make all methods that the user indicated to no_override no more virtual, delegating their
export to the ExportMethods routine'''
for member in self.class_:
if type(member) == Method and member.virtual:
member.virtual = not self.info[member.name].no_override
def ExportVirtualMethods(self):
# check if this class has any virtual methods
has_virtual_methods = False
for member in self.class_:
if type(member) == Method and member.virtual:
has_virtual_methods = True
break
holder = self.info.holder
if has_virtual_methods:
generator = _VirtualWrapperGenerator(self.class_, self.ClassBases(), self.info)
if holder:
self.Add('template', holder(generator.FullName()))
else:
self.Add('template', generator.FullName())
for definition in generator.GenerateDefinitions():
self.Add('inside', definition)
self.Add('declaration', generator.GenerateVirtualWrapper(self.INDENT))
else:
if holder:
self.Add('template', holder(self.class_.FullName()))
# operators natively supported by boost
BOOST_SUPPORTED_OPERATORS = '+ - * / % ^ & ! ~ | < > == != <= >= << >> && || += -='\
'*= /= %= ^= &= |= <<= >>='.split()
# create a map for faster lookup
BOOST_SUPPORTED_OPERATORS = dict(zip(BOOST_SUPPORTED_OPERATORS, range(len(BOOST_SUPPORTED_OPERATORS))))
# a dict of operators that are not directly supported by boost, but can be exposed
# simply as a function with a special name
BOOST_RENAME_OPERATORS = {
'()' : '__call__',
}
# converters which have a special name in python
# it's a map of a regular expression of the converter's result to the
# appropriate python name
SPECIAL_CONVERTERS = {
re.compile(r'(const)?\s*double$') : '__float__',
re.compile(r'(const)?\s*float$') : '__float__',
re.compile(r'(const)?\s*int$') : '__int__',
re.compile(r'(const)?\s*long$') : '__long__',
re.compile(r'(const)?\s*char\s*\*?$') : '__str__',
re.compile(r'(const)?.*::basic_string<.*>\s*(\*|\&)?$') : '__str__',
}
def ExportOperators(self):
'Export all member operators and free operators related to this class'
def GetFreeOperators():
'Get all the free (global) operators related to this class'
operators = []
for decl in self.declarations:
if isinstance(decl, Operator):
# check if one of the params is this class
for param in decl.parameters:
if param.name == self.class_.FullName():
operators.append(decl)
break
return operators
def GetOperand(param):
'Returns the operand of this parameter (either "self", or "other<type>")'
if param.name == self.class_.FullName():
return namespaces.python + 'self'
else:
return namespaces.python + ('other< %s >()' % param.name)
def HandleSpecialOperator(operator):
# gatter information about the operator and its parameters
result_name = operator.result.name
param1_name = ''
if operator.parameters:
param1_name = operator.parameters[0].name
# check for str
ostream = 'basic_ostream'
is_str = result_name.find(ostream) != -1 and param1_name.find(ostream) != -1
if is_str:
namespace = namespaces.python + 'self_ns::'
self_ = namespaces.python + 'self'
return '.def(%sstr(%s))' % (namespace, self_)
# is not a special operator
return None
frees = GetFreeOperators()
members = [x for x in self.public_members if type(x) == ClassOperator]
all_operators = frees + members
operators = [x for x in all_operators if not self.info['operator'][x.name].exclude]
for operator in operators:
# gatter information about the operator, for use later
wrapper = self.info['operator'][operator.name].wrapper
if wrapper:
pointer = '&' + wrapper.FullName()
if wrapper.code:
self.Add('declaration', wrapper.code)
else:
pointer = operator.PointerDeclaration()
rename = self.info['operator'][operator.name].rename
# check if this operator will be exported as a method
export_as_method = wrapper or rename or operator.name in self.BOOST_RENAME_OPERATORS
# check if this operator has a special representation in boost
special_code = HandleSpecialOperator(operator)
has_special_representation = special_code is not None
if export_as_method:
# export this operator as a normal method, renaming or using the given wrapper
if not rename:
if wrapper:
rename = wrapper.name
else:
rename = self.BOOST_RENAME_OPERATORS[operator.name]
policy = ''
policy_obj = self.info['operator'][operator.name].policy
if policy_obj:
policy = ', %s()' % policy_obj.Code()
self.Add('inside', '.def("%s", %s%s)' % (rename, pointer, policy))
elif has_special_representation:
self.Add('inside', special_code)
elif operator.name in self.BOOST_SUPPORTED_OPERATORS:
# export this operator using boost's facilities
op = operator
is_unary = isinstance(op, Operator) and len(op.parameters) == 1 or\
isinstance(op, ClassOperator) and len(op.parameters) == 0
if is_unary:
self.Add('inside', '.def( %s%sself )' % \
(operator.name, namespaces.python))
else:
# binary operator
if len(operator.parameters) == 2:
left_operand = GetOperand(operator.parameters[0])
right_operand = GetOperand(operator.parameters[1])
else:
left_operand = namespaces.python + 'self'
right_operand = GetOperand(operator.parameters[0])
self.Add('inside', '.def( %s %s %s )' % \
(left_operand, operator.name, right_operand))
# export the converters.
# export them as simple functions with a pre-determined name
converters = [x for x in self.public_members if type(x) == ConverterOperator]
def ConverterMethodName(converter):
result_fullname = converter.result.FullName()
result_name = converter.result.name
for regex, method_name in self.SPECIAL_CONVERTERS.items():
if regex.match(result_fullname):
return method_name
else:
# extract the last name from the full name
result_name = makeid(result_name)
return 'to_' + result_name
for converter in converters:
info = self.info['operator'][converter.result.FullName()]
# check if this operator should be excluded
if info.exclude:
continue
special_code = HandleSpecialOperator(converter)
if info.rename or not special_code:
# export as method
name = info.rename or ConverterMethodName(converter)
pointer = converter.PointerDeclaration()
policy_code = ''
if info.policy:
policy_code = ', %s()' % info.policy.Code()
self.Add('inside', '.def("%s", %s%s)' % (name, pointer, policy_code))
elif special_code:
self.Add('inside', special_code)
def ExportNestedClasses(self, exported_names):
nested_classes = [x for x in self.public_members if isinstance(x, NestedClass)]
for nested_class in nested_classes:
nested_info = self.info[nested_class.name]
nested_info.include = self.info.include
nested_info.name = nested_class.FullName()
exporter = ClassExporter(nested_info)
exporter.SetDeclarations(self.declarations)
codeunit = SingleCodeUnit(None, None)
exporter.Export(codeunit, exported_names)
self.nested_codeunits.append(codeunit)
def ExportNestedEnums(self, exported_names):
nested_enums = [x for x in self.public_members if isinstance(x, ClassEnumeration)]
for enum in nested_enums:
enum_info = self.info[enum.name]
enum_info.include = self.info.include
enum_info.name = enum.FullName()
exporter = EnumExporter(enum_info)
exporter.SetDeclarations(self.declarations)
codeunit = SingleCodeUnit(None, None)
exporter.Export(codeunit, exported_names)
self.nested_codeunits.append(codeunit)
def ExportSmartPointer(self):
smart_ptr = self.info.smart_ptr
if smart_ptr:
class_name = self.class_.FullName()
smart_ptr = smart_ptr % class_name
self.Add('scope', '%sregister_ptr_to_python< %s >();' % (namespaces.python, smart_ptr))
def ExportOpaquePointerPolicies(self):
# check all methods for 'return_opaque_pointer' policies
methods = [x for x in self.public_members if isinstance(x, Method)]
for method in methods:
return_opaque_policy = return_value_policy(return_opaque_pointer)
if self.info[method.name].policy == return_opaque_policy:
macro = exporterutils.EspecializeTypeID(method.result.name)
if macro:
self.Add('declaration-outside', macro)
#==============================================================================
# Virtual Wrapper utils
#==============================================================================
def _ParamsInfo(m, count=None):
if count is None:
count = len(m.parameters)
param_names = ['p%i' % i for i in range(count)]
param_types = [x.FullName() for x in m.parameters[:count]]
params = ['%s %s' % (t, n) for t, n in zip(param_types, param_names)]
#for i, p in enumerate(m.parameters[:count]):
# if p.default is not None:
# #params[i] += '=%s' % p.default
# params[i] += '=%s' % (p.name + '()')
params = ', '.join(params)
return params, param_names, param_types
class _VirtualWrapperGenerator(object):
'Generates code to export the virtual methods of the given class'
def __init__(self, class_, bases, info):
self.class_ = copy.deepcopy(class_)
self.bases = bases[:]
self.info = info
self.wrapper_name = makeid(class_.FullName()) + '_Wrapper'
self.virtual_methods = None
self._method_count = {}
self.GenerateVirtualMethods()
def DefaultImplementationNames(self, method):
'''Returns a list of default implementations for this method, one for each
number of default arguments. Always returns at least one name, and return from
the one with most arguments to the one with the least.
'''
base_name = 'default_' + method.name
minArgs = method.minArgs
maxArgs = method.maxArgs
if minArgs == maxArgs:
return [base_name]
else:
return [base_name + ('_%i' % i) for i in range(minArgs, maxArgs+1)]
def Declaration(self, method, indent):
'''Returns a string with the declarations of the virtual wrapper and
its default implementations. This string must be put inside the Wrapper
body.
'''
pyste = namespaces.pyste
python = namespaces.python
rename = self.info[method.name].rename or method.name
result = method.result.FullName()
return_str = 'return '
if result == 'void':
return_str = ''
params, param_names, param_types = _ParamsInfo(method)
constantness = ''
if method.const:
constantness = ' const'
# call_method callback
decl = indent + '%s %s(%s)%s%s {\n' % (result, method.name, params, constantness, method.Exceptions())
param_names_str = ', '.join(param_names)
if param_names_str:
param_names_str = ', ' + param_names_str
decl += indent*2 + '%s%scall_method< %s >(self, "%s"%s);\n' %\
(return_str, python, result, rename, param_names_str)
decl += indent + '}\n'
# default implementations (with overloading)
def DefaultImpl(method, param_names):
'Return the body of a default implementation wrapper'
indent2 = indent * 2
wrapper = self.info[method.name].wrapper
if not wrapper:
# return the default implementation of the class
if method.abstract:
s = indent2 + 'PyErr_SetString(PyExc_RuntimeError, "pure virtual function called");\n' +\
indent2 + 'throw_error_already_set();\n'
params = ', '.join(param_names)
s += indent2 + '%s%s(%s);\n' % \
(return_str, method.name, params)
return s
else:
return indent2 + '%s%s(%s);\n' % \
(return_str, method.FullName(), ', '.join(param_names))
else:
# return a call for the wrapper
params = ', '.join(['this'] + param_names)
return indent2 + '%s%s(%s);\n' % (return_str, wrapper.FullName(), params)
if method.visibility != Scope.private:
minArgs = method.minArgs
maxArgs = method.maxArgs
impl_names = self.DefaultImplementationNames(method)
for impl_name, argNum in zip(impl_names, range(minArgs, maxArgs+1)):
params, param_names, param_types = _ParamsInfo(method, argNum)
decl += '\n'
decl += indent + '%s %s(%s)%s {\n' % (result, impl_name, params, constantness)
decl += DefaultImpl(method, param_names)
decl += indent + '}\n'
return decl
def MethodDefinition(self, method):
'''Returns a list of lines, which should be put inside the class_
statement to export this method.'''
# dont define abstract methods
pyste = namespaces.pyste
rename = self.info[method.name].rename or method.name
default_names = self.DefaultImplementationNames(method)
class_name = self.class_.FullName()
wrapper_name = pyste + self.wrapper_name
result = method.result.FullName()
is_method_unique = method.is_unique
constantness = ''
if method.const:
constantness = ' const'
# create a list of default-impl pointers
minArgs = method.minArgs
maxArgs = method.maxArgs
if is_method_unique:
default_pointers = ['&%s::%s' % (wrapper_name, x) for x in default_names]
else:
default_pointers = []
for impl_name, argNum in zip(default_names, range(minArgs, maxArgs+1)):
param_list = [x.FullName() for x in method.parameters[:argNum]]
params = ', '.join(param_list)
signature = '%s (%s::*)(%s)%s' % (result, wrapper_name, params, constantness)
default_pointer = '(%s)&%s::%s' % (signature, wrapper_name, impl_name)
default_pointers.append(default_pointer)
# get the pointer of the method
pointer = method.PointerDeclaration()
# Add policy to overloaded methods also
policy = self.info[method.name].policy or ''
if policy:
policy = ', %s%s()' % (namespaces.python, policy.Code())
# generate the defs
definitions = []
# basic def
definitions.append('.def("%s", %s, %s%s)' % (rename, pointer, default_pointers[-1], policy))
for default_pointer in default_pointers[:-1]:
definitions.append('.def("%s", %s%s)' % (rename, default_pointer, policy))
return definitions
def FullName(self):
return namespaces.pyste + self.wrapper_name
def GenerateVirtualMethods(self):
'''To correctly export all virtual methods, we must also make wrappers
for the virtual methods of the bases of this class, as if the methods
were from this class itself.
This method creates the instance variable self.virtual_methods.
'''
def IsVirtual(m):
return type(m) is Method and \
m.virtual and \
m.visibility != Scope.private
# extract the virtual methods, avoiding duplications. The duplication
# must take in account the full signature without the class name, so
# that inherited members are correctly excluded if the subclass overrides
# them.
def MethodSig(method):
if method.const:
const = ' const'
else:
const = ''
if method.result:
result = method.result.FullName()
else:
result = ''
params = ', '.join([x.FullName() for x in method.parameters])
return '%s %s(%s)%s%s' % (
result, method.name, params, const, method.Exceptions())
already_added = {}
self.virtual_methods = []
for member in self.class_:
if IsVirtual(member):
already_added[MethodSig(member)] = None
self.virtual_methods.append(member)
for base in self.bases:
base_methods = [copy.deepcopy(x) for x in base if IsVirtual(x)]
for base_method in base_methods:
self.class_.AddMember(base_method)
all_methods = [x for x in self.class_ if IsVirtual(x)]
for member in all_methods:
sig = MethodSig(member)
if IsVirtual(member) and not sig in already_added:
self.virtual_methods.append(member)
already_added[sig] = 0
def Constructors(self):
return self.class_.Constructors(publics_only=True)
def GenerateDefinitions(self):
defs = []
for method in self.virtual_methods:
exclude = self.info[method.name].exclude
# generate definitions only for public methods and non-abstract methods
if method.visibility == Scope.public and not exclude:
defs.extend(self.MethodDefinition(method))
return defs
def GenerateVirtualWrapper(self, indent):
'Return the wrapper for this class'
# generate the class code
class_name = self.class_.FullName()
code = 'struct %s: %s\n' % (self.wrapper_name, class_name)
code += '{\n'
# generate constructors (with the overloads for each one)
for cons in self.Constructors(): # only public constructors
minArgs = cons.minArgs
maxArgs = cons.maxArgs
# from the min number of arguments to the max number, generate
# all version of the given constructor
cons_code = ''
for argNum in range(minArgs, maxArgs+1):
params, param_names, param_types = _ParamsInfo(cons, argNum)
if params:
params = ', ' + params
cons_code += indent + '%s(PyObject* self_%s):\n' % \
(self.wrapper_name, params)
cons_code += indent*2 + '%s(%s), self(self_) {}\n\n' % \
(class_name, ', '.join(param_names))
code += cons_code
# generate the body
body = []
for method in self.virtual_methods:
if not self.info[method.name].exclude:
body.append(self.Declaration(method, indent))
body = '\n'.join(body)
code += body + '\n'
# add the self member
code += indent + 'PyObject* self;\n'
code += '};\n'
return code

View File

@@ -1,221 +0,0 @@
from GCCXMLParser import ParseDeclarations
import tempfile
import shutil
import os
import sys
import os.path
import settings
import shutil
import shelve
from cPickle import dump, load
#==============================================================================
# exceptions
#==============================================================================
class CppParserError(Exception): pass
#==============================================================================
# CppParser
#==============================================================================
class CppParser:
'Parses a header file and returns a list of declarations'
def __init__(self, includes=None, defines=None, cache_dir=None):
'includes and defines ar the directives given to gcc'
if includes is None:
includes = []
if defines is None:
defines = []
self.includes = includes
self.defines = defines
#if cache_dir is None:
# cache_dir = tempfile.mktemp()
# self.delete_cache = True
#else:
# self.delete_cache = False
self.delete_cache = False
self.cache_dir = cache_dir
self.cache_files = []
self.mem_cache = {}
# create the cache dir
if cache_dir:
try:
os.makedirs(cache_dir)
except OSError: pass
def __del__(self):
self.Close()
def _IncludeParams(self, filename):
includes = self.includes[:]
filedir = os.path.dirname(filename)
if not filedir:
filedir = '.'
includes.insert(0, filedir)
includes = ['-I "%s"' % x for x in includes]
return ' '.join(includes)
def _DefineParams(self):
defines = ['-D "%s"' % x for x in self.defines]
return ' '.join(defines)
def FindHeader(self, header):
if os.path.isfile(header):
return header
for path in self.includes:
filename = os.path.join(path, header)
if os.path.isfile(filename):
return filename
else:
name = os.path.basename(header)
raise RuntimeError, 'Header file "%s" not found!' % name
def AppendTail(self, filename, tail):
'''Creates a temporary file, appends the text tail to it, and returns
the filename of the file.
'''
temp = tempfile.mktemp('.h')
shutil.copyfile(filename, temp)
f = file(temp, 'a')
f.write('\n\n'+tail)
f.close()
return temp
def ParseWithGCCXML(self, header, tail):
'''Parses the given header using gccxml and GCCXMLParser.
'''
header = self.FindHeader(header)
if tail:
filename = self.AppendTail(header, tail)
else:
filename = header
xmlfile = tempfile.mktemp('.xml')
try:
# get the params
includes = self._IncludeParams(filename)
defines = self._DefineParams()
# call gccxml
cmd = 'gccxml %s %s %s -fxml=%s'
status = os.system(cmd % (includes, defines, filename, xmlfile))
if status != 0 or not os.path.isfile(xmlfile):
raise CppParserError, 'Error executing gccxml'
# parse the resulting xml
declarations = ParseDeclarations(xmlfile)
# make the declarations' location to point to the original file
if tail:
for decl in declarations:
decl_filename = os.path.normpath(os.path.normcase(decl.location[0]))
filename = os.path.normpath(os.path.normcase(filename))
if decl_filename == filename:
decl.location = header, decl.location[1]
# return the declarations
return declarations
finally:
if settings.DEBUG and os.path.isfile(xmlfile):
filename = os.path.basename(header)
filename = os.path.splitext(filename)[0] + '.xml'
shutil.copy(xmlfile, filename)
# delete the temporary files
try:
os.remove(xmlfile)
if tail:
os.remove(filename)
except OSError: pass
def Parse(self, header, interface, tail=None):
'''Parses the given filename related to the given interface and returns
the (declarations, headerfile). The header returned is normally the
same as the given to this method (except that it is the full path),
except if tail is not None: in this case, the header is copied to a temp
filename and the tail code is appended to it before being passed on to
gccxml. This temp filename is then returned.
'''
if tail is None:
tail = ''
tail.strip()
declarations = self.GetCache(header, interface, tail)
if declarations is None:
declarations = self.ParseWithGCCXML(header, tail)
self.CreateCache(header, interface, tail, declarations)
return declarations, header
def CacheFileName(self, interface):
interface_name = os.path.basename(interface)
cache_file = os.path.splitext(interface_name)[0] + '.pystec'
cache_file = os.path.join(self.cache_dir, cache_file)
return cache_file
def GetCache(self, header, interface, tail):
key = (header, interface, tail)
# try memory cache first
if key in self.mem_cache:
return self.mem_cache[key]
# get the cache from the disk
if self.cache_dir is None:
return None
header = self.FindHeader(header)
cache_file = self.CacheFileName(interface)
if os.path.isfile(cache_file):
f = file(cache_file, 'rb')
try:
cache = load(f)
if cache.has_key(key):
self.cache_files.append(cache_file)
return cache[key]
else:
return None
finally:
f.close()
else:
return None
def CreateCache(self, header, interface, tail, declarations):
key = (header, interface, tail)
# our memory cache only holds one item
self.mem_cache.clear()
self.mem_cache[key] = declarations
# save the cache in the disk
if self.cache_dir is None:
return
header = self.FindHeader(header)
cache_file = self.CacheFileName(interface)
if os.path.isfile(cache_file):
f = file(cache_file, 'rb')
try:
cache = load(f)
finally:
f.close()
else:
cache = {}
cache[key] = declarations
self.cache_files.append(cache_file)
f = file(cache_file, 'wb')
try:
dump(cache, f, 1)
finally:
f.close()
return cache_file
def Close(self):
if self.delete_cache and self.cache_files:
for filename in self.cache_files:
try:
os.remove(filename)
except OSError:
pass
self.cache_files = []
shutil.rmtree(self.cache_dir)

View File

@@ -1,44 +0,0 @@
from Exporter import Exporter
from settings import *
import utils
#==============================================================================
# EnumExporter
#==============================================================================
class EnumExporter(Exporter):
'Exports enumerators'
def __init__(self, info):
Exporter.__init__(self, info)
def SetDeclarations(self, declarations):
Exporter.SetDeclarations(self, declarations)
if self.declarations:
self.enum = self.GetDeclaration(self.info.name)
else:
self.enum = None
def Export(self, codeunit, exported_names):
if not self.info.exclude:
indent = self.INDENT
in_indent = self.INDENT*2
rename = self.info.rename or self.enum.name
full_name = self.enum.FullName()
if rename == "$_0" or rename == '._0':
full_name = "int"
rename = "unnamed"
code = indent + namespaces.python
code += 'enum_< %s >("%s")\n' % (full_name, rename)
for name in self.enum.values:
rename = self.info[name].rename or name
value_fullname = self.enum.ValueFullName(name)
code += in_indent + '.value("%s", %s)\n' % (rename, value_fullname)
code += indent + ';\n\n'
codeunit.Write('module', code)
exported_names[self.Name()] = 1
def Name(self):
return self.info.name

View File

@@ -1,88 +0,0 @@
import os.path
#==============================================================================
# Exporter
#==============================================================================
class Exporter(object):
'Base class for objects capable to generate boost.python code.'
INDENT = ' ' * 4
def __init__(self, info, parser_tail=None):
self.info = info
self.parser_tail = parser_tail
self.interface_file = None
self.declarations = []
def Name(self):
raise NotImplementedError(self.__class__.__name__)
def Tail(self):
return self.parser_tail
def Parse(self, parser):
self.parser = parser
header = self.info.include
tail = self.parser_tail
declarations, parser_header = parser.parse(header, tail)
self.parser_header = parser_header
self.SetDeclarations(declarations)
def SetParsedHeader(self, parsed_header):
self.parser_header = parsed_header
def SetDeclarations(self, declarations):
self.declarations = declarations
def GenerateCode(self, codeunit, exported_names):
self.WriteInclude(codeunit)
self.Export(codeunit, exported_names)
def WriteInclude(self, codeunit):
codeunit.Write('include', '#include <%s>\n' % self.info.include)
def Export(self, codeunit, exported_names):
'subclasses must override this to do the real work'
pass
def GetDeclarations(self, fullname):
decls = []
for decl in self.declarations:
if decl.FullName() == fullname:
decls.append(decl)
if not decls:
raise RuntimeError, 'no %s declaration found!' % fullname
return decls
def GetDeclaration(self, fullname):
decls = self.GetDeclarations(fullname)
#assert len(decls) == 1
return decls[0]
def Order(self):
'''Returns a string that uniquely identifies this instance. All
exporters will be sorted by Order before being exported.
'''
return 0, self.info.name
def Header(self):
return self.info.include
def __eq__(self, other):
return self.Name() == other.Name()
def __ne__(self, other):
return self.Name() != other.Name()

View File

@@ -1,87 +0,0 @@
from Exporter import Exporter
from policies import *
from declarations import *
from settings import *
import utils
import exporterutils
#==============================================================================
# FunctionExporter
#==============================================================================
class FunctionExporter(Exporter):
'Generates boost.python code to export the given function.'
def __init__(self, info, tail=None):
Exporter.__init__(self, info, tail)
def Export(self, codeunit, exported_names):
if not self.info.exclude:
decls = self.GetDeclarations(self.info.name)
for decl in decls:
self.info.policy = exporterutils.HandlePolicy(decl, self.info.policy)
self.ExportDeclaration(decl, len(decls) == 1, codeunit)
self.ExportOpaquePointer(decl, codeunit)
self.GenerateOverloads(decls, codeunit)
exported_names[self.Name()] = 1
def ExportDeclaration(self, decl, unique, codeunit):
name = self.info.rename or decl.name
defs = namespaces.python + 'def("%s", ' % name
wrapper = self.info.wrapper
if wrapper:
pointer = '&' + wrapper.FullName()
else:
pointer = decl.PointerDeclaration()
defs += pointer
defs += self.PolicyCode()
overload = self.OverloadName(decl)
if overload:
defs += ', %s()' % (namespaces.pyste + overload)
defs += ');'
codeunit.Write('module', self.INDENT + defs + '\n')
# add the code of the wrapper
if wrapper and wrapper.code:
codeunit.Write('declaration', wrapper.code + '\n')
def OverloadName(self, decl):
if decl.minArgs != decl.maxArgs:
return '%s_overloads_%i_%i' % \
(decl.name, decl.minArgs, decl.maxArgs)
else:
return ''
def GenerateOverloads(self, declarations, codeunit):
codes = {}
for decl in declarations:
overload = self.OverloadName(decl)
if overload and overload not in codes:
code = 'BOOST_PYTHON_FUNCTION_OVERLOADS(%s, %s, %i, %i)' %\
(overload, decl.FullName(), decl.minArgs, decl_.maxArgs)
codeunit.Write('declaration', code + '\n')
codes[overload] = None
def PolicyCode(self):
policy = self.info.policy
if policy is not None:
assert isinstance(policy, Policy)
return ', %s()' % policy.Code()
else:
return ''
def ExportOpaquePointer(self, function, codeunit):
if self.info.policy == return_value_policy(return_opaque_pointer):
typename = function.result.name
macro = exporterutils.EspecializeTypeID(typename)
if macro:
codeunit.Write('declaration-outside', macro)
def Name(self):
return self.info.name

View File

@@ -1,461 +0,0 @@
from declarations import *
from elementtree.ElementTree import ElementTree
from xml.parsers.expat import ExpatError
from copy import deepcopy
from utils import enumerate
#==============================================================================
# Exceptions
#==============================================================================
class InvalidXMLError(Exception): pass
class ParserError(Exception): pass
class InvalidContextError(ParserError): pass
#==============================================================================
# GCCXMLParser
#==============================================================================
class GCCXMLParser(object):
'Parse a GCC_XML file and extract the top-level declarations.'
interested_tags = {'Class':0, 'Function':0, 'Variable':0, 'Enumeration':0}
def Parse(self, filename):
self.elements = self.GetElementsFromXML(filename)
# high level declarations
self.declarations = []
self._names = {}
# parse the elements
for id in self.elements:
element, decl = self.elements[id]
if decl is None:
try:
self.ParseElement(id, element)
except InvalidContextError:
pass # ignore those nodes with invalid context
# (workaround gccxml bug)
def Declarations(self):
return self.declarations
def AddDecl(self, decl):
if decl.FullName() in self._names:
decl.is_unique= False
for d in self.declarations:
if d.FullName() == decl.FullName():
d.is_unique = False
self._names[decl.FullName()] = 0
self.declarations.append(decl)
def ParseElement(self, id, element):
method = 'Parse' + element.tag
if hasattr(self, method):
func = getattr(self, method)
func(id, element)
else:
self.ParseUnknown(id, element)
def GetElementsFromXML(self,filename):
'Extracts a dictionary of elements from the gcc_xml file.'
tree = ElementTree()
try:
tree.parse(filename)
except ExpatError:
raise InvalidXMLError, 'Not a XML file: %s' % filename
root = tree.getroot()
if root.tag != 'GCC_XML':
raise InvalidXMLError, 'Not a valid GCC_XML file'
# build a dictionary of id -> element, None
elementlist = root.getchildren()
elements = {}
for element in elementlist:
id = element.get('id')
if id:
elements[id] = element, None
return elements
def GetDecl(self, id):
if id not in self.elements:
if id == '_0':
raise InvalidContextError, 'Invalid context found in the xml file.'
else:
msg = 'ID not found in elements: %s' % id
raise ParserError, msg
elem, decl = self.elements[id]
if decl is None:
self.ParseElement(id, elem)
elem, decl = self.elements[id]
if decl is None:
raise ParserError, 'Could not parse element: %s' % elem.tag
return decl
def GetType(self, id):
def Check(id, feature):
pos = id.find(feature)
if pos != -1:
id = id[:pos] + id[pos+1:]
return True, id
else:
return False, id
const, id = Check(id, 'c')
volatile, id = Check(id, 'v')
restricted, id = Check(id, 'r')
decl = self.GetDecl(id)
if isinstance(decl, Type):
res = deepcopy(decl)
if const:
res.const = const
if volatile:
res.volatile = volatile
if restricted:
res.restricted = restricted
else:
res = Type(decl.FullName(), const)
res.volatile = volatile
res.restricted = restricted
return res
def GetLocation(self, location):
file, line = location.split(':')
file = self.GetDecl(file)
return file, int(line)
def Update(self, id, decl):
element, _ = self.elements[id]
self.elements[id] = element, decl
def ParseUnknown(self, id, element):
name = '__Unknown_Element_%s' % id
decl = Unknown(name)
self.Update(id, decl)
def ParseNamespace(self, id, element):
namespace = element.get('name')
context = element.get('context')
if context:
outer = self.GetDecl(context)
if not outer.endswith('::'):
outer += '::'
namespace = outer + namespace
if namespace.startswith('::'):
namespace = namespace[2:]
self.Update(id, namespace)
def ParseFile(self, id, element):
filename = element.get('name')
self.Update(id, filename)
def ParseVariable(self, id, element):
# in gcc_xml, a static Field is declared as a Variable, so we check
# this and call the Field parser.
context = self.GetDecl(element.get('context'))
if isinstance(context, Class):
self.ParseField(id, element)
elem, decl = self.elements[id]
decl.static = True
else:
namespace = context
name = element.get('name')
type_ = self.GetType(element.get('type'))
location = self.GetLocation(element.get('location'))
variable = Variable(type_, name, namespace)
variable.location = location
self.AddDecl(variable)
self.Update(id, variable)
def GetArguments(self, element):
args = []
for child in element:
if child.tag == 'Argument':
type = self.GetType(child.get('type'))
type.default = child.get('default')
args.append(type)
return args
def GetExceptions(self, exception_list):
if exception_list is None:
return None
exceptions = []
for t in exception_list.split():
exceptions.append(self.GetType(t))
return exceptions
def ParseFunction(self, id, element, functionType=Function):
'''functionType is used because a Operator is identical to a normal
function, only the type of the function changes.'''
name = element.get('name')
returns = self.GetType(element.get('returns'))
namespace = self.GetDecl(element.get('context'))
location = self.GetLocation(element.get('location'))
params = self.GetArguments(element)
incomplete = bool(int(element.get('incomplete', 0)))
throws = self.GetExceptions(element.get('throw', None))
function = functionType(name, namespace, returns, params, throws)
function.location = location
self.AddDecl(function)
self.Update(id, function)
def ParseOperatorFunction(self, id, element):
self.ParseFunction(id, element, Operator)
def GetHierarchy(self, bases):
'''Parses the string "bases" from the xml into a list of tuples of Base
instances. The first tuple is the most direct inheritance, and then it
goes up in the hierarchy.
'''
if bases is None:
return []
base_names = bases.split()
this_level = []
next_levels = []
for base in base_names:
# get the visibility
split = base.split(':')
if len(split) == 2:
visib = split[0]
base = split[1]
else:
visib = Scope.public
decl = self.GetDecl(base)
if not isinstance(decl, Class):
# on windows, there are some classes which "bases" points to an
# "Unimplemented" tag, but we are not interested in this classes
# anyway
continue
base = Base(decl.FullName(), visib)
this_level.append(base)
# normalize with the other levels
for index, level in enumerate(decl.hierarchy):
if index < len(next_levels):
next_levels[index] = next_levels[index] + level
else:
next_levels.append(level)
hierarchy = []
if this_level:
hierarchy.append(tuple(this_level))
if next_levels:
hierarchy.extend(next_levels)
return hierarchy
def GetMembers(self, member_list):
# members must be a string with the ids of the members
if member_list is None:
return []
members = []
for member in member_list.split():
decl = self.GetDecl(member)
if type(decl) in Class.ValidMemberTypes():
if type(decl) is str:
print decl
members.append(decl)
return members
def ParseClass(self, id, element):
name = element.get('name')
abstract = bool(int(element.get('abstract', '0')))
location = self.GetLocation(element.get('location'))
context = self.GetDecl(element.get('context'))
incomplete = bool(int(element.get('incomplete', 0)))
if isinstance(context, str):
class_ = Class(name, context, [], abstract)
else:
# a nested class
visib = element.get('access', Scope.public)
class_ = NestedClass(
name, context.FullName(), visib, [], abstract)
class_.incomplete = incomplete
# we have to add the declaration of the class before trying
# to parse its members and bases, to avoid recursion.
self.AddDecl(class_)
class_.location = location
self.Update(id, class_)
# now we can get the members and the bases
class_.hierarchy = self.GetHierarchy(element.get('bases'))
if class_.hierarchy:
class_.bases = class_.hierarchy[0]
members = self.GetMembers(element.get('members'))
for member in members:
if type(member) is str:
print member
class_.AddMember(member)
def ParseStruct(self, id, element):
self.ParseClass(id, element)
def ParseFundamentalType(self, id, element):
name = element.get('name')
type_ = FundamentalType(name)
self.Update(id, type_)
def ParseArrayType(self, id, element):
type = self.GetType(element.get('type'))
min = element.get('min')
max = element.get('max')
array = ArrayType(type.name, type.const, min, max)
self.Update(id, array)
def ParseReferenceType(self, id, element):
type = self.GetType(element.get('type'))
expand = not isinstance(type, FunctionType)
ref = ReferenceType(type.name, type.const, None, expand, type.suffix)
self.Update(id, ref)
def ParsePointerType(self, id, element):
type = self.GetType(element.get('type'))
expand = not isinstance(type, FunctionType)
ref = PointerType(type.name, type.const, None, expand, type.suffix)
self.Update(id, ref)
def ParseFunctionType(self, id, element):
result = self.GetType(element.get('returns'))
args = self.GetArguments(element)
func = FunctionType(result, args)
self.Update(id, func)
def ParseMethodType(self, id, element):
class_ = self.GetDecl(element.get('basetype')).FullName()
result = self.GetType(element.get('returns'))
args = self.GetArguments(element)
method = MethodType(result, args, class_)
self.Update(id, method)
def ParseField(self, id, element):
name = element.get('name')
visib = element.get('access', Scope.public)
classname = self.GetDecl(element.get('context')).FullName()
type_ = self.GetType(element.get('type'))
static = bool(int(element.get('extern', '0')))
location = self.GetLocation(element.get('location'))
var = ClassVariable(type_, name, classname, visib, static)
var.location = location
self.Update(id, var)
def ParseMethod(self, id, element, methodType=Method):
name = element.get('name')
result = self.GetType(element.get('returns'))
classname = self.GetDecl(element.get('context')).FullName()
visib = element.get('access', Scope.public)
static = bool(int(element.get('static', '0')))
virtual = bool(int(element.get('virtual', '0')))
abstract = bool(int(element.get('pure_virtual', '0')))
const = bool(int(element.get('const', '0')))
location = self.GetLocation(element.get('location'))
throws = self.GetExceptions(element.get('throw', None))
params = self.GetArguments(element)
method = methodType(
name, classname, result, params, visib, virtual, abstract, static, const, throws)
method.location = location
self.Update(id, method)
def ParseOperatorMethod(self, id, element):
self.ParseMethod(id, element, ClassOperator)
def ParseConstructor(self, id, element):
name = element.get('name')
visib = element.get('access', Scope.public)
classname = self.GetDecl(element.get('context')).FullName()
location = self.GetLocation(element.get('location'))
params = self.GetArguments(element)
ctor = Constructor(name, classname, params, visib)
ctor.location = location
self.Update(id, ctor)
def ParseDestructor(self, id, element):
name = element.get('name')
visib = element.get('access', Scope.public)
classname = self.GetDecl(element.get('context')).FullName()
virtual = bool(int(element.get('virtual', '0')))
location = self.GetLocation(element.get('location'))
des = Destructor(name, classname, visib, virtual)
des.location = location
self.Update(id, des)
def ParseConverter(self, id, element):
self.ParseMethod(id, element, ConverterOperator)
def ParseTypedef(self, id, element):
name = element.get('name')
type = self.GetType(element.get('type'))
context = self.GetDecl(element.get('context'))
if isinstance(context, Class):
context = context.FullName()
typedef = Typedef(type, name, context)
self.Update(id, typedef)
self.AddDecl(typedef)
def ParseEnumeration(self, id, element):
name = element.get('name')
location = self.GetLocation(element.get('location'))
context = self.GetDecl(element.get('context'))
incomplete = bool(int(element.get('incomplete', 0)))
if isinstance(context, str):
enum = Enumeration(name, context)
else:
visib = element.get('access', Scope.public)
enum = ClassEnumeration(name, context.FullName(), visib)
self.AddDecl(enum)
enum.location = location
for child in element:
if child.tag == 'EnumValue':
name = child.get('name')
value = int(child.get('init'))
enum.values[name] = value
enum.incomplete = incomplete
self.Update(id, enum)
def ParseDeclarations(filename):
'Returns a list of the top declarations found in the gcc_xml file.'
parser = GCCXMLParser()
parser.Parse(filename)
return parser.Declarations()
if __name__ == '__main__':
ParseDeclarations(r'D:\Programming\Libraries\boost-cvs\boost\libs\python\pyste\example\test.xml')

View File

@@ -1,76 +0,0 @@
from Exporter import Exporter
from ClassExporter import ClassExporter
from FunctionExporter import FunctionExporter
from EnumExporter import EnumExporter
from VarExporter import VarExporter
from infos import *
from declarations import *
import os.path
import exporters
import MultipleCodeUnit
#==============================================================================
# HeaderExporter
#==============================================================================
class HeaderExporter(Exporter):
'Exports all declarations found in the given header'
def __init__(self, info, parser_tail=None):
Exporter.__init__(self, info, parser_tail)
def WriteInclude(self, codeunit):
pass
def IsInternalName(self, name):
'''Returns true if the given name looks like a internal compiler
structure'''
return name.startswith('_')
def Export(self, codeunit, exported_names):
header = os.path.normpath(self.parser_header)
for decl in self.declarations:
# check if this declaration is in the header
location = os.path.normpath(decl.location[0])
if location == header and not self.IsInternalName(decl.name):
# ok, check the type of the declaration and export it accordingly
self.HandleDeclaration(decl, codeunit, exported_names)
def HandleDeclaration(self, decl, codeunit, exported_names):
'''Dispatch the declaration to the appropriate method, that must create
a suitable info object for a Exporter, create a Exporter, set its
declarations and append it to the list of exporters.
'''
dispatch_table = {
Class : ClassExporter,
Enumeration : EnumExporter,
Function : FunctionExporter,
Variable : VarExporter,
}
exporter_class = dispatch_table.get(type(decl))
if exporter_class is not None:
self.HandleExporter(decl, exporter_class, codeunit, exported_names)
def HandleExporter(self, decl, exporter_type, codeunit, exported_names):
# only export complete declarations
if not decl.incomplete:
info = self.info[decl.name]
info.name = decl.FullName()
info.include = self.info.include
exporter = exporter_type(info)
exporter.SetDeclarations(self.declarations)
exporter.SetParsedHeader(self.parser_header)
if isinstance(codeunit, MultipleCodeUnit.MultipleCodeUnit):
codeunit.SetCurrent(self.interface_file, exporter.Name())
else:
codeunit.SetCurrent(exporter.Name())
exporter.GenerateCode(codeunit, exported_names)
def Name(self):
return self.info.include

View File

@@ -1,24 +0,0 @@
import os.path
from Exporter import Exporter
#==============================================================================
# IncludeExporter
#==============================================================================
class IncludeExporter(Exporter):
'''Writes an include declaration to the module. Useful to add extra code
for use in the Wrappers.
This class just reimplements the Parse method to do nothing: the
WriteInclude in Exporter already does the work for us.
'''
def __init__(self, info, parser_tail=None):
Exporter.__init__(self, info, parser_tail)
def Parse(self, parser):
pass
def Name(self):
return '__all__'
def Header(self):
return None # means "don't try to parse me!"

View File

@@ -1,130 +0,0 @@
from SingleCodeUnit import SingleCodeUnit
import os
import utils
from SmartFile import SmartFile
#==============================================================================
# MultipleCodeUnit
#==============================================================================
class MultipleCodeUnit(object):
'''
Represents a bunch of cpp files, where each cpp file represents a header
to be exported by pyste. Another cpp, named <module>.cpp is created too.
'''
def __init__(self, modulename, outdir):
self.modulename = modulename
self.outdir = outdir
self.codeunits = {} # maps from a (filename, function) to a SingleCodeUnit
self.functions = []
self._current = None
self.all = SingleCodeUnit(None, None)
def _FunctionName(self, interface_file):
name = os.path.splitext(interface_file)[0]
return 'Export_%s' % utils.makeid(name)
def _FileName(self, interface_file):
filename = os.path.basename(interface_file)
filename = '_%s.cpp' % os.path.splitext(filename)[0]
return os.path.join(self.outdir, filename)
def SetCurrent(self, interface_file, export_name):
'Changes the current code unit'
if export_name is None:
self._current = None
elif export_name is '__all__':
self._current = self.all
else:
filename = self._FileName(interface_file)
function = self._FunctionName(interface_file)
try:
codeunit = self.codeunits[filename]
except KeyError:
codeunit = SingleCodeUnit(None, filename)
codeunit.module_definition = 'void %s()' % function
self.codeunits[filename] = codeunit
if function not in self.functions:
self.functions.append(function)
self._current = codeunit
def Current(self):
return self._current
current = property(Current, SetCurrent)
def Write(self, section, code):
if self._current is not None:
self.current.Write(section, code)
def Section(self, section):
if self._current is not None:
return self.current.Section(section)
def _CreateOutputDir(self):
try:
os.mkdir(self.outdir)
except OSError: pass # already created
def Save(self):
# create the directory where all the files will go
self._CreateOutputDir();
# order all code units by filename, and merge them all
codeunits = {} # filename => list of codeunits
# While ordering all code units by file name, the first code
# unit in the list of code units is used as the main unit
# which dumps all the include, declaration and
# declaration-outside sections at the top of the file.
for filename, codeunit in self.codeunits.items():
if filename not in codeunits:
# this codeunit is the main codeunit.
codeunits[filename] = [codeunit]
codeunit.Merge(self.all)
else:
main_unit = codeunits[filename][0]
for section in ('include', 'declaration', 'declaration-outside'):
main_unit.code[section] = main_unit.code[section] + codeunit.code[section]
codeunit.code[section] = ''
codeunits[filename].append(codeunit)
# Now write all the codeunits appending them correctly.
for file_units in codeunits.values():
append = False
for codeunit in file_units:
codeunit.Save(append)
if not append:
append = True
def GenerateMain(self, interfaces):
# generate the main cpp
filename = os.path.join(self.outdir, '_main.cpp')
fout = SmartFile(filename, 'w')
fout.write(utils.left_equals('Include'))
fout.write('#include <boost/python/module.hpp>\n\n')
fout.write(utils.left_equals('Exports'))
functions = [self._FunctionName(x) for x in interfaces]
for function in functions:
fout.write('void %s();\n' % function)
fout.write('\n')
fout.write(utils.left_equals('Module'))
fout.write('BOOST_PYTHON_MODULE(%s)\n' % self.modulename)
fout.write('{\n')
indent = ' ' * 4
for function in functions:
fout.write(indent)
fout.write('%s();\n' % function)
fout.write('}\n')

View File

@@ -1,98 +0,0 @@
from settings import namespaces
import settings
from utils import remove_duplicated_lines, left_equals
from SmartFile import SmartFile
#==============================================================================
# SingleCodeUnit
#==============================================================================
class SingleCodeUnit:
'''
Represents a cpp file, where other objects can write in one of the
predefined sections.
The avaiable sections are:
include - The include area of the cpp file
declaration - The part before the module definition
module - Inside the BOOST_PYTHON_MODULE macro
'''
def __init__(self, modulename, filename):
self.modulename = modulename
self.filename = filename
# define the avaiable sections
self.code = {}
# include section
self.code['include'] = '#include <boost/python.hpp>\n'
# declaration section (inside namespace)
self.code['declaration'] = ''
# declaration (outside namespace)
self.code['declaration-outside'] = ''
# inside BOOST_PYTHON_MACRO
self.code['module'] = ''
# create the default module definition
self.module_definition = 'BOOST_PYTHON_MODULE(%s)' % modulename
def Write(self, section, code):
'write the given code in the section of the code unit'
if section not in self.code:
raise RuntimeError, 'Invalid CodeUnit section: %s' % section
self.code[section] += code
def Merge(self, other):
for section in ('include', 'declaration', 'declaration-outside', 'module'):
self.code[section] = self.code[section] + other.code[section]
def Section(self, section):
return self.code[section]
def SetCurrent(self, *args):
pass
def Current(self):
pass
def Save(self, append=False):
'Writes this code unit to the filename'
space = '\n\n'
if not append:
flag = 'w'
else:
flag = 'a'
fout = SmartFile(self.filename, flag)
# includes
if self.code['include']:
includes = remove_duplicated_lines(self.code['include'])
fout.write('\n' + left_equals('Includes'))
fout.write(includes)
fout.write(space)
# using
if settings.USING_BOOST_NS and not append:
fout.write(left_equals('Using'))
fout.write('using namespace boost::python;\n\n')
# declarations
declaration = self.code['declaration']
declaration_outside = self.code['declaration-outside']
if declaration_outside or declaration:
fout.write(left_equals('Declarations'))
if declaration_outside:
fout.write(declaration_outside + '\n\n')
if declaration:
pyste_namespace = namespaces.pyste[:-2]
fout.write('namespace %s {\n\n' % pyste_namespace)
fout.write(declaration)
fout.write('\n}// namespace %s\n' % pyste_namespace)
fout.write(space)
# module
fout.write(left_equals('Module'))
fout.write(self.module_definition + '\n')
fout.write('{\n')
fout.write(self.code['module'])
fout.write('}\n\n')
fout.close()

View File

@@ -1,55 +0,0 @@
import os
import md5
#==============================================================================
# SmartFile
#==============================================================================
class SmartFile(object):
'''
A file-like object used for writing files. The given file will only be
actually written to disk if there's not a file with the same name, or if
the existing file is *different* from the file to be written.
'''
def __init__(self, filename, mode='w'):
self.filename = filename
self.mode = mode
self._contents = []
self._closed = False
def __del__(self):
if not self._closed:
self.close()
def write(self, string):
self._contents.append(string)
def _dowrite(self, contents):
f = file(self.filename, self.mode)
f.write(contents)
f.close()
def _GetMD5(self, string):
return md5.new(string).digest()
def close(self):
# if the filename doesn't exist, write the file right away
this_contents = ''.join(self._contents)
if not os.path.isfile(self.filename):
self._dowrite(this_contents)
else:
# read the contents of the file already in disk
f = file(self.filename)
other_contents = f.read()
f.close()
# test the md5 for both files
this_md5 = self._GetMD5(this_contents)
other_md5 = self._GetMD5(other_contents)
if this_md5 != other_md5:
self._dowrite(this_contents)
self._closed = True

View File

@@ -1,35 +0,0 @@
from Exporter import Exporter
from settings import *
import utils
#==============================================================================
# VarExporter
#==============================================================================
class VarExporter(Exporter):
'''Exports a global variable.
'''
def __init__(self, info):
Exporter.__init__(self, info)
def Export(self, codeunit, exported_names):
if self.info.exclude: return
decl = self.GetDeclaration(self.info.name)
if not decl.type.const:
msg = '---> Warning: The global variable "%s" is non-const:\n' \
' changes in Python will not reflect in C++.'
print msg % self.info.name
print
rename = self.info.rename or self.info.name
code = self.INDENT + namespaces.python
code += 'scope().attr("%s") = %s;\n' % (rename, self.info.name)
codeunit.Write('module', code)
def Order(self):
return 0, self.info.name
def Name(self):
return self.info.name

View File

@@ -1,643 +0,0 @@
'''
Defines classes that represent declarations found in C++ header files.
'''
#==============================================================================
# Declaration
#==============================================================================
class Declaration(object):
'''Base class for all declarations.
@ivar name: The name of the declaration.
@ivar namespace: The namespace of the declaration.
'''
def __init__(self, name, namespace):
'''
@type name: string
@param name: The name of this declaration
@type namespace: string
@param namespace: the full namespace where this declaration resides.
'''
self.name = name
self.namespace = namespace
self.location = '', -1 # (filename, line)
self.incomplete = False
self.is_unique = True
def FullName(self):
'''
Returns the full qualified name: "boost::inner::Test"
@rtype: string
@return: The full name of the declaration.
'''
namespace = self.namespace or ''
if namespace and not namespace.endswith('::'):
namespace += '::'
return namespace + self.name
def __repr__(self):
return '<Declaration %s at %s>' % (self.FullName(), id(self))
def __str__(self):
return 'Declaration of %s' % self.FullName()
#==============================================================================
# Class
#==============================================================================
class Class(Declaration):
'''
Represents a C++ class or struct. Iteration through it yields its members.
@type abstract: bool
@ivar abstract: if the class has any abstract methods.
@type bases: tuple
@ivar bases: tuple with L{Base} instances, representing the most direct
inheritance.
@type hierarchy: list
@ivar hierarchy: a list of tuples of L{Base} instances, representing
the entire hierarchy tree of this object. The first tuple is the parent
classes, and the other ones go up in the hierarchy.
'''
def __init__(self, name, namespace, members, abstract):
Declaration.__init__(self, name, namespace)
self.__members = members
self.__member_names = {}
self.abstract = abstract
self.bases = ()
self.hierarchy = ()
self.operator = {}
def __iter__(self):
'''iterates through the class' members.
'''
return iter(self.__members)
def Constructors(self, publics_only=True):
'''Returns a list of the constructors for this class.
@rtype: list
'''
constructors = []
for member in self:
if isinstance(member, Constructor):
if publics_only and member.visibility != Scope.public:
continue
constructors.append(member)
return constructors
def HasCopyConstructor(self):
'''Returns true if this class has a public copy constructor.
@rtype: bool
'''
for cons in self.Constructors():
if cons.IsCopy():
return True
return False
def HasDefaultConstructor(self):
'''Returns true if this class has a public default constructor.
@rtype: bool
'''
for cons in self.Constructors():
if cons.IsDefault():
return True
return False
def AddMember(self, member):
if member.name in self.__member_names:
member.is_unique = False
for m in self:
if m.name == member.name:
m.is_unique = False
else:
member.is_unique = True
self.__member_names[member.name] = 1
self.__members.append(member)
if isinstance(member, ClassOperator):
self.operator[member.name] = member
def ValidMemberTypes():
return (NestedClass, Method, Constructor, Destructor, ClassVariable,
ClassOperator, ConverterOperator, ClassEnumeration)
ValidMemberTypes = staticmethod(ValidMemberTypes)
#==============================================================================
# NestedClass
#==============================================================================
class NestedClass(Class):
'''The declaration of a class/struct inside another class/struct.
@type class: string
@ivar class: fullname of the class where this class is contained.
@type visibility: L{Scope}
@ivar visibility: the visibility of this class.
'''
def __init__(self, name, class_, visib, members, abstract):
Class.__init__(self, name, None, members, abstract)
self.class_ = class_
self.visibility = visib
def FullName(self):
'''The full name of this class, like ns::outer::inner.
@rtype: string
'''
return '%s::%s' % (self.class_, self.name)
#==============================================================================
# Scope
#==============================================================================
class Scope:
'''Used to represent the visibility of various members inside a class.
@cvar public: public visibility
@cvar private: private visibility
@cvar protected: protected visibility
'''
public = 'public'
private = 'private'
protected = 'protected'
#==============================================================================
# Base
#==============================================================================
class Base:
'''Represents a base class of another class.
@ivar _name: the full name of the base class.
@ivar _visibility: the visibility of the derivation.
'''
def __init__(self, name, visibility=Scope.public):
self.name = name
self.visibility = visibility
#==============================================================================
# Function
#==============================================================================
class Function(Declaration):
'''The declaration of a function.
@ivar _result: instance of L{Type} or None.
@ivar _parameters: list of L{Type} instances.
@ivar _throws: exception specifiers or None
'''
def __init__(self, name, namespace, result, params, throws=None):
Declaration.__init__(self, name, namespace)
# the result type: instance of Type, or None (constructors)
self.result = result
# the parameters: instances of Type
self.parameters = params
# the exception specification
self.throws = throws
def Exceptions(self):
if self.throws is None:
return ""
else:
return " throw(%s)" % ', '.join (self.throws)
def PointerDeclaration(self, force=False):
'''Returns a declaration of a pointer to this function.
@param force: If True, returns a complete pointer declaration regardless
if this function is unique or not.
'''
if self.is_unique and not force:
return '&%s' % self.FullName()
else:
result = self.result.FullName()
params = ', '.join([x.FullName() for x in self.parameters])
return '(%s (*)(%s))&%s' % (result, params, self.FullName())
def MinArgs(self):
min = 0
for arg in self.parameters:
if arg.default is None:
min += 1
return min
minArgs = property(MinArgs)
def MaxArgs(self):
return len(self.parameters)
maxArgs = property(MaxArgs)
#==============================================================================
# Operator
#==============================================================================
class Operator(Function):
'''The declaration of a custom operator. Its name is the same as the
operator name in C++, ie, the name of the declaration "operator+(..)" is
"+".
'''
def FullName(self):
namespace = self.namespace or ''
if not namespace.endswith('::'):
namespace += '::'
return namespace + 'operator' + self.name
#==============================================================================
# Method
#==============================================================================
class Method(Function):
'''The declaration of a method.
@ivar _visibility: the visibility of this method.
@ivar _virtual: if this method is declared as virtual.
@ivar _abstract: if this method is virtual but has no default implementation.
@ivar _static: if this method is static.
@ivar _class: the full name of the class where this method was declared.
@ivar _const: if this method is declared as const.
@ivar _throws: list of exception specificiers or None
'''
def __init__(self, name, class_, result, params, visib, virtual, abstract, static, const, throws=None):
Function.__init__(self, name, None, result, params, throws)
self.visibility = visib
self.virtual = virtual
self.abstract = abstract
self.static = static
self.class_ = class_
self.const = const
def FullName(self):
return self.class_ + '::' + self.name
def PointerDeclaration(self, force=False):
'''Returns a declaration of a pointer to this member function.
@param force: If True, returns a complete pointer declaration regardless
if this function is unique or not.
'''
if self.static:
# static methods are like normal functions
return Function.PointerDeclaration(self, force)
if self.is_unique and not force:
return '&%s' % self.FullName()
else:
result = self.result.FullName()
params = ', '.join([x.FullName() for x in self.parameters])
const = ''
if self.const:
const = 'const'
return '(%s (%s::*)(%s) %s%s)&%s' %\
(result, self.class_, params, const, self.Exceptions(), self.FullName())
#==============================================================================
# Constructor
#==============================================================================
class Constructor(Method):
'''A class' constructor.
'''
def __init__(self, name, class_, params, visib):
Method.__init__(self, name, class_, None, params, visib, False, False, False, False)
def IsDefault(self):
'''Returns True if this constructor is a default constructor.
'''
return len(self.parameters) == 0 and self.visibility == Scope.public
def IsCopy(self):
'''Returns True if this constructor is a copy constructor.
'''
if len(self.parameters) != 1:
return False
param = self.parameters[0]
class_as_param = self.parameters[0].name == self.class_
param_reference = isinstance(param, ReferenceType)
is_public = self.visibility = Scope.public
return param_reference and class_as_param and param.const and is_public
def PointerDeclaration(self, force=False):
return ''
#==============================================================================
# Destructor
#==============================================================================
class Destructor(Method):
'The destructor of a class.'
def __init__(self, name, class_, visib, virtual):
Method.__init__(self, name, class_, None, [], visib, virtual, False, False, False)
def FullName(self):
return self.class_ + '::~' + self.name
def PointerDeclaration(self, force=False):
return ''
#==============================================================================
# ClassOperator
#==============================================================================
class ClassOperator(Method):
'A custom operator in a class.'
def FullName(self):
return self.class_ + '::operator ' + self.name
#==============================================================================
# ConverterOperator
#==============================================================================
class ConverterOperator(ClassOperator):
'An operator in the form "operator OtherClass()".'
def FullName(self):
return self.class_ + '::operator ' + self.result.FullName()
#==============================================================================
# Type
#==============================================================================
class Type(Declaration):
'''Represents the type of a variable or parameter.
@ivar _const: if the type is constant.
@ivar _default: if this type has a default value associated with it.
@ivar _volatile: if this type was declared with the keyword volatile.
@ivar _restricted: if this type was declared with the keyword restricted.
@ivar _suffix: Suffix to get the full type name. '*' for pointers, for
example.
'''
def __init__(self, name, const=False, default=None, suffix=''):
Declaration.__init__(self, name, None)
# whatever the type is constant or not
self.const = const
# used when the Type is a function argument
self.default = default
self.volatile = False
self.restricted = False
self.suffix = suffix
def __repr__(self):
if self.const:
const = 'const '
else:
const = ''
return '<Type ' + const + self.name + '>'
def FullName(self):
if self.const:
const = 'const '
else:
const = ''
return const + self.name + self.suffix
#==============================================================================
# ArrayType
#==============================================================================
class ArrayType(Type):
'''Represents an array.
@ivar min: the lower bound of the array, usually 0. Can be None.
@ivar max: the upper bound of the array. Can be None.
'''
def __init__(self, name, const, min, max):
'min and max can be None.'
Type.__init__(self, name, const)
self.min = min
self.max = max
#==============================================================================
# ReferenceType
#==============================================================================
class ReferenceType(Type):
'''A reference type.'''
def __init__(self, name, const=False, default=None, expandRef=True, suffix=''):
Type.__init__(self, name, const, default)
if expandRef:
self.suffix = suffix + '&'
#==============================================================================
# PointerType
#==============================================================================
class PointerType(Type):
'A pointer type.'
def __init__(self, name, const=False, default=None, expandPointer=False, suffix=''):
Type.__init__(self, name, const, default)
if expandPointer:
self.suffix = suffix + '*'
#==============================================================================
# FundamentalType
#==============================================================================
class FundamentalType(Type):
'One of the fundamental types, like int, void, etc.'
def __init__(self, name, const=False, default=None):
Type.__init__(self, name, const, default)
#==============================================================================
# FunctionType
#==============================================================================
class FunctionType(Type):
'''A pointer to a function.
@ivar _result: the return value
@ivar _parameters: a list of Types, indicating the parameters of the function.
@ivar _name: the name of the function.
'''
def __init__(self, result, parameters):
Type.__init__(self, '', False)
self.result = result
self.parameters = parameters
self.name = self.FullName()
def FullName(self):
full = '%s (*)' % self.result.FullName()
params = [x.FullName() for x in self.parameters]
full += '(%s)' % ', '.join(params)
return full
#==============================================================================
# MethodType
#==============================================================================
class MethodType(FunctionType):
'''A pointer to a member function of a class.
@ivar _class: The fullname of the class that the method belongs to.
'''
def __init__(self, result, parameters, class_):
self.class_ = class_
FunctionType.__init__(self, result, parameters)
def FullName(self):
full = '%s (%s::*)' % (self.result.FullName(), self.class_)
params = [x.FullName() for x in self.parameters]
full += '(%s)' % ', '.join(params)
return full
#==============================================================================
# Variable
#==============================================================================
class Variable(Declaration):
'''Represents a global variable.
@type _type: L{Type}
@ivar _type: The type of the variable.
'''
def __init__(self, type, name, namespace):
Declaration.__init__(self, name, namespace)
self.type = type
#==============================================================================
# ClassVariable
#==============================================================================
class ClassVariable(Variable):
'''Represents a class variable.
@type _visibility: L{Scope}
@ivar _visibility: The visibility of this variable within the class.
@type _static: bool
@ivar _static: Indicates if the variable is static.
@ivar _class: Full name of the class that this variable belongs to.
'''
def __init__(self, type, name, class_, visib, static):
Variable.__init__(self, type, name, None)
self.visibility = visib
self.static = static
self.class_ = class_
def FullName(self):
return self.class_ + '::' + self.name
#==============================================================================
# Enumeration
#==============================================================================
class Enumeration(Declaration):
'''Represents an enum.
@type _values: dict of str => int
@ivar _values: holds the values for this enum.
'''
def __init__(self, name, namespace):
Declaration.__init__(self, name, namespace)
self.values = {} # dict of str => int
def ValueFullName(self, name):
'''Returns the full name for a value in the enum.
'''
assert name in self.values
namespace = self.namespace
if namespace:
namespace += '::'
return namespace + name
#==============================================================================
# ClassEnumeration
#==============================================================================
class ClassEnumeration(Enumeration):
'''Represents an enum inside a class.
@ivar _class: The full name of the class where this enum belongs.
@ivar _visibility: The visibility of this enum inside his class.
'''
def __init__(self, name, class_, visib):
Enumeration.__init__(self, name, None)
self.class_ = class_
self.visibility = visib
def FullName(self):
return '%s::%s' % (self.class_, self.name)
def ValueFullName(self, name):
assert name in self.values
return '%s::%s' % (self.class_, name)
#==============================================================================
# Typedef
#==============================================================================
class Typedef(Declaration):
'''A Typedef declaration.
@type _type: L{Type}
@ivar _type: The type of the typedef.
@type _visibility: L{Scope}
@ivar _visibility: The visibility of this typedef.
'''
def __init__(self, type, name, namespace):
Declaration.__init__(self, name, namespace)
self.type = type
self.visibility = Scope.public
#==============================================================================
# Unknown
#==============================================================================
class Unknown(Declaration):
'''A declaration that Pyste does not know how to handle.
'''
def __init__(self, name):
Declaration.__init__(self, name, None)

View File

@@ -1,5 +0,0 @@
# a list of Exporter instances
exporters = []
current_interface = None # the current interface file being processed

View File

@@ -1,82 +0,0 @@
'''
Various helpers for interface files.
'''
from settings import *
from policies import *
from declarations import *
#==============================================================================
# FunctionWrapper
#==============================================================================
class FunctionWrapper(object):
'''Holds information about a wrapper for a function or a method. It is
divided in 2 parts: the name of the Wrapper, and its code. The code is
placed in the declaration section of the module, while the name is used to
def' the function or method (with the pyste namespace prepend to it). If
code is None, the name is left unchanged.
'''
def __init__(self, name, code=None):
self.name = name
self.code = code
def FullName(self):
if self.code:
return namespaces.pyste + self.name
else:
return self.name
_printed_warnings = {} # used to avoid double-prints of warnings
#==============================================================================
# HandlePolicy
#==============================================================================
def HandlePolicy(function, policy):
'''Show a warning to the user if the function needs a policy and doesn't
have one. Return a policy to the function, which is the given policy itself
if it is not None, or a default policy for this method.
'''
def IsString(type):
'Return True if the Type instance can be considered a string'
return type.FullName() == 'const char*'
def IsPyObject(type):
return type.FullName() == '_object *' # internal name of PyObject
result = function.result
# if the function returns const char*, a policy is not needed
if IsString(result) or IsPyObject(result):
return policy
# if returns a const T&, set the default policy
if policy is None and result.const and isinstance(result, ReferenceType):
policy = return_value_policy(copy_const_reference)
# basic test if the result type demands a policy
needs_policy = isinstance(result, (ReferenceType, PointerType))
# show a warning to the user, if needed
if needs_policy and policy is None:
global _printed_warnings
warning = '---> Error: %s returns a pointer or a reference, ' \
'but no policy was specified.' % function.FullName()
if warning not in _printed_warnings:
print warning
print
# avoid double prints of the same warning
_printed_warnings[warning] = 1
return policy
#==============================================================================
# EspecializeTypeID
#==============================================================================
_exported_type_ids = {}
def EspecializeTypeID(typename):
global _exported_type_ids
macro = 'BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(%s)\n' % typename
if macro not in _exported_type_ids:
_exported_type_ids[macro] = 1
return macro
else:
return None

View File

@@ -1,237 +0,0 @@
import os.path
import copy
import exporters
from ClassExporter import ClassExporter
from FunctionExporter import FunctionExporter
from IncludeExporter import IncludeExporter
from EnumExporter import EnumExporter
from HeaderExporter import HeaderExporter
from VarExporter import VarExporter
from exporterutils import FunctionWrapper
from utils import makeid
#==============================================================================
# DeclarationInfo
#==============================================================================
class DeclarationInfo:
def __init__(self, otherInfo=None):
self.__infos = {}
self.__attributes = {}
if otherInfo is not None:
self.__infos = copy.deepcopy(otherInfo.__infos)
self.__attributes = copy.deepcopy(otherInfo.__attributes)
def __getitem__(self, name):
'Used to access sub-infos'
if name.startswith('__'):
raise AttributeError
default = DeclarationInfo()
default._Attribute('name', name)
return self.__infos.setdefault(name, default)
def __getattr__(self, name):
return self[name]
def _Attribute(self, name, value=None):
if value is None:
# get value
return self.__attributes.get(name)
else:
# set value
self.__attributes[name] = value
#==============================================================================
# FunctionInfo
#==============================================================================
class FunctionInfo(DeclarationInfo):
def __init__(self, name, include, tail=None, otherOption=None):
DeclarationInfo.__init__(self, otherOption)
self._Attribute('name', name)
self._Attribute('include', include)
self._Attribute('exclude', False)
# create a FunctionExporter
exporter = FunctionExporter(InfoWrapper(self), tail)
if exporter not in exporters.exporters:
exporters.exporters.append(exporter)
exporter.interface_file = exporters.current_interface
#==============================================================================
# ClassInfo
#==============================================================================
class ClassInfo(DeclarationInfo):
def __init__(self, name, include, tail=None, otherInfo=None):
DeclarationInfo.__init__(self, otherInfo)
self._Attribute('name', name)
self._Attribute('include', include)
self._Attribute('exclude', False)
# create a ClassExporter
exporter = ClassExporter(InfoWrapper(self), tail)
if exporter not in exporters.exporters:
exporters.exporters.append(exporter)
exporter.interface_file = exporters.current_interface
#==============================================================================
# IncludeInfo
#==============================================================================
class IncludeInfo(DeclarationInfo):
def __init__(self, include):
DeclarationInfo.__init__(self)
self._Attribute('include', include)
exporter = IncludeExporter(InfoWrapper(self))
if exporter not in exporters.exporters:
exporters.exporters.append(exporter)
exporter.interface_file = exporters.current_interface
#==============================================================================
# templates
#==============================================================================
def GenerateName(name, type_list):
name = name.replace('::', '_')
names = [name] + type_list
return makeid('_'.join(names))
class ClassTemplateInfo(DeclarationInfo):
def __init__(self, name, include):
DeclarationInfo.__init__(self)
self._Attribute('name', name)
self._Attribute('include', include)
def Instantiate(self, type_list, rename=None):
if not rename:
rename = GenerateName(self._Attribute('name'), type_list)
# generate code to instantiate the template
types = ', '.join(type_list)
tail = 'typedef %s< %s > %s;\n' % (self._Attribute('name'), types, rename)
tail += 'void __instantiate_%s()\n' % rename
tail += '{ sizeof(%s); }\n\n' % rename
# create a ClassInfo
class_ = ClassInfo(rename, self._Attribute('include'), tail, self)
return class_
def __call__(self, types, rename=None):
if isinstance(types, str):
types = types.split()
return self.Instantiate(types, rename)
#==============================================================================
# EnumInfo
#==============================================================================
class EnumInfo(DeclarationInfo):
def __init__(self, name, include):
DeclarationInfo.__init__(self)
self._Attribute('name', name)
self._Attribute('include', include)
self._Attribute('exclude', False)
exporter = EnumExporter(InfoWrapper(self))
if exporter not in exporters.exporters:
exporters.exporters.append(exporter)
exporter.interface_file = exporters.current_interface
#==============================================================================
# HeaderInfo
#==============================================================================
class HeaderInfo(DeclarationInfo):
def __init__(self, include):
DeclarationInfo.__init__(self)
self._Attribute('include', include)
exporter = HeaderExporter(InfoWrapper(self))
if exporter not in exporters.exporters:
exporters.exporters.append(exporter)
exporter.interface_file = exporters.current_interface
#==============================================================================
# VarInfo
#==============================================================================
class VarInfo(DeclarationInfo):
def __init__(self, name, include):
DeclarationInfo.__init__(self)
self._Attribute('name', name)
self._Attribute('include', include)
exporter = VarExporter(InfoWrapper(self))
if exporter not in exporters.exporters:
exporters.exporters.append(exporter)
exporter.interface_file = exporters.current_interface
#==============================================================================
# InfoWrapper
#==============================================================================
class InfoWrapper:
'Provides a nicer interface for a info'
def __init__(self, info):
self.__dict__['_info'] = info # so __setattr__ is not called
def __getitem__(self, name):
return InfoWrapper(self._info[name])
def __getattr__(self, name):
return self._info._Attribute(name)
def __setattr__(self, name, value):
self._info._Attribute(name, value)
#==============================================================================
# Functions
#==============================================================================
def exclude(info):
info._Attribute('exclude', True)
def set_policy(info, policy):
info._Attribute('policy', policy)
def rename(info, name):
info._Attribute('rename', name)
def set_wrapper(info, wrapper):
if isinstance(wrapper, str):
wrapper = FunctionWrapper(wrapper)
info._Attribute('wrapper', wrapper)
def instantiate(template, types, rename=None):
if isinstance(types, str):
types = types.split()
return template.Instantiate(types, rename)
def use_shared_ptr(info):
info._Attribute('smart_ptr', 'boost::shared_ptr< %s >')
def use_auto_ptr(info):
info._Attribute('smart_ptr', 'std::auto_ptr< %s >')
def holder(info, function):
msg = "Expected a callable that accepts one string argument."
assert callable(function), msg
info._Attribute('holder', function)
def add_method(info, name, rename=None):
added = info._Attribute('__added__')
if added is None:
info._Attribute('__added__', [(name, rename)])
else:
added.append((name, rename))
def final(info):
info._Attribute('no_override', True)

View File

@@ -1,83 +0,0 @@
class Policy:
'Represents one of the call policies of boost.python.'
def __init__(self):
raise RuntimeError, "Can't create an instance of the class Policy"
def Code(self):
'Returns the string corresponding to a instancialization of the policy.'
pass
def _next(self):
if self.next is not None:
return ', %s >' % self.next.Code()
else:
return ' >'
def __eq__(self, other):
try:
return self.Code() == other.Code()
except AttributeError:
return False
class return_internal_reference(Policy):
'Ties the return value to one of the parameters.'
def __init__(self, param=1, next=None):
'''
param is the position of the parameter, or None for "self".
next indicates the next policy, or None.
'''
self.param = param
self.next=next
def Code(self):
c = 'return_internal_reference< %i' % self.param
c += self._next()
return c
class with_custodian_and_ward(Policy):
'Ties lifetime of two arguments of a function.'
def __init__(self, custodian, ward, next=None):
self.custodian = custodian
self.ward = ward
self.next = next
def Code(self):
c = 'with_custodian_and_ward< %i, %i' % (self.custodian, self.ward)
c += self._next()
return c
class return_value_policy(Policy):
'Policy to convert return values.'
def __init__(self, which, next=None):
self.which = which
self.next = next
def Code(self):
c = 'return_value_policy< %s' % self.which
c += self._next()
return c
# values for return_value_policy
reference_existing_object = 'reference_existing_object'
copy_const_reference = 'copy_const_reference'
copy_non_const_reference = 'copy_non_const_reference'
manage_new_object = 'manage_new_object'
return_opaque_pointer = 'return_opaque_pointer'

View File

@@ -1,16 +0,0 @@
import profile
import pstats
import pyste
import elementtree.XMLTreeBuilder as XMLTreeBuilder
import GCCXMLParser
if __name__ == '__main__':
#psyco.bind(XMLTreeBuilder.fixtext)
#psyco.bind(XMLTreeBuilder.fixname)
#psyco.bind(XMLTreeBuilder.TreeBuilder)
#psyco.bind(GCCXMLParser.GCCXMLParser)
profile.run('pyste.main()', 'profile')
p = pstats.Stats('profile')
p.strip_dirs().sort_stats('cumulative').print_stats()

View File

@@ -1,370 +0,0 @@
"""
Pyste version %s
Usage:
pyste [options] interface-files
where options are:
--module=<name> The name of the module that will be generated;
defaults to the first interface filename, without
the extension.
-I <path> Add an include path
-D <symbol> Define symbol
--multiple Create various cpps, instead of only one
(useful during development)
--out=<name> Specify output filename (default: <module>.cpp)
in --multiple mode, this will be a directory
--no-using Do not declare "using namespace boost";
use explicit declarations instead
--pyste-ns=<name> Set the namespace where new types will be declared;
default is the empty namespace
--debug Writes the xml for each file parsed in the current
directory
--cache-dir=<dir> Directory for cache files (speeds up future runs)
--only-create-cache Recreates all caches (doesn't generate code).
--generate-main Generates the _main.cpp file (in multiple mode)
-h, --help Print this help and exit
-v, --version Print version information
"""
import sys
import os
import getopt
import exporters
import SingleCodeUnit
import MultipleCodeUnit
import infos
import exporterutils
import settings
import gc
import sys
from policies import *
from CppParser import CppParser, CppParserError
import time
from declarations import Typedef
__VERSION__ = '0.9.14'
def RecursiveIncludes(include):
'Return a list containg the include dir and all its subdirectories'
dirs = [include]
def visit(arg, dir, names):
# ignore CVS dirs
if os.path.split(dir)[1] != 'CVS':
dirs.append(dir)
os.path.walk(include, visit, None)
return dirs
def GetDefaultIncludes():
if 'INCLUDE' in os.environ:
include = os.environ['INCLUDE']
return include.split(os.pathsep)
else:
return []
def ProcessIncludes(includes):
if sys.platform == 'win32':
index = 0
for include in includes:
includes[index] = include.replace('\\', '/')
index += 1
def ParseArguments():
def Usage():
print __doc__ % __VERSION__
sys.exit(1)
try:
options, files = getopt.getopt(
sys.argv[1:],
'R:I:D:vh',
['module=', 'multiple', 'out=', 'no-using', 'pyste-ns=', 'debug', 'cache-dir=',
'only-create-cache', 'version', 'generate-main', 'help'])
except getopt.GetoptError, e:
print
print 'ERROR:', e
Usage()
includes = GetDefaultIncludes()
defines = []
module = None
out = None
multiple = False
cache_dir = None
create_cache = False
generate_main = False
for opt, value in options:
if opt == '-I':
includes.append(value)
elif opt == '-D':
defines.append(value)
elif opt == '-R':
includes.extend(RecursiveIncludes(value))
elif opt == '--module':
module = value
elif opt == '--out':
out = value
elif opt == '--no-using':
settings.namespaces.python = 'boost::python::'
settings.USING_BOOST_NS = False
elif opt == '--pyste-ns':
settings.namespaces.pyste = value + '::'
elif opt == '--debug':
settings.DEBUG = True
elif opt == '--multiple':
multiple = True
elif opt == '--cache-dir':
cache_dir = value
elif opt == '--only-create-cache':
create_cache = True
elif opt in ['-h', '--help']:
Usage()
elif opt in ['-v', '--version']:
print 'Pyste version %s' % __VERSION__
sys.exit(2)
elif opt == '--generate-main':
generate_main = True
else:
print 'Unknown option:', opt
Usage()
if not files:
Usage()
if not module:
module = os.path.splitext(files[0])[0]
if not out:
out = module
if not multiple:
out += '.cpp'
for file in files:
d = os.path.dirname(os.path.abspath(file))
if d not in sys.path:
sys.path.append(d)
if create_cache and not cache_dir:
print 'Error: Use --cache-dir to indicate where to create the cache files!'
Usage()
sys.exit(3)
if generate_main and not multiple:
print 'Error: --generate-main only valid in multiple mode.'
Usage()
sys.exit(3)
ProcessIncludes(includes)
return includes, defines, module, out, files, multiple, cache_dir, create_cache, generate_main
def CreateContext():
'create the context where a interface file will be executed'
context = {}
context['Import'] = ExecuteInterface
# infos
context['Function'] = infos.FunctionInfo
context['Class'] = infos.ClassInfo
context['Include'] = infos.IncludeInfo
context['Template'] = infos.ClassTemplateInfo
context['Enum'] = infos.EnumInfo
context['AllFromHeader'] = infos.HeaderInfo
context['Var'] = infos.VarInfo
# functions
context['rename'] = infos.rename
context['set_policy'] = infos.set_policy
context['exclude'] = infos.exclude
context['set_wrapper'] = infos.set_wrapper
context['use_shared_ptr'] = infos.use_shared_ptr
context['use_auto_ptr'] = infos.use_auto_ptr
context['holder'] = infos.holder
context['add_method'] = infos.add_method
context['final'] = infos.final
# policies
context['return_internal_reference'] = return_internal_reference
context['with_custodian_and_ward'] = with_custodian_and_ward
context['return_value_policy'] = return_value_policy
context['reference_existing_object'] = reference_existing_object
context['copy_const_reference'] = copy_const_reference
context['copy_non_const_reference'] = copy_non_const_reference
context['return_opaque_pointer'] = return_opaque_pointer
context['manage_new_object'] = manage_new_object
# utils
context['Wrapper'] = exporterutils.FunctionWrapper
return context
def Begin():
# parse arguments
includes, defines, module, out, interfaces, multiple, cache_dir, create_cache, generate_main = ParseArguments()
# run pyste scripts
for interface in interfaces:
ExecuteInterface(interface)
# create the parser
parser = CppParser(includes, defines, cache_dir)
try:
if not create_cache:
if not generate_main:
return GenerateCode(parser, module, out, interfaces, multiple)
else:
return GenerateMain(module, out, OrderInterfaces(interfaces))
else:
return CreateCaches(parser)
finally:
parser.Close()
def CreateCaches(parser):
# There is one cache file per interface so we organize the headers
# by interfaces. For each interface collect the tails from the
# exporters sharing the same header.
tails = JoinTails(exporters.exporters)
# now for each interface file take each header, and using the tail
# get the declarations and cache them.
for interface, header in tails:
tail = tails[(interface, header)]
declarations = parser.ParseWithGCCXML(header, tail)
cachefile = parser.CreateCache(header, interface, tail, declarations)
print 'Cached', cachefile
return 0
_imported_count = {} # interface => count
def ExecuteInterface(interface):
old_interface = exporters.current_interface
if not os.path.exists(interface):
if old_interface and os.path.exists(old_interface):
d = os.path.dirname(old_interface)
interface = os.path.join(d, interface)
if not os.path.exists(interface):
raise IOError, "Cannot find interface file %s."%interface
_imported_count[interface] = _imported_count.get(interface, 0) + 1
exporters.current_interface = interface
context = CreateContext()
execfile(interface, context)
exporters.current_interface = old_interface
def JoinTails(exports):
'''Returns a dict of {(interface, header): tail}, where tail is the
joining of all tails of all exports for the header.
'''
tails = {}
for export in exports:
interface = export.interface_file
header = export.Header()
tail = export.Tail() or ''
if (interface, header) in tails:
all_tails = tails[(interface,header)]
all_tails += '\n' + tail
tails[(interface, header)] = all_tails
else:
tails[(interface, header)] = tail
return tails
def OrderInterfaces(interfaces):
interfaces_order = [(_imported_count[x], x) for x in interfaces]
interfaces_order.sort()
interfaces_order.reverse()
return [x for _, x in interfaces_order]
def GenerateMain(module, out, interfaces):
codeunit = MultipleCodeUnit.MultipleCodeUnit(module, out)
codeunit.GenerateMain(interfaces)
return 0
def GenerateCode(parser, module, out, interfaces, multiple):
# prepare to generate the wrapper code
if multiple:
codeunit = MultipleCodeUnit.MultipleCodeUnit(module, out)
else:
codeunit = SingleCodeUnit.SingleCodeUnit(module, out)
# stop referencing the exporters here
exports = exporters.exporters
exporters.exporters = None
exported_names = dict([(x.Name(), None) for x in exports])
# order the exports
interfaces_order = OrderInterfaces(interfaces)
order = {}
for export in exports:
if export.interface_file in order:
order[export.interface_file].append(export)
else:
order[export.interface_file] = [export]
exports = []
for interface in interfaces_order:
exports.extend(order[interface])
del order
del interfaces_order
# now generate the code in the correct order
#print exported_names
tails = JoinTails(exports)
for i in xrange(len(exports)):
export = exports[i]
interface = export.interface_file
header = export.Header()
if header:
tail = tails[(interface, header)]
declarations, parsed_header = parser.Parse(header, interface, tail)
else:
declarations = []
parsed_header = None
ExpandTypedefs(declarations, exported_names)
export.SetDeclarations(declarations)
export.SetParsedHeader(parsed_header)
if multiple:
codeunit.SetCurrent(export.interface_file, export.Name())
export.GenerateCode(codeunit, exported_names)
# force collect of cyclic references
exports[i] = None
del declarations
del export
gc.collect()
# finally save the code unit
codeunit.Save()
if not multiple:
print 'Module %s generated' % module
return 0
def ExpandTypedefs(declarations, exported_names):
'''Check if the names in exported_names are a typedef, and add the real class
name in the dict.
'''
for name in exported_names.keys():
for decl in declarations:
if isinstance(decl, Typedef):
exported_names[decl.type.FullName()] = None
def UsePsyco():
'Tries to use psyco if possible'
try:
import psyco
psyco.profile()
except: pass
def main():
start = time.clock()
UsePsyco()
status = Begin()
print '%0.2f seconds' % (time.clock()-start)
sys.exit(status)
if __name__ == '__main__':
main()

View File

@@ -1,13 +0,0 @@
#==============================================================================
# Global information
#==============================================================================
DEBUG = False
USING_BOOST_NS = True
class namespaces:
boost = 'boost::'
pyste = ''
python = '' # default is to not use boost::python namespace explicitly, so
# use the "using namespace" statement instead

View File

@@ -1,71 +0,0 @@
from __future__ import generators
import string
import sys
#==============================================================================
# enumerate
#==============================================================================
def enumerate(seq):
i = 0
for x in seq:
yield i, x
i += 1
#==============================================================================
# makeid
#==============================================================================
_valid_chars = string.ascii_letters + string.digits + '_'
_valid_chars = dict(zip(_valid_chars, _valid_chars))
def makeid(name):
'Returns the name as a valid identifier'
if type(name) != str:
print type(name), name
newname = []
for char in name:
if char not in _valid_chars:
char = '_'
newname.append(char)
newname = ''.join(newname)
# avoid duplications of '_' chars
names = [x for x in newname.split('_') if x]
return '_'.join(names)
#==============================================================================
# remove_duplicated_lines
#==============================================================================
def remove_duplicated_lines(text):
includes = text.splitlines()
d = dict([(include, 0) for include in includes])
return '\n'.join(d.keys())
#==============================================================================
# left_equals
#==============================================================================
def left_equals(s):
s = '// %s ' % s
return s + ('='*(80-len(s))) + '\n'
#==============================================================================
# post_mortem
#==============================================================================
def post_mortem():
def info(type, value, tb):
if hasattr(sys, 'ps1') or not sys.stderr.isatty():
# we are in interactive mode or we don't have a tty-like
# device, so we call the default hook
sys.__excepthook__(type, value, tb)
else:
import traceback, pdb
# we are NOT in interactive mode, print the exception...
traceback.print_exception(type, value, tb)
print
# ...then start the debugger in post-mortem mode.
pdb.pm()
sys.excepthook = info

View File

@@ -1,7 +0,0 @@
*.pyc
*.exp
*.lib
*.obj
*.arg
*.dll
.sconsign

View File

@@ -1,336 +0,0 @@
import sys
sys.path.append('../src')
import unittest
import tempfile
import os.path
import GCCXMLParser
from declarations import *
class Tester(unittest.TestCase):
def TestConstructor(self, class_, method, visib):
self.assert_(isinstance(method, Constructor))
self.assertEqual(method.FullName(), class_.FullName() + '::' + method.name)
self.assertEqual(method.result, None)
self.assertEqual(method.visibility, visib)
self.assert_(not method.virtual)
self.assert_(not method.abstract)
self.assert_(not method.static)
def TestDefaultConstructor(self, class_, method, visib):
self.TestConstructor(class_, method, visib)
self.assert_(method.IsDefault())
def TestCopyConstructor(self, class_, method, visib):
self.TestConstructor(class_, method, visib)
self.assertEqual(len(method.parameters), 1)
param = method.parameters[0]
self.TestType(
param,
ReferenceType,
class_.FullName(),
'const %s&' % class_.FullName(),
True)
self.assert_(method.IsCopy())
def TestType(self, type_, classtype_, name, fullname, const):
self.assert_(isinstance(type_, classtype_))
self.assertEqual(type_.name, name)
self.assertEqual(type_.namespace, None)
self.assertEqual(type_.FullName(), fullname)
self.assertEqual(type_.const, const)
class ClassBaseTest(Tester):
def setUp(self):
self.base = GetDecl('Base')
def testClass(self):
'test the properties of the class Base'
self.assert_(isinstance(self.base, Class))
self.assert_(self.base.abstract)
def testFoo(self):
'test function foo in class Base'
foo = GetMember(self.base, 'foo')
self.assert_(isinstance(foo, Method))
self.assertEqual(foo.visibility, Scope.public)
self.assert_(foo.virtual)
self.assert_(foo.abstract)
self.failIf(foo.static)
self.assertEqual(foo.class_, 'test::Base')
self.failIf(foo.const)
self.assertEqual(foo.FullName(), 'test::Base::foo')
self.assertEqual(foo.result.name, 'void')
self.assertEqual(len(foo.parameters), 1)
param = foo.parameters[0]
self.TestType(param, FundamentalType, 'int', 'int', False)
self.assertEqual(foo.namespace, None)
self.assertEqual(
foo.PointerDeclaration(1), '(void (test::Base::*)(int) )&test::Base::foo')
def testX(self):
'test the member x in class Base'
x = GetMember(self.base, 'x')
self.assertEqual(x.class_, 'test::Base')
self.assertEqual(x.FullName(), 'test::Base::x')
self.assertEqual(x.namespace, None)
self.assertEqual(x.visibility, Scope.private)
self.TestType(x.type, FundamentalType, 'int', 'int', False)
self.assertEqual(x.static, False)
def testConstructors(self):
'test constructors in class Base'
constructors = GetMembers(self.base, 'Base')
for cons in constructors:
if len(cons.parameters) == 0:
self.TestDefaultConstructor(self.base, cons, Scope.public)
elif len(cons.parameters) == 1: # copy constructor
self.TestCopyConstructor(self.base, cons, Scope.public)
elif len(cons.parameters) == 2: # other constructor
intp, floatp = cons.parameters
self.TestType(intp, FundamentalType, 'int', 'int', False)
self.TestType(floatp, FundamentalType, 'float', 'float', False)
def testSimple(self):
'test function simple in class Base'
simple = GetMember(self.base, 'simple')
self.assert_(isinstance(simple, Method))
self.assertEqual(simple.visibility, Scope.protected)
self.assertEqual(simple.FullName(), 'test::Base::simple')
self.assertEqual(len(simple.parameters), 1)
param = simple.parameters[0]
self.TestType(param, ReferenceType, 'std::string', 'const std::string&', True)
self.TestType(simple.result, FundamentalType, 'bool', 'bool', False)
self.assertEqual(
simple.PointerDeclaration(1),
'(bool (test::Base::*)(const std::string&) )&test::Base::simple')
def testZ(self):
z = GetMember(self.base, 'z')
self.assert_(isinstance(z, Variable))
self.assertEqual(z.visibility, Scope.public)
self.assertEqual(z.FullName(), 'test::Base::z')
self.assertEqual(z.type.name, 'int')
self.assertEqual(z.type.const, False)
self.assert_(z.static)
class ClassTemplateTest(Tester):
def setUp(self):
self.template = GetDecl('Template<int>')
def testClass(self):
'test the properties of the Template<int> class'
self.assert_(isinstance(self.template, Class))
self.assert_(not self.template.abstract)
self.assertEqual(self.template.FullName(), 'Template<int>')
self.assertEqual(self.template.namespace, '')
self.assertEqual(self.template.name, 'Template<int>')
def testConstructors(self):
'test the automatic constructors of the class Template<int>'
constructors = GetMembers(self.template, 'Template')
for cons in constructors:
if len(cons.parameters) == 0:
self.TestDefaultConstructor(self.template, cons, Scope.public)
elif len(cons.parameters) == 1:
self.TestCopyConstructor(self.template, cons, Scope.public)
def testValue(self):
'test the class variable value'
value = GetMember(self.template, 'value')
self.assert_(isinstance(value, ClassVariable))
self.assert_(value.name, 'value')
self.TestType(value.type, FundamentalType, 'int', 'int', False)
self.assert_(not value.static)
self.assertEqual(value.visibility, Scope.public)
self.assertEqual(value.class_, 'Template<int>')
self.assertEqual(value.FullName(), 'Template<int>::value')
def testBase(self):
'test the superclasses of Template<int>'
bases = self.template.bases
self.assertEqual(len(bases), 1)
base = bases[0]
self.assert_(isinstance(base, Base))
self.assertEqual(base.name, 'test::Base')
self.assertEqual(base.visibility, Scope.protected)
class FreeFuncTest(Tester):
def setUp(self):
self.func = GetDecl('FreeFunc')
def testFunc(self):
'test attributes of FreeFunc'
self.assert_(isinstance(self.func, Function))
self.assertEqual(self.func.name, 'FreeFunc')
self.assertEqual(self.func.FullName(), 'test::FreeFunc')
self.assertEqual(self.func.namespace, 'test')
self.assertEqual(
self.func.PointerDeclaration(1),
'(const test::Base& (*)(const std::string&, int))&test::FreeFunc')
def testResult(self):
'test the return value of FreeFunc'
res = self.func.result
self.TestType(res, ReferenceType, 'test::Base', 'const test::Base&', True)
def testParameters(self):
'test the parameters of FreeFunc'
self.assertEqual(len(self.func.parameters), 2)
strp, intp = self.func.parameters
self.TestType(strp, ReferenceType, 'std::string', 'const std::string&', True)
self.assertEqual(strp.default, None)
self.TestType(intp, FundamentalType, 'int', 'int', False)
self.assertEqual(intp.default, '10')
class testFunctionPointers(Tester):
def testMethodPointer(self):
'test declaration of a pointer-to-method'
meth = GetDecl('MethodTester')
param = meth.parameters[0]
fullname = 'void (test::Base::*)(int)'
self.TestType(param, PointerType, fullname, fullname, False)
def testFunctionPointer(self):
'test declaration of a pointer-to-function'
func = GetDecl('FunctionTester')
param = func.parameters[0]
fullname = 'void (*)(int)'
self.TestType(param, PointerType, fullname, fullname, False)
# =============================================================================
# Support routines
# =============================================================================
cppcode = '''
namespace std {
class string;
}
namespace test {
class Base
{
public:
Base();
Base(const Base&);
Base(int, float);
virtual void foo(int = 0.0) = 0;
static int z;
protected:
bool simple(const std::string&);
private:
int x;
};
void MethodTester( void (Base::*)(int) );
void FunctionTester( void (*)(int) );
const Base & FreeFunc(const std::string&, int=10);
}
template <class T>
struct Template: protected test::Base
{
T value;
virtual void foo(int);
};
Template<int> __aTemplateInt;
'''
def GetXMLFile():
'''Generates an gccxml file using the code from the global cppcode.
Returns the xml's filename.'''
# write the code to a header file
tmpfile = tempfile.mktemp() + '.h'
f = file(tmpfile, 'w')
f.write(cppcode)
f.close()
# run gccxml
outfile = tmpfile + '.xml'
if os.system('gccxml "%s" "-fxml=%s"' % (tmpfile, outfile)) != 0:
raise RuntimeError, 'Error executing GCCXML.'
# read the output file into the xmlcode
f = file(outfile)
xmlcode = f.read()
#print xmlcode
f.close()
# remove the header
os.remove(tmpfile)
return outfile
def GetDeclarations():
'Uses the GCCXMLParser module to get the declarations.'
xmlfile = GetXMLFile()
declarations = GCCXMLParser.ParseDeclarations(xmlfile)
os.remove(xmlfile)
return declarations
# the declarations to be analysed
declarations = GetDeclarations()
def GetDecl(name):
'returns one of the top declarations given its name'
for decl in declarations:
if decl.name == name:
return decl
else:
raise RuntimeError, 'Declaration not found: %s' % name
def GetMember(class_, name):
'gets the member of the given class by its name'
res = None
multipleFound = False
for member in class_:
if member.name == name:
if res is not None:
multipleFound = True
break
res = member
if res is None or multipleFound:
raise RuntimeError, \
'No member or more than one member found in class %s: %s' \
% (class_.name, name)
return res
def GetMembers(class_, name):
'gets the members of the given class by its name'
res = []
for member in class_:
if member.name == name:
res.append(member)
if len(res) in (0, 1):
raise RuntimeError, \
'GetMembers: 0 or 1 members found in class %s: %s' \
% (class_.name, name)
return res
if __name__ == '__main__':
unittest.main()

View File

@@ -1,80 +0,0 @@
import sys
sys.path.append('../src')
from SmartFile import *
import unittest
import tempfile
import os
import time
class SmartFileTest(unittest.TestCase):
FILENAME = tempfile.mktemp()
def setUp(self):
self._Clean()
def tearDown(self):
self._Clean()
def _Clean(self):
try:
os.remove(self.FILENAME)
except OSError: pass
def testNonExistant(self):
"Must override the file, as there's no file in the disk yet"
self.assert_(not os.path.isfile(self.FILENAME))
f = SmartFile(self.FILENAME, 'w')
f.write('Testing 123\nTesting again.')
f.close()
self.assert_(os.path.isfile(self.FILENAME))
def testOverride(self):
"Must override the file, because the contents are different"
contents = 'Contents!\nContents!'
# create the file normally first
f = file(self.FILENAME, 'w')
f.write(contents)
f.close()
file_time = os.path.getmtime(self.FILENAME)
self.assert_(os.path.isfile(self.FILENAME))
time.sleep(2)
f = SmartFile(self.FILENAME, 'w')
f.write(contents + '_')
f.close()
new_file_time = os.path.getmtime(self.FILENAME)
self.assert_(new_file_time != file_time)
def testNoOverride(self):
"Must not override the file, because the contents are the same"
contents = 'Contents!\nContents!'
# create the file normally first
f = file(self.FILENAME, 'w')
f.write(contents)
f.close()
file_time = os.path.getmtime(self.FILENAME)
self.assert_(os.path.isfile(self.FILENAME))
time.sleep(2)
f = SmartFile(self.FILENAME, 'w')
f.write(contents)
f.close()
new_file_time = os.path.getmtime(self.FILENAME)
self.assert_(new_file_time == file_time)
def testAutoClose(self):
"Must be closed when garbage-collected"
def foo():
f = SmartFile(self.FILENAME)
f.write('testing')
self.assert_(not os.path.isfile(self.FILENAME))
foo()
self.assert_(os.path.isfile(self.FILENAME))
if __name__ == '__main__':
unittest.main()

View File

@@ -1,17 +0,0 @@
#include <vector>
#include <string>
namespace abstract {
struct A {
virtual ~A() {}
virtual std::string f()=0;
};
struct B: A {
std::string f() { return "B::f"; }
};
std::string call(A* a) { return a->f(); }
}

View File

@@ -1,3 +0,0 @@
Class('abstract::A', 'abstract_test.h')
Class('abstract::B', 'abstract_test.h')
Function('abstract::call', 'abstract_test.h')

View File

@@ -1,22 +0,0 @@
import unittest
from _abstract_test import *
class AbstractTest(unittest.TestCase):
def testIt(self):
class C(A):
def f(self):
return 'C::f'
a = A()
b = B()
c = C()
self.assertRaises(RuntimeError, a.f)
self.assertEqual(b.f(), 'B::f')
self.assertEqual(call(b), 'B::f')
self.assertEqual(c.f(), 'C::f')
self.assertEqual(call(c), 'C::f')
if __name__ == '__main__':
unittest.main()

View File

@@ -1,13 +0,0 @@
namespace add_test {
struct C
{
int x;
};
const int get_x(C& c)
{
return c.x;
}
}

View File

@@ -1,2 +0,0 @@
C = Class('add_test::C', 'add_test.h')
add_method(C, 'add_test::get_x')

View File

@@ -1,12 +0,0 @@
import unittest
from _add_test import *
class AddMethodTest(unittest.TestCase):
def testIt(self):
c = C()
c.x = 10
self.assertEqual(c.get_x(), 10)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,8 +0,0 @@
#include "basic.h"
namespace basic {
int C::static_value = 3;
const int C::const_static_value = 100;
}

View File

@@ -1,64 +0,0 @@
#ifndef BASIC_H
#define BASIC_H
#include <string>
namespace basic {
struct C
{
// test virtuallity
C(): value(1), const_value(0) {}
virtual int f(int x = 10)
{
return x*2;
}
int foo(int x=1){
return x+1;
}
const std::string& get_name() { return name; }
void set_name(const std::string& name) { this->name = name; }
private:
std::string name;
public:
// test data members
static int static_value;
static const int const_static_value;
int value;
const int const_value;
// test static functions
static int mul(int x, int y) { return x*y; }
static double mul(double x, double y) { return x*y; }
static int square(int x=2) { return x*x; }
};
inline int call_f(C& c)
{
return c.f();
}
inline int call_f(C& c, int x)
{
return c.f(x);
}
inline int get_static()
{
return C::static_value;
}
inline int get_value(C& c)
{
return c.value;
}
}
#endif

View File

@@ -1,5 +0,0 @@
Class('basic::C', 'basic.h')
Function('basic::call_f', 'basic.h')
Function('basic::get_static', 'basic.h')
Function('basic::get_value', 'basic.h')

View File

@@ -1,69 +0,0 @@
import unittest
from _basic import *
class BasicExampleTest(unittest.TestCase):
def testIt(self):
# test virtual functions
class D(C):
def f(self, x=10):
return x+1
d = D()
c = C()
self.assertEqual(c.f(), 20)
self.assertEqual(c.f(3), 6)
self.assertEqual(d.f(), 11)
self.assertEqual(d.f(3), 4)
self.assertEqual(call_f(c), 20)
self.assertEqual(call_f(c, 4), 8)
self.assertEqual(call_f(d), 11)
self.assertEqual(call_f(d, 3), 4)
# test data members
def testValue(value):
self.assertEqual(c.value, value)
self.assertEqual(d.value, value)
self.assertEqual(get_value(c), value)
self.assertEqual(get_value(d), value)
testValue(1)
c.value = 30
d.value = 30
testValue(30)
self.assertEqual(c.const_value, 0)
self.assertEqual(d.const_value, 0)
def set_const_value():
c.const_value = 12
self.assertRaises(AttributeError, set_const_value)
# test static data-members
def testStatic(value):
self.assertEqual(C.static_value, value)
self.assertEqual(c.static_value, value)
self.assertEqual(D.static_value, value)
self.assertEqual(d.static_value, value)
self.assertEqual(get_static(), value)
testStatic(3)
C.static_value = 10
testStatic(10)
self.assertEqual(C.const_static_value, 100)
def set_const_static():
C.const_static_value = 1
self.assertRaises(AttributeError, set_const_static)
# test static function
def test_mul(result, *args):
self.assertEqual(C.mul(*args), result)
self.assertEqual(c.mul(*args), result)
test_mul(16, 8, 2)
test_mul(6.0, 2.0, 3.0)
self.assertEqual(C.square(), 4)
self.assertEqual(c.square(), 4)
self.assertEqual(C.square(3), 9)
self.assertEqual(c.square(3), 9)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,29 +0,0 @@
#ifndef ENUMS_H
#define ENUMS_H
namespace enums {
enum color { red, blue };
struct X
{
enum choices
{
good = 1,
bad = 2
};
int set(choices c)
{
return (int)c;
}
};
enum {
x = 0,
y = 1
};
}
#endif

View File

@@ -1,7 +0,0 @@
h = AllFromHeader('enums.h')
rename(h.color.red, 'Red')
rename(h.color.blue, 'Blue')
rename(h.X.choices.bad, 'Bad')
rename(h.X.choices.good, 'Good')
rename(h.X.choices, 'Choices')

View File

@@ -1,20 +0,0 @@
import unittest
from _enums import *
class EnumsTest(unittest.TestCase):
def testIt(self):
self.assertEqual(int(color.Red), 0)
self.assertEqual(int(color.Blue), 1)
self.assertEqual(int(X.Choices.Good), 1)
self.assertEqual(int(X.Choices.Bad), 2)
x = X()
self.assertEqual(x.set(x.Choices.Good), 1)
self.assertEqual(x.set(x.Choices.Bad), 2)
self.assertEqual(unnamed.x, 0)
self.assertEqual(unnamed.y, 1)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,38 +0,0 @@
#ifndef HEADER_TEST_H
#define HEADER_TEST_H
#include <map>
#include <string>
namespace header_test {
enum choice { red, blue };
inline std::string choice_str(choice c)
{
std::map<choice, std::string> choice_map;
choice_map[red] = "red";
choice_map[blue] = "blue";
return choice_map[c];
}
struct C
{
choice c;
std::string get()
{
return choice_str(c);
}
};
// test the exclusion of the following
struct ForwardDeclared; // should be excluded automatically
struct A {};
void foo();
enum bar { value };
}
#endif

View File

@@ -1,4 +0,0 @@
h = AllFromHeader('header_test.h')
exclude(h.A)
exclude(h.foo)
exclude(h.bar)

View File

@@ -1,23 +0,0 @@
import unittest
from _header_test import *
class HeaderTest(unittest.TestCase):
def testIt(self):
self.assertEqual(choice.red, 0)
self.assertEqual(choice.blue, 1)
self.assertEqual(choice_str(choice.blue), 'blue')
self.assertEqual(choice_str(choice.red), 'red')
c = C()
c.c = choice.blue
self.assertEqual(c.get(), 'blue')
c.c = choice.red
self.assertEqual(c.get(), 'red')
# the following classes/functions should not have being exported
self.assertRaises(NameError, lambda: A())
self.assertRaises(NameError, lambda: foo())
self.assertRaises(NameError, lambda: bar.value)
self.assertRaises(NameError, lambda: ForwardDeclared())
if __name__ == '__main__':
unittest.main()

View File

@@ -1,50 +0,0 @@
import sys
sys.path.append('../src')
from infos import *
from policies import *
from exporterutils import *
import unittest
class InfosTest(unittest.TestCase):
def testFunctionInfo(self):
info = FunctionInfo('test::foo', 'foo.h')
rename(info, 'hello')
set_policy(info, return_internal_reference())
set_wrapper(info, FunctionWrapper('foo_wrapper'))
info = InfoWrapper(info)
self.assertEqual(info.rename, 'hello')
self.assertEqual(info.policy.Code(), 'return_internal_reference< 1 >')
self.assertEqual(info.wrapper.name, 'foo_wrapper')
def testClassInfo(self):
info = ClassInfo('test::IFoo', 'foo.h')
rename(info.name, 'Name')
rename(info.exclude, 'Exclude')
rename(info, 'Foo')
rename(info.Bar, 'bar')
set_policy(info.Baz, return_internal_reference())
rename(info.operator['>>'], 'from_string')
exclude(info.Bar)
set_wrapper(info.Baz, FunctionWrapper('baz_wrapper'))
info = InfoWrapper(info)
self.assertEqual(info.rename, 'Foo')
self.assertEqual(info['Bar'].rename, 'bar')
self.assertEqual(info['name'].rename, 'Name')
self.assertEqual(info['exclude'].rename, 'Exclude')
self.assertEqual(info['Bar'].exclude, True)
self.assertEqual(info['Baz'].policy.Code(), 'return_internal_reference< 1 >')
self.assertEqual(info['Baz'].wrapper.name, 'baz_wrapper')
self.assertEqual(info['operator']['>>'].rename, 'from_string')
if __name__ == '__main__':
unittest.main()

View File

@@ -1,3 +0,0 @@
#include "inherit.h"
int inherit::C::s = 1;

View File

@@ -1,39 +0,0 @@
namespace inherit {
template<typename T>
class A
{
public:
void set(T v) { mData = v; }
T get() const { return mData; }
private:
T mData;
};
class B : public A<int>
{
public:
int go() { return get(); }
};
struct C : B
{
enum ab { a = 1, b = 2 };
int f1() { return 1; }
int x;
static int s;
};
struct D : C
{
int f2() { return 2; }
int y;
};
struct X {};
struct E: X, D {};
}

View File

@@ -1,8 +0,0 @@
A = Template('inherit::A', 'inherit.h')
A_int = A('int', 'A_int')
Class('inherit::B', 'inherit.h')
Class('inherit::D', 'inherit.h')
E = Class('inherit::E', 'inherit.h')
exclude(E.s)
exclude(E.ab)

View File

@@ -1,30 +0,0 @@
namespace inherit2 {
struct A
{
int x;
int getx() { return x; }
int foo() { return 0; }
int foo(int x) { return x; }
};
struct B : A
{
int y;
int gety() { return y; }
int foo() { return 1; }
};
struct C : B
{
int z;
int getz() { return z; }
};
struct D : C
{
int w;
int getw() { return w; }
};
}

View File

@@ -1,2 +0,0 @@
Class('inherit2::B', 'inherit2.h')
Class('inherit2::D', 'inherit2.h')

View File

@@ -1,27 +0,0 @@
import unittest
from _inherit2 import *
class InheritExampleTest(unittest.TestCase):
def testIt(self):
b = B()
d = D()
self.assert_(issubclass(D, B))
b.x, b.y = 10, 5
self.assertEqual(b.getx(), 10)
self.assertEqual(b.gety(), 5)
d.x, d.y, d.z, d.w = 20, 15, 10, 5
self.assertEqual(d.getx(), 20)
self.assertEqual(d.gety(), 15)
self.assertEqual(d.getz(), 10)
self.assertEqual(d.getw(), 5)
self.assertEqual(b.foo(), 1)
self.assertEqual(b.foo(3), 3)
def wrong():
return b.getw()
self.assertRaises(AttributeError, wrong)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,39 +0,0 @@
namespace inherit3 {
struct A
{
struct X { int y; };
int x;
virtual int foo() { return 0; }
virtual int foo(int x) { return x; }
A operator+(A o) const
{
A r;
r.x = o.x + x;
return r;
}
enum E { i, j };
};
struct B: A
{
struct X { int y; };
int x;
int foo() { return 1; }
A operator+(A o) const
{
A r;
r.x = o.x + x;
return r;
}
enum E { i, j };
};
struct C: A
{
};
}

View File

@@ -1,2 +0,0 @@
Class('inherit3::B', 'inherit3.h')
Class('inherit3::C', 'inherit3.h')

View File

@@ -1,23 +0,0 @@
import unittest
from _inherit3 import *
class testInherit3(unittest.TestCase):
def testIt(self):
def testInst(c):
self.assertEqual(c.x, 0)
self.assertEqual(c.foo(3), 3)
x = c.X()
self.assertEqual(x.y, 0)
self.assertEqual(c.E.i, 0)
self.assertEqual(c.E.j, 1)
b = B()
c = C()
testInst(b)
testInst(c)
self.assertEqual(b.foo(), 1)
self.assertEqual(c.foo(), 0)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,29 +0,0 @@
import unittest
from _inherit import *
class InheritExampleTest(unittest.TestCase):
def testIt(self):
a = A_int()
b = B()
self.assert_(isinstance(b, A_int))
self.assert_(issubclass(B, A_int))
a.set(10)
self.assertEqual(a.get(), 10)
b.set(1)
self.assertEqual(b.go(), 1)
self.assertEqual(b.get(), 1)
d = D()
self.assert_(issubclass(D, B))
self.assertEqual(d.x, 0)
self.assertEqual(d.y, 0)
self.assertEqual(d.s, 1)
self.assertEqual(D.s, 1)
self.assertEqual(d.f1(), 1)
self.assertEqual(d.f2(), 2)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,4 +0,0 @@
#include "nested.h"
int nested::X::staticXValue = 10;
int nested::X::Y::staticYValue = 20;

View File

@@ -1,26 +0,0 @@
#ifndef NESTED_H
#define NESTED_H
namespace nested {
struct X
{
struct Y
{
int valueY;
static int staticYValue;
struct Z
{
int valueZ;
};
};
static int staticXValue;
int valueX;
};
typedef X Root;
}
#endif

View File

@@ -1 +0,0 @@
Class('nested::Root', 'nested.h')

View File

@@ -1,15 +0,0 @@
import unittest
from _nested import *
class NestedTest(unittest.TestCase):
def testIt(self):
self.assertEqual(Root.staticXValue, 10)
self.assertEqual(Root.Y.staticYValue, 20)
z = Root.Y.Z()
z.valueZ = 3
self.assertEqual(z.valueZ, 3)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,52 +0,0 @@
#ifndef OPAQUE_H
#define OPAQUE_H
#include <iostream>
namespace opaque {
struct C {
C(int v): value(v) {}
int value;
};
inline C* new_C()
{
return new C(10);
}
inline C* new_C_zero()
{
return new C(0);
}
inline int get(C* c)
{
return c->value;
}
struct D {
D(double v): value(v) {}
double value;
};
struct A
{
D* new_handle()
{
return new D(3.0);
}
double get(D* d)
{
return d->value;
}
int f(int x=0) { return x; }
};
}
#endif

View File

@@ -1,7 +0,0 @@
foo = Function('opaque::new_C', 'opaque.h')
set_policy(foo, return_value_policy(return_opaque_pointer))
foo = Function('opaque::new_C_zero', 'opaque.h')
set_policy(foo, return_value_policy(return_opaque_pointer))
Function('opaque::get', 'opaque.h' )
A = Class('opaque::A', 'opaque.h')
set_policy(A.new_handle, return_value_policy(return_opaque_pointer))

View File

@@ -1,20 +0,0 @@
import unittest
from _opaque import *
class OpaqueTest(unittest.TestCase):
def testIt(self):
c = new_C()
self.assertEqual(get(c), 10)
c = new_C_zero()
self.assertEqual(get(c), 0)
a = A()
d = a.new_handle()
self.assertEqual(a.get(d), 3.0)
self.assertEqual(a.f(), 0)
self.assertEqual(a.f(3), 3)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,3 +0,0 @@
#include "operators.h"
double operators::C::x = 10;

View File

@@ -1,47 +0,0 @@
#ifndef OPERATORS_H
#define OPERATORS_H
namespace operators {
struct C
{
static double x;
double value;
const C operator+(const C other) const
{
C c;
c.value = value + other.value;
return c;
}
operator int() const
{
return (int)value;
}
double operator()()
{
return C::x;
}
double operator()(double other)
{
return C::x + other;
}
operator const char*() { return "C"; }
};
inline const C operator*(const C& lhs, const C& rhs)
{
C c;
c.value = lhs.value * rhs.value;
return c;
}
}
#endif

View File

@@ -1,2 +0,0 @@
C = Class('operators::C', 'operators.h')
#exclude(C.operator['+'])

Some files were not shown because too many files have changed in this diff Show More