Compare commits
4 Commits
boost-0.7.
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c75c27e7ca | ||
|
|
4eadbb299e | ||
|
|
ac20fcca63 | ||
|
|
cd00f7b01f |
142
build/Jamfile
Normal file
@@ -0,0 +1,142 @@
|
||||
# (C) Copyright David Abrahams 2001. 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.
|
||||
#
|
||||
# Boost.Python build and test Jamfile
|
||||
#
|
||||
# To run all tests quietly: jam test
|
||||
# To run all tests with verbose output: jam -sPYTHON_TEST_ARGS=-v test
|
||||
#
|
||||
# Declares the following targets:
|
||||
# 1. libboost_python, a static link library to be linked with all
|
||||
# Boost.Python modules
|
||||
#
|
||||
# 2. pairs of test targets of the form <name>.test and <name>.run
|
||||
# <name>.test runs the test when it is out-of-date, and the "test"
|
||||
# pseudotarget depends on it. <name>.run runs
|
||||
# a test unconditionally, and can be used to force a test to run.. Each
|
||||
# test target builds one or more Boost.Python modules and runs a Python
|
||||
# script to test them. The test names are:
|
||||
#
|
||||
# from ../test
|
||||
#
|
||||
# comprehensive - a comprehensive test of Boost.Python features
|
||||
#
|
||||
# from ../example:
|
||||
# abstract -
|
||||
# getting_started1 -
|
||||
# getting_started2 -
|
||||
# simple_vector -
|
||||
# do_it_yourself_convts -
|
||||
# pickle1 -
|
||||
# pickle2 -
|
||||
# pickle3 -
|
||||
#
|
||||
# dvect1 -
|
||||
# dvect2 -
|
||||
# ivect1 -
|
||||
# ivect2 -
|
||||
# noncopyable -
|
||||
#
|
||||
# subproject-specific environment/command-line variables:
|
||||
#
|
||||
# PYTHON - How to invoke the Python interpreter. Defaults to "python"
|
||||
#
|
||||
# PYTHON_ROOT - Windows only: where Python is installed. Defaults to "c:/tools/python"
|
||||
#
|
||||
# PYTHON_VERSION - Version of Python. Defaults to "2.1" on Windows, "1.5" on Unix
|
||||
#
|
||||
# PYTHON_TEST_ARGS - specifies arguments to be passed to test scripts on
|
||||
# the command line. "-v" can be useful if you want to
|
||||
# see the output of successful tests.
|
||||
#
|
||||
# PYTHON_VECT_ITERATIONS - specifies the number of test iterations to use for
|
||||
# the dvect and ivect tests above.
|
||||
|
||||
# declare the location of this subproject relative to the root
|
||||
subproject libs/python/build ;
|
||||
|
||||
# bring in the rules for python
|
||||
SEARCH on <module@>python.jam = $(BOOST_BUILD_PATH) ;
|
||||
include <module@>python.jam ;
|
||||
|
||||
#######################
|
||||
local rule bpl-test ( test-name : sources + )
|
||||
{
|
||||
boost-python-test $(test-name) : $(sources) <lib>libboost_python ;
|
||||
}
|
||||
|
||||
#######################
|
||||
|
||||
#
|
||||
# Declare the boost python static link library
|
||||
#
|
||||
|
||||
# Base names of the source files for libboost_python
|
||||
local CPP_SOURCES =
|
||||
types classes conversions extension_class functions
|
||||
init_function module_builder objects cross_module ;
|
||||
|
||||
lib libboost_python : ../src/$(CPP_SOURCES).cpp
|
||||
# requirements
|
||||
: $(BOOST_PYTHON_INCLUDES)
|
||||
<shared-linkable>true
|
||||
$(PYTHON_PROPERTIES) ;
|
||||
|
||||
|
||||
############# comprehensive module and test ###########
|
||||
bpl-test boost_python_test
|
||||
: ../test/comprehensive.cpp ;
|
||||
|
||||
boost-python-runtest comprehensive
|
||||
: ../test/comprehensive.py <lib>boost_python_test <lib>libboost_python ;
|
||||
|
||||
############# simple tests from ../example ############
|
||||
|
||||
local rule boost-python-example-runtest ( name )
|
||||
{
|
||||
bpl-test $(name)
|
||||
: ../example/$(name).cpp ;
|
||||
|
||||
boost-python-runtest $(name)
|
||||
: ../example/test_$(name).py <lib>$(name) ;
|
||||
}
|
||||
|
||||
|
||||
boost-python-example-runtest abstract ;
|
||||
boost-python-example-runtest getting_started1 ;
|
||||
boost-python-example-runtest getting_started2 ;
|
||||
boost-python-example-runtest simple_vector ;
|
||||
boost-python-example-runtest do_it_yourself_convts ;
|
||||
boost-python-example-runtest pickle1 ;
|
||||
boost-python-example-runtest pickle2 ;
|
||||
boost-python-example-runtest pickle3 ;
|
||||
|
||||
|
||||
bpl-test ivect : ../example/ivect.cpp ;
|
||||
bpl-test dvect : ../example/dvect.cpp ;
|
||||
bpl-test noncopyable_export : ../example/noncopyable_export.cpp ;
|
||||
bpl-test noncopyable_import : ../example/noncopyable_import.cpp ;
|
||||
|
||||
############## cross-module tests from ../example ##########
|
||||
|
||||
# A simple rule to build a test which depends on multiple modules in the PYTHONPATH
|
||||
local rule boost-python-multi-example-runtest ( test-name : modules + )
|
||||
{
|
||||
boost-python-runtest $(test-name)
|
||||
: ../example/tst_$(test-name).py <lib>$(modules) <lib>libboost_python
|
||||
: : : $(PYTHON_VECT_ITERATIONS) ;
|
||||
}
|
||||
|
||||
PYTHON_VECT_ITERATIONS ?= 10 ;
|
||||
|
||||
boost-python-multi-example-runtest dvect1 : ivect dvect ;
|
||||
boost-python-multi-example-runtest dvect2 : ivect dvect ;
|
||||
|
||||
boost-python-multi-example-runtest ivect1 : ivect dvect ;
|
||||
boost-python-multi-example-runtest ivect2 : ivect dvect ;
|
||||
|
||||
boost-python-multi-example-runtest
|
||||
noncopyable : noncopyable_import noncopyable_export ;
|
||||
|
||||
233
include/boost/python/detail/arg_tuple_size.hpp
Normal file
@@ -0,0 +1,233 @@
|
||||
// (C) Copyright David Abrahams 2001. 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.
|
||||
//
|
||||
// This work was funded in part by Lawrence Berkeley National Labs
|
||||
//
|
||||
// This file generated for 5-argument member functions and 6-argument free
|
||||
// functions by gen_arg_tuple_size.python
|
||||
|
||||
#ifndef ARG_TUPLE_SIZE_DWA20011201_HPP
|
||||
# define ARG_TUPLE_SIZE_DWA20011201_HPP
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
// Computes (at compile-time) the number of elements that a Python
|
||||
// argument tuple must have in order to be passed to a wrapped C++
|
||||
// (member) function of the given type.
|
||||
template <class F> struct arg_tuple_size;
|
||||
|
||||
# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__BORLANDC__)
|
||||
|
||||
template <class R>
|
||||
struct arg_tuple_size<R (*)()>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(std::size_t, value = 0);
|
||||
};
|
||||
|
||||
template <class R, class A1>
|
||||
struct arg_tuple_size<R (*)(A1)>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(std::size_t, value = 1);
|
||||
};
|
||||
|
||||
template <class R, class A1, class A2>
|
||||
struct arg_tuple_size<R (*)(A1, A2)>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(std::size_t, value = 2);
|
||||
};
|
||||
|
||||
template <class R, class A1, class A2, class A3>
|
||||
struct arg_tuple_size<R (*)(A1, A2, A3)>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(std::size_t, value = 3);
|
||||
};
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4>
|
||||
struct arg_tuple_size<R (*)(A1, A2, A3, A4)>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(std::size_t, value = 4);
|
||||
};
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4, class A5>
|
||||
struct arg_tuple_size<R (*)(A1, A2, A3, A4, A5)>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(std::size_t, value = 5);
|
||||
};
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
struct arg_tuple_size<R (*)(A1, A2, A3, A4, A5, A6)>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(std::size_t, value = 6);
|
||||
};
|
||||
|
||||
|
||||
template <class R, class A0>
|
||||
struct arg_tuple_size<R (A0::*)()>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(std::size_t, value = 1);
|
||||
};
|
||||
|
||||
template <class R, class A0, class A1>
|
||||
struct arg_tuple_size<R (A0::*)(A1)>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(std::size_t, value = 2);
|
||||
};
|
||||
|
||||
template <class R, class A0, class A1, class A2>
|
||||
struct arg_tuple_size<R (A0::*)(A1, A2)>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(std::size_t, value = 3);
|
||||
};
|
||||
|
||||
template <class R, class A0, class A1, class A2, class A3>
|
||||
struct arg_tuple_size<R (A0::*)(A1, A2, A3)>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(std::size_t, value = 4);
|
||||
};
|
||||
|
||||
template <class R, class A0, class A1, class A2, class A3, class A4>
|
||||
struct arg_tuple_size<R (A0::*)(A1, A2, A3, A4)>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(std::size_t, value = 5);
|
||||
};
|
||||
|
||||
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
|
||||
struct arg_tuple_size<R (A0::*)(A1, A2, A3, A4, A5)>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(std::size_t, value = 6);
|
||||
};
|
||||
|
||||
# else
|
||||
|
||||
// We will use the "sizeof() trick" to work around the lack of
|
||||
// partial specialization in MSVC6 and its broken-ness in borland.
|
||||
// See http://opensource.adobe.com or
|
||||
// http://groups.yahoo.com/group/boost/message/5441 for
|
||||
// more examples
|
||||
|
||||
// This little package is used to transmit the number of arguments
|
||||
// from the helper functions below to the sizeof() expression below.
|
||||
// Because we can never have an array of fewer than 1 element, we
|
||||
// add 1 to n and then subtract 1 from the result of sizeof() below.
|
||||
template <int n>
|
||||
struct char_array
|
||||
{
|
||||
char elements[n+1];
|
||||
};
|
||||
|
||||
// The following helper functions are never actually called, since
|
||||
// they are only used within a sizeof() expression, but the type of
|
||||
// their return value is used to discriminate between various free
|
||||
// and member function pointers at compile-time.
|
||||
|
||||
template <class R>
|
||||
char_array<0> arg_tuple_size_helper(R (*)());
|
||||
|
||||
template <class R, class A1>
|
||||
char_array<1> arg_tuple_size_helper(R (*)(A1));
|
||||
|
||||
template <class R, class A1, class A2>
|
||||
char_array<2> arg_tuple_size_helper(R (*)(A1, A2));
|
||||
|
||||
template <class R, class A1, class A2, class A3>
|
||||
char_array<3> arg_tuple_size_helper(R (*)(A1, A2, A3));
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4>
|
||||
char_array<4> arg_tuple_size_helper(R (*)(A1, A2, A3, A4));
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4, class A5>
|
||||
char_array<5> arg_tuple_size_helper(R (*)(A1, A2, A3, A4, A5));
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
char_array<6> arg_tuple_size_helper(R (*)(A1, A2, A3, A4, A5, A6));
|
||||
|
||||
template <class R, class A0>
|
||||
char_array<1> arg_tuple_size_helper(R (A0::*)());
|
||||
|
||||
template <class R, class A0, class A1>
|
||||
char_array<2> arg_tuple_size_helper(R (A0::*)(A1));
|
||||
|
||||
template <class R, class A0, class A1, class A2>
|
||||
char_array<3> arg_tuple_size_helper(R (A0::*)(A1, A2));
|
||||
|
||||
template <class R, class A0, class A1, class A2, class A3>
|
||||
char_array<4> arg_tuple_size_helper(R (A0::*)(A1, A2, A3));
|
||||
|
||||
template <class R, class A0, class A1, class A2, class A3, class A4>
|
||||
char_array<5> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4));
|
||||
|
||||
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
|
||||
char_array<6> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4, A5));
|
||||
|
||||
|
||||
template <class R, class A0>
|
||||
char_array<1> arg_tuple_size_helper(R (A0::*)() const);
|
||||
|
||||
template <class R, class A0, class A1>
|
||||
char_array<2> arg_tuple_size_helper(R (A0::*)(A1) const);
|
||||
|
||||
template <class R, class A0, class A1, class A2>
|
||||
char_array<3> arg_tuple_size_helper(R (A0::*)(A1, A2) const);
|
||||
|
||||
template <class R, class A0, class A1, class A2, class A3>
|
||||
char_array<4> arg_tuple_size_helper(R (A0::*)(A1, A2, A3) const);
|
||||
|
||||
template <class R, class A0, class A1, class A2, class A3, class A4>
|
||||
char_array<5> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4) const);
|
||||
|
||||
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
|
||||
char_array<6> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4, A5) const);
|
||||
|
||||
|
||||
template <class R, class A0>
|
||||
char_array<1> arg_tuple_size_helper(R (A0::*)() volatile);
|
||||
|
||||
template <class R, class A0, class A1>
|
||||
char_array<2> arg_tuple_size_helper(R (A0::*)(A1) volatile);
|
||||
|
||||
template <class R, class A0, class A1, class A2>
|
||||
char_array<3> arg_tuple_size_helper(R (A0::*)(A1, A2) volatile);
|
||||
|
||||
template <class R, class A0, class A1, class A2, class A3>
|
||||
char_array<4> arg_tuple_size_helper(R (A0::*)(A1, A2, A3) volatile);
|
||||
|
||||
template <class R, class A0, class A1, class A2, class A3, class A4>
|
||||
char_array<5> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4) volatile);
|
||||
|
||||
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
|
||||
char_array<6> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4, A5) volatile);
|
||||
|
||||
|
||||
template <class R, class A0>
|
||||
char_array<1> arg_tuple_size_helper(R (A0::*)() const volatile);
|
||||
|
||||
template <class R, class A0, class A1>
|
||||
char_array<2> arg_tuple_size_helper(R (A0::*)(A1) const volatile);
|
||||
|
||||
template <class R, class A0, class A1, class A2>
|
||||
char_array<3> arg_tuple_size_helper(R (A0::*)(A1, A2) const volatile);
|
||||
|
||||
template <class R, class A0, class A1, class A2, class A3>
|
||||
char_array<4> arg_tuple_size_helper(R (A0::*)(A1, A2, A3) const volatile);
|
||||
|
||||
template <class R, class A0, class A1, class A2, class A3, class A4>
|
||||
char_array<5> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4) const volatile);
|
||||
|
||||
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
|
||||
char_array<6> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4, A5) const volatile);
|
||||
|
||||
|
||||
template <class F>
|
||||
struct arg_tuple_size
|
||||
{
|
||||
// The sizeof() magic happens here
|
||||
BOOST_STATIC_CONSTANT(std::size_t, value
|
||||
= sizeof(arg_tuple_size_helper(F(0)).elements) - 1);
|
||||
};
|
||||
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // ARG_TUPLE_SIZE_DWA20011201_HPP
|
||||
|
||||
64
include/boost/python/detail/base_object.hpp
Normal file
@@ -0,0 +1,64 @@
|
||||
// (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.
|
||||
//
|
||||
// Revision History:
|
||||
// Mar 01 01 Use PyObject_INIT() instead of trying to hand-initialize (David Abrahams)
|
||||
|
||||
#ifndef BASE_OBJECT_DWA051600_H_
|
||||
# define BASE_OBJECT_DWA051600_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/signatures.hpp> // really just for type<>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <cstring>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
// base_object - adds a constructor and non-virtual destructor to a
|
||||
// base Python type (e.g. PyObject, PyTypeObject).
|
||||
template <class PythonType>
|
||||
struct base_object : PythonType
|
||||
{
|
||||
typedef PythonType base_python_type;
|
||||
|
||||
// Initializes type and reference count. All other fields of base_python_type are 0
|
||||
base_object(PyTypeObject* type_obj);
|
||||
|
||||
// Decrements reference count on the type
|
||||
~base_object();
|
||||
};
|
||||
|
||||
// Easy typedefs for common usage
|
||||
typedef base_object<PyObject> python_object;
|
||||
typedef base_object<PyTypeObject> python_type;
|
||||
|
||||
|
||||
//
|
||||
// base_object member function implementations
|
||||
//
|
||||
template <class PythonType>
|
||||
base_object<PythonType>::base_object(PyTypeObject* type_obj)
|
||||
{
|
||||
base_python_type* bp = this;
|
||||
#if !defined(_MSC_VER) || defined(__STLPORT)
|
||||
std::
|
||||
#endif
|
||||
memset(bp, 0, sizeof(base_python_type));
|
||||
Py_INCREF(type_obj);
|
||||
PyObject_INIT(bp, type_obj);
|
||||
}
|
||||
|
||||
template <class PythonType>
|
||||
inline base_object<PythonType>::~base_object()
|
||||
{
|
||||
Py_DECREF(ob_type);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // BASE_OBJECT_DWA051600_H_
|
||||
27
include/boost/python/detail/caller.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright David Abrahams 2001. 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.
|
||||
#ifndef CALLER_DWA20011214_HPP
|
||||
# define CALLER_DWA20011214_HPP
|
||||
|
||||
# include <boost/python/call.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
struct caller
|
||||
{
|
||||
typedef PyObject* result_type;
|
||||
|
||||
template <class F>
|
||||
PyObject* operator()(F f, PyObject* args, PyObject* keywords)
|
||||
{
|
||||
return call(f, args, keywords);
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // CALLER_DWA20011214_HPP
|
||||
78
include/boost/python/detail/cast.hpp
Normal file
@@ -0,0 +1,78 @@
|
||||
// (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.
|
||||
|
||||
#ifndef CAST_DWA052500_H_
|
||||
# define CAST_DWA052500_H_
|
||||
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/operators.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail {
|
||||
inline PyTypeObject* as_base_object(const PyTypeObject*, PyObject* p)
|
||||
{
|
||||
return reinterpret_cast<PyTypeObject*>(p);
|
||||
}
|
||||
|
||||
inline PyObject* as_base_object(const PyObject*, PyObject* p)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
inline const PyTypeObject* as_base_object(const PyTypeObject*, const PyObject* p)
|
||||
{
|
||||
return reinterpret_cast<const PyTypeObject*>(p);
|
||||
}
|
||||
|
||||
inline const PyObject* as_base_object(const PyObject*, const PyObject* p)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
// Convert a pointer to any type derived from PyObject or PyTypeObject to a PyObject*
|
||||
inline PyObject* as_object(PyObject* p) { return p; }
|
||||
inline PyObject* as_object(PyTypeObject* p) { return reinterpret_cast<PyObject*>(p); }
|
||||
|
||||
// If I didn't have to support stupid MSVC6 we could just use a simple template function:
|
||||
// template <class T> T* downcast(PyObject*).
|
||||
template <class T>
|
||||
struct downcast
|
||||
{
|
||||
downcast(PyObject* p)
|
||||
: m_p(static_cast<T*>(detail::as_base_object((T*)0, p)))
|
||||
{}
|
||||
|
||||
downcast(const PyObject* p)
|
||||
: m_p(static_cast<T*>(detail::as_base_object((const T*)0, p)))
|
||||
{}
|
||||
|
||||
downcast(PyTypeObject* p)
|
||||
: m_p(static_cast<T*>(p))
|
||||
{}
|
||||
|
||||
downcast(const PyTypeObject* p)
|
||||
: m_p(static_cast<T*>(p))
|
||||
{}
|
||||
|
||||
operator T*() const { return m_p; }
|
||||
|
||||
// MSVC doesn't like boost::dereferencable unless T has a default
|
||||
// constructor, so operator-> must be defined by hand :(
|
||||
T* operator->() const { return &**this; }
|
||||
|
||||
T* get() const { return m_p; }
|
||||
T& operator*() const { return *m_p; }
|
||||
private:
|
||||
T* m_p;
|
||||
};
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // CAST_DWA052500_H_
|
||||
68
include/boost/python/detail/config.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
// (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.
|
||||
|
||||
// Revision History:
|
||||
// 04 Mar 01 Some fixes so it will compile with Intel C++ (Dave Abrahams)
|
||||
|
||||
#ifndef CONFIG_DWA052200_H_
|
||||
# define CONFIG_DWA052200_H_
|
||||
|
||||
# include <boost/config.hpp>
|
||||
# include <cstddef>
|
||||
|
||||
# ifdef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
// A gcc bug forces some symbols into the global namespace
|
||||
# define BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||
# define BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
# define BOOST_PYTHON_CONVERSION
|
||||
# define BOOST_PYTHON_IMPORT_CONVERSION(x) using ::x
|
||||
# else
|
||||
# define BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE namespace boost { namespace python {
|
||||
# define BOOST_PYTHON_END_CONVERSION_NAMESPACE }} // namespace boost::python
|
||||
# define BOOST_PYTHON_CONVERSION boost::python
|
||||
# define BOOST_PYTHON_IMPORT_CONVERSION(x) void never_defined() // so we can follow the macro with a ';'
|
||||
# endif
|
||||
|
||||
# if defined(BOOST_MSVC)
|
||||
# if _MSC_VER <= 1200
|
||||
# define BOOST_MSVC6_OR_EARLIER 1
|
||||
# endif
|
||||
|
||||
# pragma warning (disable : 4786)
|
||||
|
||||
# endif
|
||||
|
||||
// Work around the broken library implementation/strict ansi checking on some
|
||||
// EDG-based compilers (e.g. alpha), which incorrectly warn that the result of
|
||||
// offsetof() is not an integer constant expression.
|
||||
# if defined(__DECCXX_VER) && __DECCXX_VER <= 60290024
|
||||
# define BOOST_OFFSETOF(s_name, s_member) \
|
||||
((size_t)__INTADDR__(&(((s_name *)0)->s_member)))
|
||||
# else
|
||||
# define BOOST_OFFSETOF(s_name, s_member) \
|
||||
offsetof(s_name, s_member)
|
||||
# endif
|
||||
|
||||
// The STLport puts all of the standard 'C' library names in std (as far as the
|
||||
// user is concerned), but without it you need a fix if you're using MSVC or
|
||||
// Intel C++
|
||||
# if defined(BOOST_MSVC_STD_ITERATOR)
|
||||
# define BOOST_CSTD_
|
||||
# else
|
||||
# define BOOST_CSTD_ std
|
||||
# endif
|
||||
|
||||
# ifndef BOOST_PYTHON_MODULE_INIT
|
||||
# if defined(_WIN32) || defined(__CYGWIN__)
|
||||
# define BOOST_PYTHON_MODULE_INIT(name) void init_module_##name(); extern "C" __declspec(dllexport) void init##name() { boost::python::handle_exception(init_module_##name); } void init_module_##name()
|
||||
# else
|
||||
# define BOOST_PYTHON_MODULE_INIT(name) void init_module_##name(); extern "C" void init##name() { boost::python::handle_exception(init_module_##name); } void init_module_##name()
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#endif // CONFIG_DWA052200_H_
|
||||
942
include/boost/python/detail/extension_class.hpp
Normal file
@@ -0,0 +1,942 @@
|
||||
// (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
|
||||
|
||||
// Revision History:
|
||||
// 17 Apr 01 Comment added with reference to cross_module.hpp (R.W. Grosse-Kunstleve)
|
||||
// 05 Mar 01 Fixed a bug which prevented auto_ptr values from being converted
|
||||
// to_python (Dave Abrahams)
|
||||
|
||||
#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 Held> 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(const 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>.
|
||||
//
|
||||
// A look-alike of this class in root/boost/python/cross_module.hpp
|
||||
// is used for the implementation of the cross-module support
|
||||
// (export_converters and import_converters). If from_python
|
||||
// and to_python converters are added or removed from the class
|
||||
// below, the class python_import_extension_class_converters has
|
||||
// to be modified accordingly.
|
||||
//
|
||||
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();
|
||||
#if defined(__MWERKS__) && __MWERKS__ <= 0x2406
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// 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*>());
|
||||
}
|
||||
|
||||
// Extract from obj a mutable reference to the PtrType object which is holding a T.
|
||||
template <class PtrType>
|
||||
static PtrType& smart_ptr_reference(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();
|
||||
#if defined(__MWERKS__) && __MWERKS__ <= 0x2406
|
||||
return *(PtrType*)0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Extract from obj a reference to the PtrType object which is holding a
|
||||
// T. If it weren't for auto_ptr, it would be a constant reference. Do not
|
||||
// modify the referent except by copying an auto_ptr! If obj is None, the
|
||||
// reference denotes a default-constructed PtrType
|
||||
template <class PtrType>
|
||||
static PtrType& smart_ptr_value(PyObject* obj, boost::python::type<PtrType>)
|
||||
{
|
||||
if (obj == Py_None)
|
||||
{
|
||||
static PtrType null_ptr;
|
||||
return null_ptr;
|
||||
}
|
||||
return smart_ptr_reference(obj, boost::python::type<PtrType>());
|
||||
}
|
||||
|
||||
template <class PtrType>
|
||||
static PyObject* smart_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 smart_ptr_reference(p, boost::python::type<std::auto_ptr<T> >()); }
|
||||
|
||||
friend std::auto_ptr<T> from_python(PyObject* p, boost::python::type<std::auto_ptr<T> >)
|
||||
{ return smart_ptr_value(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 smart_ptr_value(p, boost::python::type<std::auto_ptr<T> >()); }
|
||||
|
||||
friend PyObject* to_python(std::auto_ptr<T> x)
|
||||
{ return smart_ptr_to_python(x); }
|
||||
|
||||
friend boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T>&>)
|
||||
{ return smart_ptr_reference(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 smart_ptr_value(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 smart_ptr_value(p, boost::python::type<boost::shared_ptr<T> >()); }
|
||||
|
||||
friend PyObject* to_python(boost::shared_ptr<T> x)
|
||||
{ return smart_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_op<(which & op_gt)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_ge)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_lt)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_le)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_eq)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_ne)>::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);
|
||||
choose_op<(which & op_gt)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_ge)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_lt)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_le)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_eq)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_ne)>::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 Held>
|
||||
class held_instance : public Held
|
||||
{
|
||||
// There are no member functions: we want to avoid inadvertently overriding
|
||||
// any virtual functions in Held.
|
||||
public:
|
||||
held_instance(PyObject*) : Held() {}
|
||||
template <class A1>
|
||||
held_instance(PyObject*, A1 a1) : Held(a1) {}
|
||||
template <class A1, class A2>
|
||||
held_instance(PyObject*, A1 a1, A2 a2) : Held(a1, a2) {}
|
||||
template <class A1, class A2, class A3>
|
||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3) : Held(a1, a2, a3) {}
|
||||
template <class A1, class A2, class A3, class A4>
|
||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) : Held(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) : Held(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) : Held(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) : Held(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) : Held(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) : Held(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) : Held(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_
|
||||
311
include/boost/python/detail/functions.hpp
Normal file
@@ -0,0 +1,311 @@
|
||||
// (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.
|
||||
|
||||
#ifndef FUNCTIONS_DWA051400_H_
|
||||
# define FUNCTIONS_DWA051400_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/reference.hpp>
|
||||
# include <boost/python/detail/signatures.hpp>
|
||||
# include <boost/python/caller.hpp>
|
||||
# include <boost/call_traits.hpp>
|
||||
# include <boost/python/objects.hpp>
|
||||
# include <boost/python/detail/base_object.hpp>
|
||||
# include <typeinfo>
|
||||
# include <vector>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
// forward declaration
|
||||
class extension_instance;
|
||||
|
||||
|
||||
// function --
|
||||
// the common base class for all overloadable function and method objects
|
||||
// supplied by the library.
|
||||
class function : public python_object
|
||||
{
|
||||
public:
|
||||
function();
|
||||
// function objects are reasonably rare, so we guess we can afford a virtual table.
|
||||
// This cuts down on the number of distinct type objects which need to be defined.
|
||||
virtual ~function() {}
|
||||
|
||||
PyObject* call(PyObject* args, PyObject* keywords) const;
|
||||
static void add_to_namespace(reference<function> f, const char* name, PyObject* dict);
|
||||
|
||||
private:
|
||||
virtual PyObject* do_call(PyObject* args, PyObject* keywords) const = 0;
|
||||
virtual const char* description() const = 0;
|
||||
private:
|
||||
struct type_object;
|
||||
private:
|
||||
reference<function> m_overloads; // A linked list of the function overloads
|
||||
};
|
||||
|
||||
// wrapped_function_pointer<> --
|
||||
// A single function or member function pointer wrapped and presented to
|
||||
// Python as a callable object.
|
||||
//
|
||||
// Template parameters:
|
||||
// R - the return type of the function pointer
|
||||
// F - the complete type of the wrapped function pointer
|
||||
template <class R, class F>
|
||||
struct wrapped_function_pointer : function
|
||||
{
|
||||
typedef F ptr_fun; // pointer-to--function or pointer-to-member-function
|
||||
|
||||
wrapped_function_pointer(ptr_fun pf)
|
||||
: m_pf(pf) {}
|
||||
|
||||
private:
|
||||
PyObject* do_call(PyObject* args, PyObject* keywords) const
|
||||
{
|
||||
// This is where the boundary between the uniform Python function
|
||||
// interface and the statically-checked C++ function interface is
|
||||
// crossed.
|
||||
return caller<R>::call(m_pf, args, keywords);
|
||||
}
|
||||
|
||||
const char* description() const
|
||||
{ return typeid(F).name(); }
|
||||
|
||||
private:
|
||||
const ptr_fun m_pf;
|
||||
};
|
||||
|
||||
// raw_arguments_function
|
||||
// A function that passes the Python argument tuple and keyword dictionary
|
||||
// verbatim to C++ (useful for customized argument parsing and variable
|
||||
// argument lists)
|
||||
template <class Ret, class Args, class Keywords>
|
||||
struct raw_arguments_function : function
|
||||
{
|
||||
typedef Ret (*ptr_fun)(Args, Keywords);
|
||||
|
||||
raw_arguments_function(ptr_fun pf)
|
||||
: m_pf(pf) {}
|
||||
|
||||
private:
|
||||
PyObject* do_call(PyObject* args, PyObject* keywords) const
|
||||
{
|
||||
ref dict(keywords ?
|
||||
ref(keywords, ref::increment_count) :
|
||||
ref(PyDict_New()));
|
||||
|
||||
return to_python(
|
||||
(*m_pf)(from_python(args, boost::python::type<Args>()),
|
||||
from_python(dict.get(), boost::python::type<Keywords>())));
|
||||
}
|
||||
|
||||
const char* description() const
|
||||
{ return typeid(ptr_fun).name(); }
|
||||
|
||||
private:
|
||||
const ptr_fun m_pf;
|
||||
};
|
||||
|
||||
// virtual_function<> --
|
||||
// A virtual function with a default implementation wrapped and presented
|
||||
// to Python as a callable object.
|
||||
//
|
||||
// Template parameters:
|
||||
// T - the type of the target class
|
||||
// R - the return type of the function pointer
|
||||
// V - the virtual function pointer being wrapped
|
||||
// (should be of the form R(T::*)(<args>), or R (*)(T, <args>))
|
||||
// D - a function which takes a T&, const T&, T*, or const T* first
|
||||
// parameter and calls T::f on it /non-virtually/, where V
|
||||
// approximates &T::f.
|
||||
template <class T, class R, class V, class D>
|
||||
class virtual_function : public function
|
||||
{
|
||||
public:
|
||||
virtual_function(V virtual_function_ptr, D default_implementation)
|
||||
: m_virtual_function_ptr(virtual_function_ptr),
|
||||
m_default_implementation(default_implementation)
|
||||
{}
|
||||
|
||||
private:
|
||||
PyObject* do_call(PyObject* args, PyObject* keywords) const;
|
||||
|
||||
const char* description() const
|
||||
{ return typeid(V).name(); }
|
||||
|
||||
private:
|
||||
const V m_virtual_function_ptr;
|
||||
const D m_default_implementation;
|
||||
};
|
||||
|
||||
// A helper function for new_member_function(), below. Implements the core
|
||||
// functionality once the return type has already been deduced. R is expected to
|
||||
// be type<X>, where X is the actual return type of pmf.
|
||||
template <class F, class R>
|
||||
function* new_wrapped_function_aux(R, F pmf)
|
||||
{
|
||||
// We can't just use "typename R::Type" below because MSVC (incorrectly) pukes.
|
||||
typedef typename R::type return_type;
|
||||
return new wrapped_function_pointer<return_type, F>(pmf);
|
||||
}
|
||||
|
||||
// Create and return a new member function object wrapping the given
|
||||
// pointer-to-member function
|
||||
template <class F>
|
||||
inline function* new_wrapped_function(F pmf)
|
||||
{
|
||||
// Deduce the return type and pass it off to the helper function above
|
||||
return new_wrapped_function_aux(return_value(pmf), pmf);
|
||||
}
|
||||
|
||||
template <class R, class Args, class keywords>
|
||||
function* new_raw_arguments_function(R (*pmf)(Args, keywords))
|
||||
{
|
||||
return new raw_arguments_function<R, Args, keywords>(pmf);
|
||||
}
|
||||
|
||||
|
||||
// A helper function for new_virtual_function(), below. Implements the core
|
||||
// functionality once the return type has already been deduced. R is expected to
|
||||
// be type<X>, where X is the actual return type of V.
|
||||
template <class T, class R, class V, class D>
|
||||
inline function* new_virtual_function_aux(
|
||||
type<T>, R, V virtual_function_ptr, D default_implementation
|
||||
)
|
||||
{
|
||||
// We can't just use "typename R::Type" below because MSVC (incorrectly) pukes.
|
||||
typedef typename R::type return_type;
|
||||
return new virtual_function<T, return_type, V, D>(
|
||||
virtual_function_ptr, default_implementation);
|
||||
}
|
||||
|
||||
// Create and return a new virtual_function object wrapping the given
|
||||
// virtual_function_ptr and default_implementation
|
||||
template <class T, class V, class D>
|
||||
inline function* new_virtual_function(
|
||||
type<T>, V virtual_function_ptr, D default_implementation
|
||||
)
|
||||
{
|
||||
// Deduce the return type and pass it off to the helper function above
|
||||
return new_virtual_function_aux(
|
||||
type<T>(), return_value(virtual_function_ptr),
|
||||
virtual_function_ptr, default_implementation);
|
||||
}
|
||||
|
||||
// A function with a bundled "bound target" object. This is what is produced by
|
||||
// the expression a.b where a is an instance or extension_instance object and b
|
||||
// is a callable object not found in the obj namespace but on its class or
|
||||
// a base class.
|
||||
class bound_function : public python_object
|
||||
{
|
||||
public:
|
||||
static bound_function* create(const ref& target, const ref& fn);
|
||||
|
||||
bound_function(const ref& target, const ref& fn);
|
||||
PyObject* call(PyObject*args, PyObject* keywords) const;
|
||||
PyObject* getattr(const char* name) const;
|
||||
|
||||
private:
|
||||
struct type_object;
|
||||
friend struct type_object;
|
||||
|
||||
ref m_target;
|
||||
ref m_unbound_function;
|
||||
|
||||
private: // data members for allocation/deallocation optimization
|
||||
bound_function* m_free_list_link;
|
||||
|
||||
static bound_function* free_list;
|
||||
};
|
||||
|
||||
// Special functions designed to access data members of a wrapped C++ object.
|
||||
template <class ClassType, class MemberType>
|
||||
class getter_function : public function
|
||||
{
|
||||
public:
|
||||
typedef MemberType ClassType::* pointer_to_member;
|
||||
|
||||
getter_function(pointer_to_member pm)
|
||||
: m_pm(pm) {}
|
||||
|
||||
private:
|
||||
PyObject* do_call(PyObject* args, PyObject* keywords) const;
|
||||
|
||||
const char* description() const
|
||||
{ return typeid(MemberType (*)(const ClassType&)).name(); }
|
||||
private:
|
||||
pointer_to_member m_pm;
|
||||
};
|
||||
|
||||
template <class ClassType, class MemberType>
|
||||
class setter_function : public function
|
||||
{
|
||||
public:
|
||||
typedef MemberType ClassType::* pointer_to_member;
|
||||
|
||||
setter_function(pointer_to_member pm)
|
||||
: m_pm(pm) {}
|
||||
|
||||
private:
|
||||
PyObject* do_call(PyObject* args, PyObject* keywords) const;
|
||||
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(const ClassType&, const MemberType&)).name(); }
|
||||
private:
|
||||
pointer_to_member m_pm;
|
||||
};
|
||||
|
||||
template <class ClassType, class MemberType>
|
||||
PyObject* getter_function<ClassType, MemberType>::do_call(
|
||||
PyObject* args, PyObject* /* keywords */) const
|
||||
{
|
||||
PyObject* self;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &self))
|
||||
return 0;
|
||||
|
||||
return to_python(
|
||||
from_python(self, type<const ClassType*>())->*m_pm);
|
||||
}
|
||||
|
||||
template <class ClassType, class MemberType>
|
||||
PyObject* setter_function<ClassType, MemberType>::do_call(
|
||||
PyObject* args, PyObject* /* keywords */) const
|
||||
{
|
||||
PyObject* self;
|
||||
PyObject* value;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &self, &value))
|
||||
return 0;
|
||||
|
||||
typedef typename boost::call_traits<MemberType>::const_reference extract_type;
|
||||
from_python(self, type<ClassType*>())->*m_pm
|
||||
= from_python(value, type<extract_type>());
|
||||
|
||||
return none();
|
||||
}
|
||||
|
||||
template <class T, class R, class V, class D>
|
||||
PyObject* virtual_function<T,R,V,D>::do_call(PyObject* args, PyObject* keywords) const
|
||||
{
|
||||
// If the target object is held by pointer, we must call through the virtual
|
||||
// function pointer to the most-derived override.
|
||||
PyObject* target = PyTuple_GetItem(args, 0);
|
||||
if (target != 0)
|
||||
{
|
||||
extension_instance* self = get_extension_instance(target);
|
||||
if (self->wrapped_objects().size() == 1
|
||||
&& !self->wrapped_objects()[0]->held_by_value())
|
||||
{
|
||||
return caller<R>::call(m_virtual_function_ptr, args, keywords);
|
||||
}
|
||||
}
|
||||
return caller<R>::call(m_default_implementation, args, keywords);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // FUNCTIONS_DWA051400_H_
|
||||
508
include/boost/python/detail/init_function.hpp
Normal file
@@ -0,0 +1,508 @@
|
||||
// (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 was generated for %d-argument constructors by gen_init_function.python
|
||||
|
||||
#ifndef INIT_FUNCTION_DWA052000_H_
|
||||
# define INIT_FUNCTION_DWA052000_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/functions.hpp>
|
||||
# include <boost/python/detail/signatures.hpp>
|
||||
# include <typeinfo>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// parameter_traits - so far, this is a way to pass a const T& when we can be
|
||||
// sure T is not a reference type, and a raw T otherwise. This should be
|
||||
// rolled into boost::call_traits. Ordinarily, parameter_traits would be
|
||||
// written:
|
||||
//
|
||||
// template <class T> struct parameter_traits
|
||||
// {
|
||||
// typedef const T& const_reference;
|
||||
// };
|
||||
//
|
||||
// template <class T> struct parameter_traits<T&>
|
||||
// {
|
||||
// typedef T& const_reference;
|
||||
// };
|
||||
//
|
||||
// template <> struct parameter_traits<void>
|
||||
// {
|
||||
// typedef void const_reference;
|
||||
// };
|
||||
//
|
||||
// ...but since we can't partially specialize on reference types, we need this
|
||||
// long-winded but equivalent incantation.
|
||||
|
||||
// const_ref_selector -- an implementation detail of parameter_traits (below). This uses
|
||||
// the usual "poor man's partial specialization" hack for MSVC.
|
||||
template <bool is_ref>
|
||||
struct const_ref_selector
|
||||
{
|
||||
template <class T>
|
||||
struct const_ref
|
||||
{
|
||||
typedef const T& type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct const_ref_selector<true>
|
||||
{
|
||||
template <class T>
|
||||
struct const_ref
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
};
|
||||
|
||||
# ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4181)
|
||||
# endif // BOOST_MSVC
|
||||
template <class T>
|
||||
struct parameter_traits
|
||||
{
|
||||
private:
|
||||
enum { is_ref = boost::is_reference<T>::value };
|
||||
typedef const_ref_selector<is_ref> selector;
|
||||
public:
|
||||
typedef typename selector::template const_ref<T>::type const_reference;
|
||||
};
|
||||
# ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
# endif // BOOST_MSVC
|
||||
|
||||
// Full spcialization for void
|
||||
template <>
|
||||
struct parameter_traits<void>
|
||||
{
|
||||
typedef void const_reference;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class reference_parameter
|
||||
{
|
||||
typedef typename parameter_traits<T>::const_reference const_reference;
|
||||
public:
|
||||
reference_parameter(const_reference value)
|
||||
: value(value) {}
|
||||
operator const_reference() { return value; }
|
||||
private:
|
||||
const_reference value;
|
||||
};
|
||||
|
||||
class extension_instance;
|
||||
class instance_holder_base;
|
||||
|
||||
class init;
|
||||
template <class T> struct init0;
|
||||
template <class T, class A1> struct init1;
|
||||
template <class T, class A1, class A2> struct init2;
|
||||
template <class T, class A1, class A2, class A3> struct init3;
|
||||
template <class T, class A1, class A2, class A3, class A4> struct init4;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5> struct init5;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6> struct init6;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7> struct init7;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> struct init8;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> struct init9;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10> struct init10;
|
||||
|
||||
template <class T>
|
||||
struct init_function
|
||||
{
|
||||
static init* create(signature0) {
|
||||
return new init0<T>;
|
||||
}
|
||||
|
||||
template <class A1>
|
||||
static init* create(signature1<A1>) {
|
||||
return new init1<T,
|
||||
detail::parameter_traits<A1>::const_reference>;
|
||||
}
|
||||
|
||||
template <class A1, class A2>
|
||||
static init* create(signature2<A1, A2>) {
|
||||
return new init2<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference>;
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3>
|
||||
static init* create(signature3<A1, A2, A3>) {
|
||||
return new init3<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference>;
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4>
|
||||
static init* create(signature4<A1, A2, A3, A4>) {
|
||||
return new init4<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
detail::parameter_traits<A4>::const_reference>;
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5>
|
||||
static init* create(signature5<A1, A2, A3, A4, A5>) {
|
||||
return new init5<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
detail::parameter_traits<A4>::const_reference,
|
||||
detail::parameter_traits<A5>::const_reference>;
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
static init* create(signature6<A1, A2, A3, A4, A5, A6>) {
|
||||
return new init6<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
detail::parameter_traits<A4>::const_reference,
|
||||
detail::parameter_traits<A5>::const_reference,
|
||||
detail::parameter_traits<A6>::const_reference>;
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
static init* create(signature7<A1, A2, A3, A4, A5, A6, A7>) {
|
||||
return new init7<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
detail::parameter_traits<A4>::const_reference,
|
||||
detail::parameter_traits<A5>::const_reference,
|
||||
detail::parameter_traits<A6>::const_reference,
|
||||
detail::parameter_traits<A7>::const_reference>;
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
static init* create(signature8<A1, A2, A3, A4, A5, A6, A7, A8>) {
|
||||
return new init8<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
detail::parameter_traits<A4>::const_reference,
|
||||
detail::parameter_traits<A5>::const_reference,
|
||||
detail::parameter_traits<A6>::const_reference,
|
||||
detail::parameter_traits<A7>::const_reference,
|
||||
detail::parameter_traits<A8>::const_reference>;
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
static init* create(signature9<A1, A2, A3, A4, A5, A6, A7, A8, A9>) {
|
||||
return new init9<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
detail::parameter_traits<A4>::const_reference,
|
||||
detail::parameter_traits<A5>::const_reference,
|
||||
detail::parameter_traits<A6>::const_reference,
|
||||
detail::parameter_traits<A7>::const_reference,
|
||||
detail::parameter_traits<A8>::const_reference,
|
||||
detail::parameter_traits<A9>::const_reference>;
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
static init* create(signature10<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>) {
|
||||
return new init10<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
detail::parameter_traits<A4>::const_reference,
|
||||
detail::parameter_traits<A5>::const_reference,
|
||||
detail::parameter_traits<A6>::const_reference,
|
||||
detail::parameter_traits<A7>::const_reference,
|
||||
detail::parameter_traits<A8>::const_reference,
|
||||
detail::parameter_traits<A9>::const_reference,
|
||||
detail::parameter_traits<A10>::const_reference>;
|
||||
}
|
||||
};
|
||||
|
||||
class init : public function
|
||||
{
|
||||
private: // override function hook
|
||||
PyObject* do_call(PyObject* args, PyObject* keywords) const;
|
||||
private:
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* tail_args, PyObject* keywords) const = 0;
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
struct init0 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("")))
|
||||
throw argument_error();
|
||||
return new T(self
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1>
|
||||
struct init1 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &a1))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2>
|
||||
struct init2 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3>
|
||||
struct init3 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOO"), &a1, &a2, &a3))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4>
|
||||
struct init4 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
PyObject* a4;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOO"), &a1, &a2, &a3, &a4))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
|
||||
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3, A4)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5>
|
||||
struct init5 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
PyObject* a4;
|
||||
PyObject* a5;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOO"), &a1, &a2, &a3, &a4, &a5))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
|
||||
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
|
||||
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
struct init6 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
PyObject* a4;
|
||||
PyObject* a5;
|
||||
PyObject* a6;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
|
||||
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
|
||||
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>())),
|
||||
boost::python::detail::reference_parameter<A6>(from_python(a6, type<A6>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
struct init7 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
PyObject* a4;
|
||||
PyObject* a5;
|
||||
PyObject* a6;
|
||||
PyObject* a7;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
|
||||
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
|
||||
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>())),
|
||||
boost::python::detail::reference_parameter<A6>(from_python(a6, type<A6>())),
|
||||
boost::python::detail::reference_parameter<A7>(from_python(a7, type<A7>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6, A7)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
struct init8 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
PyObject* a4;
|
||||
PyObject* a5;
|
||||
PyObject* a6;
|
||||
PyObject* a7;
|
||||
PyObject* a8;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
|
||||
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
|
||||
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>())),
|
||||
boost::python::detail::reference_parameter<A6>(from_python(a6, type<A6>())),
|
||||
boost::python::detail::reference_parameter<A7>(from_python(a7, type<A7>())),
|
||||
boost::python::detail::reference_parameter<A8>(from_python(a8, type<A8>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6, A7, A8)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
struct init9 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
PyObject* a4;
|
||||
PyObject* a5;
|
||||
PyObject* a6;
|
||||
PyObject* a7;
|
||||
PyObject* a8;
|
||||
PyObject* a9;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
|
||||
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
|
||||
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>())),
|
||||
boost::python::detail::reference_parameter<A6>(from_python(a6, type<A6>())),
|
||||
boost::python::detail::reference_parameter<A7>(from_python(a7, type<A7>())),
|
||||
boost::python::detail::reference_parameter<A8>(from_python(a8, type<A8>())),
|
||||
boost::python::detail::reference_parameter<A9>(from_python(a9, type<A9>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6, A7, A8, A9)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
struct init10 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
PyObject* a4;
|
||||
PyObject* a5;
|
||||
PyObject* a6;
|
||||
PyObject* a7;
|
||||
PyObject* a8;
|
||||
PyObject* a9;
|
||||
PyObject* a10;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
|
||||
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
|
||||
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>())),
|
||||
boost::python::detail::reference_parameter<A6>(from_python(a6, type<A6>())),
|
||||
boost::python::detail::reference_parameter<A7>(from_python(a7, type<A7>())),
|
||||
boost::python::detail::reference_parameter<A8>(from_python(a8, type<A8>())),
|
||||
boost::python::detail::reference_parameter<A9>(from_python(a9, type<A9>())),
|
||||
boost::python::detail::reference_parameter<A10>(from_python(a10, type<A10>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)).name(); }
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // INIT_FUNCTION_DWA052000_H_
|
||||
21
include/boost/python/detail/none.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
// (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.
|
||||
|
||||
#ifndef NONE_DWA_052000_H_
|
||||
# define NONE_DWA_052000_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
inline PyObject* none() { Py_INCREF(Py_None); return Py_None; }
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // NONE_DWA_052000_H_
|
||||
846
include/boost/python/detail/returning.hpp
Normal file
@@ -0,0 +1,846 @@
|
||||
// (C) Copyright David Abrahams 2001. 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.
|
||||
//
|
||||
// This work was funded in part by Lawrence Berkeley National Labs
|
||||
//
|
||||
// This file generated for 5-argument member functions and 6-argument free
|
||||
// functions by gen_returning.py
|
||||
|
||||
#ifndef RETURNING_DWA20011201_HPP
|
||||
# define RETURNING_DWA20011201_HPP
|
||||
|
||||
//# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/config.hpp>
|
||||
# include <boost/python/convert.hpp>
|
||||
# include <boost/python/detail/none.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
// Calling C++ from Python
|
||||
template <class R>
|
||||
struct returning
|
||||
{
|
||||
template <class A0>
|
||||
static PyObject* call(R (A0::*pmf)(), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c0);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)() );
|
||||
};
|
||||
template <class A0, class A1>
|
||||
static PyObject* call(R (A0::*pmf)(A1), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c1);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)(*c1) );
|
||||
};
|
||||
template <class A0, class A1, class A2>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c2);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)(*c1, *c2) );
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c3);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)(*c1, *c2, *c3) );
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3, class A4>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c4);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) );
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3, class A4, class A5>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
|
||||
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c5);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5) );
|
||||
};
|
||||
|
||||
template <class A0>
|
||||
static PyObject* call(R (A0::*pmf)() const, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c0);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)() );
|
||||
};
|
||||
template <class A0, class A1>
|
||||
static PyObject* call(R (A0::*pmf)(A1) const, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c1);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)(*c1) );
|
||||
};
|
||||
template <class A0, class A1, class A2>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2) const, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c2);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)(*c1, *c2) );
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3) const, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c3);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)(*c1, *c2, *c3) );
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3, class A4>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c4);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) );
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3, class A4, class A5>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
|
||||
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c5);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5) );
|
||||
};
|
||||
|
||||
template <class A0>
|
||||
static PyObject* call(R (A0::*pmf)() volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c0);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)() );
|
||||
};
|
||||
template <class A0, class A1>
|
||||
static PyObject* call(R (A0::*pmf)(A1) volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c1);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)(*c1) );
|
||||
};
|
||||
template <class A0, class A1, class A2>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2) volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c2);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)(*c1, *c2) );
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3) volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c3);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)(*c1, *c2, *c3) );
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3, class A4>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c4);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) );
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3, class A4, class A5>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
|
||||
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c5);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5) );
|
||||
};
|
||||
|
||||
|
||||
// missing const volatile type traits
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template <class A0>
|
||||
static PyObject* call(R (A0::*pmf)() const volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c0);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)() );
|
||||
};
|
||||
template <class A0, class A1>
|
||||
static PyObject* call(R (A0::*pmf)(A1) const volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c1);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)(*c1) );
|
||||
};
|
||||
template <class A0, class A1, class A2>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2) const volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c2);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)(*c1, *c2) );
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3) const volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c3);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)(*c1, *c2, *c3) );
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3, class A4>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c4);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) );
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3, class A4, class A5>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
|
||||
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c5);
|
||||
if (!c0) return 0;
|
||||
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5) );
|
||||
};
|
||||
|
||||
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
static PyObject* call(R (*pf)(), PyObject*, PyObject* /* keywords */ )
|
||||
{
|
||||
// find the result converter
|
||||
wrap<R> r;
|
||||
return r( (*pf)() );
|
||||
};
|
||||
template <class A0>
|
||||
static PyObject* call(R (*pf)(A0), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c0);
|
||||
if (!c0) return 0;
|
||||
return r( (*pf)(*c0) );
|
||||
};
|
||||
template <class A0, class A1>
|
||||
static PyObject* call(R (*pf)(A0, A1), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c1);
|
||||
if (!c0) return 0;
|
||||
return r( (*pf)(*c0, *c1) );
|
||||
};
|
||||
template <class A0, class A1, class A2>
|
||||
static PyObject* call(R (*pf)(A0, A1, A2), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c2);
|
||||
if (!c0) return 0;
|
||||
return r( (*pf)(*c0, *c1, *c2) );
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3>
|
||||
static PyObject* call(R (*pf)(A0, A1, A2, A3), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c3);
|
||||
if (!c0) return 0;
|
||||
return r( (*pf)(*c0, *c1, *c2, *c3) );
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3, class A4>
|
||||
static PyObject* call(R (*pf)(A0, A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c4);
|
||||
if (!c0) return 0;
|
||||
return r( (*pf)(*c0, *c1, *c2, *c3, *c4) );
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3, class A4, class A5>
|
||||
static PyObject* call(R (*pf)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
|
||||
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
|
||||
|
||||
// find the result converter
|
||||
wrap_more<R> r(c5);
|
||||
if (!c0) return 0;
|
||||
return r( (*pf)(*c0, *c1, *c2, *c3, *c4, *c5) );
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct returning<void>
|
||||
{
|
||||
typedef void R;
|
||||
template <class A0>
|
||||
static PyObject* call(R (A0::*pmf)(), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)();
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1>
|
||||
static PyObject* call(R (A0::*pmf)(A1), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)(*c1);
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1, class A2>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)(*c1, *c2);
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)(*c1, *c2, *c3);
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3, class A4>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)(*c1, *c2, *c3, *c4);
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3, class A4, class A5>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
|
||||
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5);
|
||||
return detail::none();
|
||||
};
|
||||
|
||||
template <class A0>
|
||||
static PyObject* call(R (A0::*pmf)() const, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)();
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1>
|
||||
static PyObject* call(R (A0::*pmf)(A1) const, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)(*c1);
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1, class A2>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2) const, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)(*c1, *c2);
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3) const, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)(*c1, *c2, *c3);
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3, class A4>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)(*c1, *c2, *c3, *c4);
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3, class A4, class A5>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
|
||||
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5);
|
||||
return detail::none();
|
||||
};
|
||||
|
||||
template <class A0>
|
||||
static PyObject* call(R (A0::*pmf)() volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)();
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1>
|
||||
static PyObject* call(R (A0::*pmf)(A1) volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)(*c1);
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1, class A2>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2) volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)(*c1, *c2);
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3) volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)(*c1, *c2, *c3);
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3, class A4>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)(*c1, *c2, *c3, *c4);
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3, class A4, class A5>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
|
||||
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5);
|
||||
return detail::none();
|
||||
};
|
||||
|
||||
|
||||
// missing const volatile type traits
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template <class A0>
|
||||
static PyObject* call(R (A0::*pmf)() const volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)();
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1>
|
||||
static PyObject* call(R (A0::*pmf)(A1) const volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)(*c1);
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1, class A2>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2) const volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)(*c1, *c2);
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3) const volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)(*c1, *c2, *c3);
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3, class A4>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)(*c1, *c2, *c3, *c4);
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3, class A4, class A5>
|
||||
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const volatile, PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
|
||||
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
|
||||
|
||||
if (!c0) return 0;
|
||||
((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5);
|
||||
return detail::none();
|
||||
};
|
||||
|
||||
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
static PyObject* call(R (*pf)(), PyObject*, PyObject* /* keywords */ )
|
||||
{
|
||||
(*pf)();
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0>
|
||||
static PyObject* call(R (*pf)(A0), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
|
||||
|
||||
if (!c0) return 0;
|
||||
(*pf)(*c0);
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1>
|
||||
static PyObject* call(R (*pf)(A0, A1), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
|
||||
if (!c0) return 0;
|
||||
(*pf)(*c0, *c1);
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1, class A2>
|
||||
static PyObject* call(R (*pf)(A0, A1, A2), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
|
||||
if (!c0) return 0;
|
||||
(*pf)(*c0, *c1, *c2);
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3>
|
||||
static PyObject* call(R (*pf)(A0, A1, A2, A3), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
|
||||
if (!c0) return 0;
|
||||
(*pf)(*c0, *c1, *c2, *c3);
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3, class A4>
|
||||
static PyObject* call(R (*pf)(A0, A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
|
||||
|
||||
if (!c0) return 0;
|
||||
(*pf)(*c0, *c1, *c2, *c3, *c4);
|
||||
return detail::none();
|
||||
};
|
||||
template <class A0, class A1, class A2, class A3, class A4, class A5>
|
||||
static PyObject* call(R (*pf)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ )
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
|
||||
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
|
||||
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
|
||||
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
|
||||
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
|
||||
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
|
||||
|
||||
if (!c0) return 0;
|
||||
(*pf)(*c0, *c1, *c2, *c3, *c4, *c5);
|
||||
return detail::none();
|
||||
};
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // RETURNING_DWA20011201_HPP
|
||||
|
||||
251
include/boost/python/detail/signatures.hpp
Normal file
@@ -0,0 +1,251 @@
|
||||
// (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 by gen_signatures.python for 10 arguments.
|
||||
#ifndef SIGNATURES_DWA050900_H_
|
||||
# define SIGNATURES_DWA050900_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail {
|
||||
// A stand-in for the built-in void. This one can be passed to functions and
|
||||
// (under MSVC, which has a bug, be used as a default template type parameter).
|
||||
struct void_t {};
|
||||
}
|
||||
|
||||
// An envelope in which type information can be delivered for the purposes
|
||||
// of selecting an overloaded from_python() function. This is needed to work
|
||||
// around MSVC's lack of partial specialiation/ordering. Where normally we'd
|
||||
// want to form a function call like void f<const T&>(), We instead pass
|
||||
// type<const T&> as one of the function parameters to select a particular
|
||||
// overload.
|
||||
//
|
||||
// The id typedef helps us deal with the lack of partial ordering by generating
|
||||
// unique types for constructor signatures. In general, type<T>::id is type<T>,
|
||||
// but type<void_t>::id is just void_t.
|
||||
template <class T>
|
||||
struct type
|
||||
{
|
||||
typedef type id;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct type<boost::python::detail::void_t>
|
||||
{
|
||||
typedef boost::python::detail::void_t id;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
// These basically encapsulate a chain of types, , used to make the syntax of
|
||||
// add(constructor<T1, ...>()) work. We need to produce a unique type for each number
|
||||
// of non-default parameters to constructor<>. Q: why not use a recursive
|
||||
// formulation for infinite extensibility? A: MSVC6 seems to choke on constructs
|
||||
// that involve recursive template nesting.
|
||||
//
|
||||
// signature chaining
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10>
|
||||
struct signature10 {};
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
|
||||
struct signature9 {};
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class X>
|
||||
inline signature10<X, T1, T2, T3, T4, T5, T6, T7, T8, T9> prepend(type<X>, signature9<T1, T2, T3, T4, T5, T6, T7, T8, T9>)
|
||||
{ return signature10<X, T1, T2, T3, T4, T5, T6, T7, T8, T9>(); }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
|
||||
struct signature8 {};
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class X>
|
||||
inline signature9<X, T1, T2, T3, T4, T5, T6, T7, T8> prepend(type<X>, signature8<T1, T2, T3, T4, T5, T6, T7, T8>)
|
||||
{ return signature9<X, T1, T2, T3, T4, T5, T6, T7, T8>(); }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7>
|
||||
struct signature7 {};
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class X>
|
||||
inline signature8<X, T1, T2, T3, T4, T5, T6, T7> prepend(type<X>, signature7<T1, T2, T3, T4, T5, T6, T7>)
|
||||
{ return signature8<X, T1, T2, T3, T4, T5, T6, T7>(); }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6>
|
||||
struct signature6 {};
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class X>
|
||||
inline signature7<X, T1, T2, T3, T4, T5, T6> prepend(type<X>, signature6<T1, T2, T3, T4, T5, T6>)
|
||||
{ return signature7<X, T1, T2, T3, T4, T5, T6>(); }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5>
|
||||
struct signature5 {};
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class X>
|
||||
inline signature6<X, T1, T2, T3, T4, T5> prepend(type<X>, signature5<T1, T2, T3, T4, T5>)
|
||||
{ return signature6<X, T1, T2, T3, T4, T5>(); }
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
struct signature4 {};
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class X>
|
||||
inline signature5<X, T1, T2, T3, T4> prepend(type<X>, signature4<T1, T2, T3, T4>)
|
||||
{ return signature5<X, T1, T2, T3, T4>(); }
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
struct signature3 {};
|
||||
|
||||
template <class T1, class T2, class T3, class X>
|
||||
inline signature4<X, T1, T2, T3> prepend(type<X>, signature3<T1, T2, T3>)
|
||||
{ return signature4<X, T1, T2, T3>(); }
|
||||
|
||||
template <class T1, class T2>
|
||||
struct signature2 {};
|
||||
|
||||
template <class T1, class T2, class X>
|
||||
inline signature3<X, T1, T2> prepend(type<X>, signature2<T1, T2>)
|
||||
{ return signature3<X, T1, T2>(); }
|
||||
|
||||
template <class T1>
|
||||
struct signature1 {};
|
||||
|
||||
template <class T1, class X>
|
||||
inline signature2<X, T1> prepend(type<X>, signature1<T1>)
|
||||
{ return signature2<X, T1>(); }
|
||||
|
||||
struct signature0 {};
|
||||
|
||||
template <class X>
|
||||
inline signature1<X> prepend(type<X>, signature0)
|
||||
{ return signature1<X>(); }
|
||||
|
||||
|
||||
// This one terminates the chain. Prepending void_t to the head of a void_t
|
||||
// signature results in a void_t signature again.
|
||||
inline signature0 prepend(void_t, signature0) { return signature0(); }
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class A1 = detail::void_t, class A2 = detail::void_t, class A3 = detail::void_t, class A4 = detail::void_t, class A5 = detail::void_t, class A6 = detail::void_t, class A7 = detail::void_t, class A8 = detail::void_t, class A9 = detail::void_t, class A10 = detail::void_t>
|
||||
struct constructor
|
||||
{
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
// Return value extraction:
|
||||
|
||||
// This is just another little envelope for carrying a typedef (see type,
|
||||
// above). I could have re-used type, but that has a very specific purpose. I
|
||||
// thought this would be clearer.
|
||||
template <class T>
|
||||
struct return_value_select { typedef T type; };
|
||||
|
||||
// free functions
|
||||
template <class R>
|
||||
return_value_select<R> return_value(R (*)()) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1>
|
||||
return_value_select<R> return_value(R (*)(A1)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2>
|
||||
return_value_select<R> return_value(R (*)(A1, A2)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3, A4)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4, class A5>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5, A6)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5, A6, A7)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5, A6, A7, A8)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { return return_value_select<R>(); }
|
||||
|
||||
// TODO(?): handle 'const void'
|
||||
|
||||
// member functions
|
||||
template <class R, class T>
|
||||
return_value_select<R> return_value(R (T::*)()) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1>
|
||||
return_value_select<R> return_value(R (T::*)(A1)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T>
|
||||
return_value_select<R> return_value(R (T::*)() const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1>
|
||||
return_value_select<R> return_value(R (T::*)(A1) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) const) { return return_value_select<R>(); }
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif
|
||||
68
include/boost/python/detail/singleton.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
// (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.
|
||||
|
||||
#ifndef SINGLETON_DWA051900_H_
|
||||
# define SINGLETON_DWA051900_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
struct empty {};
|
||||
template <class Derived, class Base = empty>
|
||||
struct singleton : Base
|
||||
{
|
||||
typedef singleton singleton_base; // Convenience type for derived class constructors
|
||||
|
||||
static Derived* instance();
|
||||
|
||||
// Pass-through constructors
|
||||
singleton() : Base() {}
|
||||
|
||||
template <class A1>
|
||||
singleton(const A1& a1) : Base(a1) {}
|
||||
|
||||
template <class A1, class A2>
|
||||
singleton(const A1& a1, const A2& a2) : Base(a1, a2) {}
|
||||
|
||||
template <class A1, class A2, class A3>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3) : Base(a1, a2, a3) {}
|
||||
|
||||
template <class A1, class A2, class A3, class A4>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4) : Base(a1, a2, a3, a4) {}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) : Base(a1, a2, a3, a4, a5) {}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6) : Base(a1, a2, a3, a4, a5, a6) {}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7) : Base(a1, a2, a3, a4, a5, a6, a7) {}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8) : Base(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>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9) : Base(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>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10) : Base(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {}
|
||||
|
||||
};
|
||||
|
||||
template <class Derived, class Base>
|
||||
Derived* singleton<Derived,Base>::instance()
|
||||
{
|
||||
static Derived x;
|
||||
return &x;
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif
|
||||
417
include/boost/python/detail/types.hpp
Normal file
@@ -0,0 +1,417 @@
|
||||
// (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.
|
||||
|
||||
#ifndef TYPES_DWA051800_H_
|
||||
# define TYPES_DWA051800_H_
|
||||
|
||||
// Usage:
|
||||
// class X : public
|
||||
// boost::python::callable<
|
||||
// boost::python::getattrable <
|
||||
// boost::python::setattrable<python_object, X> > >
|
||||
// {
|
||||
// public:
|
||||
// ref call(args, kw);
|
||||
// ref getattr(args, kw);
|
||||
// ref setattr(args, kw);
|
||||
// };
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/signatures.hpp> // really just for type<>
|
||||
# include <boost/python/detail/cast.hpp>
|
||||
# include <boost/python/detail/base_object.hpp>
|
||||
# include <typeinfo>
|
||||
# include <vector>
|
||||
# include <cassert>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
class string;
|
||||
|
||||
namespace detail {
|
||||
|
||||
class instance_holder_base;
|
||||
|
||||
class type_object_base : public python_type
|
||||
{
|
||||
public:
|
||||
explicit type_object_base(PyTypeObject* type_type);
|
||||
virtual ~type_object_base();
|
||||
|
||||
public:
|
||||
enum capability {
|
||||
hash, call, str, getattr, setattr, compare, repr, richcompare,
|
||||
|
||||
mapping_length, mapping_subscript, mapping_ass_subscript,
|
||||
|
||||
sequence_length, sequence_item, sequence_ass_item,
|
||||
sequence_concat, sequence_repeat, sequence_slice, sequence_ass_slice,
|
||||
|
||||
number_add, number_subtract, number_multiply, number_divide,
|
||||
number_remainder, number_divmod, number_power, number_negative,
|
||||
number_positive, number_absolute, number_nonzero, number_invert,
|
||||
number_lshift, number_rshift, number_and, number_xor, number_or,
|
||||
number_coerce, number_int, number_long, number_float, number_oct,
|
||||
number_hex, number_inplace_add, number_inplace_subtract,
|
||||
number_inplace_multiply, number_inplace_divide,
|
||||
number_inplace_remainder, number_inplace_power,
|
||||
number_inplace_lshift, number_inplace_rshift,
|
||||
number_inplace_and, number_inplace_or, number_inplace_xor
|
||||
};
|
||||
|
||||
void enable(capability);
|
||||
|
||||
//
|
||||
// type behaviors
|
||||
//
|
||||
public: // Callbacks for basic type functionality.
|
||||
virtual PyObject* instance_repr(PyObject*) const;
|
||||
virtual int instance_compare(PyObject*, PyObject* other) const;
|
||||
virtual PyObject* instance_str(PyObject*) const;
|
||||
virtual long instance_hash(PyObject*) const;
|
||||
virtual PyObject* instance_call(PyObject* obj, PyObject* args, PyObject* kw) const;
|
||||
virtual PyObject* instance_getattr(PyObject* obj, const char* name) const;
|
||||
virtual int instance_setattr(PyObject* obj, const char* name, PyObject* value) const;
|
||||
|
||||
// Dealloc is a special case, since every type needs a nonzero tp_dealloc slot.
|
||||
virtual void instance_dealloc(PyObject*) const = 0;
|
||||
|
||||
public: // Callbacks for mapping methods
|
||||
virtual int instance_mapping_length(PyObject*) const;
|
||||
virtual PyObject* instance_mapping_subscript(PyObject*, PyObject*) const ;
|
||||
virtual int instance_mapping_ass_subscript(PyObject*, PyObject*, PyObject*) const;
|
||||
|
||||
public: // Callbacks for sequence methods
|
||||
virtual int instance_sequence_length(PyObject* obj) const;
|
||||
virtual PyObject* instance_sequence_concat(PyObject* obj, PyObject* other) const;
|
||||
virtual PyObject* instance_sequence_repeat(PyObject* obj, int n) const;
|
||||
virtual PyObject* instance_sequence_item(PyObject* obj, int n) const;
|
||||
virtual PyObject* instance_sequence_slice(PyObject* obj, int start, int finish) const;
|
||||
virtual int instance_sequence_ass_item(PyObject* obj, int n, PyObject* value) const;
|
||||
virtual int instance_sequence_ass_slice(PyObject* obj, int start, int finish, PyObject* value) const;
|
||||
|
||||
public: // Callbacks for number methods
|
||||
virtual PyObject* instance_number_add(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_subtract(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_multiply(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_divide(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_remainder(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_divmod(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_power(PyObject*, PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_negative(PyObject*) const;
|
||||
virtual PyObject* instance_number_positive(PyObject*) const;
|
||||
virtual PyObject* instance_number_absolute(PyObject*) const;
|
||||
virtual int instance_number_nonzero(PyObject*) const;
|
||||
virtual PyObject* instance_number_invert(PyObject*) const;
|
||||
virtual PyObject* instance_number_lshift(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_rshift(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_and(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_xor(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_or(PyObject*, PyObject*) const;
|
||||
virtual int instance_number_coerce(PyObject*, PyObject**, PyObject**) const;
|
||||
virtual PyObject* instance_number_int(PyObject*) const;
|
||||
virtual PyObject* instance_number_long(PyObject*) const;
|
||||
virtual PyObject* instance_number_float(PyObject*) const;
|
||||
virtual PyObject* instance_number_oct(PyObject*) const;
|
||||
virtual PyObject* instance_number_hex(PyObject*) const;
|
||||
|
||||
virtual PyObject* instance_number_inplace_add(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_inplace_subtract(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_inplace_multiply(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_inplace_divide(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_inplace_remainder(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_inplace_power(PyObject*, PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_inplace_lshift(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_inplace_rshift(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_inplace_and(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_inplace_or(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_inplace_xor(PyObject*, PyObject*) const;
|
||||
|
||||
public: // Callbacks for rich comparisons
|
||||
virtual PyObject* instance_lt(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_le(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_eq(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_ne(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_gt(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_ge(PyObject*, PyObject*) const;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class type_object : public type_object_base
|
||||
{
|
||||
public:
|
||||
typedef T instance;
|
||||
|
||||
type_object(PyTypeObject* type_type, const char* name)
|
||||
: type_object_base(type_type)
|
||||
{
|
||||
assert(name != 0);
|
||||
this->tp_name = const_cast<char*>(name);
|
||||
}
|
||||
|
||||
type_object(PyTypeObject* type_type)
|
||||
: type_object_base(type_type)
|
||||
{
|
||||
this->tp_name = const_cast<char*>(typeid(instance).name());
|
||||
}
|
||||
|
||||
private: // Overridable behaviors.
|
||||
// Called when the reference count goes to zero. The default implementation
|
||||
// is "delete p". If you have not allocated your object with operator new or
|
||||
// you have other constraints, you'll need to override this
|
||||
virtual void dealloc(T* p) const;
|
||||
|
||||
private: // Implementation of type_object_base hooks. Do not reimplement in derived classes.
|
||||
void instance_dealloc(PyObject*) const;
|
||||
};
|
||||
|
||||
//
|
||||
// type objects
|
||||
//
|
||||
template <class Base>
|
||||
class callable : public Base
|
||||
{
|
||||
public:
|
||||
typedef callable properties; // Convenience for derived class construction
|
||||
typedef typename Base::instance instance;
|
||||
callable(PyTypeObject* type_type, const char* name);
|
||||
callable(PyTypeObject* type_type);
|
||||
private:
|
||||
PyObject* instance_call(PyObject* obj, PyObject* args, PyObject* kw) const;
|
||||
};
|
||||
|
||||
template <class Base>
|
||||
class getattrable : public Base
|
||||
{
|
||||
public:
|
||||
typedef getattrable properties; // Convenience for derived class construction
|
||||
typedef typename Base::instance instance;
|
||||
getattrable(PyTypeObject* type_type, const char* name);
|
||||
getattrable(PyTypeObject* type_type);
|
||||
private:
|
||||
PyObject* instance_getattr(PyObject* obj, const char* name) const;
|
||||
};
|
||||
|
||||
template <class Base>
|
||||
class setattrable : public Base
|
||||
{
|
||||
public:
|
||||
typedef setattrable properties; // Convenience for derived class construction
|
||||
typedef typename Base::instance instance;
|
||||
setattrable(PyTypeObject* type_type, const char* name);
|
||||
setattrable(PyTypeObject* type_type);
|
||||
private:
|
||||
int instance_setattr(PyObject* obj, const char* name, PyObject* value) const;
|
||||
};
|
||||
|
||||
template <class Base>
|
||||
class reprable : public Base
|
||||
{
|
||||
public:
|
||||
typedef reprable properties; // Convenience for derived class construction
|
||||
typedef typename Base::instance instance;
|
||||
reprable(PyTypeObject* type_type, const char* name);
|
||||
reprable(PyTypeObject* type_type);
|
||||
private:
|
||||
PyObject* instance_repr(PyObject* obj) const;
|
||||
};
|
||||
|
||||
//
|
||||
// Member function definitions
|
||||
//
|
||||
|
||||
// type_object<>
|
||||
template <class T>
|
||||
void type_object<T>::instance_dealloc(PyObject* obj) const
|
||||
{
|
||||
this->dealloc(downcast<instance>(obj).get());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void type_object<T>::dealloc(T* obj) const
|
||||
{
|
||||
delete obj;
|
||||
}
|
||||
|
||||
// callable
|
||||
template <class Base>
|
||||
callable<Base>::callable(PyTypeObject* type_type, const char* name)
|
||||
: Base(type_type, name)
|
||||
{
|
||||
this->enable(call);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
callable<Base>::callable(PyTypeObject* type_type)
|
||||
: Base(type_type)
|
||||
{
|
||||
this->enable(call);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
PyObject* callable<Base>::instance_call(PyObject* obj, PyObject* args, PyObject* kw) const
|
||||
{
|
||||
return downcast<instance>(obj)->call(args, kw);
|
||||
}
|
||||
|
||||
// getattrable
|
||||
template <class Base>
|
||||
getattrable<Base>::getattrable(PyTypeObject* type_type, const char* name)
|
||||
: Base(type_type, name)
|
||||
{
|
||||
this->enable(getattr);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
getattrable<Base>::getattrable(PyTypeObject* type_type)
|
||||
: Base(type_type)
|
||||
{
|
||||
this->enable(getattr);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
PyObject* getattrable<Base>::instance_getattr(PyObject* obj, const char* name) const
|
||||
{
|
||||
return downcast<instance>(obj)->getattr(name);
|
||||
}
|
||||
|
||||
// setattrable
|
||||
template <class Base>
|
||||
setattrable<Base>::setattrable(PyTypeObject* type_type, const char* name)
|
||||
: Base(type_type, name)
|
||||
{
|
||||
this->enable(setattr);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
setattrable<Base>::setattrable(PyTypeObject* type_type)
|
||||
: Base(type_type)
|
||||
{
|
||||
this->enable(setattr);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
int setattrable<Base>::instance_setattr(PyObject* obj, const char* name, PyObject* value) const
|
||||
{
|
||||
return downcast<instance>(obj)->setattr(name, value);
|
||||
}
|
||||
|
||||
// reprable
|
||||
template <class Base>
|
||||
reprable<Base>::reprable(PyTypeObject* type_type, const char* name)
|
||||
: Base(type_type, name)
|
||||
{
|
||||
this->enable(repr);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
reprable<Base>::reprable(PyTypeObject* type_type)
|
||||
: Base(type_type)
|
||||
{
|
||||
this->enable(repr);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
PyObject* reprable<Base>::instance_repr(PyObject* obj) const
|
||||
{
|
||||
return downcast<instance>(obj)->repr();
|
||||
}
|
||||
|
||||
// Helper class for optimized allocation of PODs: If two PODs
|
||||
// happen to contain identical byte patterns, they may share their
|
||||
// memory. Reference counting is used to free unused memory.
|
||||
// This is useful because method tables of related extension classes tend
|
||||
// to be identical, so less memory is needed for them.
|
||||
class shared_pod_manager
|
||||
{
|
||||
typedef std::pair<char*, std::size_t> holder;
|
||||
typedef std::vector<holder> storage;
|
||||
|
||||
public:
|
||||
static shared_pod_manager& obj();
|
||||
~shared_pod_manager();
|
||||
|
||||
// Allocate memory for POD T and fill it with zeros.
|
||||
// This memory is initially not shared.
|
||||
template <class T>
|
||||
static void create(T*& t)
|
||||
{
|
||||
t = reinterpret_cast<T*>(obj().create(sizeof(T)));
|
||||
}
|
||||
|
||||
// Decrement the refcount for the memory t points to. If the count
|
||||
// goes to zero, the memory is freed.
|
||||
template <class T>
|
||||
static void dispose(T* t)
|
||||
{
|
||||
obj().dec_ref(t, sizeof(T));
|
||||
}
|
||||
|
||||
// Attempt to share the memory t points to. If memory with the same
|
||||
// contents already exists, t is replaced by a pointer to this memory,
|
||||
// and t's old memory is disposed. Otherwise, t will be registered for
|
||||
// potential future sharing.
|
||||
template <class T>
|
||||
static void replace_if_equal(T*& t)
|
||||
{
|
||||
t = reinterpret_cast<T*>(obj().replace_if_equal(t, sizeof(T)));
|
||||
}
|
||||
|
||||
// Create a copy of t's memory that is guaranteed to be private to t.
|
||||
// Afterwards t points to the new memory, unless it was already private, in
|
||||
// which case there is no change (except that t's memory will no longer
|
||||
// be considered for future sharing - see raplade_if_equal())
|
||||
// This function *must* be called before the contents of (*t) can
|
||||
// be overwritten. Otherwise, inconsistencies and crashes may result.
|
||||
template <class T>
|
||||
static void make_unique_copy(T*& t)
|
||||
{
|
||||
t = reinterpret_cast<T*>(obj().make_unique_copy(t, sizeof(T)));
|
||||
}
|
||||
|
||||
private:
|
||||
void* replace_if_equal(void* pod, std::size_t size);
|
||||
void* make_unique_copy(void* pod, std::size_t size);
|
||||
void* create(std::size_t size);
|
||||
void dec_ref(void* pod, std::size_t size);
|
||||
void erase_from_list(void* pod);
|
||||
|
||||
struct compare;
|
||||
struct identical;
|
||||
|
||||
private:
|
||||
shared_pod_manager() {} // instance
|
||||
|
||||
#ifdef TYPE_OBJECT_BASE_STANDALONE_TEST
|
||||
public:
|
||||
#endif
|
||||
storage m_storage;
|
||||
};
|
||||
|
||||
|
||||
void add_capability(type_object_base::capability capability,
|
||||
PyTypeObject* dest);
|
||||
|
||||
// This macro gets the length of an array as a compile-time constant, and will
|
||||
// fail to compile if the parameter is a pointer.
|
||||
#ifdef __BORLANDC__ // smart implementation doesn't work for borland; maybe someone knows a workaround?
|
||||
# define PY_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#else
|
||||
# define PY_ARRAY_LENGTH(a) \
|
||||
(sizeof(::boost::python::detail::countof_validate(a, &(a))) ? sizeof(a) / sizeof((a)[0]) : 0)
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
inline void countof_validate(T* const, T* const*);
|
||||
|
||||
template<typename T>
|
||||
inline int countof_validate(const void*, T);
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // TYPES_DWA051800_H_
|
||||
39
include/boost/python/detail/void_adaptor.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
// (C) Copyright David Abrahams 2001. 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.
|
||||
|
||||
#ifndef VOID_ADAPTOR_DWA20011112_HPP
|
||||
# define VOID_ADAPTOR_DWA20011112_HPP
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
extern PyObject arbitrary_object;
|
||||
|
||||
template <class T>
|
||||
struct void_adaptor
|
||||
{
|
||||
typedef PyObject* result_type;
|
||||
|
||||
void_adaptor(T const& f)
|
||||
: m_f(f)
|
||||
{}
|
||||
|
||||
PyObject* operator()() const
|
||||
{
|
||||
m_f();
|
||||
return &arbitrary_object;
|
||||
}
|
||||
private:
|
||||
T m_f;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void_adaptor<T> make_void_adaptor(T const& f)
|
||||
{
|
||||
return void_adaptor<T>(f);
|
||||
}
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // VOID_ADAPTOR_DWA20011112_HPP
|
||||
|
||||
118
include/boost/python/detail/wrap_python.hpp
Normal file
@@ -0,0 +1,118 @@
|
||||
// (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 serves as a wrapper around <Python.h> which allows it to be
|
||||
// compiled with GCC 2.95.2 under Win32 and which disables the default MSVC
|
||||
// behavior so that a program may be compiled in debug mode without requiring a
|
||||
// special debugging build of the Python library.
|
||||
|
||||
|
||||
// To use the Python debugging library, #define BOOST_DEBUG_PYTHON on the
|
||||
// compiler command-line.
|
||||
|
||||
// Revision History:
|
||||
// 05 Mar 01 Suppress warnings under Cygwin with Python 2.0 (Dave Abrahams)
|
||||
// 04 Mar 01 Rolled in some changes from the Dragon fork (Dave Abrahams)
|
||||
// 01 Mar 01 define PyObject_INIT() for Python 1.x (Dave Abrahams)
|
||||
|
||||
|
||||
#include <patchlevel.h>
|
||||
|
||||
#ifdef _DEBUG
|
||||
# ifndef BOOST_DEBUG_PYTHON
|
||||
# undef _DEBUG // Don't let Python force the debug library just because we're debugging.
|
||||
# define DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//
|
||||
// Some things we need in order to get Python.h to work with compilers other
|
||||
// than MSVC on Win32
|
||||
//
|
||||
#if defined(_WIN32)
|
||||
# if defined(__GNUC__) && defined(__CYGWIN__)
|
||||
# if PY_MAJOR_VERSION < 2 || PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 2
|
||||
typedef int pid_t;
|
||||
# define WORD_BIT 32
|
||||
# define hypot _hypot
|
||||
# include <stdio.h>
|
||||
# endif
|
||||
# if !defined(PY_MAJOR_VERSION) || PY_MAJOR_VERSION < 2
|
||||
# define HAVE_CLOCK
|
||||
# define HAVE_STRFTIME
|
||||
# define HAVE_STRERROR
|
||||
# endif
|
||||
# define NT_THREADS
|
||||
# define WITH_THREAD
|
||||
# ifndef NETSCAPE_PI
|
||||
# define USE_SOCKET
|
||||
# endif
|
||||
|
||||
# ifdef USE_DL_IMPORT
|
||||
# define DL_IMPORT(RTYPE) __declspec(dllimport) RTYPE
|
||||
# endif
|
||||
|
||||
# ifdef USE_DL_EXPORT
|
||||
# define DL_IMPORT(RTYPE) __declspec(dllexport) RTYPE
|
||||
# define DL_EXPORT(RTYPE) __declspec(dllexport) RTYPE
|
||||
# endif
|
||||
|
||||
# define HAVE_LONG_LONG 1
|
||||
# define LONG_LONG long long
|
||||
|
||||
# elif defined(__MWERKS__)
|
||||
|
||||
# ifndef _MSC_VER
|
||||
# define PY_MSC_VER_DEFINED_FROM_WRAP_PYTHON_H 1
|
||||
# define _MSC_VER 900
|
||||
# endif
|
||||
|
||||
# if PY_MAJOR_VERSION < 2 || PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 2
|
||||
# include <config.h>
|
||||
# else
|
||||
# include <pyconfig.h>
|
||||
# endif
|
||||
# undef hypot // undo the evil #define left by Python.
|
||||
|
||||
# elif defined(__BORLANDC__)
|
||||
# if PY_MAJOR_VERSION < 2 || PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 2
|
||||
# include <config.h>
|
||||
# else
|
||||
# include <pyconfig.h>
|
||||
# endif
|
||||
# undef HAVE_HYPOT
|
||||
# define HAVE_HYPOT 1
|
||||
# elif defined(_MSC_VER)
|
||||
# ifdef __cplusplus
|
||||
# include <limits> // prevents Python.h from defining LONGLONG_MAX, LONGLONG_MIN, and ULONGLONG_MAX
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#ifdef PY_MSC_VER_DEFINED_FROM_WRAP_PYTHON_H
|
||||
# undef _MSC_VER
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
|
||||
# undef DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
|
||||
# define _DEBUG
|
||||
#endif
|
||||
|
||||
#if !defined(PY_MAJOR_VERSION) || PY_MAJOR_VERSION < 2
|
||||
# define PyObject_INIT(op, typeobj) \
|
||||
( (op)->ob_type = (typeobj), _Py_NewReference((PyObject *)(op)), (op) )
|
||||
#endif
|
||||
|
||||
#ifdef __MWERKS__
|
||||
# pragma warn_possunwant off
|
||||
#elif _MSC_VER
|
||||
# pragma warning(disable:4786)
|
||||
#endif
|
||||
46
pyste/NEWS
@@ -1,46 +0,0 @@
|
||||
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.
|
||||
31
pyste/README
@@ -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).
|
||||
2
pyste/dist/.cvsignore
vendored
@@ -1,2 +0,0 @@
|
||||
*.zip
|
||||
*.pyc
|
||||
51
pyste/dist/create_build.py
vendored
@@ -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
@@ -1,6 +0,0 @@
|
||||
from distutils.core import setup
|
||||
import py2exe
|
||||
import sys
|
||||
|
||||
sys.path.append('../src')
|
||||
setup(name='pyste', scripts=['../src/pyste.py'])
|
||||
@@ -1,77 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
||||
<title>Exporting All Declarations from a 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 All Declarations from a 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>-></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><< </span><span class=string>"value: " </span><span class=special><< (</span><span class=keyword>int</span><span class=special>)</span><span class=identifier>c </span><span class=special><< </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>"hello.h"</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>"World"</span><span class=special>, </span><span class=string>"hello.h"</span><span class=special>)
|
||||
</span><span class=identifier>Enum</span><span class=special>(</span><span class=string>"choice"</span><span class=special>, </span><span class=string>"hello.h"</span><span class=special>)
|
||||
</span><span class=identifier>Function</span><span class=special>(</span><span class=string>"show"</span><span class=special>, </span><span class=string>"hello.h"</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>"Greet"</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>"Set"</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 © 2003 Bruno da Silva de Oliveira<br>Copyright © 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 "as is" without express or implied warranty, and with
|
||||
no claim as to its suitability for any purpose. </font> </p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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>-></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>"World"</span><span class=special>, </span><span class=string>"world.h"</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 "<tt>hello.cpp</tt>" 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 "free" enums and class enums)</li><li>Nested Classes</li><li>Support for <tt>boost::shared_ptr</tt> and <tt>std::auto_ptr</tt></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 © 2003 Bruno da Silva de Oliveira<br>Copyright © 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 "as is" without express or implied warranty, and with
|
||||
no claim as to its suitability for any purpose. </font> </p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,90 +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
|
||||
methods, 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><</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>
|
||||
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 methods 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 method needs a policy and the user
|
||||
doesn't set one?</b><br><br> If a function/method 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/methods that return <tt>const T&</tt>, the policy
|
||||
<tt>return_value_policy<copy_const_reference>()</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 © 2003 Bruno da Silva de Oliveira<br>Copyright © 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 "as is" without express or implied warranty, and with
|
||||
no claim as to its suitability for any purpose. </font> </p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,467 +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]
|
||||
|
||||
[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, 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 classes and methods, excluding methods and attributes,
|
||||
and so 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, methods, 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 methods 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, methods, 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]
|
||||
|
||||
[page:1 Policies]
|
||||
|
||||
Even thought Pyste can identify various elements in the C++ code, like virtual
|
||||
methods, 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 methods 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 method needs a policy and the user
|
||||
doesn't set one?][br][br] If a function/method 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/methods 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 methods too. Just remember that the first
|
||||
parameter of wrappers for methods is a pointer to the class, like in
|
||||
Boost.Python:
|
||||
|
||||
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 method.
|
||||
]
|
||||
|
||||
[page:1 Exporting All Declarations from a 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.
|
||||
|
||||
@@ -1,76 +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, methods, 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>"World"</span><span class=special>, </span><span class=string>"hello.h"</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>"IWorld"</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>"choice"</span><span class=special>, </span><span class=string>"hello.h"</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>"Show"</span><span class=special>)
|
||||
</span></pre></code>
|
||||
<p>
|
||||
You can rename methods 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>"Greet"</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>"Set"</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>"choice"</span><span class=special>, </span><span class=string>"hello.h"</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>"Red"</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>"Blue"</span><span class=special>)
|
||||
</span></pre></code>
|
||||
<p>
|
||||
You can exclude functions, classes, methods, 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>'<<'</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>
|
||||
<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 © 2003 Bruno da Silva de Oliveira<br>Copyright © 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 "as is" without express or implied warranty, and with
|
||||
no claim as to its suitability for any purpose. </font> </p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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>
|
||||
|
||||
>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, 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
|
||||
|
||||
</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><module>.cpp</tt>), or in multiple mode,
|
||||
names a output directory for the files (default: <tt><module></tt>).</p>
|
||||
<p>
|
||||
<tt>--no-using</tt> tells Pyste to don't declare "<tt>using namespace boost;</tt>" 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>>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>>python pyste.py --module=mymodule --multiple file.pyste file2.pyste ...</pre></code><p>
|
||||
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).</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 © 2003 Bruno da Silva de Oliveira<br>Copyright © 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 "as is" without express or implied warranty, and with
|
||||
no claim as to its suitability for any purpose. </font> </p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,74 +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_all_declarations_from_a_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>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_all_declarations_from_a_header.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>
|
||||
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><</span><span class=identifier>C</span><span class=special>> </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><</span><span class=identifier>C</span><span class=special>> </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>-></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><</span><span class=identifier>C</span><span class=special>> </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><< </span><span class=identifier>c</span><span class=special>-></span><span class=identifier>value </span><span class=special><< </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<C></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>
|
||||
<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_all_declarations_from_a_header.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 © 2003 Bruno da Silva de Oliveira<br>Copyright © 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 "as is" without express or implied warranty, and with
|
||||
no claim as to its suitability for any purpose. </font> </p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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><</span><span class=keyword>class </span><span class=identifier>T</span><span class=special>>
|
||||
</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>"Point"</span><span class=special>, </span><span class=string>"point.h"</span><span class=special>)
|
||||
</span><span class=identifier>Point</span><span class=special>(</span><span class=string>"int"</span><span class=special>)
|
||||
</span><span class=identifier>Point</span><span class=special>(</span><span class=string>"double"</span><span class=special>)
|
||||
</span></pre></code>
|
||||
<p>
|
||||
Pyste will assign default names for each instantiation. In this example, those
|
||||
would be "<tt>Point_int</tt>" and "<tt>Point_double</tt>", 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>"int"</span><span class=special>, </span><span class=string>"IPoint"</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>"double"</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>"DPoint"</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>"Point"</span><span class=special>, </span><span class=string>"point.h"</span><span class=special>)
|
||||
</span><span class=identifier>Point</span><span class=special>(</span><span class=string>"float"</span><span class=special>, </span><span class=string>"FPoint"</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>"X"</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>"Y"</span><span class=special>)
|
||||
</span><span class=identifier>Point</span><span class=special>(</span><span class=string>"int"</span><span class=special>, </span><span class=string>"IPoint"</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>"double"</span><span class=special>, </span><span class=string>"DPoint"</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>"Point"</span><span class=special>, </span><span class=string>"point.h"</span><span class=special>)
|
||||
</span><span class=identifier>Point</span><span class=special>(</span><span class=string>"int"</span><span class=special>, </span><span class=string>"IPoint"</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>"double"</span><span class=special>, </span><span class=string>"DPoint"</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>"X"</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>"Y"</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
|
||||
("int double" or ["int", "double"] 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 © 2003 Bruno da Silva de Oliveira<br>Copyright © 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 "as is" without express or implied warranty, and with
|
||||
no claim as to its suitability for any purpose. </font> </p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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 classes and methods, excluding methods and attributes,
|
||||
and so 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>-></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><< </span><span class=string>"value: " </span><span class=special><< (</span><span class=keyword>int</span><span class=special>)</span><span class=identifier>c </span><span class=special><< </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>"test::show"</span><span class=special>, </span><span class=string>"hello.h"</span><span class=special>)
|
||||
</span><span class=identifier>Class</span><span class=special>(</span><span class=string>"World"</span><span class=special>, </span><span class=string>"hello.h"</span><span class=special>)
|
||||
</span><span class=identifier>Enum</span><span class=special>(</span><span class=string>"choice"</span><span class=special>, </span><span class=string>"hello.h"</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 © 2003 Bruno da Silva de Oliveira<br>Copyright © 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 "as is" without express or implied warranty, and with
|
||||
no claim as to its suitability for any purpose. </font> </p>
|
||||
</body>
|
||||
</html>
|
||||
BIN
pyste/doc/theme/alert.gif
vendored
|
Before Width: | Height: | Size: 577 B |
BIN
pyste/doc/theme/arrow.gif
vendored
|
Before Width: | Height: | Size: 70 B |
BIN
pyste/doc/theme/bkd.gif
vendored
|
Before Width: | Height: | Size: 1.3 KiB |
BIN
pyste/doc/theme/bkd2.gif
vendored
|
Before Width: | Height: | Size: 2.5 KiB |
BIN
pyste/doc/theme/bulb.gif
vendored
|
Before Width: | Height: | Size: 944 B |
BIN
pyste/doc/theme/bullet.gif
vendored
|
Before Width: | Height: | Size: 152 B |
BIN
pyste/doc/theme/c++boost.gif
vendored
|
Before Width: | Height: | Size: 8.6 KiB |
BIN
pyste/doc/theme/l_arr.gif
vendored
|
Before Width: | Height: | Size: 147 B |
BIN
pyste/doc/theme/l_arr_disabled.gif
vendored
|
Before Width: | Height: | Size: 91 B |
BIN
pyste/doc/theme/note.gif
vendored
|
Before Width: | Height: | Size: 151 B |
BIN
pyste/doc/theme/r_arr.gif
vendored
|
Before Width: | Height: | Size: 147 B |
BIN
pyste/doc/theme/r_arr_disabled.gif
vendored
|
Before Width: | Height: | Size: 91 B |
BIN
pyste/doc/theme/smiley.gif
vendored
|
Before Width: | Height: | Size: 879 B |
170
pyste/doc/theme/style.css
vendored
@@ -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 }
|
||||
BIN
pyste/doc/theme/u_arr.gif
vendored
|
Before Width: | Height: | Size: 170 B |
@@ -1,125 +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_all_declarations_from_a_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_all_declarations_from_a_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><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>> </span><span class=identifier>names</span><span class=special>();
|
||||
</span></pre></code>
|
||||
<p>
|
||||
But you don't want to export <tt>std::vector<std::string></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><</span><span class=identifier>string</span><span class=special>> </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><</span><span class=identifier>string</span><span class=special>>::</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>"names"</span><span class=special>, &</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 "<tt>test_wrappers.h</tt>" and in the interface file:</p>
|
||||
<code><pre>
|
||||
<span class=identifier>Include</span><span class=special>(</span><span class=string>"test_wrappers.h"</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>"names"</span><span class=special>, </span><span class=string>"test.h"</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>"names_wrapper"</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>"names_wrapper"</span><span class=special>,
|
||||
</span><span class=string>""</span><span class=string>"
|
||||
list names_wrapper()
|
||||
{
|
||||
// code to call name() and convert the vector to a list...
|
||||
}
|
||||
"</span><span class=string>""</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>"names"</span><span class=special>, </span><span class=string>"test.h"</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 methods too. Just remember that the first
|
||||
parameter of wrappers for methods is a pointer to the class, like in
|
||||
<a href="../../index.html">
|
||||
Boost.Python</a>:</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><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>> </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>-></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>"C"</span><span class=special>, </span><span class=string>"test.h"</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>"names_wrapper"</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 method.
|
||||
</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_all_declarations_from_a_header.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<hr size="1"><p class="copyright">Copyright © 2003 Bruno da Silva de Oliveira<br>Copyright © 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 "as is" without express or implied warranty, and with
|
||||
no claim as to its suitability for any purpose. </font> </p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,2 +0,0 @@
|
||||
.sconsign
|
||||
*.obj
|
||||
@@ -1,5 +0,0 @@
|
||||
To use this examples, just execute the command-line:
|
||||
|
||||
pyste --module=<example> <example>.pyste
|
||||
|
||||
For more information, please refer to the documentation.
|
||||
@@ -1,8 +0,0 @@
|
||||
#include "basic.h"
|
||||
|
||||
namespace basic {
|
||||
|
||||
int C::static_value = 3;
|
||||
const int C::const_static_value = 100;
|
||||
|
||||
}
|
||||
@@ -1,59 +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& name() { return _name; }
|
||||
void set_name(const std::string& name) { _name = name; }
|
||||
std::string _name;
|
||||
|
||||
// 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=2, int y=3) { return x*y; }
|
||||
};
|
||||
|
||||
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
|
||||
@@ -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')
|
||||
|
||||
@@ -1,24 +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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,8 +0,0 @@
|
||||
color = Enum('enums::color', 'enums.h')
|
||||
rename(color.red, 'Red')
|
||||
rename(color.blue, 'Blue')
|
||||
X = Class('enums::X', 'enums.h')
|
||||
rename(X.choices.bad, 'Bad')
|
||||
rename(X.choices.good, 'Good')
|
||||
rename(X.choices, 'Choices')
|
||||
|
||||
@@ -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
|
||||
@@ -1,4 +0,0 @@
|
||||
h = AllFromHeader('header_test.h')
|
||||
exclude(h.A)
|
||||
exclude(h.foo)
|
||||
exclude(h.bar)
|
||||
@@ -1,18 +0,0 @@
|
||||
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(); }
|
||||
};
|
||||
@@ -1,8 +0,0 @@
|
||||
# Doesn't work:
|
||||
A = Template('A', 'inherit.h')
|
||||
A_int = A('int')
|
||||
|
||||
Class('B', 'inherit.h')
|
||||
|
||||
# Does work:
|
||||
#AllFromHeader('inherit.h')
|
||||
@@ -1,4 +0,0 @@
|
||||
#include "nested.h"
|
||||
|
||||
int nested::X::staticXValue = 10;
|
||||
int nested::X::Y::staticYValue = 20;
|
||||
@@ -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
|
||||
@@ -1 +0,0 @@
|
||||
Class('nested::Root', 'nested.h')
|
||||
@@ -1,47 +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 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
|
||||
@@ -1,5 +0,0 @@
|
||||
foo = Function('opaque::new_C', '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))
|
||||
@@ -1,3 +0,0 @@
|
||||
#include "operators.h"
|
||||
|
||||
double operators::C::x = 10;
|
||||
@@ -1,49 +0,0 @@
|
||||
#ifndef OPERATORS_H
|
||||
#define OPERATORS_H
|
||||
|
||||
|
||||
#include <iostream>
|
||||
|
||||
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
|
||||
@@ -1,2 +0,0 @@
|
||||
C = Class('operators::C', 'operators.h')
|
||||
#exclude(C.operator['+'])
|
||||
@@ -1,44 +0,0 @@
|
||||
#ifndef SMART_PTR_H
|
||||
#define SMART_PTR_H
|
||||
|
||||
|
||||
#include <memory>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace smart_ptr {
|
||||
|
||||
struct C
|
||||
{
|
||||
int value;
|
||||
};
|
||||
|
||||
inline boost::shared_ptr<C> NewC() { return boost::shared_ptr<C>( new C() ); }
|
||||
|
||||
struct D
|
||||
{
|
||||
boost::shared_ptr<C> Get() { return ptr; }
|
||||
void Set( boost::shared_ptr<C> c ) { ptr = c; }
|
||||
private:
|
||||
boost::shared_ptr<C> ptr;
|
||||
};
|
||||
|
||||
inline std::auto_ptr<D> NewD() { return std::auto_ptr<D>( new D() ); }
|
||||
|
||||
|
||||
// test an abstract class
|
||||
struct A
|
||||
{
|
||||
virtual int f() = 0;
|
||||
};
|
||||
|
||||
struct B: A
|
||||
{
|
||||
virtual int f(){ return 1; }
|
||||
};
|
||||
|
||||
inline boost::shared_ptr<A> NewA() { return boost::shared_ptr<A>(new B()); }
|
||||
inline int GetA(boost::shared_ptr<A> a) { return a->f(); }
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,13 +0,0 @@
|
||||
C = Class('smart_ptr::C', 'smart_ptr.h')
|
||||
use_shared_ptr(C)
|
||||
|
||||
D = Class('smart_ptr::D', 'smart_ptr.h')
|
||||
use_auto_ptr(D)
|
||||
|
||||
A = Class('smart_ptr::A', 'smart_ptr.h')
|
||||
use_shared_ptr(A)
|
||||
|
||||
Function('smart_ptr::NewC', 'smart_ptr.h')
|
||||
Function('smart_ptr::NewD', 'smart_ptr.h')
|
||||
Function('smart_ptr::NewA', 'smart_ptr.h')
|
||||
Function('smart_ptr::GetA', 'smart_ptr.h')
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace templates {
|
||||
|
||||
template <class T>
|
||||
struct Point
|
||||
{
|
||||
T x;
|
||||
T y;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
Point = Template('templates::Point', 'templates.h')
|
||||
rename(Point.x, 'i')
|
||||
rename(Point.y, 'j')
|
||||
IPoint = Point('int')
|
||||
FPoint = Point('double', 'FPoint')
|
||||
rename(IPoint, 'IPoint')
|
||||
rename(IPoint.x, 'x')
|
||||
rename(IPoint.y, 'y')
|
||||
@@ -1,16 +0,0 @@
|
||||
namespace unions {
|
||||
|
||||
class UnionTest
|
||||
{
|
||||
public:
|
||||
union // unions are not supported for now
|
||||
{
|
||||
int i;
|
||||
short s1;
|
||||
short s2;
|
||||
} mBad;
|
||||
|
||||
int mGood;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
UnionTest = Class('unions::UnionTest', 'unions.h')
|
||||
exclude(UnionTest.mBad)
|
||||
@@ -1,28 +0,0 @@
|
||||
namespace virtual_ {
|
||||
|
||||
struct C
|
||||
{
|
||||
public:
|
||||
virtual int f()
|
||||
{
|
||||
return f_abs();
|
||||
}
|
||||
|
||||
virtual void bar(int) {}
|
||||
virtual void bar(char*) {}
|
||||
|
||||
const char* get_name()
|
||||
{
|
||||
return name();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual int f_abs() = 0;
|
||||
|
||||
private:
|
||||
virtual const char* name() { return "C"; }
|
||||
};
|
||||
|
||||
inline int call_f(C& c) { return c.f(); }
|
||||
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
Class('virtual_::C', 'virtual.h')
|
||||
Function('virtual_::call_f', 'virtual.h')
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
namespace virtual2 {
|
||||
|
||||
struct A
|
||||
{
|
||||
virtual int f() { return 0; }
|
||||
virtual int f1() { return 10; }
|
||||
};
|
||||
|
||||
struct B: A
|
||||
{
|
||||
virtual int f() { return 1; }
|
||||
virtual int f2() { return 20; }
|
||||
};
|
||||
|
||||
inline int call_fs(A*a)
|
||||
{
|
||||
int r = a->f1();
|
||||
B* b = dynamic_cast<B*>(a);
|
||||
return r + b->f2();
|
||||
}
|
||||
|
||||
inline int call_f(A* a)
|
||||
{
|
||||
return a->f();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
Class('virtual2::A', 'virtual2.h')
|
||||
Class('virtual2::B', 'virtual2.h')
|
||||
Function('virtual2::call_fs', 'virtual2.h')
|
||||
Function('virtual2::call_f', 'virtual2.h')
|
||||
@@ -1,46 +0,0 @@
|
||||
#ifndef WRAPPER_TEST
|
||||
#define WRAPPER_TEST
|
||||
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace wrappertest {
|
||||
|
||||
inline std::vector<int> Range(int count)
|
||||
{
|
||||
std::vector<int> v;
|
||||
v.reserve(count);
|
||||
for (int i = 0; i < count; ++i){
|
||||
v.push_back(i);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
struct C
|
||||
{
|
||||
C() {}
|
||||
|
||||
std::vector<int> Mul(int value)
|
||||
{
|
||||
std::vector<int> res;
|
||||
res.reserve(value);
|
||||
std::vector<int>::const_iterator it;
|
||||
std::vector<int> v(Range(value));
|
||||
for (it = v.begin(); it != v.end(); ++it){
|
||||
res.push_back(*it * value);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct A
|
||||
{
|
||||
virtual int f() { return 1; };
|
||||
};
|
||||
|
||||
inline int call_foo(A* a){ return a->f(); }
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
Include('wrappertest_wrappers.h')
|
||||
|
||||
f = Function('wrappertest::Range', 'wrappertest.h')
|
||||
set_wrapper(f, 'RangeWrapper')
|
||||
|
||||
mul = Wrapper('MulWrapper',
|
||||
'''
|
||||
list MulWrapper(wrappertest::C& c, int value){
|
||||
return VectorToList(c.Mul(value));
|
||||
}
|
||||
'''
|
||||
)
|
||||
|
||||
C = Class('wrappertest::C', 'wrappertest.h')
|
||||
set_wrapper(C.Mul, mul)
|
||||
|
||||
|
||||
A = Class('wrappertest::A', 'wrappertest.h')
|
||||
set_wrapper(A.f, 'f_wrapper')
|
||||
|
||||
Function('wrappertest::call_foo', 'wrappertest.h')
|
||||
@@ -1,28 +0,0 @@
|
||||
#ifndef WRAPPER_TEST_WRAPPERS
|
||||
#define WRAPPER_TEST_WRAPPERS
|
||||
|
||||
#include <vector>
|
||||
#include <boost/python.hpp>
|
||||
#include "wrappertest.h"
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
template <class T>
|
||||
list VectorToList(const std::vector<T> & v)
|
||||
{
|
||||
list res;
|
||||
typename std::vector<T>::const_iterator it;
|
||||
for(it = v.begin(); it != v.end(); ++it){
|
||||
res.append(*it);
|
||||
}
|
||||
Py_XINCREF(res.ptr());
|
||||
return res;
|
||||
}
|
||||
|
||||
inline list RangeWrapper(int count){
|
||||
return VectorToList(wrappertest::Range(count));
|
||||
}
|
||||
|
||||
inline int f_wrapper(wrappertest::A*) { return 10; }
|
||||
|
||||
#endif
|
||||
@@ -1,76 +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_all_declarations_from_a_header.html">Exporting All Declarations from a Header</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="toc_cells_L1">
|
||||
<a href="doc/smart_pointers.html">Smart Pointers</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<hr size="1"><p class="copyright">Copyright © 2003 Bruno da Silva de Oliveira<br>Copyright © 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 "as is" without express or implied warranty, and with
|
||||
no claim as to its suitability for any purpose. </font> </p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1 +0,0 @@
|
||||
*.pyc
|
||||
@@ -1,840 +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
|
||||
from copy import deepcopy
|
||||
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 = []
|
||||
self._exported_opaque_pointers = {}
|
||||
|
||||
|
||||
def ScopeName(self):
|
||||
return makeid(self.class_.FullName()) + '_scope'
|
||||
|
||||
|
||||
def Unit(self):
|
||||
return makeid(self.class_.name)
|
||||
|
||||
|
||||
def Name(self):
|
||||
return self.class_.FullName()
|
||||
|
||||
|
||||
def SetDeclarations(self, declarations):
|
||||
Exporter.SetDeclarations(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.public_members = \
|
||||
[x for x in self.class_.members if x.visibility == Scope.public]
|
||||
|
||||
|
||||
def ClassBases(self):
|
||||
bases = []
|
||||
def GetBases(class_):
|
||||
this_bases = [self.GetDeclaration(x.name) for x in class_.bases]
|
||||
bases.extend(this_bases)
|
||||
for base in this_bases:
|
||||
GetBases(base)
|
||||
|
||||
GetBases(self.class_)
|
||||
return 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.
|
||||
'''
|
||||
return '%s_%s' % (len(self.ClassBases()), self.class_.FullName())
|
||||
|
||||
|
||||
def Export(self, codeunit, exported_names):
|
||||
if not self.info.exclude:
|
||||
self.CheckIsForwardDeclared()
|
||||
self.CheckForwardDeclarations()
|
||||
self.ExportBasics()
|
||||
self.ExportBases(exported_names)
|
||||
self.ExportConstructors()
|
||||
self.ExportVariables()
|
||||
self.ExportMethods()
|
||||
self.ExportVirtualMethods()
|
||||
self.ExportOperators()
|
||||
self.ExportNestedClasses(exported_names)
|
||||
self.ExportNestedEnums()
|
||||
self.ExportSmartPointer()
|
||||
self.ExportOpaquePointerPolicies()
|
||||
self.Write(codeunit)
|
||||
|
||||
|
||||
def CheckIsForwardDeclared(self):
|
||||
if self.class_.incomplete:
|
||||
print "--> Error: Class %s is forward declared! " \
|
||||
"Please use the header with its complete definition." % self.class_.FullName()
|
||||
print
|
||||
|
||||
|
||||
def CheckForwardDeclarations(self):
|
||||
for m in self.public_members:
|
||||
if isinstance(m, Function):
|
||||
exporterutils.WarnForwardDeclarations(m)
|
||||
|
||||
|
||||
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'
|
||||
self.Add('template', self.class_.FullName())
|
||||
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'
|
||||
bases = self.class_.bases
|
||||
bases_list = []
|
||||
for base in bases:
|
||||
if base.visibility == Scope.public and base.name in exported_names:
|
||||
bases_list.append(base.name)
|
||||
if bases_list:
|
||||
code = namespaces.python + 'bases< %s > ' % \
|
||||
(', '.join(bases_list))
|
||||
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 ExportMethods(self):
|
||||
'Export all the non-virtual methods of this class'
|
||||
|
||||
def OverloadName(m):
|
||||
'Returns the name of the overloads struct for the given method'
|
||||
return makeid(m.FullName()) + ('_overloads_%i_%i' % (m.minArgs, m.maxArgs))
|
||||
|
||||
declared = {}
|
||||
def DeclareOverloads(m):
|
||||
'Declares the macro for the generation of the overloads'
|
||||
if not m.virtual:
|
||||
if m.static:
|
||||
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, 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[method.name].wrapper
|
||||
if wrapper:
|
||||
return '&' + wrapper.FullName()
|
||||
# return normal pointers to the methods of the class
|
||||
is_unique = self.class_.IsUnique(m.name)
|
||||
if is_unique:
|
||||
return '&' + method.FullName()
|
||||
else:
|
||||
return method.PointerDeclaration()
|
||||
|
||||
def IsExportable(m):
|
||||
'Returns true if the given method is exportable by this routine'
|
||||
ignore = (Constructor, ClassOperator, Destructor)
|
||||
return isinstance(m, Method) and not isinstance(m, ignore) and not m.virtual
|
||||
|
||||
methods = [x for x in self.public_members if IsExportable(x)]
|
||||
|
||||
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 = 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 method.static:
|
||||
code = '.staticmethod("%s")' % name
|
||||
self.Add('inside', code)
|
||||
# add wrapper code if this method has one
|
||||
wrapper = method_info.wrapper
|
||||
if wrapper and wrapper.code:
|
||||
self.Add('declaration', wrapper.code)
|
||||
|
||||
|
||||
def ExportVirtualMethods(self):
|
||||
# check if this class has any virtual methods
|
||||
has_virtual_methods = False
|
||||
for member in self.class_.members:
|
||||
if type(member) == Method and member.virtual:
|
||||
has_virtual_methods = True
|
||||
break
|
||||
|
||||
if has_virtual_methods:
|
||||
generator = _VirtualWrapperGenerator(self.class_, self.ClassBases(), self.info)
|
||||
self.Add('template', generator.FullName())
|
||||
for definition in generator.GenerateDefinitions():
|
||||
self.Add('inside', definition)
|
||||
self.Add('declaration', generator.GenerateVirtualWrapper(self.INDENT))
|
||||
|
||||
|
||||
# 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 signature
|
||||
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)
|
||||
elif isinstance(operator, ClassOperator) and self.class_.IsUnique(operator.name):
|
||||
pointer = '&' + operator.FullName()
|
||||
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)
|
||||
if self.class_.IsUnique(converter.name):
|
||||
pointer = '&' + converter.FullName()
|
||||
else:
|
||||
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 + [nested_class])
|
||||
codeunit = SingleCodeUnit(None, None)
|
||||
exporter.Export(codeunit, exported_names)
|
||||
self.nested_codeunits.append(codeunit)
|
||||
|
||||
|
||||
def ExportNestedEnums(self):
|
||||
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 + [enum])
|
||||
codeunit = SingleCodeUnit(None, None)
|
||||
exporter.Export(codeunit, None)
|
||||
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('template', smart_ptr)
|
||||
|
||||
self.Add('scope', '// Temporary code for smart pointers')
|
||||
self.Add('scope', namespaces.python + 'objects::class_value_wrapper< ')
|
||||
self.Add('scope', ' %s, objects::make_ptr_instance< ' % smart_ptr)
|
||||
self.Add('scope', ' %s, objects::pointer_holder< ' % class_name)
|
||||
self.Add('scope', ' %s, %s >' % (smart_ptr, class_name))
|
||||
self.Add('scope', ' >')
|
||||
self.Add('scope', '>();')
|
||||
|
||||
|
||||
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 = 'BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(%s)' % method.result.name
|
||||
if macro not in self._exported_opaque_pointers:
|
||||
self.Add('declaration-outside', macro)
|
||||
self._exported_opaque_pointers[macro] = 1
|
||||
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# 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_ = 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 {\n' % (result, method.name, params, constantness)
|
||||
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'
|
||||
wrapper = self.info[method.name].wrapper
|
||||
if not wrapper:
|
||||
# return the default implementation of the class
|
||||
return '%s%s::%s(%s);\n' % \
|
||||
(return_str, self.class_.FullName(), method.name, ', '.join(param_names))
|
||||
else:
|
||||
# return a call for the wrapper
|
||||
params = ', '.join(['this'] + param_names)
|
||||
return '%s%s(%s);\n' % (return_str, wrapper.FullName(), params)
|
||||
|
||||
if not method.abstract and 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 += indent*2 + 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 = self.IsMethodUnique(method.name)
|
||||
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
|
||||
if is_method_unique:
|
||||
pointer = '&' + method.FullName()
|
||||
else:
|
||||
pointer = method.PointerDeclaration()
|
||||
|
||||
# generate the defs
|
||||
definitions = []
|
||||
# basic def
|
||||
definitions.append('.def("%s", %s, %s)' % (rename, pointer, default_pointers[-1]))
|
||||
for default_pointer in default_pointers[:-1]:
|
||||
definitions.append('.def("%s", %s)' % (rename, default_pointer))
|
||||
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 m.virtual and m.visibility != Scope.private
|
||||
|
||||
all_members = self.class_.members[:]
|
||||
for base in self.bases:
|
||||
for base_member in base.members:
|
||||
base_member.class_ = self.class_.FullName()
|
||||
all_members.append(base_member)
|
||||
|
||||
# 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' % (result, method.name, params, const)
|
||||
|
||||
all_members = [x for x in all_members if type(x) == Method]
|
||||
self.virtual_methods = []
|
||||
already_added = {}
|
||||
for member in all_members:
|
||||
sig = MethodSig(member)
|
||||
if IsVirtual(member) and not sig in already_added:
|
||||
self.virtual_methods.append(member)
|
||||
already_added[sig] = 0
|
||||
|
||||
|
||||
def IsMethodUnique(self, method):
|
||||
if not self._method_count:
|
||||
for m in self.virtual_methods:
|
||||
self._method_count[m.name] = self._method_count.get(m.name, 0) + 1
|
||||
return self._method_count[method] == 1
|
||||
|
||||
|
||||
def Constructors(self):
|
||||
def IsValid(m):
|
||||
return isinstance(m, Constructor) and m.visibility == Scope.public
|
||||
return [m for m in self.class_.members if IsValid(m)]
|
||||
|
||||
|
||||
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 method.abstract 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
|
||||
@@ -1,117 +0,0 @@
|
||||
from GCCXMLParser import ParseDeclarations
|
||||
import tempfile
|
||||
import shutil
|
||||
import os
|
||||
import os.path
|
||||
import settings
|
||||
|
||||
class CppParserError(Exception): pass
|
||||
|
||||
|
||||
class CppParser:
|
||||
'Parses a header file and returns a list of declarations'
|
||||
|
||||
def __init__(self, includes=None, defines=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
|
||||
self._cache = []
|
||||
self._CACHE_SIZE = 5
|
||||
|
||||
|
||||
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 UpdateCache(self, include, tail, decl_name, declarations, header):
|
||||
self._cache.append((include, tail, decl_name, declarations, header))
|
||||
if len(self._cache) > self._CACHE_SIZE:
|
||||
self._cache.pop(0)
|
||||
|
||||
|
||||
def Cache(self, include, tail, decl_name):
|
||||
for cache_include, cache_tail, cache_decl, declarations, header in self._cache:
|
||||
if cache_include == include \
|
||||
and cache_tail == tail \
|
||||
and cache_decl == decl_name:
|
||||
return declarations, header
|
||||
return None
|
||||
|
||||
|
||||
def FindFileName(self, include):
|
||||
if os.path.isfile(include):
|
||||
return include
|
||||
for path in self.includes:
|
||||
filename = os.path.join(path, include)
|
||||
if os.path.isfile(filename):
|
||||
return filename
|
||||
name = os.path.basename(include)
|
||||
raise RuntimeError, 'Header file "%s" not found!' % name
|
||||
|
||||
|
||||
def parse(self, include, tail=None, decl_name=None):
|
||||
'''Parses the given filename, and returns (declaration, header). The
|
||||
header returned is normally the same as the given to this method,
|
||||
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 gcc.
|
||||
This temp filename is then returned.
|
||||
'''
|
||||
# check if this header was already parsed
|
||||
cached = self.Cache(include, tail, decl_name)
|
||||
if cached:
|
||||
return cached
|
||||
filename = self.FindFileName(include)
|
||||
# copy file to temp folder, if needed
|
||||
if tail:
|
||||
tempfilename = tempfile.mktemp('.h')
|
||||
infilename = tempfilename
|
||||
shutil.copyfile(filename, infilename)
|
||||
f = file(infilename, 'a')
|
||||
f.write('\n\n'+tail)
|
||||
f.close()
|
||||
else:
|
||||
infilename = filename
|
||||
xmlfile = tempfile.mktemp('.xml')
|
||||
try:
|
||||
# get the params
|
||||
includes = self._includeparams(filename)
|
||||
defines = self._defineparams()
|
||||
# call gccxml
|
||||
cmd = 'gccxml %s %s %s -fxml=%s' \
|
||||
% (includes, defines, infilename, xmlfile)
|
||||
if decl_name is not None:
|
||||
cmd += ' "-fxml-start=%s"' % decl_name
|
||||
status = os.system(cmd)
|
||||
if status != 0 or not os.path.isfile(xmlfile):
|
||||
raise CppParserError, 'Error executing gccxml'
|
||||
# parse the resulting xml
|
||||
declarations = ParseDeclarations(xmlfile)
|
||||
# cache the results
|
||||
self.UpdateCache(include, tail, decl_name, declarations, infilename)
|
||||
# return the declarations
|
||||
return declarations, infilename
|
||||
finally:
|
||||
if settings.DEBUG and os.path.isfile(xmlfile):
|
||||
filename = os.path.basename(include)
|
||||
shutil.copy(xmlfile, os.path.splitext(filename)[0] + '.xml')
|
||||
# delete the temporary files
|
||||
try:
|
||||
os.remove(xmlfile)
|
||||
if tail:
|
||||
os.remove(tempfilename)
|
||||
except OSError: pass
|
||||
@@ -1,40 +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)
|
||||
self.enum = self.GetDeclaration(self.info.name)
|
||||
|
||||
|
||||
def Export(self, codeunit, expoted_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()
|
||||
code = indent + namespaces.python + '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)
|
||||
|
||||
|
||||
def Unit(self):
|
||||
return utils.makeid(self.info.include)
|
||||
|
||||
|
||||
def Order(self):
|
||||
return self.info.name
|
||||
@@ -1,74 +0,0 @@
|
||||
import os.path
|
||||
|
||||
#==============================================================================
|
||||
# Exporter
|
||||
#==============================================================================
|
||||
class Exporter:
|
||||
'Base class for objects capable to generate boost.python code.'
|
||||
|
||||
INDENT = ' ' * 4
|
||||
|
||||
def __init__(self, info, parser_tail=None, parser_decl=None):
|
||||
self.info = info
|
||||
self.parser_tail = parser_tail
|
||||
self.parser_decl = parser_decl
|
||||
|
||||
|
||||
def Name(self):
|
||||
return self.info.name
|
||||
|
||||
|
||||
def Parse(self, parser):
|
||||
self.parser = parser
|
||||
header = self.info.include
|
||||
tail = self.parser_tail
|
||||
decl = self.parser_decl
|
||||
declarations, parser_header = parser.parse(header, tail, decl)
|
||||
self.parser_header = parser_header
|
||||
self.SetDeclarations(declarations)
|
||||
|
||||
|
||||
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 Unit(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def GetDeclarations(self, fullname):
|
||||
decls = [x for x in self.declarations if x.FullName() == fullname]
|
||||
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.
|
||||
'''
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def Unit(self):
|
||||
return self.info.include
|
||||
@@ -1,95 +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)
|
||||
self._exported_opaque_pointers = {}
|
||||
|
||||
|
||||
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)
|
||||
exporterutils.WarnForwardDeclarations(decl)
|
||||
self.ExportDeclaration(decl, len(decls) == 1, codeunit)
|
||||
self.ExportOpaquePointer(decl, codeunit)
|
||||
self.GenerateOverloads(decls, codeunit)
|
||||
|
||||
|
||||
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()
|
||||
elif not unique:
|
||||
pointer = decl.PointerDeclaration()
|
||||
else:
|
||||
pointer = '&' + decl.FullName()
|
||||
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', 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):
|
||||
type = function.result.name
|
||||
macro = 'BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(%s)' % type
|
||||
if macro not in self._exported_opaque_pointers:
|
||||
codeunit.Write('declaration-outside', macro)
|
||||
self._exported_opaque_pointers[macro] = 1
|
||||
|
||||
|
||||
def Order(self):
|
||||
return self.info.name
|
||||
|
||||
|
||||
def Unit(self):
|
||||
return utils.makeid(self.info.include)
|
||||
@@ -1,417 +0,0 @@
|
||||
from declarations import *
|
||||
from elementtree.ElementTree import ElementTree
|
||||
from xml.parsers.expat import ExpatError
|
||||
from copy import deepcopy
|
||||
|
||||
|
||||
class InvalidXMLError(Exception): pass
|
||||
|
||||
class ParserError(Exception): pass
|
||||
|
||||
class InvalidContextError(ParserError): pass
|
||||
|
||||
|
||||
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 = []
|
||||
# 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):
|
||||
self.declarations.append(decl)
|
||||
|
||||
|
||||
def ParseElement(self, id, element):
|
||||
method = 'Parse' + element.tag
|
||||
if hasattr(self, method):
|
||||
func = getattr(self, method)
|
||||
func(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 = decl.Copy()
|
||||
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
|
||||
res.incomplete = decl.incomplete
|
||||
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 ParseNamespace(self, id, element):
|
||||
namespace = element.get('name')
|
||||
context = element.get('context')
|
||||
if context:
|
||||
outerns = self.GetDecl(context)
|
||||
if not outerns.endswith('::'):
|
||||
outerns += '::'
|
||||
namespace = outerns + 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 if apply.
|
||||
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 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)
|
||||
function = functionType(name, namespace, returns, params)
|
||||
function.location = location
|
||||
self.AddDecl(function)
|
||||
self.Update(id, function)
|
||||
|
||||
|
||||
def ParseOperatorFunction(self, id, element):
|
||||
self.ParseFunction(id, element, Operator)
|
||||
|
||||
|
||||
def GetBases(self, bases):
|
||||
'Parses the string "bases" from the xml into a list of Base instances.'
|
||||
|
||||
if bases is None:
|
||||
return []
|
||||
bases = bases.split()
|
||||
baseobjs = []
|
||||
for base in bases:
|
||||
# get the visibility
|
||||
split = base.split(':')
|
||||
if len(split) == 2:
|
||||
visib = split[0]
|
||||
base = split[1]
|
||||
else:
|
||||
visib = Scope.public
|
||||
decl = self.GetDecl(base)
|
||||
baseobj = Base(decl.FullName(), visib)
|
||||
baseobjs.append(baseobj)
|
||||
return baseobjs
|
||||
|
||||
|
||||
def GetMembers(self, members):
|
||||
# members must be a string with the ids of the members
|
||||
if members is None:
|
||||
return []
|
||||
memberobjs = []
|
||||
for member in members.split():
|
||||
memberobjs.append(self.GetDecl(member))
|
||||
return memberobjs
|
||||
|
||||
|
||||
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(element.get('incomplete', False))
|
||||
if isinstance(context, str):
|
||||
class_ = Class(name, context, [], abstract, [])
|
||||
self.AddDecl(class_)
|
||||
else:
|
||||
# a nested class
|
||||
visib = element.get('access', Scope.public)
|
||||
class_ = NestedClass(
|
||||
name, context.FullName(), visib, [], abstract, [])
|
||||
# we have to add the declaration of the class before trying
|
||||
# to parse its members and bases, to avoid recursion.
|
||||
class_.location = location
|
||||
class_.incomplete = incomplete
|
||||
self.Update(id, class_)
|
||||
# now we can get the members and the bases
|
||||
class_.bases = self.GetBases(element.get('bases'))
|
||||
class_.members = self.GetMembers(element.get('members'))
|
||||
|
||||
|
||||
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)
|
||||
array.min = min
|
||||
array.max = 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, type_.incomplete, expand)
|
||||
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, type_.incomplete, expand)
|
||||
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'))
|
||||
params = self.GetArguments(element)
|
||||
method = methodType(
|
||||
name, classname, result, params, visib, virtual, abstract, static, const)
|
||||
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'))
|
||||
if isinstance(context, str):
|
||||
enum = Enumeration(name, context)
|
||||
self.AddDecl(enum) # in this case, is a top level decl
|
||||
else:
|
||||
visib = element.get('access', Scope.public)
|
||||
enum = ClassEnumeration(name, context.FullName(), visib)
|
||||
|
||||
enum.location = location
|
||||
for child in element:
|
||||
if child.tag == 'EnumValue':
|
||||
name = child.get('name')
|
||||
value = int(child.get('init'))
|
||||
enum.values[name] = value
|
||||
self.Update(id, enum)
|
||||
|
||||
|
||||
def ParseUnimplemented(self, id, element):
|
||||
'No idea of what this is'
|
||||
self.Update(id, Declaration('', ''))
|
||||
|
||||
|
||||
def ParseUnion(self, id, element):
|
||||
name = element.get('name')
|
||||
context = self.GetDecl(element.get('context'))
|
||||
location = self.GetLocation(element.get('location'))
|
||||
if isinstance(context, str):
|
||||
# a free union
|
||||
union = Union(name, context)
|
||||
self.AddDecl(union)
|
||||
else:
|
||||
visib = element.get('access', Scope.public)
|
||||
union = ClassUnion(name, context.FullName(), visib)
|
||||
union.location = location
|
||||
self.Update(id, union)
|
||||
|
||||
|
||||
|
||||
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')
|
||||
@@ -1,75 +0,0 @@
|
||||
from Exporter import Exporter
|
||||
from ClassExporter import ClassExporter
|
||||
from FunctionExporter import FunctionExporter
|
||||
from EnumExporter import EnumExporter
|
||||
from infos import *
|
||||
from declarations import *
|
||||
import os.path
|
||||
import exporters
|
||||
|
||||
#==============================================================================
|
||||
# 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 SetDeclarations(self, declarations):
|
||||
def IsInternalName(name):
|
||||
'''Returns true if the given name looks like a internal compiler
|
||||
structure'''
|
||||
return name.startswith('__')
|
||||
|
||||
Exporter.SetDeclarations(self, declarations)
|
||||
header = os.path.normpath(self.parser_header)
|
||||
for decl in declarations:
|
||||
# check if this declaration is in the header
|
||||
location = os.path.normpath(decl.location[0])
|
||||
if location != header or IsInternalName(decl.name):
|
||||
continue
|
||||
# ok, check the type of the declaration and export it accordingly
|
||||
self.HandleDeclaration(decl)
|
||||
|
||||
|
||||
def HandleDeclaration(self, decl):
|
||||
'''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,
|
||||
}
|
||||
|
||||
exporter_class = dispatch_table.get(type(decl))
|
||||
if exporter_class is not None:
|
||||
self.HandleExporter(decl, exporter_class)
|
||||
|
||||
|
||||
def HandleExporter(self, decl, exporter_type):
|
||||
# only export complete declarations
|
||||
if not getattr(decl, "incomplete", False):
|
||||
info = self.info[decl.name]
|
||||
info.name = decl.FullName()
|
||||
info.include = self.info.include
|
||||
exporter = exporter_type(info)
|
||||
exporter.SetDeclarations(self.declarations)
|
||||
exporters.exporters.append(exporter)
|
||||
|
||||
|
||||
def Unit(self):
|
||||
return None # doesn't write anything by himself
|
||||
|
||||
|
||||
def Order(self):
|
||||
return self.info.include
|
||||
|
||||
|
||||
@@ -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 Order(self):
|
||||
return self.info.include
|
||||
|
||||
def Unit(self):
|
||||
return '__all__' # include it in all generated cpps (multiple mode)
|
||||
@@ -1,104 +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 header to a SingleCodeUnit
|
||||
self.functions = []
|
||||
self._current = None
|
||||
|
||||
|
||||
def _FunctionName(self, code_unit_name):
|
||||
return '_Export_%s' % utils.makeid(code_unit_name)
|
||||
|
||||
|
||||
def _FileName(self, code_unit_name):
|
||||
filename = os.path.basename(code_unit_name)
|
||||
filename = '_%s.cpp' % os.path.splitext(filename)[0]
|
||||
return os.path.join(self.outdir, filename)
|
||||
|
||||
|
||||
def SetCurrent(self, code_unit_name):
|
||||
'Changes the current code unit'
|
||||
try:
|
||||
if code_unit_name is not None:
|
||||
codeunit = self.codeunits[code_unit_name]
|
||||
else:
|
||||
codeunit = None
|
||||
except KeyError:
|
||||
filename = self._FileName(code_unit_name)
|
||||
function_name = self._FunctionName(code_unit_name)
|
||||
codeunit = SingleCodeUnit(None, filename)
|
||||
codeunit.module_definition = 'void %s()' % function_name
|
||||
self.codeunits[code_unit_name] = codeunit
|
||||
if code_unit_name != '__all__':
|
||||
self.functions.append(function_name)
|
||||
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();
|
||||
# write all the codeunits, merging first the contents of
|
||||
# the special code unit named __all__
|
||||
__all__ = self.codeunits.get('__all__')
|
||||
for name, codeunit in self.codeunits.items():
|
||||
if name != '__all__':
|
||||
if __all__:
|
||||
codeunit.Merge(__all__)
|
||||
codeunit.Save()
|
||||
# generate the main cpp
|
||||
filename = os.path.join(self.outdir, self.modulename + '.cpp')
|
||||
fout = SmartFile(filename, 'w')
|
||||
fout.write(utils.left_equals('Include'))
|
||||
fout.write('#include <boost/python.hpp>\n\n')
|
||||
fout.write(utils.left_equals('Exports'))
|
||||
for function in self.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 self.functions:
|
||||
fout.write(indent)
|
||||
fout.write('%s();\n' % function)
|
||||
fout.write('}\n')
|
||||
|
||||
|
||||
|
||||
@@ -1,84 +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'] = ''
|
||||
# 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 Save(self):
|
||||
'Writes this code unit to the filename'
|
||||
space = '\n\n'
|
||||
fout = SmartFile(self.filename, 'w')
|
||||
# includes
|
||||
includes = remove_duplicated_lines(self.code['include'])
|
||||
fout.write('\n' + left_equals('Includes'))
|
||||
fout.write('#include <boost/python.hpp>\n')
|
||||
fout.write(includes)
|
||||
fout.write(space)
|
||||
# using
|
||||
if settings.USING_BOOST_NS:
|
||||
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'))
|
||||
fout.write(declaration_outside + '\n\n')
|
||||
if declaration:
|
||||
pyste_namespace = namespaces.pyste[:-2]
|
||||
fout.write('namespace %s {\n\n\n' % pyste_namespace)
|
||||
fout.write(declaration)
|
||||
fout.write('\n\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')
|
||||
@@ -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
|
||||
@@ -1,538 +0,0 @@
|
||||
'''
|
||||
Module declarations
|
||||
|
||||
Defines classes that represent declarations found in C++ header files.
|
||||
|
||||
'''
|
||||
|
||||
class Declaration(object):
|
||||
'Represents a basic declaration.'
|
||||
|
||||
__slots__ = 'name namespace location incomplete'.split()
|
||||
|
||||
def __init__(self, name, namespace):
|
||||
# the declaration name
|
||||
self.name = name
|
||||
# all the namespaces, separated by '::' = 'boost::inner'
|
||||
self.namespace = namespace
|
||||
# tuple (filename, line)
|
||||
self.location = '', -1
|
||||
# if a declaration is incomplete it means that it was
|
||||
# forward declared
|
||||
self.incomplete = False
|
||||
|
||||
|
||||
def FullName(self):
|
||||
'Returns the full qualified name: "boost::inner::Test"'
|
||||
namespace = self.namespace or ''
|
||||
#if not namespace:
|
||||
# namespace = ''
|
||||
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(Declaration):
|
||||
'The declaration of a class or struct.'
|
||||
|
||||
__slots__= 'members abstract bases _members_count'.split()
|
||||
def __init__(self, name, namespace, members, abstract, bases):
|
||||
Declaration.__init__(self, name, namespace)
|
||||
# list of members
|
||||
self.members = members
|
||||
# whatever the class has any abstract methods
|
||||
self.abstract = abstract
|
||||
# instances of Base
|
||||
self.bases = bases
|
||||
self._members_count = {}
|
||||
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.members)
|
||||
|
||||
|
||||
def IsAbstract(self):
|
||||
'Returns True if any method of this class is abstract'
|
||||
for member in self.members:
|
||||
if isinstance(member, Method):
|
||||
if member.abstract:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def RawName(self):
|
||||
'Returns the raw name of a template class. name = Foo<int>, raw = Foo'
|
||||
lesspos = self.name.find('<')
|
||||
if lesspos != -1:
|
||||
return self.name[:lesspos]
|
||||
else:
|
||||
return self.name
|
||||
|
||||
|
||||
def Constructors(self, publics_only=True):
|
||||
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):
|
||||
for cons in self.Constructors():
|
||||
if cons.IsCopy():
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def HasDefaultConstructor(self):
|
||||
for cons in self.Constructors():
|
||||
if cons.IsDefault():
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def IsUnique(self, member_name):
|
||||
if not self._members_count:
|
||||
for m in self:
|
||||
self._members_count[m.name] = self._members_count.get(m.name, 0) + 1
|
||||
try:
|
||||
return self._members_count[member_name] == 1
|
||||
except KeyError:
|
||||
print self._members_count
|
||||
print 'Key', member_name
|
||||
|
||||
|
||||
|
||||
class NestedClass(Class):
|
||||
'The declaration of a class/struct inside another class/struct.'
|
||||
|
||||
__slots__= 'class_ visibility'.split()
|
||||
|
||||
def __init__(self, name, class_, visib, members, abstract, bases):
|
||||
Class.__init__(self, name, None, members, abstract, bases)
|
||||
self.class_ = class_
|
||||
self.visibility = visib
|
||||
|
||||
|
||||
def FullName(self):
|
||||
return '%s::%s' % (self.class_, self.name)
|
||||
|
||||
|
||||
|
||||
class Base:
|
||||
'Represents a base class of another class.'
|
||||
|
||||
__slots__= 'name visibility'.split()
|
||||
|
||||
def __init__(self, name, visibility=None):
|
||||
# class_ is the full name of the base class
|
||||
self.name = name
|
||||
# visibility of the derivation
|
||||
if visibility is None:
|
||||
visibility = Scope.public
|
||||
self.visibility = visibility
|
||||
|
||||
|
||||
|
||||
class Scope:
|
||||
public = 'public'
|
||||
private = 'private'
|
||||
protected = 'protected'
|
||||
|
||||
|
||||
|
||||
class Function(Declaration):
|
||||
'The declaration of a function.'
|
||||
|
||||
__slots__= 'result parameters'.split()
|
||||
|
||||
def __init__(self, name, namespace, result, params):
|
||||
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
|
||||
|
||||
|
||||
def PointerDeclaration(self):
|
||||
'returns a declaration of a pointer to this function'
|
||||
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)
|
||||
|
||||
|
||||
|
||||
class Operator(Function):
|
||||
'The declaration of a custom operator.'
|
||||
|
||||
def FullName(self):
|
||||
namespace = self.namespace or ''
|
||||
if not namespace.endswith('::'):
|
||||
namespace += '::'
|
||||
return namespace + 'operator' + self.name
|
||||
|
||||
|
||||
|
||||
class Method(Function):
|
||||
'The declaration of a method.'
|
||||
|
||||
__slots__= 'visibility virtual abstract static class_ const'.split()
|
||||
|
||||
def __init__(self, name, class_, result, params, visib, virtual, abstract, static, const):
|
||||
Function.__init__(self, name, None, result, params)
|
||||
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):
|
||||
'returns a declaration of a pointer to this function'
|
||||
if self.static:
|
||||
# static methods are like normal functions
|
||||
return Function.PointerDeclaration(self)
|
||||
else:
|
||||
# using syntax of methods
|
||||
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' %\
|
||||
(result, self.class_, params, const, self.FullName())
|
||||
|
||||
|
||||
class Constructor(Method):
|
||||
'A constructor of a class.'
|
||||
|
||||
def __init__(self, name, class_, params, visib):
|
||||
Method.__init__(self, name, class_, None, params, visib, False, False, False, False)
|
||||
|
||||
|
||||
def IsDefault(self):
|
||||
return len(self.parameters) == 0
|
||||
|
||||
|
||||
def IsCopy(self):
|
||||
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)
|
||||
return param_reference and class_as_param and param.const
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
class ClassOperator(Method):
|
||||
'The declaration of a custom operator in a class.'
|
||||
|
||||
def FullName(self):
|
||||
return self.class_ + '::operator ' + self.name
|
||||
|
||||
|
||||
|
||||
class ConverterOperator(ClassOperator):
|
||||
'An operator in the form "operator OtherClass()".'
|
||||
|
||||
def FullName(self):
|
||||
return self.class_ + '::operator ' + self.result.FullName()
|
||||
|
||||
|
||||
|
||||
class Type(Declaration):
|
||||
'Represents a type.'
|
||||
|
||||
__slots__= 'const default volatile restricted incomplete'.split()
|
||||
|
||||
def __init__(self, name, const=False, default=None, incomplete=False):
|
||||
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.incomplete = incomplete
|
||||
|
||||
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
|
||||
|
||||
|
||||
def Copy(self):
|
||||
t = self.__class__(self.name, self.const, self.default, self.incomplete)
|
||||
t.volatile = self.volatile
|
||||
t.restricted = self.restricted
|
||||
return t
|
||||
|
||||
|
||||
class ArrayType(Type):
|
||||
'Represents an array.'
|
||||
|
||||
__slots__= 'min max'.split()
|
||||
|
||||
def __init__(self, name, const=False, default=None, incomplete=False):
|
||||
'min and max can be None.'
|
||||
Type.__init__(self, name, const)
|
||||
self.min = None
|
||||
self.max = None
|
||||
|
||||
def Copy(self):
|
||||
t = Type.Copy(self)
|
||||
t.min = self.min
|
||||
t.max = self.max
|
||||
return t
|
||||
|
||||
|
||||
|
||||
class ReferenceType(Type):
|
||||
'A reference type.'
|
||||
|
||||
__slots__= 'expand'.split()
|
||||
|
||||
def __init__(self, name, const=False, default=None, incomplete=False, expandRef=True):
|
||||
Type.__init__(self, name, const, default, incomplete)
|
||||
self.expand = expandRef
|
||||
|
||||
|
||||
def FullName(self):
|
||||
'expand is False for function pointers'
|
||||
expand = ' &'
|
||||
if not self.expand:
|
||||
expand = ''
|
||||
return Type.FullName(self) + expand
|
||||
|
||||
|
||||
def Copy(self):
|
||||
t = Type.Copy(self)
|
||||
t.expand = self.expand
|
||||
return t
|
||||
|
||||
|
||||
|
||||
class PointerType(Type):
|
||||
'A pointer type.'
|
||||
|
||||
__slots__= 'expand'.split()
|
||||
|
||||
def __init__(self, name, const=False, default=None, incomplete=False, expandPointer=False):
|
||||
Type.__init__(self, name, const, default, incomplete)
|
||||
self.expand = expandPointer
|
||||
|
||||
|
||||
def FullName(self):
|
||||
'expand is False for function pointer'
|
||||
expand = ' *'
|
||||
if not self.expand:
|
||||
expand = ''
|
||||
return Type.FullName(self) + expand
|
||||
|
||||
def Copy(self):
|
||||
t = Type.Copy(self)
|
||||
t.expand = self.expand
|
||||
return t
|
||||
|
||||
|
||||
|
||||
class FundamentalType(Type):
|
||||
'One of the fundamental types (int, void...).'
|
||||
|
||||
def __init__(self, name, const=False, default=None, incomplete=False):
|
||||
Type.__init__(self, name, const, default, incomplete)
|
||||
|
||||
|
||||
|
||||
class FunctionType(Type):
|
||||
'A pointer to a function.'
|
||||
|
||||
__slots__= 'result parameters name'.split()
|
||||
|
||||
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
|
||||
|
||||
|
||||
def Copy(self):
|
||||
return FunctionType(self.result, self.parameters[:])
|
||||
|
||||
|
||||
class MethodType(FunctionType):
|
||||
'A pointer to a member function of a class.'
|
||||
|
||||
__slots__= 'result parameters class_ name'.split()
|
||||
|
||||
def __init__(self, result, parameters, class_):
|
||||
Type.__init__(self, '', False)
|
||||
self.result = result
|
||||
self.parameters = parameters
|
||||
self.class_ = class_
|
||||
self.name = self.FullName()
|
||||
|
||||
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
|
||||
|
||||
def Copy(self):
|
||||
return MethodType(self.result, self.parameters[:], self.class_)
|
||||
|
||||
|
||||
class Variable(Declaration):
|
||||
'Represents a global variable.'
|
||||
|
||||
__slots__= 'type'.split()
|
||||
|
||||
def __init__(self, type, name, namespace):
|
||||
Declaration.__init__(self, name, namespace)
|
||||
# instance of Type
|
||||
self.type = type
|
||||
|
||||
|
||||
|
||||
class ClassVariable(Variable):
|
||||
'Represents a class variable.'
|
||||
|
||||
__slots__= 'visibility static class_'.split()
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
class Enumeration(Declaration):
|
||||
|
||||
__slots__= 'values'.split()
|
||||
|
||||
def __init__(self, name, namespace):
|
||||
Declaration.__init__(self, name, namespace)
|
||||
self.values = {} # dict of str => int
|
||||
|
||||
def ValueFullName(self, name):
|
||||
assert name in self.values
|
||||
namespace = self.namespace
|
||||
if namespace:
|
||||
namespace += '::'
|
||||
return namespace + name
|
||||
|
||||
|
||||
|
||||
class ClassEnumeration(Enumeration):
|
||||
|
||||
__slots__= 'class_ visibility'.split()
|
||||
|
||||
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)
|
||||
|
||||
|
||||
|
||||
class Typedef(Declaration):
|
||||
|
||||
__slots__= 'type visibility'.split()
|
||||
|
||||
def __init__(self, type, name, namespace):
|
||||
Declaration.__init__(self, name, namespace)
|
||||
self.type = type
|
||||
self.visibility = Scope.public
|
||||
|
||||
|
||||
class Union(Declaration):
|
||||
'Shallow declaration, because Unions are not supported yet'
|
||||
def __init__(self, name, namespace):
|
||||
Declaration.__init__(self, name, namespace)
|
||||
|
||||
|
||||
class ClassUnion(Union):
|
||||
|
||||
__slots__= 'class_ visibility'.split()
|
||||
|
||||
def __init__(self, name, class_, visib):
|
||||
Union.__init__(self, name, None)
|
||||
self.class_ = class_
|
||||
self.visibility = visib
|
||||
|
||||
def FullName(self):
|
||||
return '%s::%s' % (self.class_, self.name)
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
|
||||
# a list of Exporter instances
|
||||
exporters = []
|
||||
@@ -1,91 +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 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.const and type.name == 'char' and isinstance(type, PointerType)
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# WarnForwardDeclarations
|
||||
#==============================================================================
|
||||
def WarnForwardDeclarations(function):
|
||||
'''Checks if any of the parameters or the result of the function are
|
||||
incomplete types.'''
|
||||
|
||||
types = [function.result] + function.parameters
|
||||
types = [x for x in types if x]
|
||||
for type in types:
|
||||
if type.incomplete:
|
||||
msg = '---> Error: %s is forward declared. Please include the ' \
|
||||
'appropriate header with its definition' % type.name
|
||||
# disable this for now... it was reporting too many false
|
||||
# forward declarations to be useful
|
||||
if 0 and msg not in _printed_warnings:
|
||||
print msg
|
||||
print
|
||||
_printed_warnings[msg] = 1
|
||||
|
||||
@@ -1,198 +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 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)
|
||||
exporters.exporters.append(exporter)
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# 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)
|
||||
exporters.exporters.append(exporter)
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# IncludeInfo
|
||||
#==============================================================================
|
||||
class IncludeInfo(DeclarationInfo):
|
||||
|
||||
def __init__(self, include):
|
||||
DeclarationInfo.__init__(self)
|
||||
self._Attribute('include', include)
|
||||
exporter = IncludeExporter(InfoWrapper(self))
|
||||
exporters.exporters.append(exporter)
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# 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))
|
||||
exporters.exporters.append(exporter)
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# HeaderInfo
|
||||
#==============================================================================
|
||||
class HeaderInfo(DeclarationInfo):
|
||||
|
||||
def __init__(self, include):
|
||||
DeclarationInfo.__init__(self)
|
||||
self._Attribute('include', include)
|
||||
exporter = HeaderExporter(InfoWrapper(self))
|
||||
exporters.exporters.append(exporter)
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# 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(option):
|
||||
option._Attribute('exclude', True)
|
||||
|
||||
def set_policy(option, policy):
|
||||
option._Attribute('policy', policy)
|
||||
|
||||
def rename(option, name):
|
||||
option._Attribute('rename', name)
|
||||
|
||||
def set_wrapper(option, wrapper):
|
||||
if isinstance(wrapper, str):
|
||||
wrapper = FunctionWrapper(wrapper)
|
||||
option._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(option):
|
||||
option._Attribute('smart_ptr', 'boost::shared_ptr< %s >')
|
||||
|
||||
def use_auto_ptr(option):
|
||||
option._Attribute('smart_ptr', 'std::auto_ptr< %s >')
|
||||
|
||||
|
||||
@@ -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'
|
||||
@@ -1,17 +0,0 @@
|
||||
import profile
|
||||
import pstats
|
||||
import pyste
|
||||
|
||||
import psyco
|
||||
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(-1).print_stats()
|
||||
@@ -1,197 +0,0 @@
|
||||
'''
|
||||
Pyste version %s
|
||||
|
||||
Usage:
|
||||
pyste [options] --module=<name> interface-files
|
||||
|
||||
where options are:
|
||||
-I <path> add an include path
|
||||
-D <symbol> define symbol
|
||||
--multiple create various cpps, 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
|
||||
'''
|
||||
|
||||
import sys
|
||||
import os
|
||||
import getopt
|
||||
import exporters
|
||||
import SingleCodeUnit
|
||||
import MultipleCodeUnit
|
||||
import infos
|
||||
import exporterutils
|
||||
import settings
|
||||
from policies import *
|
||||
from CppParser import CppParser, CppParserError
|
||||
import time
|
||||
|
||||
__VERSION__ = '0.7.7'
|
||||
|
||||
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 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', 'version', 'help'])
|
||||
except getopt.GetoptError, e:
|
||||
print
|
||||
print 'ERROR:', e
|
||||
Usage()
|
||||
includes = GetDefaultIncludes()
|
||||
defines = []
|
||||
module = None
|
||||
out = None
|
||||
multiple = 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 in ['-h', '--help']:
|
||||
Usage()
|
||||
elif opt in ['-v', '--version']:
|
||||
print 'Pyste version %s' % __VERSION__
|
||||
sys.exit(2)
|
||||
else:
|
||||
print 'Unknown option:', opt
|
||||
Usage()
|
||||
|
||||
if not files or not module:
|
||||
Usage()
|
||||
if not out:
|
||||
out = module
|
||||
if not multiple:
|
||||
out += '.cpp'
|
||||
return includes, defines, module, out, files, multiple
|
||||
|
||||
|
||||
def CreateContext():
|
||||
'create the context where a interface file will be executed'
|
||||
context = {}
|
||||
# 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
|
||||
# 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
|
||||
# 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 Main():
|
||||
includes, defines, module, out, interfaces, multiple = ParseArguments()
|
||||
# execute the interface files
|
||||
for interface in interfaces:
|
||||
context = CreateContext()
|
||||
execfile(interface, context)
|
||||
# parse all the C++ code
|
||||
parser = CppParser(includes, defines)
|
||||
exports = exporters.exporters[:]
|
||||
for export in exports:
|
||||
try:
|
||||
export.Parse(parser)
|
||||
except CppParserError, e:
|
||||
print '\n'
|
||||
print '***', e, ': exitting'
|
||||
return 2
|
||||
print
|
||||
# sort the exporters by its order
|
||||
exports = [(x.Order(), x) for x in exporters.exporters]
|
||||
exports.sort()
|
||||
exports = [x for _, x in exports]
|
||||
# now generate the wrapper code
|
||||
if multiple:
|
||||
codeunit = MultipleCodeUnit.MultipleCodeUnit(module, out)
|
||||
else:
|
||||
codeunit = SingleCodeUnit.SingleCodeUnit(module, out)
|
||||
exported_names = []
|
||||
for export in exports:
|
||||
if multiple:
|
||||
codeunit.SetCurrent(export.Unit())
|
||||
export.GenerateCode(codeunit, exported_names)
|
||||
exported_names.append(export.Name())
|
||||
codeunit.Save()
|
||||
print 'Module %s generated' % module
|
||||
return 0
|
||||
|
||||
|
||||
def UsePsyco():
|
||||
'Tries to use psyco if possible'
|
||||
try:
|
||||
import psyco
|
||||
psyco.profile()
|
||||
except: pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
start = time.clock()
|
||||
UsePsyco()
|
||||
status = Main()
|
||||
print '%0.2f seconds' % (time.clock()-start)
|
||||
sys.exit(status)
|
||||
@@ -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
|
||||
@@ -1,47 +0,0 @@
|
||||
from __future__ import generators
|
||||
import string
|
||||
|
||||
#==============================================================================
|
||||
# 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'
|
||||
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'
|
||||