From 1d4dfdf271155f94ed4684b92bf426de8445aa4c Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 5 Feb 2001 23:28:01 +0000 Subject: [PATCH 001/369] converted <> to <> [SVN r8954] --- doc/pointers.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/pointers.html b/doc/pointers.html index 26f96f0d..bf8ec8ae 100644 --- a/doc/pointers.html +++ b/doc/pointers.html @@ -90,7 +90,7 @@ BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround PyObject* to_python(const Foo* p) { - return to_python(const_cast(p)); + return to_python(const_cast<Foo*>(p)); } BOOST_PYTHON_END_CONVERSION_NAMESPACE From 4d19be8ea477d05df16c979032326175d088d299 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 6 Feb 2001 03:08:00 +0000 Subject: [PATCH 002/369] PyExtensionClassConverters -> python_extension_class_converters<Foo> [SVN r8968] --- doc/pointers.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/pointers.html b/doc/pointers.html index bf8ec8ae..e26cea02 100644 --- a/doc/pointers.html +++ b/doc/pointers.html @@ -85,7 +85,7 @@ code before the last Python reference to it disappears: BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround PyObject* to_python(Foo* p) { - return boost::python::PyExtensionClassConverters::ptr_to_python(p); + return boost::python::python_extension_class_converters<Foo>::ptr_to_python(p); } PyObject* to_python(const Foo* p) From 1d17690f694f72b7b663f048f93b4f356905a404 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 7 Feb 2001 23:50:41 +0000 Subject: [PATCH 003/369] Add back old example files that were accidentally removed from the main branch. [SVN r9016] --- example/example1.cpp | 54 ++++++++++++++++++++++++++++++++++++++++ example/rwgk1.cpp | 41 ++++++++++++++++++++++++++++++ example/test_example1.py | 50 +++++++++++++++++++++++++++++++++++++ example/test_rwgk1.py | 17 +++++++++++++ 4 files changed, 162 insertions(+) create mode 100644 example/example1.cpp create mode 100644 example/rwgk1.cpp create mode 100644 example/test_example1.py create mode 100644 example/test_rwgk1.py diff --git a/example/example1.cpp b/example/example1.cpp new file mode 100644 index 00000000..467ac0dc --- /dev/null +++ b/example/example1.cpp @@ -0,0 +1,54 @@ +#include + +namespace hello { + class world + { + public: + world(int) {} + ~world() {} + const char* get() const { return "hi, world"; } + }; + + size_t length(const world& x) { return strlen(x.get()); } +} + +#include + +// Python requires an exported function called init in every +// extension module. This is where we build the module contents. +extern "C" +#ifdef _WIN32 +__declspec(dllexport) +#endif +void inithello() +{ + try + { + // create an object representing this extension module + boost::python::module_builder hello("hello"); + + // Create the Python type object for our extension class + boost::python::class_builder world_class(hello, "world"); + + // Add the __init__ function + world_class.def(boost::python::constructor()); + // Add a regular member function + world_class.def(&hello::world::get, "get"); + + // Add a regular function to the module + hello.def(hello::length, "length"); + } + catch(...) + { + boost::python::handle_exception(); // Deal with the exception for Python + } +} + +// Win32 DLL boilerplate +#if defined(_WIN32) +#include +extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) +{ + return 1; +} +#endif // _WIN32 diff --git a/example/rwgk1.cpp b/example/rwgk1.cpp new file mode 100644 index 00000000..b21ae4d1 --- /dev/null +++ b/example/rwgk1.cpp @@ -0,0 +1,41 @@ +#include + +namespace { // Avoid cluttering the global namespace. + + // A couple of simple C++ functions that we want to expose to Python. + std::string greet() { return "hello, world"; } + int square(int number) { return number * number; } +} + +#include + +namespace python = boost::python; + +// Python requires an exported function called init in every +// extension module. This is where we build the module contents. +extern "C" +#ifdef _WIN32 +__declspec(dllexport) +#endif +void initrwgk1() +{ + try + { + // Create an object representing this extension module. + python::module_builder this_module("rwgk1"); + + // Add regular functions to the module. + this_module.def(greet, "greet"); + this_module.def(square, "square"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} + +// Win32 DLL boilerplate +#if defined(_WIN32) +#include +extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) { return 1; } +#endif // _WIN32 diff --git a/example/test_example1.py b/example/test_example1.py new file mode 100644 index 00000000..0e3a9a18 --- /dev/null +++ b/example/test_example1.py @@ -0,0 +1,50 @@ +r''' +// (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. + +That's it! If we build this shared library and put it on our PYTHONPATH we can +now access our C++ class and function from Python. + + >>> import hello + >>> hi_world = hello.world(3) + >>> hi_world.get() + 'hi, world' + >>> hello.length(hi_world) + 9 + +We can even make a subclass of hello.world: + + + >>> class my_subclass(hello.world): + ... def get(self): + ... return 'hello, world' + ... + >>> y = my_subclass(2) + >>> y.get() + 'hello, world' + +Pretty cool! You can't do that with an ordinary Python extension type! + + >>> hello.length(y) + 9 + +Of course, you may now have a slightly empty feeling in the pit of your little +pythonic stomach. Perhaps you feel your subclass deserves to have a length() of +12? If so, read on... +''' +from hello import * + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_example1 + doctest.testmod(test_example1) + +if __name__ == '__main__': + run() diff --git a/example/test_rwgk1.py b/example/test_rwgk1.py new file mode 100644 index 00000000..87298875 --- /dev/null +++ b/example/test_rwgk1.py @@ -0,0 +1,17 @@ +r'''>>> import rwgk1 + >>> print rwgk1.greet() + hello, world + >>> number = 11 + >>> print number, '*', number, '=', rwgk1.square(number) + 11 * 11 = 121 +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_rwgk1 + doctest.testmod(test_rwgk1) + +if __name__ == '__main__': + run() From 0d04bf8e34031d7413bce85c4eeabf73e5024445 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 7 Feb 2001 23:58:44 +0000 Subject: [PATCH 004/369] Remove example files that were accidentally added to the main branch. [SVN r9017] --- example/README | 6 +++ example/dvect.cpp | 69 ---------------------------------- example/dvect.h | 32 ---------------- example/ivect.cpp | 69 ---------------------------------- example/ivect.h | 32 ---------------- example/noncopyable_export.cpp | 24 ------------ example/noncopyable_import.cpp | 42 --------------------- example/store.h | 14 ------- example/tst_dvect.py | 16 -------- example/tst_ivect.py | 16 -------- example/tst_noncopyable.py | 8 ---- 11 files changed, 6 insertions(+), 322 deletions(-) create mode 100644 example/README delete mode 100644 example/dvect.cpp delete mode 100644 example/dvect.h delete mode 100644 example/ivect.cpp delete mode 100644 example/ivect.h delete mode 100644 example/noncopyable_export.cpp delete mode 100644 example/noncopyable_import.cpp delete mode 100644 example/store.h delete mode 100644 example/tst_dvect.py delete mode 100644 example/tst_ivect.py delete mode 100644 example/tst_noncopyable.py diff --git a/example/README b/example/README new file mode 100644 index 00000000..34b50d61 --- /dev/null +++ b/example/README @@ -0,0 +1,6 @@ +To get started with the Boost Python Library, use the examples +getting_started?.cpp and abstract.cpp. + +The files example1.cpp and rwgk1.cpp are obsolete. They are only +included because the makefiles in the build directory still refer to +them. This will be fixed later. diff --git a/example/dvect.cpp b/example/dvect.cpp deleted file mode 100644 index 3228010c..00000000 --- a/example/dvect.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include "ivect.h" -#include "dvect.h" -#include -#include -namespace python = boost::python; - -namespace { - - vects::ivect dvect_as_ivect(const vects::dvect& dv) - { - vects::ivect iv(dv.size()); - vects::ivect::iterator iviter = iv.begin(); - for (int i = 0; i < dv.size(); i++) iviter[i] = static_cast(dv[i]); - return iv; - } - - boost::python::tuple ivect_as_tuple(const vects::ivect& iv) - { - return iv.as_tuple(); - } - - std::auto_ptr auto_ptr_ivect(const vects::dvect& dv) - { - return std::auto_ptr(new vects::ivect(dvect_as_ivect(dv))); - } - - boost::shared_ptr shared_ptr_ivect(const vects::dvect& dv) - { - return boost::shared_ptr(new vects::ivect(dvect_as_ivect(dv))); - } - - boost::python::tuple auto_ptr_ivect_as_tuple(std::auto_ptr& iv) - { - return iv->as_tuple(); - } - - boost::python::tuple shared_ptr_ivect_as_tuple(boost::shared_ptr& iv) - { - return iv->as_tuple(); - } -} - -extern "C" -DL_EXPORT(void) -initdvect() -{ - try - { - python::module_builder this_module("dvect"); - - python::x_class_builder dvect_class(this_module, "dvect"); - - python::import_class_builder ivect_class("ivect", "ivect"); - - dvect_class.def(python::constructor()); - dvect_class.def(&vects::dvect::as_tuple, "as_tuple"); - dvect_class.def(dvect_as_ivect, "as_ivect"); - - this_module.def(ivect_as_tuple, "ivect_as_tuple"); - dvect_class.def(auto_ptr_ivect, "auto_ptr_ivect"); - dvect_class.def(shared_ptr_ivect, "shared_ptr_ivect"); - this_module.def(auto_ptr_ivect_as_tuple, "auto_ptr_ivect_as_tuple"); - this_module.def(shared_ptr_ivect_as_tuple, "shared_ptr_ivect_as_tuple"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/dvect.h b/example/dvect.h deleted file mode 100644 index 8ffe7b50..00000000 --- a/example/dvect.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef DVECT_H -#define DVECT_H - -#include -#include - -namespace vects { - - struct dvect : public std::vector - { - dvect() : std::vector() {} - dvect(size_t n) : std::vector(n) {} - dvect(boost::python::tuple tuple) : std::vector(tuple.size()) - { - std::vector::iterator v_it = begin(); - for (int i = 0; i < tuple.size(); i++) - v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), - boost::python::type()); - } - - boost::python::tuple as_tuple() const - { - boost::python::tuple t(size()); - for (int i = 0; i < size(); i++) - t.set_item(i, - boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i]))); - return t; - } - }; -} - -#endif // DVECT_H diff --git a/example/ivect.cpp b/example/ivect.cpp deleted file mode 100644 index f8ca8707..00000000 --- a/example/ivect.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include "ivect.h" -#include "dvect.h" -#include -#include -namespace python = boost::python; - -namespace { - - vects::dvect ivect_as_dvect(const vects::ivect& iv) - { - vects::dvect dv(iv.size()); - vects::dvect::iterator dviter = dv.begin(); - for (int i = 0; i < iv.size(); i++) dviter[i] = static_cast(iv[i]); - return dv; - } - - boost::python::tuple dvect_as_tuple(const vects::dvect& dv) - { - return dv.as_tuple(); - } - - std::auto_ptr auto_ptr_dvect(const vects::ivect& iv) - { - return std::auto_ptr(new vects::dvect(ivect_as_dvect(iv))); - } - - boost::shared_ptr shared_ptr_dvect(const vects::ivect& iv) - { - return boost::shared_ptr(new vects::dvect(ivect_as_dvect(iv))); - } - - boost::python::tuple auto_ptr_dvect_as_tuple(std::auto_ptr& dv) - { - return dv->as_tuple(); - } - - boost::python::tuple shared_ptr_dvect_as_tuple(boost::shared_ptr& dv) - { - return dv->as_tuple(); - } -} - -extern "C" -DL_EXPORT(void) -initivect() -{ - try - { - python::module_builder this_module("ivect"); - - python::x_class_builder ivect_class(this_module, "ivect"); - - python::import_class_builder dvect_class("dvect", "dvect"); - - ivect_class.def(python::constructor()); - ivect_class.def(&vects::ivect::as_tuple, "as_tuple"); - ivect_class.def(ivect_as_dvect, "as_dvect"); - - this_module.def(dvect_as_tuple, "dvect_as_tuple"); - ivect_class.def(auto_ptr_dvect, "auto_ptr_dvect"); - ivect_class.def(shared_ptr_dvect, "shared_ptr_dvect"); - this_module.def(auto_ptr_dvect_as_tuple, "auto_ptr_dvect_as_tuple"); - this_module.def(shared_ptr_dvect_as_tuple, "shared_ptr_dvect_as_tuple"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/ivect.h b/example/ivect.h deleted file mode 100644 index a0187307..00000000 --- a/example/ivect.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef IVECT_H -#define IVECT_H - -#include -#include - -namespace vects { - - struct ivect : public std::vector - { - ivect() : std::vector() {} - ivect(size_t n) : std::vector(n) {} - ivect(boost::python::tuple tuple) : std::vector(tuple.size()) - { - std::vector::iterator v_it = begin(); - for (int i = 0; i < tuple.size(); i++) - v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), - boost::python::type()); - } - - boost::python::tuple as_tuple() const - { - boost::python::tuple t(size()); - for (int i = 0; i < size(); i++) - t.set_item(i, - boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i]))); - return t; - } - }; -} - -#endif // IVECT_H diff --git a/example/noncopyable_export.cpp b/example/noncopyable_export.cpp deleted file mode 100644 index 82c3f049..00000000 --- a/example/noncopyable_export.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -namespace python = boost::python; - -#include "store.h" - -extern "C" -DL_EXPORT(void) -initnoncopyable_export() -{ - try - { - python::module_builder this_module("noncopyable_export"); - - python::xptr_class_builder store_class(this_module, "store"); - - store_class.def(python::constructor()); - store_class.def(&store::recall, "recall"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/noncopyable_import.cpp b/example/noncopyable_import.cpp deleted file mode 100644 index 529c9f42..00000000 --- a/example/noncopyable_import.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include -namespace python = boost::python; - -#include "store.h" - -namespace { // Avoid cluttering the global namespace. - - // A function with store objects as both input and output parameters. - // Because the copy constructor is disabled, we cannot pass a store - // object by value. Instead, we pass a smart pointer. - std::auto_ptr add_stores(const store& s1, const store& s2) - { - int sum = s1.recall() + s2.recall(); - std::auto_ptr ss = std::auto_ptr(new store(sum)); - return ss; - } -} - -extern "C" -DL_EXPORT(void) -initnoncopyable_import() -{ - try - { - python::module_builder this_module("noncopyable_import"); - - python::import_class_builder - dvect_class("noncopyable_export", "store"); - - // Imagine all the additional classes with member functions - // that have store objects as input and output parameters. - // Lots and lots of them. - // However, to keep this example simple, we only define a - // module-level function. - this_module.def(add_stores, "add_stores"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/store.h b/example/store.h deleted file mode 100644 index 74ef0477..00000000 --- a/example/store.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef STORE_H -#define STORE_H - -class store -{ - private: - store(const store&) { } // Disable the copy constructor. - int number; - public: - store(const int i) : number(i) { } - int recall() const { return number; } -}; - -#endif // STORE_H diff --git a/example/tst_dvect.py b/example/tst_dvect.py deleted file mode 100644 index 563f0ad5..00000000 --- a/example/tst_dvect.py +++ /dev/null @@ -1,16 +0,0 @@ -import dvect -print dvect.dvect.__converters__ -dv = dvect.dvect((1,2,3,4,5)) -print dv -print dv.as_tuple() -iv = dv.as_ivect() -print iv -print iv.as_tuple() -print dvect.ivect_as_tuple(iv) -aiv = dv.auto_ptr_ivect() -print aiv -siv = dv.shared_ptr_ivect() -print dvect.auto_ptr_ivect_as_tuple(aiv) -print dvect.ivect_as_tuple(aiv) -print dvect.shared_ptr_ivect_as_tuple(siv) -print dvect.ivect_as_tuple(siv) diff --git a/example/tst_ivect.py b/example/tst_ivect.py deleted file mode 100644 index 58bc323f..00000000 --- a/example/tst_ivect.py +++ /dev/null @@ -1,16 +0,0 @@ -import ivect -print ivect.ivect.__converters__ -iv = ivect.ivect((1,2,3,4,5)) -print iv -print iv.as_tuple() -dv = iv.as_dvect() -print dv -print dv.as_tuple() -print ivect.dvect_as_tuple(dv) -adv = iv.auto_ptr_dvect() -print adv -sdv = iv.shared_ptr_dvect() -print ivect.auto_ptr_dvect_as_tuple(adv) -print ivect.dvect_as_tuple(adv) -print ivect.shared_ptr_dvect_as_tuple(sdv) -print ivect.dvect_as_tuple(sdv) diff --git a/example/tst_noncopyable.py b/example/tst_noncopyable.py deleted file mode 100644 index 913df039..00000000 --- a/example/tst_noncopyable.py +++ /dev/null @@ -1,8 +0,0 @@ -import noncopyable_export -import noncopyable_import -s1 = noncopyable_export.store(1) -print s1.recall() -s2 = noncopyable_export.store(2) -print s2.recall() -s3 = noncopyable_import.add_stores(s1, s2) -print s3.recall() From f3d9193743d8635a46b53c7d36a3c77d8c61c83c Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 8 Feb 2001 01:54:59 +0000 Subject: [PATCH 005/369] Fix for linux gcc-2.95.2 [SVN r9023] --- example/getting_started5.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/example/getting_started5.cpp b/example/getting_started5.cpp index bbe4725a..4b64e4b8 100644 --- a/example/getting_started5.cpp +++ b/example/getting_started5.cpp @@ -70,7 +70,8 @@ BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // MillerIndex from_python(PyObject* p, python::type) { - python::tuple tup = python::tuple(python::ref(p, ref::increment_count)); + python::tuple tup + = python::tuple(python::ref(p, python::ref::increment_count)); if (tup.size() != 3) { PyErr_SetString(PyExc_ValueError, "expecting exactly 3 values in tuple."); From b000c759477dc3cdaaa6ced47accf92e890fc7f3 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 23 Feb 2001 08:58:32 +0000 Subject: [PATCH 006/369] Fix for python::tuple.set_item() memory leak. [SVN r9316] --- example/getting_started5.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/getting_started5.cpp b/example/getting_started5.cpp index 4b64e4b8..c9f1ce36 100644 --- a/example/getting_started5.cpp +++ b/example/getting_started5.cpp @@ -97,7 +97,7 @@ BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE { python::tuple result(3); for (int i = 0; i < 3; i++) - result.set_item(i, to_python(hkl.v[i])); + result.set_item(i, python::ref(to_python(hkl.v[i]))); return result.reference().release(); } From 977841a7f383115244b27fdf58a4af6429852ff8 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 2 Mar 2001 01:48:30 +0000 Subject: [PATCH 007/369] Use PyObject_INIT() instead of hand-initializing objects [SVN r9375] --- include/boost/python/detail/base_object.hpp | 6 ++-- include/boost/python/detail/wrap_python.hpp | 7 +++++ src/extension_class.cpp | 7 +++-- src/functions.cpp | 31 ++++++++++++--------- 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/include/boost/python/detail/base_object.hpp b/include/boost/python/detail/base_object.hpp index f8ed665b..bf0faa7b 100644 --- a/include/boost/python/detail/base_object.hpp +++ b/include/boost/python/detail/base_object.hpp @@ -5,6 +5,9 @@ // // 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_ @@ -46,9 +49,8 @@ base_object::base_object(PyTypeObject* type_obj) std:: #endif memset(bp, 0, sizeof(base_python_type)); - ob_refcnt = 1; - ob_type = type_obj; Py_INCREF(type_obj); + PyObject_INIT(bp, type_obj); } template diff --git a/include/boost/python/detail/wrap_python.hpp b/include/boost/python/detail/wrap_python.hpp index eb831b68..9e57c287 100644 --- a/include/boost/python/detail/wrap_python.hpp +++ b/include/boost/python/detail/wrap_python.hpp @@ -15,6 +15,9 @@ // To use the Python debugging library, #define BOOST_DEBUG_PYTHON on the // compiler command-line. +// Revision History: +// 01 Mar 01 define PyObject_INIT() for Python 1.x + #ifdef _DEBUG # ifndef BOOST_DEBUG_PYTHON # undef _DEBUG // Don't let Python force the debug library just because we're debugging. @@ -76,3 +79,7 @@ typedef int pid_t; # 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 diff --git a/src/extension_class.cpp b/src/extension_class.cpp index c15e538b..47862ec7 100644 --- a/src/extension_class.cpp +++ b/src/extension_class.cpp @@ -5,6 +5,9 @@ // // 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) #include #include @@ -446,8 +449,8 @@ operator_dispatcher::operator_dispatcher(const ref& o, const ref& s) : m_object(o), m_self(s), m_free_list_link(0) { - ob_refcnt = 1; - ob_type = &type_obj; + PyObject* self = this; + PyObject_INIT(self, &type_obj); } operator_dispatcher* diff --git a/src/functions.cpp b/src/functions.cpp index e166c91c..71b59136 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -5,6 +5,9 @@ // // 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) #include #include @@ -97,19 +100,6 @@ PyObject* function::call(PyObject* args, PyObject* keywords) const return 0; } -bound_function* bound_function::create(const ref& target, const ref& fn) -{ - bound_function* const result = free_list; - if (result == 0) - return new bound_function(target, fn); - - free_list = result->m_free_list_link; - result->m_target = target; - result->m_unbound_function = fn; - Py_INCREF(result); - return result; -} - // The instance class whose obj represents the type of bound_function // objects in Python. bound_functions must be GetAttrable so the __doc__ // attribute of built-in Python functions can be accessed when bound. @@ -123,6 +113,21 @@ private: // type_object hook override void dealloc(bound_function*) const; }; +bound_function* bound_function::create(const ref& target, const ref& fn) +{ + bound_function* const result = free_list; + if (result == 0) + return new bound_function(target, fn); + + free_list = result->m_free_list_link; + result->m_target = target; + result->m_unbound_function = fn; + + PyObject* self = result; + PyObject_INIT(self, type_object::instance()); + return result; +} + bound_function::bound_function(const ref& target, const ref& fn) : python_object(type_object::instance()), m_target(target), From f5fa4a460a27afdfb53b5054c6a9550c009b1817 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 3 Mar 2001 10:22:35 +0000 Subject: [PATCH 008/369] Wrong file name replaced (instance.hpp -> singleton.hpp). [SVN r9390] --- src/gen_all.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gen_all.py b/src/gen_all.py index 416c66f1..3877d181 100644 --- a/src/gen_all.py +++ b/src/gen_all.py @@ -10,7 +10,7 @@ def gen_all(args): open('caller.hpp', 'w').write(gen_caller(args)) open('init_function.hpp', 'w').write(gen_init_function(args)) open('signatures.hpp', 'w').write(gen_signatures(args)) - open('instance.hpp', 'w').write(gen_singleton(args)) + open('singleton.hpp', 'w').write(gen_singleton(args)) open('extension_class.hpp', 'w').write(gen_extclass(args)) if __name__ == '__main__': From 51d60a603590d559647283bbf3d9c33ebf866002 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 3 Mar 2001 11:48:52 +0000 Subject: [PATCH 009/369] added: converters for [plain] char and std::complex [SVN r9397] --- include/boost/python/conversions.hpp | 39 ++++++++++++++++++++++++++++ src/conversions.cpp | 21 +++++++++++++++ test/comprehensive.cpp | 34 ++++++++++++++++++++++++ test/comprehensive.py | 33 +++++++++++++++++++++++ 4 files changed, 127 insertions(+) diff --git a/include/boost/python/conversions.hpp b/include/boost/python/conversions.hpp index d11f7f14..b633c0ee 100644 --- a/include/boost/python/conversions.hpp +++ b/include/boost/python/conversions.hpp @@ -5,6 +5,9 @@ // // The author gratefully acknowleges the support of Dragon Systems, Inc., in // producing this work. +// +// Revision History: +// Mar 03 01 added: converters for [plain] char and std::complex (Ralf W. Grosse-Kunstleve) #ifndef METHOD_DWA122899_H_ # define METHOD_DWA122899_H_ @@ -16,6 +19,7 @@ # include # include # include +# include BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround @@ -100,6 +104,10 @@ PyObject* to_python(unsigned short); unsigned short from_python(PyObject*, boost::python::type); unsigned short from_python(PyObject*, boost::python::type); +PyObject* to_python(char); +char from_python(PyObject*, boost::python::type); +char from_python(PyObject*, boost::python::type); + PyObject* to_python(signed char); signed char from_python(PyObject*, boost::python::type); signed char from_python(PyObject*, boost::python::type); @@ -130,6 +138,32 @@ PyObject* to_python(const std::string& s); std::string from_python(PyObject*, boost::python::type); std::string from_python(PyObject*, boost::python::type); +template +PyObject* to_python(const std::complex& sc) { + Py_complex pcc; + pcc.real = sc.real(); + pcc.imag = sc.imag(); + return PyComplex_FromCComplex(pcc); +} + +template +std::complex from_python(PyObject* p, + boost::python::type&>) { + if (! PyComplex_Check(p)) { + PyErr_SetString(PyExc_TypeError, "expected a complex number"); + throw boost::python::argument_error(); + } + return std::complex( + static_cast(PyComplex_RealAsDouble(p)), + static_cast(PyComplex_ImagAsDouble(p))); +} + +template +inline std::complex from_python(PyObject* p, + boost::python::type >) { + return from_python(p, boost::python::type&>()); +} + // For when your C++ function really wants to pass/return a PyObject* PyObject* to_python(PyObject*); PyObject* from_python(PyObject*, boost::python::type); @@ -304,6 +338,11 @@ inline unsigned short from_python(PyObject* p, boost::python::type()); } +inline char from_python(PyObject* p, boost::python::type) +{ + return from_python(p, boost::python::type()); +} + inline signed char from_python(PyObject* p, boost::python::type) { return from_python(p, boost::python::type()); diff --git a/src/conversions.cpp b/src/conversions.cpp index ded01e0e..369f197a 100644 --- a/src/conversions.cpp +++ b/src/conversions.cpp @@ -5,6 +5,9 @@ // // The author gratefully acknowleges the support of Dragon Systems, Inc., in // producing this work. +// +// Revision History: +// Mar 03 01 added: converters for [plain] char (Ralf W. Grosse-Kunstleve) #include #include @@ -160,6 +163,24 @@ unsigned short from_python(PyObject* p, boost::python::type type return integer_from_python(p, type); } +PyObject* to_python(char c) +{ + if (c == '\0') return PyString_FromString(""); + return PyString_FromStringAndSize(&c, 1); +} + +char from_python(PyObject* p, boost::python::type) +{ + int l = -1; + if (PyString_Check(p)) l = PyString_Size(p); + if (l < 0 || l > 1) { + PyErr_SetString(PyExc_TypeError, "expected string of length 0 or 1"); + throw boost::python::argument_error(); + } + if (l == 0) return '\0'; + return PyString_AsString(p)[0]; +} + PyObject* to_python(unsigned char i) { return integer_to_python(i); diff --git a/test/comprehensive.cpp b/test/comprehensive.cpp index 7fad74bb..592b0ebd 100644 --- a/test/comprehensive.cpp +++ b/test/comprehensive.cpp @@ -815,6 +815,25 @@ namespace bpl_test { w.set_secret_number(number); } + // Test plain char converters. + char get_plain_char() { return 'x'; } + std::string use_plain_char(char c) { return std::string(3, c); } + std::string use_const_plain_char(const char c) { return std::string(5, c); } + + // Test std::complex converters. + std::complex dpolar(double rho, double theta) { + return std::polar(rho, theta); + } + double dreal(const std::complex& c) { return c.real(); } + double dimag(std::complex c) { return c.imag(); } + + // Test std::complex converters. + std::complex fpolar(float rho, float theta) { + return std::polar(rho, theta); + } + double freal(const std::complex& c) { return c.real(); } + double fimag(std::complex c) { return c.imag(); } + /************************************************************/ /* */ /* init the module */ @@ -1036,6 +1055,21 @@ void init_module(boost::python::module_builder& m) world_class.def(world_getinitargs, "__getinitargs__"); world_class.def(world_getstate, "__getstate__"); world_class.def(world_setstate, "__setstate__"); + + // Test plain char converters. + m.def(get_plain_char, "get_plain_char"); + m.def(use_plain_char, "use_plain_char"); + m.def(use_const_plain_char, "use_const_plain_char"); + + // Test std::complex converters. + m.def(dpolar, "dpolar"); + m.def(dreal, "dreal"); + m.def(dimag, "dimag"); + + // Test std::complex converters. + m.def(fpolar, "fpolar"); + m.def(freal, "freal"); + m.def(fimag, "fimag"); } PyObject* raw(const boost::python::tuple& args, const boost::python::dictionary& keywords) diff --git a/test/comprehensive.py b/test/comprehensive.py index a8e181d2..8bc8021c 100644 --- a/test/comprehensive.py +++ b/test/comprehensive.py @@ -1070,6 +1070,39 @@ test methodologies for wrapping functions that return a pointer 3 >>> eo.second 1 + +======== test [plain] char converters ============== + >>> get_plain_char() + 'x' + >>> use_plain_char('a') + 'aaa' + >>> use_const_plain_char('b') + 'bbbbb' + +======== test std::complex converters ============== + >>> c = dpolar(3, 5) + >>> type(c) + + >>> '%.3g' % (dreal(c)) + '0.851' + >>> '%.3g' % (dimag(c)) + '-2.88' + >>> '%.3g' % (freal(c)) + '0.851' + >>> '%.3g' % (fimag(c)) + '-2.88' + >>> c = fpolar(7, 13) + >>> type(c) + + >>> '%.3g' % (fimag(c)) + '2.94' + >>> '%.3g' % (freal(c)) + '6.35' + >>> '%.3g' % (dimag(c)) + '2.94' + >>> '%.3g' % (dreal(c)) + '6.35' + ''' from test import * From 1d4427c056ef90b36aaaecc9babc86a778b82e95 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 3 Mar 2001 12:05:15 +0000 Subject: [PATCH 010/369] "T" replaced by "Held" to reduce chances of name clashes. [SVN r9398] --- .../boost/python/detail/extension_class.hpp | 30 +++++++++---------- src/gen_extclass.py | 10 +++---- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/include/boost/python/detail/extension_class.hpp b/include/boost/python/detail/extension_class.hpp index 94d9bf6b..bf43ec5c 100644 --- a/include/boost/python/detail/extension_class.hpp +++ b/include/boost/python/detail/extension_class.hpp @@ -61,7 +61,7 @@ T* check_non_null(T* p) return p; } -template class held_instance; +template class held_instance; typedef void* (*conversion_function_ptr)(void*); @@ -613,33 +613,33 @@ class extension_class // A simple wrapper over a T which allows us to use extension_class with a // single template parameter only. See extension_class, above. -template -class held_instance : public T +template +class held_instance : public Held { // There are no member functions: we want to avoid inadvertently overriding - // any virtual functions in T. + // any virtual functions in Held. public: - held_instance(PyObject*) : T() {} + held_instance(PyObject*) : Held() {} template - held_instance(PyObject*, A1 a1) : T(a1) {} + held_instance(PyObject*, A1 a1) : Held(a1) {} template - held_instance(PyObject*, A1 a1, A2 a2) : T(a1, a2) {} + held_instance(PyObject*, A1 a1, A2 a2) : Held(a1, a2) {} template - held_instance(PyObject*, A1 a1, A2 a2, A3 a3) : T(a1, a2, a3) {} + held_instance(PyObject*, A1 a1, A2 a2, A3 a3) : Held(a1, a2, a3) {} template - held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) : T(a1, a2, a3, a4) {} + held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) : Held(a1, a2, a3, a4) {} template - held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : T(a1, a2, a3, a4, a5) {} + held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : Held(a1, a2, a3, a4, a5) {} template - held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) : T(a1, a2, a3, a4, a5, a6) {} + held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) : Held(a1, a2, a3, a4, a5, a6) {} template - held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) : T(a1, a2, a3, a4, a5, a6, a7) {} + 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 - held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) : T(a1, a2, a3, a4, a5, a6, a7, a8) {} + 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 - held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) : T(a1, a2, a3, a4, a5, a6, a7, a8, a9) {} + 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 - held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) : T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {} + 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 diff --git a/src/gen_extclass.py b/src/gen_extclass.py index f8906970..7c378d45 100644 --- a/src/gen_extclass.py +++ b/src/gen_extclass.py @@ -66,7 +66,7 @@ T* check_non_null(T* p) return p; } -template class held_instance; +template class held_instance; typedef void* (*conversion_function_ptr)(void*); @@ -613,15 +613,15 @@ class extension_class // A simple wrapper over a T which allows us to use extension_class with a // single template parameter only. See extension_class, above. -template -class held_instance : public T +template +class held_instance : public Held { // There are no member functions: we want to avoid inadvertently overriding - // any virtual functions in T. + // any virtual functions in Held. public:""" + gen_functions("""%{ template <%(class A%n%:, %)>%} - held_instance(PyObject*%(, A%n% a%n%)) : T(%(a%n%:, %)) {}""", args) + held_instance(PyObject*%(, A%n% a%n%)) : Held(%(a%n%:, %)) {}""", args) + """ }; From b06d9e50ebf64969d198ab03430d21eb40cb8442 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 3 Mar 2001 12:55:53 +0000 Subject: [PATCH 011/369] added: pickle safety measures; bug fix: use bound_function::create() [SVN r9399] --- include/boost/python/class_builder.hpp | 10 ++++++ src/classes.cpp | 46 ++++++++++++++++++++------ test/comprehensive.py | 41 +++++++++++++++++++++++ 3 files changed, 87 insertions(+), 10 deletions(-) diff --git a/include/boost/python/class_builder.hpp b/include/boost/python/class_builder.hpp index 7ef843c4..4a9ec1b2 100644 --- a/include/boost/python/class_builder.hpp +++ b/include/boost/python/class_builder.hpp @@ -1,3 +1,6 @@ +// Revision History: +// Mar 03 01 added: pickle safety measures (Ralf W. Grosse-Kunstleve) + #ifndef CLASS_WRAPPER_DWA101000_H_ # define CLASS_WRAPPER_DWA101000_H_ @@ -24,6 +27,13 @@ class class_builder ~class_builder() {} + + inline void dict_defines_state() { + add(ref(BOOST_PYTHON_CONVERSION::to_python(1)), "__dict_defines_state__"); + } + inline void getstate_manages_dict() { + add(ref(BOOST_PYTHON_CONVERSION::to_python(1)), "__getstate_manages_dict__"); + } // define constructors template diff --git a/src/classes.cpp b/src/classes.cpp index 2901aa81..625d67b7 100644 --- a/src/classes.cpp +++ b/src/classes.cpp @@ -5,6 +5,10 @@ // // The author gratefully acknowleges the support of Dragon Systems, Inc., in // producing this work. +// +// Revision History: +// Mar 03 01 added: pickle safety measures (Ralf W. Grosse-Kunstleve) +// Mar 03 01 bug fix: use bound_function::create() (instead of new bound_function) #include #include @@ -67,8 +71,7 @@ namespace { ref global_class_reduce() { - static ref result(detail::new_wrapped_function(class_reduce)); - return result; + return ref(detail::new_wrapped_function(class_reduce)); } @@ -93,17 +96,41 @@ namespace { ref getstate(PyObject_GetAttrString(obj, const_cast("__getstate__")), ref::null_ok); PyErr_Clear(); + + ref dict(PyObject_GetAttrString(obj, const_cast("__dict__")), ref::null_ok); + PyErr_Clear(); + if (getstate.get() != 0) { + if (dict.get() != 0 && dictionary(dict).size() > 0) + { + ref getstate_manages_dict(PyObject_GetAttrString(instance_class.get(), const_cast("__getstate_manages_dict__")), ref::null_ok); + PyErr_Clear(); + if (getstate_manages_dict.get() == 0) + { + PyErr_SetString(PyExc_RuntimeError, "Incomplete pickle support (__getstate_manages_dict__ not set)"); + throw error_already_set(); + } + } + ref state = ref(PyEval_CallObject(getstate.get(), NULL)); return tuple(instance_class, initargs, state); } - ref state(PyObject_GetAttrString(obj, const_cast("__dict__")), ref::null_ok); - PyErr_Clear(); - if (state.get() != 0 && dictionary(state).size() > 0) + if (getinitargs.get() == 0) { - return tuple(instance_class, initargs, state); + ref dict_defines_state(PyObject_GetAttrString(instance_class.get(), const_cast("__dict_defines_state__")), ref::null_ok); + PyErr_Clear(); + if (dict_defines_state.get() == 0) + { + PyErr_SetString(PyExc_RuntimeError, "Incomplete pickle support (__dict_defines_state__ not set)"); + throw error_already_set(); + } + } + + if (dict.get() != 0 && dictionary(dict).size() > 0) + { + return tuple(instance_class, initargs, dict); } return tuple(instance_class, initargs); @@ -111,8 +138,7 @@ namespace { ref global_instance_reduce() { - static ref result(detail::new_wrapped_function(instance_reduce)); - return result; + return ref(detail::new_wrapped_function(instance_reduce)); } } @@ -177,7 +203,7 @@ namespace detail { if (!BOOST_CSTD_::strcmp(name, "__reduce__")) { ref target(as_object(this), ref::increment_count); - return new bound_function(target, global_class_reduce()); + return bound_function::create(target, global_class_reduce()); } ref local_attribute = m_name_space.get_item(string(name).reference()); @@ -348,7 +374,7 @@ PyObject* instance::getattr(const char* name, bool use_special_function) if (!BOOST_CSTD_::strcmp(name, "__reduce__")) { - return new detail::bound_function(ref(this, ref::increment_count), global_instance_reduce()); + return detail::bound_function::create(ref(this, ref::increment_count), global_instance_reduce()); } ref local_attribute = m_name_space.get_item(string(name).reference()); diff --git a/test/comprehensive.py b/test/comprehensive.py index 8bc8021c..3c7f3c61 100644 --- a/test/comprehensive.py +++ b/test/comprehensive.py @@ -239,6 +239,47 @@ Pickling tests: Hello from California! 42 Hello from California! 0 +Pickle safety measures: + >>> r=Rational(3, 4) + >>> r + Rational(3, 4) + >>> try: s=pickle.dumps(r) + ... except RuntimeError, err: print err[0] + ... + Incomplete pickle support (__dict_defines_state__ not set) + >>> class myrational(Rational): + ... __dict_defines_state__ = 1 # this is a lie but good enough for testing. + ... + >>> r=myrational(3, 4) + >>> r + Rational(3, 4) + >>> s=pickle.dumps(r) + + >>> class myworld(world): + ... def __init__(self): + ... world.__init__(self, 'anywhere') + ... self.x = 1 + ... + >>> w = myworld() + >>> w.greet() + 'Hello from anywhere!' + >>> w.__dict__ + {'x': 1} + >>> try: s=pickle.dumps(w) + ... except RuntimeError, err: print err[0] + ... + Incomplete pickle support (__getstate_manages_dict__ not set) + + >>> class myunsafeworld(myworld): + ... __getstate_manages_dict__ = 1 # this is a lie but good enough for testing. + ... + >>> w = myunsafeworld() + >>> w.greet() + 'Hello from anywhere!' + >>> w.__dict__ + {'x': 1} + >>> s=pickle.dumps(w) + Special member attributes. Tests courtesy of Barry Scott >>> class DerivedFromFoo(Foo): From fc62d3b44ec404cb470746c3c681764b846b88a8 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 3 Mar 2001 14:46:26 +0000 Subject: [PATCH 012/369] New Makefiles for tru64_cxx, linux_gcc, mingw32. [SVN r9400] --- build/Makefile.linux_gcc | 166 +++++++++++++++++++++++++++++++ build/Makefile.mingw32 | 210 +++++++++++++++++++++++++++++++++++++++ build/Makefile.tru64_cxx | 170 +++++++++++++++++++++++++++++++ build/tru64.mak | 51 ---------- 4 files changed, 546 insertions(+), 51 deletions(-) create mode 100644 build/Makefile.linux_gcc create mode 100644 build/Makefile.mingw32 create mode 100644 build/Makefile.tru64_cxx delete mode 100644 build/tru64.mak diff --git a/build/Makefile.linux_gcc b/build/Makefile.linux_gcc new file mode 100644 index 00000000..3e8f1041 --- /dev/null +++ b/build/Makefile.linux_gcc @@ -0,0 +1,166 @@ +# Usage: +# +# Create a new empty directory anywhere (preferably not in the boost tree). +# Copy this Makefile to that new directory and rename it to "Makefile" +# Set the BOOST pathname below. +# +# make softlinks Create softlinks to source code and tests +# make Compile all sources +# make test Run doctest tests +# make clean Remove all object files +# make unlink Remove softlinks + +BOOST= /net/cci/rwgk/boost + +PYEXE= /usr/local/Python-1.5.2/bin/python +PYINC= -I/usr/local/Python-1.5.2/include/python1.5 +#PYEXE= /usr/local/Python-2.0/bin/python +#PYINC= -I/usr/local/Python-2.0/include/python2.0 +#STLPORTINC= -I/usr/local/STLport-4.1b3/stlport +#STLPORTOPTS= \ +# -D__USE_STD_IOSTREAM \ +# -D__STL_NO_SGI_IOSTREAMS \ +# -D__STL_USE_NATIVE_STRING \ +# -D__STL_NO_NEW_C_HEADERS \ +# -D_RWSTD_COMPILE_INSTANTIATE=1 +#STLPORTINC= -I/usr/local/STLport-4.1b4/stlport +#STLPORTOPTS= -D__NO_USE_STD_IOSTREAM -D__STL_NO_SGI_IOSTREAMS +#STLPORTINC= -I/net/cci/xp/C++_C_headers + +STDOPTS= -ftemplate-depth-21 +WARNOPTS= +# use -msg_display_number to obtain integer tags for -msg_disable + +CPP= g++ +CPPOPTS= $(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \ + $(STDOPTS) $(WARNOPTS) -g +MAKEDEP= -M + +LD= g++ +LDOPTS= -shared + +#HIDDEN= -hidden + +BPL_SRC = $(BOOST)/libs/python/src +BPL_TST = $(BOOST)/libs/python/test +BPL_EXA = $(BOOST)/libs/python/example +SOFTLINKS = \ +$(BPL_SRC)/classes.cpp \ +$(BPL_SRC)/conversions.cpp \ +$(BPL_SRC)/extension_class.cpp \ +$(BPL_SRC)/functions.cpp \ +$(BPL_SRC)/init_function.cpp \ +$(BPL_SRC)/module_builder.cpp \ +$(BPL_SRC)/objects.cpp \ +$(BPL_SRC)/types.cpp \ +$(BPL_TST)/comprehensive.cpp \ +$(BPL_TST)/comprehensive.hpp \ +$(BPL_TST)/comprehensive.py \ +$(BPL_TST)/doctest.py \ +$(BPL_EXA)/abstract.cpp \ +$(BPL_EXA)/getting_started1.cpp \ +$(BPL_EXA)/getting_started2.cpp \ +$(BPL_EXA)/getting_started3.cpp \ +$(BPL_EXA)/getting_started4.cpp \ +$(BPL_EXA)/getting_started5.cpp \ +$(BPL_EXA)/test_abstract.py \ +$(BPL_EXA)/test_getting_started1.py \ +$(BPL_EXA)/test_getting_started2.py \ +$(BPL_EXA)/test_getting_started3.py \ +$(BPL_EXA)/test_getting_started4.py \ +$(BPL_EXA)/test_getting_started5.py + +OBJ = classes.o conversions.o extension_class.o functions.o \ + init_function.o module_builder.o \ + objects.o types.o +DEPOBJ= $(OBJ) comprehensive.o abstract.o \ + getting_started1.o getting_started2.o getting_started3.o \ + getting_started4.o getting_started5.o + +.SUFFIXES: .o .cpp + +all: libbpl.a test.so abstract.so \ + getting_started1.so getting_started2.so getting_started3.so \ + getting_started4.so getting_started5.so + +softlinks: + @ for pn in $(SOFTLINKS); \ + do \ + bn=`basename "$$pn"`; \ + if [ ! -e "$$bn" ]; then \ + echo "ln -s $$pn ."; \ + ln -s "$$pn" .; \ + else \ + echo "info: no softlink created (file exists): $$bn"; \ + fi; \ + done + +unlink: + @ for pn in $(SOFTLINKS); \ + do \ + bn=`basename "$$pn"`; \ + if [ -L "$$bn" ]; then \ + echo "rm $$bn"; \ + rm "$$bn"; \ + elif [ -e "$$bn" ]; then \ + echo "info: not a softlink: $$bn"; \ + fi; \ + done + +libbpl.a: $(OBJ) + rm -f libbpl.a + ar r libbpl.a $(OBJ) + +test.so: $(OBJ) comprehensive.o + $(LD) $(LDOPTS) $(OBJ) comprehensive.o -o test.so -lm + +abstract.so: $(OBJ) abstract.o + $(LD) $(LDOPTS) $(OBJ) abstract.o -o abstract.so + +getting_started1.so: $(OBJ) getting_started1.o + $(LD) $(LDOPTS) $(OBJ) getting_started1.o -o getting_started1.so + +getting_started2.so: $(OBJ) getting_started2.o + $(LD) $(LDOPTS) $(OBJ) getting_started2.o -o getting_started2.so + +getting_started3.so: $(OBJ) getting_started3.o + $(LD) $(LDOPTS) $(OBJ) getting_started3.o -o getting_started3.so + +getting_started4.so: $(OBJ) getting_started4.o + $(LD) $(LDOPTS) $(OBJ) getting_started4.o -o getting_started4.so + +getting_started5.so: $(OBJ) getting_started5.o + $(LD) $(LDOPTS) $(OBJ) getting_started5.o -o getting_started5.so + +.cpp.o: + $(CPP) $(CPPOPTS) -c $*.cpp + +test: + $(PYEXE) comprehensive.py + $(PYEXE) test_abstract.py + $(PYEXE) test_getting_started1.py + $(PYEXE) test_getting_started2.py + $(PYEXE) test_getting_started3.py + $(PYEXE) test_getting_started4.py + $(PYEXE) test_getting_started5.py + +clean: + rm -f $(OBJ) libbpl.a libbpl.a.input + rm -f comprehensive.o test.so + rm -f abstract.o abstract.so + rm -f getting_started1.o getting_started1.so + rm -f getting_started2.o getting_started2.so + rm -f getting_started3.o getting_started3.so + rm -f getting_started4.o getting_started4.so + rm -f getting_started5.o getting_started5.so + rm -f so_locations *.pyc + rm -rf cxx_repository + +depend: + @ cat Makefile.nodepend; \ + for obj in $(DEPOBJ); \ + do \ + bn=`echo "$$obj" | cut -d. -f1`; \ + $(CPP) $(CPPOPTS) $(MAKEDEP) "$$bn".cpp; \ + done + diff --git a/build/Makefile.mingw32 b/build/Makefile.mingw32 new file mode 100644 index 00000000..2d86efcd --- /dev/null +++ b/build/Makefile.mingw32 @@ -0,0 +1,210 @@ +# Usage: +# +# Create a new empty directory anywhere (preferably not in the boost tree). +# Copy this Makefile to that new directory and rename it to "Makefile" +# Set the BOOST_* pathnames below. +# +# The idea is that the build directory is on a Unix filesystem that +# is mounted on a PC using SAMBA. Use this makefile under both Unix +# and Windows: +# +# Unix: make softlinks Create softlinks to source code and tests +# Win: make Compile all sources +# Win: make test Run doctest tests +# Unix: make clean Remove all object files +# Unix: make unlink Remove softlinks + +# To install mingw32, follow instructions at: +# http://starship.python.net/crew/kernr/mingw32/Notes.html +# In particular, install: +# ftp://ftp.xraylith.wisc.edu/pub/khan/gnu-win32/mingw32/gcc-2.95.2/gcc-2.95.2-msvcrt.exe +# ftp://ftp.xraylith.wisc.edu/pub/khan/gnu-win32/mingw32/gcc-2.95.2/fixes/quote-fix-msvcrt.exe +# http://starship.python.net/crew/kernr/mingw32/Python-1.5.2-mingw32.zip +# Unpack the first two archives in the default locations and update your PATH. +# Unpack the third archive in \usr. + +# Note: comprehensive.cpp generates compiler errors and later crashes. +# L:\boost\boost\python\detail\extension_class.hpp:643: warning: +# alignment of `vtable for class +# boost::python::detail::held_instance' +# is greater than maximum object file alignment. Using 16. +# Could this be fixed with compiler options? +# -fhuge-objects looks interesting, but requires recompiling the C++ library. +# (what exactly does that mean?) +# -fvtable-thunks eliminates the compiler warning, but "import test" still +# causes a crash. + +BOOST_UNIX= /net/cci/rwgk/boost +BOOST_WIN= "L:\boost" + +PYEXE= "C:\Program files\Python\python.exe" +PYINC= -I"C:\usr\include\python1.5" +PYLIB= "C:\usr\lib\libpython15.a" + +STDOPTS= -ftemplate-depth-21 +WARNOPTS= + +CPP= g++ +CPPOPTS= $(STLPORTINC) $(STLPORTOPTS) -I$(BOOST_WIN) $(PYINC) \ + $(STDOPTS) $(WARNOPTS) -g + +LD= g++ +LDOPTS= -shared + +BPL_SRC = $(BOOST_UNIX)/libs/python/src +BPL_TST = $(BOOST_UNIX)/libs/python/test +BPL_EXA = $(BOOST_UNIX)/libs/python/example +SOFTLINKS = \ +$(BPL_SRC)/classes.cpp \ +$(BPL_SRC)/conversions.cpp \ +$(BPL_SRC)/extension_class.cpp \ +$(BPL_SRC)/functions.cpp \ +$(BPL_SRC)/init_function.cpp \ +$(BPL_SRC)/module_builder.cpp \ +$(BPL_SRC)/objects.cpp \ +$(BPL_SRC)/types.cpp \ +$(BPL_TST)/comprehensive.cpp \ +$(BPL_TST)/comprehensive.hpp \ +$(BPL_TST)/comprehensive.py \ +$(BPL_TST)/doctest.py \ +$(BPL_EXA)/abstract.cpp \ +$(BPL_EXA)/getting_started1.cpp \ +$(BPL_EXA)/getting_started2.cpp \ +$(BPL_EXA)/getting_started3.cpp \ +$(BPL_EXA)/getting_started4.cpp \ +$(BPL_EXA)/getting_started5.cpp \ +$(BPL_EXA)/passing_char.cpp \ +$(BPL_EXA)/test_abstract.py \ +$(BPL_EXA)/test_getting_started1.py \ +$(BPL_EXA)/test_getting_started2.py \ +$(BPL_EXA)/test_getting_started3.py \ +$(BPL_EXA)/test_getting_started4.py \ +$(BPL_EXA)/test_getting_started5.py + +DEFS= \ +test \ +abstract \ +getting_started1 \ +getting_started2 \ +getting_started3 \ +getting_started4 \ +getting_started5 + +OBJ = classes.o conversions.o extension_class.o functions.o \ + init_function.o module_builder.o \ + objects.o types.o + +.SUFFIXES: .o .cpp + +all: libbpl.a test.pyd abstract.pyd \ + getting_started1.pyd getting_started2.pyd getting_started3.pyd \ + getting_started4.pyd getting_started5.pyd + +softlinks: defs + @ for pn in $(SOFTLINKS); \ + do \ + bn=`basename "$$pn"`; \ + if [ ! -e "$$bn" ]; then \ + echo "ln -s $$pn ."; \ + ln -s "$$pn" .; \ + else \ + echo "info: no softlink created (file exists): $$bn"; \ + fi; \ + done + +unlink: rmdefs + @ for pn in $(SOFTLINKS); \ + do \ + bn=`basename "$$pn"`; \ + if [ -L "$$bn" ]; then \ + echo "rm $$bn"; \ + rm "$$bn"; \ + elif [ -e "$$bn" ]; then \ + echo "info: not a softlink: $$bn"; \ + fi; \ + done + +defs: + @ for def in $(DEFS); \ + do \ + echo "EXPORTS\n\tinit$$def" > $$def.def; \ + done + +rmdefs: + @ for def in $(DEFS); \ + do \ + rm $$def.def; \ + done + +libbpl.a: $(OBJ) + del libbpl.a + ar r libbpl.a $(OBJ) + +DLLWRAPOPTS= -s --driver-name g++ -s + --entry _DllMainCRTStartup@12 --target=i386-mingw32 + +test.pyd: $(OBJ) comprehensive.o + dllwrap $(DLLWRAPOPTS) \ + --dllname test.pyd \ + --def test.def \ + $(OBJ) comprehensive.o $(PYLIB) + +abstract.pyd: $(OBJ) abstract.o + dllwrap $(DLLWRAPOPTS) \ + --dllname abstract.pyd \ + --def abstract.def \ + $(OBJ) abstract.o $(PYLIB) + +getting_started1.pyd: $(OBJ) getting_started1.o + dllwrap $(DLLWRAPOPTS) \ + --dllname getting_started1.pyd \ + --def getting_started1.def \ + $(OBJ) getting_started1.o $(PYLIB) + +getting_started2.pyd: $(OBJ) getting_started2.o + dllwrap $(DLLWRAPOPTS) \ + --dllname getting_started2.pyd \ + --def getting_started2.def \ + $(OBJ) getting_started2.o $(PYLIB) + +getting_started3.pyd: $(OBJ) getting_started3.o + dllwrap $(DLLWRAPOPTS) \ + --dllname getting_started3.pyd \ + --def getting_started3.def \ + $(OBJ) getting_started3.o $(PYLIB) + +getting_started4.pyd: $(OBJ) getting_started4.o + dllwrap $(DLLWRAPOPTS) \ + --dllname getting_started4.pyd \ + --def getting_started4.def \ + $(OBJ) getting_started4.o $(PYLIB) + +getting_started5.pyd: $(OBJ) getting_started5.o + dllwrap $(DLLWRAPOPTS) \ + --dllname getting_started5.pyd \ + --def getting_started5.def \ + $(OBJ) getting_started5.o $(PYLIB) + +.cpp.o: + $(CPP) $(CPPOPTS) -c $*.cpp + +test: + $(PYEXE) comprehensive.py + $(PYEXE) test_abstract.py + $(PYEXE) test_getting_started1.py + $(PYEXE) test_getting_started2.py + $(PYEXE) test_getting_started3.py + $(PYEXE) test_getting_started4.py + $(PYEXE) test_getting_started5.py + +clean: + rm -f $(OBJ) libbpl.a libbpl.a.input + rm -f comprehensive.o test.pyd + rm -f abstract.o abstract.pyd + rm -f getting_started1.o getting_started1.pyd + rm -f getting_started2.o getting_started2.pyd + rm -f getting_started3.o getting_started3.pyd + rm -f getting_started4.o getting_started4.pyd + rm -f getting_started5.o getting_started5.pyd + rm -f so_locations *.pyc + rm -rf cxx_repository diff --git a/build/Makefile.tru64_cxx b/build/Makefile.tru64_cxx new file mode 100644 index 00000000..7b932bd3 --- /dev/null +++ b/build/Makefile.tru64_cxx @@ -0,0 +1,170 @@ +# Usage: +# +# Create a new empty directory anywhere (preferably not in the boost tree). +# Copy this Makefile to that new directory and rename it to "Makefile" +# Set the BOOST pathname below. +# +# make softlinks Create softlinks to source code and tests +# make Compile all sources +# make test Run doctest tests +# make clean Remove all object files +# make unlink Remove softlinks + +BOOST= /net/cci/rwgk/boost + +PYEXE= /usr/local/Python-1.5.2/bin/python +PYINC= -I/usr/local/Python-1.5.2/include/python1.5 +#PYEXE= /usr/local/Python-2.0/bin/python +#PYINC= -I/usr/local/Python-2.0/include/python2.0 +#STLPORTINC= -I/usr/local/STLport-4.1b3/stlport +#STLPORTOPTS= \ +# -D__USE_STD_IOSTREAM \ +# -D__STL_NO_SGI_IOSTREAMS \ +# -D__STL_USE_NATIVE_STRING \ +# -D__STL_NO_NEW_C_HEADERS \ +# -D_RWSTD_COMPILE_INSTANTIATE=1 +#STLPORTINC= -I/usr/local/STLport-4.1b4/stlport +#STLPORTOPTS= -D__NO_USE_STD_IOSTREAM -D__STL_NO_SGI_IOSTREAMS +STLPORTINC= -I/net/cci/xp/C++_C_headers + +STDOPTS= -std strict_ansi +WARNOPTS= -msg_disable 186,450,1115 +# use -msg_display_number to obtain integer tags for -msg_disable + +CPP= cxx +CPPOPTS= $(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \ + $(STDOPTS) $(WARNOPTS) -g +MAKEDEP= -Em + +LD= cxx +LDOPTS= -shared -expect_unresolved 'Py*' -expect_unresolved '_Py*' + +#HIDDEN= -hidden + +BPL_SRC = $(BOOST)/libs/python/src +BPL_TST = $(BOOST)/libs/python/test +BPL_EXA = $(BOOST)/libs/python/example +SOFTLINKS = \ +$(BPL_SRC)/classes.cpp \ +$(BPL_SRC)/conversions.cpp \ +$(BPL_SRC)/extension_class.cpp \ +$(BPL_SRC)/functions.cpp \ +$(BPL_SRC)/init_function.cpp \ +$(BPL_SRC)/module_builder.cpp \ +$(BPL_SRC)/objects.cpp \ +$(BPL_SRC)/types.cpp \ +$(BPL_TST)/comprehensive.cpp \ +$(BPL_TST)/comprehensive.hpp \ +$(BPL_TST)/comprehensive.py \ +$(BPL_TST)/doctest.py \ +$(BPL_EXA)/abstract.cpp \ +$(BPL_EXA)/getting_started1.cpp \ +$(BPL_EXA)/getting_started2.cpp \ +$(BPL_EXA)/getting_started3.cpp \ +$(BPL_EXA)/getting_started4.cpp \ +$(BPL_EXA)/getting_started5.cpp \ +$(BPL_EXA)/test_abstract.py \ +$(BPL_EXA)/test_getting_started1.py \ +$(BPL_EXA)/test_getting_started2.py \ +$(BPL_EXA)/test_getting_started3.py \ +$(BPL_EXA)/test_getting_started4.py \ +$(BPL_EXA)/test_getting_started5.py + +OBJ = classes.o conversions.o extension_class.o functions.o \ + init_function.o module_builder.o \ + objects.o types.o +DEPOBJ= $(OBJ) comprehensive.o abstract.o \ + getting_started1.o getting_started2.o getting_started3.o \ + getting_started4.o getting_started5.o + +.SUFFIXES: .o .cpp + +all: libbpl.a test.so abstract.so \ + getting_started1.so getting_started2.so getting_started3.so \ + getting_started4.so getting_started5.so + +softlinks: + @ for pn in $(SOFTLINKS); \ + do \ + bn=`basename "$$pn"`; \ + if [ ! -e "$$bn" ]; then \ + echo "ln -s $$pn ."; \ + ln -s "$$pn" .; \ + else \ + echo "info: no softlink created (file exists): $$bn"; \ + fi; \ + done + +unlink: + @ for pn in $(SOFTLINKS); \ + do \ + bn=`basename "$$pn"`; \ + if [ -L "$$bn" ]; then \ + echo "rm $$bn"; \ + rm "$$bn"; \ + elif [ -e "$$bn" ]; then \ + echo "info: not a softlink: $$bn"; \ + fi; \ + done + +libbpl.a: $(OBJ) + rm -f libbpl.a + cd cxx_repository; \ + ls -1 > ../libbpl.a.input; \ + ar r ../libbpl.a -input ../libbpl.a.input + rm -f libbpl.a.input + ar r libbpl.a $(OBJ) + +test.so: $(OBJ) comprehensive.o + $(LD) $(LDOPTS) $(OBJ) comprehensive.o -o test.so -lm + +abstract.so: $(OBJ) abstract.o + $(LD) $(LDOPTS) $(OBJ) abstract.o -o abstract.so + +getting_started1.so: $(OBJ) getting_started1.o + $(LD) $(LDOPTS) $(OBJ) getting_started1.o -o getting_started1.so + +getting_started2.so: $(OBJ) getting_started2.o + $(LD) $(LDOPTS) $(OBJ) getting_started2.o -o getting_started2.so + +getting_started3.so: $(OBJ) getting_started3.o + $(LD) $(LDOPTS) $(OBJ) getting_started3.o -o getting_started3.so + +getting_started4.so: $(OBJ) getting_started4.o + $(LD) $(LDOPTS) $(OBJ) getting_started4.o -o getting_started4.so + +getting_started5.so: $(OBJ) getting_started5.o + $(LD) $(LDOPTS) $(OBJ) getting_started5.o -o getting_started5.so + +.cpp.o: + $(CPP) $(CPPOPTS) -c $*.cpp + +test: + $(PYEXE) comprehensive.py + $(PYEXE) test_abstract.py + $(PYEXE) test_getting_started1.py + $(PYEXE) test_getting_started2.py + $(PYEXE) test_getting_started3.py + $(PYEXE) test_getting_started4.py + $(PYEXE) test_getting_started5.py + +clean: + rm -f $(OBJ) libbpl.a libbpl.a.input + rm -f comprehensive.o test.so + rm -f abstract.o abstract.so + rm -f getting_started1.o getting_started1.so + rm -f getting_started2.o getting_started2.so + rm -f getting_started3.o getting_started3.so + rm -f getting_started4.o getting_started4.so + rm -f getting_started5.o getting_started5.so + rm -f so_locations *.pyc + rm -rf cxx_repository + +depend: + @ cat Makefile.nodepend; \ + for obj in $(DEPOBJ); \ + do \ + bn=`echo "$$obj" | cut -d. -f1`; \ + $(CPP) $(CPPOPTS) $(MAKEDEP) "$$bn".cpp; \ + done + diff --git a/build/tru64.mak b/build/tru64.mak deleted file mode 100644 index 6631615c..00000000 --- a/build/tru64.mak +++ /dev/null @@ -1,51 +0,0 @@ -# -# Tested with: -# Compaq C++ V6.2-024 for Digital UNIX V5.0 (Rev. 910) -# -# Python 1.5.2 was installed without any customizations. -# boost_all.zip vers. 1.18.1 was unpacked using unzip -aa and not modified. -# STLport-4.1b3 was unpacked using unzip -aa and not modified. -# -# Initial version 2000-10-20: Ralf W. Grosse-Kunstleve, rwgk@cci.lbl.gov -# - -PYINC= /usr/local/include/python1.5 -BOOSTINC= /usr/local/boost_1_18_1 -STLPORTINC= /usr/local/STLport-4.1b3/stlport -STLPORTOPTS= \ - -D__USE_STD_IOSTREAM \ - -D__STL_NO_SGI_IOSTREAMS \ - -D__STL_NO_NEW_C_HEADERS \ - -D_RWSTD_COMPILE_INSTANTIATE=1 - -STDOPTS= -std strict_ansi -WARNOPTS= -msg_disable 186,450,1115 -# use -msg_display_number to obtain integer tags for -msg_disable - -CPP= cxx -CPPOPTS= -I$(STLPORTINC) $(STLPORTOPTS) -I$(BOOSTINC) -I$(PYINC) \ - $(STDOPTS) $(WARNOPTS) - -LD= cxx -LDOPTS= -shared -expect_unresolved '*' - -OBJ = extclass.o functions.o init_function.o module.o newtypes.o \ - objects.o py.o subclass.o - -.SUFFIXES: .o .cpp - -all: demo.so hello.so - -demo.so: $(OBJ) extclass_demo.o - $(LD) $(LDOPTS) $(OBJ) extclass_demo.o -o demo.so - -hello.so: $(OBJ) example1.o - $(LD) $(LDOPTS) $(OBJ) example1.o -o hello.so - -.cpp.o: - -$(CPP) $(CPPOPTS) $(INC) -c $*.cpp - -clean: - rm -f $(OBJ) extclass_demo.o example1.o demo.so hello.so so_locations - rm -rf cxx_repository - rm -f *.pyc From 28e6a84acbf5c2fe893d5ca74b49dc78764588e9 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 4 Mar 2001 15:10:16 +0000 Subject: [PATCH 013/369] Fixed std::complex<> stuff to work with MSVC [SVN r9408] --- include/boost/python/conversions.hpp | 82 +++++++++++++++++++++------- 1 file changed, 61 insertions(+), 21 deletions(-) diff --git a/include/boost/python/conversions.hpp b/include/boost/python/conversions.hpp index b633c0ee..47f80989 100644 --- a/include/boost/python/conversions.hpp +++ b/include/boost/python/conversions.hpp @@ -7,7 +7,9 @@ // producing this work. // // Revision History: -// Mar 03 01 added: converters for [plain] char and std::complex (Ralf W. Grosse-Kunstleve) +// 04 Mar 01 Fixed std::complex<> stuff to work with MSVC (David Abrahams) +// 03 Mar 01 added: converters for [plain] char and std::complex +// (Ralf W. Grosse-Kunstleve) #ifndef METHOD_DWA122899_H_ # define METHOD_DWA122899_H_ @@ -19,8 +21,18 @@ # include # include # include + +# ifdef BOOST_MSVC6_OR_EARLIER +# pragma warning(push) +# pragma warning(disable:4275) // disable a bogus warning caused by +# endif + # include +# ifdef BOOST_MSVC6_OR_EARLIER +# pragma warning(pop) +# endif + BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround // This can be instantiated on an enum to provide the to_python/from_python @@ -74,6 +86,30 @@ inline void xdecref(T* p) xdecref_impl(reinterpret_cast(p_base)); } +namespace detail { + + void expect_complex(PyObject*); + + template + std::complex complex_from_python(PyObject* p, boost::python::type) + { + expect_complex(p); + + return std::complex( + static_cast(PyComplex_RealAsDouble(p)), + static_cast(PyComplex_ImagAsDouble(p))); + } + + template + PyObject* complex_to_python(const std::complex& sc) { + Py_complex pcc; + pcc.real = sc.real(); + pcc.imag = sc.imag(); + return PyComplex_FromCComplex(pcc); + } + +} + }} // namespace boost::python BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE @@ -138,30 +174,34 @@ PyObject* to_python(const std::string& s); std::string from_python(PyObject*, boost::python::type); std::string from_python(PyObject*, boost::python::type); -template -PyObject* to_python(const std::complex& sc) { - Py_complex pcc; - pcc.real = sc.real(); - pcc.imag = sc.imag(); - return PyComplex_FromCComplex(pcc); +inline PyObject* to_python(const std::complex& x) +{ + return boost::python::detail::complex_to_python(x); } -template -std::complex from_python(PyObject* p, - boost::python::type&>) { - if (! PyComplex_Check(p)) { - PyErr_SetString(PyExc_TypeError, "expected a complex number"); - throw boost::python::argument_error(); - } - return std::complex( - static_cast(PyComplex_RealAsDouble(p)), - static_cast(PyComplex_ImagAsDouble(p))); +inline PyObject* to_python(const std::complex& x) +{ + return boost::python::detail::complex_to_python(x); } -template -inline std::complex from_python(PyObject* p, - boost::python::type >) { - return from_python(p, boost::python::type&>()); +inline std::complex from_python(PyObject* p, + boost::python::type >) { + return boost::python::detail::complex_from_python(p, boost::python::type()); +} + +inline std::complex from_python(PyObject* p, + boost::python::type&>) { + return boost::python::detail::complex_from_python(p, boost::python::type()); +} + +inline std::complex from_python(PyObject* p, + boost::python::type >) { + return boost::python::detail::complex_from_python(p, boost::python::type()); +} + +inline std::complex from_python(PyObject* p, + boost::python::type&>) { + return boost::python::detail::complex_from_python(p, boost::python::type()); } // For when your C++ function really wants to pass/return a PyObject* From 0b97d9bae58d79e4c834f9e5a809a4fe36116368 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 4 Mar 2001 15:12:30 +0000 Subject: [PATCH 014/369] Some fixes so it will compile with Intel C++ [SVN r9409] --- include/boost/python/detail/config.hpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/boost/python/detail/config.hpp b/include/boost/python/detail/config.hpp index faf52ee4..3207f7c6 100644 --- a/include/boost/python/detail/config.hpp +++ b/include/boost/python/detail/config.hpp @@ -6,6 +6,9 @@ // 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_ @@ -46,8 +49,9 @@ # 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. -# if defined(BOOST_MSVC6_OR_EARLIER) && !defined(__STLPORT) +// 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 From a40daca9ef899a340608ee22b729a53160bb46b1 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 4 Mar 2001 15:14:04 +0000 Subject: [PATCH 015/369] *** empty log message *** [SVN r9410] --- include/boost/python/detail/wrap_python.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/boost/python/detail/wrap_python.hpp b/include/boost/python/detail/wrap_python.hpp index 9e57c287..d5b75374 100644 --- a/include/boost/python/detail/wrap_python.hpp +++ b/include/boost/python/detail/wrap_python.hpp @@ -16,7 +16,8 @@ // compiler command-line. // Revision History: -// 01 Mar 01 define PyObject_INIT() for Python 1.x +// 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) #ifdef _DEBUG # ifndef BOOST_DEBUG_PYTHON @@ -64,6 +65,8 @@ typedef int pid_t; # define _MSC_VER 900 # endif +# elif defined(_MSC_VER) +# include // prevents Python.h from defining LONGLONG_MAX, LONGLONG_MIN, and ULONGLONG_MAX # endif #endif // _WIN32 From 71aff9f0e8fce2dda850f08f861dc9fcbbc3f39b Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 4 Mar 2001 15:41:47 +0000 Subject: [PATCH 016/369] Changed library name to libboost_python.a [SVN r9411] --- build/como.mak | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/build/como.mak b/build/como.mak index 5a9920d8..c6f340a5 100644 --- a/build/como.mak +++ b/build/como.mak @@ -1,3 +1,5 @@ +# Revision History: +# 04 Mar 01 Changed library name to libboost_python.a (David Abrahams) LIBSRC = \ classes.cpp \ conversions.cpp \ @@ -30,8 +32,8 @@ endif | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \ [ -s $@ ] || rm -f $@ -example1: example1.o libpycpp.a - como-dyn-link -o ../example/hellomodule.$(MODULE_EXTENSION) $(PYHTON_LIB) example1.o -L. -lpycpp +example1: example1.o libboost_python.a + como-dyn-link -o ../example/hellomodule.$(MODULE_EXTENSION) $(PYHTON_LIB) example1.o -L. -lboost_python python ../example/test_example1.py example1.o: ../example/example1.cpp @@ -40,9 +42,9 @@ example1.o: ../example/example1.cpp clean: rm -rf *.o *.$(MODULE_EXTENSION) *.a *.d *.pyc *.bak a.out -libpycpp.a: $(LIBOBJ) - rm -f libpycpp.a - ar cq libpycpp.a $(LIBOBJ) +libboost_python.a: $(LIBOBJ) + rm -f libboost_python.a + ar cq libboost_python.a $(LIBOBJ) DEP = $(OBJ:.o=.d) From 4aa4f1c3b3b625450c1875548a49731db8bd6f3d Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 4 Mar 2001 15:45:02 +0000 Subject: [PATCH 017/369] Added DebugPython target; cleaned up some mess introduced by others [SVN r9412] --- build/bpl_static.dsp | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/build/bpl_static.dsp b/build/bpl_static.dsp index 701dd309..92af59c7 100644 --- a/build/bpl_static.dsp +++ b/build/bpl_static.dsp @@ -4,7 +4,7 @@ # TARGTYPE "Win32 (x86) Static Library" 0x0104 -CFG=bpl_static - Win32 Debug +CFG=bpl_static - Win32 DebugPython !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE @@ -13,12 +13,13 @@ CFG=bpl_static - Win32 Debug !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE -!MESSAGE NMAKE /f "bpl_static.mak" CFG="bpl_static - Win32 Debug" +!MESSAGE NMAKE /f "bpl_static.mak" CFG="bpl_static - Win32 DebugPython" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "bpl_static - Win32 Release" (based on "Win32 (x86) Static Library") !MESSAGE "bpl_static - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "bpl_static - Win32 DebugPython" (based on "Win32 (x86) Static Library") !MESSAGE # Begin Project @@ -64,7 +65,30 @@ LIB32=link.exe -lib # PROP Intermediate_Dir "Debug" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W4 /WX /Gm /GR /GX /ZI /Od /I "d:\boost\type_traits" /I "..\..\.." /I "c:\progra~1\python20\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W4 /WX /Gm /GR /GX /Zi /Od /I "..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "bpl_static - Win32 DebugPython" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "bpl_static___Win32_DebugPython" +# PROP BASE Intermediate_Dir "bpl_static___Win32_DebugPython" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "DebugPython" +# PROP Intermediate_Dir "DebugPython" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W4 /WX /Gm /GR /GX /Zi /Od /I "..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W4 /WX /Gm /GR /GX /Zi /Od /I "..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "BOOST_DEBUG_PYTHON" /FR /YX /FD /GZ /EHs /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe @@ -80,6 +104,7 @@ LIB32=link.exe -lib # Name "bpl_static - Win32 Release" # Name "bpl_static - Win32 Debug" +# Name "bpl_static - Win32 DebugPython" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" From 4b926b7c7fa3aaf563745281034ed2405cf8b36b Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 4 Mar 2001 15:48:50 +0000 Subject: [PATCH 018/369] Changed library name to libboost_python.a, various cleanups, attempted Cygwin compatibility. Still needs testing on Linux. [SVN r9413] --- build/gcc.mak | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/build/gcc.mak b/build/gcc.mak index d0b42548..f71185e0 100644 --- a/build/gcc.mak +++ b/build/gcc.mak @@ -1,3 +1,10 @@ +# Revision History + +# 04 Mar 01 Changed library name to libboost_python.a, various cleanups, +# attempted Cygwin compatibility. Still needs testing on Linux +# (David Abrahams) + + LIBSRC = \ classes.cpp \ conversions.cpp \ @@ -11,13 +18,16 @@ LIBSRC = \ LIBOBJ = $(LIBSRC:.cpp=.o) OBJ = $(LIBOBJ) +PYTHON_INC=$(ROOT)/usr/local/include/python2.0 +# libpython2.0.dll ifeq "$(OS)" "Windows_NT" -PYTHON_LIB=c:/tools/python/libs/python15.lib -INC = -Ic:/cygnus/usr/include/g++-3 -Ic:/cygnus/usr/include -Ic:/boost -Ic:/tools/python/include +ROOT=c:/cygnus +INC = -Ic:/cygnus/usr/include/g++-3 -Ic:/cygnus/usr/include -Ic:/boost -I$(PYTHON_INC) MODULE_EXTENSION=dll +PYTHON_LIB=c:/cygnus/usr/local/lib/python2.0/config/libpython2.0.dll.a else -INC = -I/usr/local/include/python1.5 +INC = -I$(PYTHON_INC) MODULE_EXTENSION=so endif @@ -31,20 +41,30 @@ endif [ -s $@ ] || rm -f $@ -example1: example1.o libpycpp.a - g++ -shared -o ../example/hellomodule.$(MODULE_EXTENSION) $(PYHTON_LIB) example1.o -L. -lpycpp - python ../example/test_example1.py +PYTHON = python + +test: comprehensive.o libboost_python.a + g++ $(CXXFLAGS) -shared -o ../test/boost_python_test.$(MODULE_EXTENSION) comprehensive.o -L. -lboost_python $(PYTHON_LIB) + $(PYTHON) ../test/comprehensive.py + +comprehensive.o: ../test/comprehensive.cpp + g++ $(CXXFLAGS) --template-depth-32 -fPIC -Wall -W $(INC) -o $*.o -c $< + + +example1: example1.o libboost_python.a + g++ $(CXXFLAGS) -shared -o ../example/hellomodule.$(MODULE_EXTENSION) example1.o -L. -lboost_python $(PYTHON_LIB) + $(PYTHON) ../example/test_example1.py example1.o: ../example/example1.cpp - g++ -fPIC -Wall -W $(INC) -o $*.o -c $< + g++ $(CXXFLAGS) --template-depth-32 -fPIC -Wall -W $(INC) -o $*.o -c $< clean: rm -rf *.o *.$(MODULE_EXTENSION) *.a *.d *.pyc *.bak a.out -libpycpp.a: $(LIBOBJ) - rm -f libpycpp.a - ar cq libpycpp.a $(LIBOBJ) +libboost_python.a: $(LIBOBJ) + rm -f libboost_python.a + ar cq libboost_python.a $(LIBOBJ) DEP = $(OBJ:.o=.d) From f82151f925a3481ea05dd1b095069d5b5401f3ab Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 4 Mar 2001 15:48:55 +0000 Subject: [PATCH 019/369] no message [SVN r9414] --- build/build.opt | Bin 84480 -> 80384 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/build/build.opt b/build/build.opt index a650cf1f83e6ca05cbe1a0fccd96f89b59f47f31..9cdea95b7eef30bf876fd69fc7e9971cd8f4a6f9 100644 GIT binary patch literal 80384 zcmca`Uhu)fjZzO8(10BSGsD0CoD6J8;!F$-42&?o00YCn|NsAkxG);Tu3%tb_&*AU zObGn_|Np-N0|Nsy0|NsK0|Nsq0|PkD*%=rZI2afhI2jlixEL51xEUbv&C9^Rz{kMA zz|X+IAi%)DAjrVLAjH7HAk4tPAi}`FAPQ9{&cMJR!N9;E$-uxM#lXNI&A`AQ!@$5G z%fP@O$H2fK4^`*Sz`&ryz`&r)z`&rwz`&r&z`&r!z`&r+z`&rvz`&r%z`&pdRjb3m zz@W>(z@W##z@X2-z+k|@z+lM0z+l9{z+lY4z+eJZXU4$5V9vn6V8Ot^V9CJ1V8y_| zV9mh5V8g(`V9UV3V8_6~V9&t7;K0DZ;K;zh-~`p@!oa}b%D}+j#=yYf&cMLn!N9=a z$-uzi#lXPe&A`Cm!@$7c%fP_k2UXw9z`zj5z`zj1z`zj9z`zi~z`zj7z`zj3z`zjB zz`zi}z`zj6z`zj2z`zg<)f3CWz!1m4z!1;Cz>vVez>vtmz>vhiz>v(qz>vbgz>vzo zz>vnkz>vvYfz>vwnz>vkjz>v+rz>vehz>o_yC!c|Vp@4ybp^$-rp@@Njp_qYz zp@e~fp_GAvp^Slnp&Y6X6u(sr3=Gu_3=B043=Fjl3=DM)3=H)Q3=9omx92nDGn6nW zFt{@0F_bVAF;s%GG0|9zffb(Lk;@8f1~eopN*q~ofDyU82xrJ=C}PNFC}t>NNMuN6 zNM%r92xcf@NMtAhhXposki`@jm>5Bs4U|4XG_o8nHmDo}CsuIW7ct~Blrt1Fq=Lf{ zmmXZ=0t`%ypu7XhE5zE*12PPhS-|Nng&~un1RM$=VNx+40}~@Ce}e1=VPf=)ffPaQ zXJlXn=X;it)Z!8iXRDZ`{QTmQn4HX{;+TTUl8pSkn55FooRk=lJebf+DJ}rj0$fQ2 zIq}6Mi6xoInt1dfRKYZ|7L})G8*1Uv16B|NCSjU5QY#X33vyBo4e;oLsfmFxV7fKp z^OLetlS>q|bQIuBO&zR86&EGPWaed-#HW?!C6{F8=jkOE6o8aE`TGZl#Q1nR1;+$L zhIsh<#W;m}`nbe|xCV#BxVSony2FG)3gaQ1c#v$oi=K;*PpyKUktrzXVHiEWW>kah zwX#adk55j_$r&t;HU^cmFgJrUJDkJ7z%c4)>Lm|j15i;S0m^C$x(eZ$dB#QxE~!bS z=>g!J2+DOJtd(pPQ<9&b1J9wLBwLUS$)}J^Yh)0gqL-4B!ytrd7%28cP=te0b5awF zK~)d9er9E0bl`N(&nqd)&(U=TDF@lg!NBOi3lnuJN=*b+N#OP%69Yqos7qo=Vo7B| zs)BE3abiwpdR}g79;iYBt6*hdI3VDdoSa%*tPqx&pOXm6S1^Ow7#I%ldgdtvB&Me- zxE2-VgX%M|HdzLS1Hzs;IjQN1ISQV6#U(|h;2a6l*~7qaK-96QD6vw(DZex?rC7nW zA~`iRB^6YYf=%dUU^pP=mXn`YqTrI6mtT~dn4{odkXn?O2UpU^z;HkWswA^4GbL3a zsZt>-wFp$hg3V9^yCSbFF()%c!6mb}Aip>h+5PtCm&RUgYBQhz;HkiA{AVcn4GQPoROLg5B$jt z3vd2>sxmMfknqdTOU}NFOv*_Ghg$)% zdkA@Y3MgPb^GZ_FQ;QT_u!b8EN~VI+118l7@H05Oq!y&+ zrKIMesNyLAS&)-jmYRc48GBlJie5%R0d9l%lM;(lp_MXzl^l8bd8zo7aF-M%CZ{GP zCTHVw6fdl5FUD`0aB4+KYF=?>eqMZXPGT_u)x7zjf~6$Ch=4ktocz3WNP7gIBe}s= zrV=oWzq}~1ARZE9_&vjul9^mWgtf($#kt^QkI!)&$@zI{nd$hH@FthVmlP#tmJsj( zZ*gv7QAvD3NfCbc^A_i1CZ`hi0DD1YZfY(*mvMsXDMGGF163M?ZQ}y9)KUpJT@ci+ zL$oLHW(U69)RK(+6k=?KMghLe#hsZ~Qj`p;FYpBj2VvXziZj#m5=%;p2qwtnd{8^R zg0PXi#hH2OIjJT2dH5rqBQv)kzo-PC2e=`&5r|VRSfa%nVx=XSIhiGu_}#=+P?-v9 zsTAXL6(^`Q-Ta=oXT9lfXOrVq$f>;_4ZZQ%{ zy!@aPPFzkdO3X_qB8PG%CKZFqX}nR&Sx^b;T&Cg+6CO}GPB`d<@{_tS3>rfOVVGH<@h%XS`!5d~ax`P`bBPC815z`J85l;x zU^EQqod%deT}(Fcus^6r48jpi3=E(w3mVo3Wn&Q50p(NZ)Bs2g2n#baFl>j4gVccV zA1EKx1p%o6VVHR!c^E#yz`!sKT3mqCfbbb61_llA*epyH0|QJQ$XJjX5XNO5NEb*u zNDT<%QwLHDG84;iC#aK!+FqmH0MF?7AM(I5Ekk;U4qA?m|AAW7u-rL1{s$_fM#uj~ z$N%#4K!bar0uwUSGdliqGxpc z4|DQsbo_60{BLxuir!;YqxMlh&2ca=Gx+*=`7kkXhNKpkIF}Zcr7F5uftMO278jHy zo5ds+7lf8%=D=vsa=5La<&L10zX7R5X`od#dC92?MhXG>MJ0qa>w*S3M#ujk>*PU0 z9WXq)l#Y5Mt)t_AqwD_|7#K#^|BbHy8(sgGoH4ro4|#>-==wk0%Q3k}*Z+YQ!Sar- z|3euC8eRW~5*(xJ|FA3x=N(=DhqR1-bp0P}yau$G2-L>~t^EVx(e;1SAIE`(^(Z|W zwxpy1Z2Pan88R927*fFdqCxoW0ZCw3>?2t(w@NQA)ek5cG z4p4oE&?6t7UzA;3keHmRpbp+!pl+pLqEJwj588XJQLHJD1m7~Qkd~Q~TFeuiUs{x$ zssJ*km=CsV8zRRI-v13@bAcUzsfEWQH8CZ%2%;b2FeIfo1PHkjq76c#d2n?9_vrp_ z8XgZYy8nB0|96Q3`cCH2^`E2bKS$Sp20I0f?*GPIi8Q+Z8~tE{(f!|`)--gf>*)S( zq`(;6{|!wQqx-*c&wq{X{{{~&z{YGx_kWL$Cz3LrII4DNr5DFJkaJ%JZ1VC;6hKFU z73JsTq^8($Bty@FWMDu#=@CPj2uvCBk&z4x@Z%bZ)c`pZl33N?5lhhc;pq4u_&6}| za$Q<&S|6fIDZ$kklt3SuAG9lNK}(}Y&wm8P8fa2!bpJOf6h_DYM#uj~$Nxsh|F9mz zIXeC~I{t^}aMjWAztQnO%t?dM@xRgWztQs_N6%Yi7+PahqhpKIkFSJRkUPEPke23Q zxq5;RAq}}xg@eI40J5%+fKDldPWYV`(EBDp>n0gNmk=?4Sg%+?om~*?H<$$)1dza@ z8GIoINEv>u1e`_K0O(v910w@BgL6n?QF>~LXGv-<9{=EVF-Vetn?OpSwxTSIWMtri zgtmK8erW+z1*H5&SpbPg9dk-*0V9J5@>%|%t2`1j^HPgY45X$)!e{^UWR|2BC6?q9 zI6s}Yq_iN1h=Zkx+q*{8G%yF`oHcw0JPVO@tTZtPh7-H#jHt7~!OL|CACApU)Okll z-uA$glUYo}9RtK(4M1G)MKrM}vm_%owInl{s1v@4Ia!>a=u_-@K&z4o2Qx7z1`%LTvu6@IOrA5Duk3Q;5jI90iqxjyV?r#SQ2Vo>Zcuo7i1x z#9zEX%<=Wa9YiRaoS#>gS_HmfgqXWBsJN$$Jvp@ubW%L-o)9tD7Z6@-MeMa5L|=pe zDijE(IKHIPw6xSB!U~DKwT0MgN{G8XhlmsRh(C9Y$O~nNye)wvIkC6|{|y2hpbJ#+ zE0HWIO3W(;oec!dr18ZCsmb{D2tr~DssX=RevlK0QYnJ&68r{>z%MT&%5?tX#9ZRa zAxMJ_nZ!DvOMEdz)NLlC_rD;Hb|k9dM_hYobpQA0{_mtxy!T&Gv92bvtwzrMFW|di zKpoFfJQ@O{Aut*OqaiRF0;3@?VnV=+nUNVZ7GA-q&+tN|9yA0$V*Ebp(a{hX=^+4{ z|C50qzJX=-j|V1+KKF-Lmjp}~?s-2p1_p+gtdn&!6?Bsolpy!KDrBVQddV3nnME4vdV2a01Ue8zT@$VxFMe$H!Lu&;Tu3k}To<_8~ zZkc+lrV_|yFIc6}F5!-W&I+Ygq=E`f$dn~W=^Ivdq)AQ01g03wE_fK=oW2AZGepAz z4+8*D%Tct-3sQga3xGTKVCi4f%wlGt0UN9X@W=l`&bg^teuL9_Gd{9h`T zGA}(`cKoTk-f`I{MKZHj*$;H3~J`x+` zcMvAVgglTU==t-`3^@#m48;t^3}FnJ45iM9Cnkv8_5t!0VnA334QTMu@z*Hg&D|y zuRvE`gHJ9*1PF9g41HPvYpwtlF<4R!NEm0hf+V4KjLr#w#|h9!{CSBy_Kx@y$#{|z zb8?arle6(JE+zF8I%3bABKjaJA~&KCdE_FghpZ8KLL=en1j6T%5pgslKjK_90&9W= z!RaL)d|P=cfnz9%Iq8m=)3XR4aYx)4XGEU1Na`VT#EoDRc_Jj?GeG&15{pygAq%+i zXR*=yUonqzAHDwpTn!)%pc9^w;sl)?N1$9F_9#{^Q0+jd;1EQ;nk%EA0QdOg==eW+ zgpQ8?kB{-g(GVC7fzc2c4S~@R z7YR_m0jD`T2A+U$}2RPq? z&TZY$MgF<1UQCQEpxI1N-j}d#9L@h^#>c3((GVDlApl$dBg24nJ|pN#NVN3@j11i1 znbOo^z2t%dP>F#u#|jk_POT^bt;5OBiwCQQspU;8%}XxH%+G`CMw=3W>PKIg4i$zU z?*!#TCvc!Vv^x+P7&u^ut}-w%GNSo|fdNA~#u1hb$YB905m~`Ie6fTIS*EdomI`4p zjFCYQb?p*%|6wT0fW!x3Z=ml_XJKGq06PXL>LFf*hv5JJ3=DbDlU70Jtb!sQvD^jc zIu($z(e*!xuscIX*Z)8#uF+TPKsF%|y+4--g`?|#Qj<&Y-C8=j{wKK-X|=%U`X7w_ z&7L1y8Z{LcmpjYEK1Hu1+8Aiz2=CB z(}?+sGt=`DOG=AU2`r5u{^n%f;>^7CoYa#1JOa!9AU8qatJL5f1iX1=^!!)o+Hv%5 z7T!=J{vKLlZ(8Oe<^T<1Zs{If|AW$&A?Nc0@1_ov( zMnj*{n3N2;o8o3L$LpAR>r~(P4rPVUCXf#ut|)mSiS_ zsyk?CF*2YHO=Aq~LIV$Nz#2o@==d*aK%K6ehC$=oqx(NW$$79{#A6fPH@vMso&lQW_oqMH!9YO)iTsDN4*NAuwRbTb!F%R1#lMLSXkb zu@}jWj{lC1|67LW}xAcBFxg(06InW2;+mm!rQkD-L27$QtG3A%p>c{G(6jgvr% zp!e^9n3Q5t?Wfc}bp4dr&&9yZ06xeJZYan!I0rO}Uky6F#L6lqKOS_}i3aqj9tABO z1vpbv$Jr_de2!mCPG(Xubirs$aZz#%NOL@F`7dZaFi5GBzkhH@jE|>Na7;jCh=;#l zj8mwmk4sF5Yj8-6i>p(pJ4_g)Fdo8*2g$~}=(+g#)GFv1nIb!K)X}sHX=8&S7}7)3 z(V*#boU5uqlLsKIm24GLlAoW0lFtf~!DpC3v!0Pbe2QL5P7VW(69#dvNS0+_U|?ln zbl?On)h)`;(RBtzKFC%M21W;7n5a`xYGO7_hKYfpLDVI&BoTD3l7eq$abiwpdR}g7 zUI|PED+9v;0mtOz)Z$`=u+03NM9^LUm?Rqm!vS8;JcWS7^i%~`(CI5M8CeE~1Hzs; zIjQN1ISQV6#U(|h;9UeT`5p#_1EP*aMTwOPPWh#IDa8t|70IcoDXA$i6}=1$2gKZR z@)JuGTvGG$i*gfl6#NTPixTtTO8OWW4v0XNWR_*7q$(s;Dnz9g<-^QS1G^%xEHNiD zMZqPrxFEkc6WRU!2m?IxQY#XZOB8}qi%WChzMsIra6lYlgD2D&up5vKnaIF!fDfX^ zzbv&VEhoPmX8$Axh692Sso;{t|_Rp1N;!#(7Y5>o#G4(2RQxm6?{{3 z^NYZ@zJVfAm4V@agkOGMa(-S(W?pGxQcfy3+zOE0L&(!pKmqHSSCX2ZTBP8DHQb0$ zG8L3AV5Xq^dm6}!fTGN@%$(Hp)D&z9;4diDAc2Ce+mw;v0I!RWkAh!*iGmv_b-+T* ziIL%eBuK_HFS8^wF(|;O~ zxEo#nJG%ZCl{7OBUK@H@ve5qv!vjFX$dU|8MmCKkNhg zqw9ZBDsFPt|8j`9c!h)7CZl*X1V%$(Gz3ONU^E0qLtw;&!07pZBPOaxJvtf!7$LyM z02%;9KKE;MDvfqiX+v_-a)?f)At&`AlBSIfM(6)V=l{@WvPS3sM(6+X^FWh(p!GDP z^MCkmPvR~qN=#0L+}4MC_6lh`D&D!6(fuE|cE)gw&i`?UfTm?e@Bd28Lz#paJ^u$j z?aK+e*|4NI1>Y<=UoLow3GDhq++`MLeo|IuZb1${!+48Q(^894^O95XpQto?{txbO d9^L-|?l{5D>=`}(XK=3DAKgze8ZXpH0|0G)Qbqs( literal 84480 zcmca`Uhu)fjZzO8(10BSGsD0CoD6J8;!F$-42&?o00YCn|NsAkxG);TZeU(z@W##z@X2-z+k|@z+lM0z+l9{z+lY4z+l3_z+lS2z+lF}z+le6z+l0^z+lP1 zz+lC|z+lb5z+l6`z+lV3z+eY8&w+t~!I6Q1!HI!^!I^=9!G(c=!Igo5!Ht1|!JUDD z!GnQ;!IOc3!Ha=`!JC1B!H0o?!Iy!7!HA_D_M5(5K6 zG6Mrc3RM4e1_p+71_p)<1_p*q1_p*K1_p*~1_p*41_p*)1_p*a1_p+F1_p)#1_p*g z1_p*A1_p*=1_p)_1_p*ws2Sx93=9-r@+9(2uib{v&|p z81fm)8HyQF!Qn_qFS@({0}~@C?|{llV(sSv83M{I;PjTlkjYR24h4`fshE#}i4l}X zL3V>MG5WaGA%G0wAwVZL=1y&FPCSjU5QY#X33vyBo z4e;0nQxgMYz;x@y=pmt!{QMla?=tg}b4pWEW0G?ci;MGv^fHuUc)2*0koD;4 z#bDP)juwzdD#+28mzJ4MitAD`lS@dqCoMB4l?+`u`HAFMR+^Vgx@DQU1^GoJMO0=U z8IH@$D=A9ONKMWrCD3y+i^;GmCqFNp^l->cEy>7FAwyq&N^xlcsbQF#pHfOr(#WmM zP0Y#3PbMW4b1Msq@=Nkb(L#DKtz%aU{+&LW%-bb1h`R!VpKx|Hz~0=H6B*T5%eWgQ*vT)3BE9fdKIRc zV9G#MpIT9png{YmJh=TtyhUlHdC4WDc|S8Rvm_p-k9eE%^7B%OS6!T$o|jlsT0~SV zLIbThGcP?SwIn}}cxynJgoKzcFG?(khlD&4cEIWlf=L8Ybdiw2A&HL|hm(?Zi&E24 zi&FEF@kUc|ZemeMd_f7`d4 zYCsrf9!w30KEc4iFbz8G08#_OXP6imG{9rCAQcb{QwK5@qy~g>nFrDV(hgDs!uZsI z)Pl^+iy0mN!x#!39sh$RiqY{u(8vuuk3jkhkWK(810JK}e+8rCf1~4nuu^4o{I9qq zW_0{-bo_60{14|4J!G&i20FqxI{p_kI{pXhvy9@=5Eu=C(GVC7fzc44N(gW;Ff;i2 zc=<3faE7E7mpGRem8B}WSj7|U6fOpG9VVHm$^h^#h<0v#>@-roiwhEyQx(*~+o{y8 z6igHfit<6*tu=}@A*Rt^6~taN$C9+In2f#4pxq-msiXV9A^Yw@8@fmz3LoA74GF!` z{onbBCETPZqtWr-(eYpK=^vxxzu?`C@X?mh@n6tv8Mv)8I{u3?Gk`iUIlBKlGbd(r z|2MesKpD6m-Tw{hWR2p{5Eu=C(GVC7fzc2coFS0#3Ua2e1kwu=K#pS9Zo$`2t5ig!-7(CQWJ|)!DE%6LxLGVtXHg{aZ3>EH<$$qBb=s! zlriGf%EloQ9PAXtz{tSO;2e@zl%87RS(2KI$2oW{1W7`TOmQt{rY=>;;e$=5VXvEPxFu;8w$n zGMSG@9m=6+xYhBa4XNT*$%ndy8Mi`iq?6rntKtWpI)-%M5N?&+NSi+Ks6tw$idz*2 zY#}giCA=u@Z`|s5kQajDR>lcGjS;sR9^`W`aVrzTTvLWyF%R*}o{Svn#KGe}~+zQ!~Q_B)_^fGX(0HsQzeZhl#Kn89zIpL$r zxYh6_m8PYo77-3(uEeBbP!Ups≶XgBEaG$pNWX@R`G#hJ2PUZlkzh1yMl(Zbclh z69{oDfz+Ku)QNPi?WkFo5w1CTM{7HHV+g5*L(STbxGIW@l_IEIA-at)THArz!N^fh zxLh2q?I67eq);2YwH*;v&j3`2RITlZ>$Op{PNa4pgxG3`lbBv5aor0dThhce^NDJd z5Z_~@MF~zsKHw#`6GB{-1`0aDg()$80%AK+RPQ?wIYL2H&w;r9EYgh(xZAEoRzQRc zWnu?Ki0TP|QZ3Q_8KQe-M0R|LXt5E|k0q)zLtJr7d`FSs@D|ba6H#3iB6^6#^g)Ol ztRl9aBX;bFxDgAYN8E_66Cu4t2niaZ9mS&|Fd71*Aut*OqaiRF0;3@?8UiGQ02dP@ z3ut1U&crRJ&bu$%olNFR8 z%T*LWc3CSxIr+ub3i-u)$r&k`MH=dQdioFqQlqX3R|Q%e2EVP%S^lCN7(QluWMsRU{qAr>cM@jgfaWLYA}!9@6v6&$)C#e>6l z*cM?zR~MqMq{JH4pk$9FTtLE5W2n7)k}oK=n7H+rNSBl|G6+FdZKfudAXZ&MT}Z^* z6QahW`B3kV#64|5+~6rub6LEgMRM@FG;v!=^hhl6lVe29MG!ODLd+<)5M=Ep@_szr zo+Z58hKTWIA{S(EfmV1xE{MhLAYxY^5-~GEW}DYCr;4Cww=m~7?; z1u)Xh!ni$5%%ndT;{I9O1`(bQC4N;YF;i_s&K?uH_<^|jbbhpB9&rZ;ar2mh;G9KV z0SHQSM9%;dw>q7Od0igj7CRHUR-6NNcQc-VBWj&KPf;SMf&{Gr# zTu6;uEwRfvxWO?DIYJblX~;KD<5oxH+5}KyE=tZw1zkvw+c2WnClIrAn-i2Y3Diu) zHGYV!zKEUtCVHs=52!$gT{w?B)QDJ81DVMtrUgn=$b!mpf|X@{ZUNE}M7W(#OxukJ zFB0E)AT0|LmtBa={Y2GUyeOOfaR(exy#*rLdPFzciEUpJlk?VL33ZSx#sKzPLTY`vg`4H2hB%d{rJ1jR0axPaN9}W z0A}W-LZ?KDt%iuIXGiw|V%^#fUHX9MU<#s(<){Xz=YA)0pn0F0aFh*2D+FR zb(Jh)kuOLbvH%sdAeP|j*_W)7QP%@!q~_%0!P#LSQ!oNHKMN=#t|%_ z5QFL%7K?+48IUHnBSBi;X;zwWu3%MiVz;=g^XJvlLT)BAgbaeCSs{uITKOe5?_asRv{2qOCtW>ptS@DWjFkM3S04#E-2I+rp#j7z}a4D#Z45h#gd+W{-%JE(O&Gb4VFX0OfANYxam39wMq^ zL2OS3xfKdwkFNhkUQ0sEcmc7c5aG(5*bMZ{8$!RR%} zS`^SS4oED4SOgbzU<(6K*bJxD97L7yL=1ZqRqYU8ZWG;%C#FS8T=$!(kRY~+N!;uv zs8K?6Q<nT|`b@5qH%rk;B2njI|Rx`ao>(5i{RJxTiuykAavGWl)!y@JIuZ z!vn+)h!WQoAb!S#+AB7QADt#j=EIP3rUy|lLh#sZ@`(ve9*H;yB#g|J80e*`-P zk(P3atVD@B{gJ392(b%=h-&&1(dZ<)%};D2oS6EUnA*0WvbZF%Bo*I@9Yl2=h-$$T z-$x>{kxq2uo2Vuyv4?(-uK!5IxUHI)HYpJ`Bh{PzME0pj=r9r2lm}IZL^M%}n}s2w z)j@1~pKu$Uq>d6Xt#u+BbHrBpL^kV*Yp#>j79zfdO>D1=H3hLsX}O*r6y$`xBXjOmPz1F(9gZsMi{i0CH~S=A9SX+!LYHSsM!qB|Qz4N4F_utMb) z+vxfa=oBYWwHY>BPC3SlpIb(RYKGt zAo2N@=w=)-Et1jsf0W|_iD_bh?%5;UP9?U}MRcoxaF2n=u__{J8{!)^L^h6zZA}q1 z_)gSdY*J}jT51sy@kHbi1)!$;==?v%xGk}LEn?;y2)9&;nUP2)9Os}e6Jb?Eb`Oai z5F@TBI6D8&&)|%>mlf2?gx1ER^Z$r5nMddU^YC9~LF_ObQC)4~N7x`Em&oMk{6A6_ zCVpAm==?wGG1f%4`H3CpL#vPfGcqzU2{16MkpIffk-)$K>(Y+WqhK@yhJOhB{r~@e z69WT7GXn!d3j+f~D+2>V8v_GFI|Bnl2Ll5`Cj$dR7Xt&szyJUL_b@Op^fE9o^f53n z^fNFpOkiMOn8?7uFo}VIVKM^)!xRPvhN%n;4AY?ML3(B~FfhzwU|^Wdz`!tvfq`Kz z0|Uc61_p-t3=9kl7#J89GB7YKVqjoc4Alb~S{udm3jsz3RtC`U<^TVT4BQOP&N;~jgfQWwnh-8zs1w9aMT`!UF-8kBXLS5mPfuS@Paia7jdUC_ zNyipL2be)d#Dm#bwziFq|BjCT61aYmsJSj;o1Vl?_JYRSh@L7ZYV{~F%Qr^He?@|W zoq|Tke=!C+LFsXH{1+owM#q0g$A7WiX-3?VuhIQq(545{AQ>?W+(yTLN5_AQit%l_ zA!d&z@#EUWtRx^}A;jqTFV>kYA{w2eBDt^kSy38j1HWj)p$kuIl9gu)u45u91M&O zyf9IxqSVA}m<$sGLxZSGVo4&XgQnn{S)7=YnVy%MnpXl-!OFmJK)^9MIkmW0AuKaL zC$S_mKMy9!#=vlZ*E3HcATd2v!L_I;AAJ56$VyoTh6BQ$IXS86i8%_MdBr6~rOC)T zdl(oFh&mP(B~~gp<(KBA6f3w^B&VjPq^7{k?qy&&Am)~npID;clA4!al$)5N;9rnh zl$Zxs(#ODXKm@8Jvn(?uRUxTTAu6>fA7+Lc*cEwYi8+}m3ND$&1^LC9$gb!|7~q+g zT9KGsq7al?T$%&-{R9Sv1L6=HJfX&b-GFS!L?!5+vi9msygTn3Gur zPL2w0iJ3WwlvBr$dqBW9KczG$71M}%hTH?f0Y&-AsVSvJSmZfC?t;a&M`B(|PAbgy z==dMNXx3=9kkWtSNk)ENSKwlD;;L-iHxa>z00y$eIj1xwH73H>)z?2L zQmxw9#KO$X(!xd8#M0GC*U-?}P1niI#7x(~z|qmbz{J_m$knKpfk6jqD#&@TsQdH( z|Noc&|NlS6z`y{)Dl7~PFPIn@ml&K7nd%xEx)|s>x*0lw5{!YfrGcBJ zi>n!d1oMf3fdPa=pn=0Uz<~n_kPQqB43-QG3@{oNI0o>*fdmmWbW&1F5;JpRQY%V8 zVUwR1pPZ9e3|<#bmE;4nJ&75Td>95egh1}$0uc-h3@{qXWl(d*mVBV+9K}HPQIMK) zKnE6q=Gf7T8Ycz@1`rlvVPMz-DvNOKe;+;nBNciQ!07oOIF3jdo&RwPBIZoc(epnF zFxMRue>yQSYfDGhe`B4<9i9KdRlR}oBoW7$j^6(fMAVrj#N^S@`Jd7Gp907!<)i0+ cz}o(!^k@i-ybu_j{~394KI-Gq5P*dM06)EQvH$=8 From bf5eec727e06ee5fbeaa19a2a8ff9870f66c2ff0 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 4 Mar 2001 15:53:00 +0000 Subject: [PATCH 020/369] Added DebugPython target [SVN r9415] --- build/example1/example1.dsp | 39 +++++++++++++++++++++++++++----- build/rwgk1/rwgk1.dsp | 38 +++++++++++++++++++++++++++---- build/test/test.dsp | 45 ++++++++++++++++++++++++++++++++----- 3 files changed, 107 insertions(+), 15 deletions(-) diff --git a/build/example1/example1.dsp b/build/example1/example1.dsp index 78d1f0d8..dcff3f55 100644 --- a/build/example1/example1.dsp +++ b/build/example1/example1.dsp @@ -4,7 +4,7 @@ # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 -CFG=example1 - Win32 Debug +CFG=example1 - Win32 DebugPython !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE @@ -13,12 +13,13 @@ CFG=example1 - Win32 Debug !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE -!MESSAGE NMAKE /f "example1.mak" CFG="example1 - Win32 Debug" +!MESSAGE NMAKE /f "example1.mak" CFG="example1 - Win32 DebugPython" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "example1 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "example1 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "example1 - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE # Begin Project @@ -68,8 +69,8 @@ LINK32=link.exe # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /GZ /c +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "_DEBUG" @@ -79,7 +80,34 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"Debug/hello.dll" /pdbtype:sept /libpath:"c:\tools\python\libs" +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"Debug/hello.dll" /pdbtype:sept /libpath:"c:\tools\python\libs" + +!ELSEIF "$(CFG)" == "example1 - Win32 DebugPython" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "example1___Win32_DebugPython" +# PROP BASE Intermediate_Dir "example1___Win32_DebugPython" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "DebugPython" +# PROP Intermediate_Dir "DebugPython" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /Gm /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /EHs /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"Debug/hello.dll" /pdbtype:sept /libpath:"c:\tools\python\libs" +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"DebugPython/hello_d.dll" /pdbtype:sept /libpath:"c:\tools\python\src\PCbuild" !ENDIF @@ -87,6 +115,7 @@ LINK32=link.exe # Name "example1 - Win32 Release" # Name "example1 - Win32 Debug" +# Name "example1 - Win32 DebugPython" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" diff --git a/build/rwgk1/rwgk1.dsp b/build/rwgk1/rwgk1.dsp index 18526979..daf736b3 100644 --- a/build/rwgk1/rwgk1.dsp +++ b/build/rwgk1/rwgk1.dsp @@ -4,7 +4,7 @@ # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 -CFG=rwgk1 - Win32 Debug +CFG=rwgk1 - Win32 DebugPython !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE @@ -13,12 +13,13 @@ CFG=rwgk1 - Win32 Debug !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE -!MESSAGE NMAKE /f "rwgk1.mak" CFG="rwgk1 - Win32 Debug" +!MESSAGE NMAKE /f "rwgk1.mak" CFG="rwgk1 - Win32 DebugPython" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "rwgk1 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "rwgk1 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "rwgk1 - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE # Begin Project @@ -65,9 +66,10 @@ LINK32=link.exe # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "_DEBUG" @@ -77,7 +79,34 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs" +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs" + +!ELSEIF "$(CFG)" == "rwgk1 - Win32 DebugPython" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "rwgk1___Win32_DebugPython" +# PROP BASE Intermediate_Dir "rwgk1___Win32_DebugPython" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "DebugPython" +# PROP Intermediate_Dir "DebugPython" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs" +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"DebugPython/rwgk1_d.dll" /pdbtype:sept /libpath:"C:\tools\python\src\PCbuild" !ENDIF @@ -85,6 +114,7 @@ LINK32=link.exe # Name "rwgk1 - Win32 Release" # Name "rwgk1 - Win32 Debug" +# Name "rwgk1 - Win32 DebugPython" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" diff --git a/build/test/test.dsp b/build/test/test.dsp index a29d011a..0816bf1e 100644 --- a/build/test/test.dsp +++ b/build/test/test.dsp @@ -4,7 +4,7 @@ # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 -CFG=test - Win32 Debug +CFG=test - Win32 DebugPython !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE @@ -13,12 +13,13 @@ CFG=test - Win32 Debug !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE -!MESSAGE NMAKE /f "test.mak" CFG="test - Win32 Debug" +!MESSAGE NMAKE /f "test.mak" CFG="test - Win32 DebugPython" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "test - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "test - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "test - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE # Begin Project @@ -44,6 +45,7 @@ RSC=rc.exe # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /c # ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /Zm200 /c +# SUBTRACT CPP /Fr # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "NDEBUG" @@ -53,7 +55,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /libpath:"c:\tools\python\libs" +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"Release/boost_python_test.dll" /libpath:"c:\tools\python\libs" !ELSEIF "$(CFG)" == "test - Win32 Debug" @@ -68,8 +70,9 @@ LINK32=link.exe # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /GZ /Zm200 /c +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /GZ /Zm200 /c +# SUBTRACT CPP /Fr # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "_DEBUG" @@ -79,7 +82,36 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs" +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"Debug/boost_python_test.dll" /pdbtype:sept /libpath:"c:\tools\python\libs" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "test - Win32 DebugPython" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "test___Win32_DebugPython" +# PROP BASE Intermediate_Dir "test___Win32_DebugPython" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "DebugPython" +# PROP Intermediate_Dir "DebugPython" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /Gm /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /GZ /Zm200 /c +# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /Zm200 /EHs /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs" +# SUBTRACT BASE LINK32 /pdb:none +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"DebugPython/boost_python_test_d.dll" /pdbtype:sept /libpath:"c:\tools\python\src\PCbuild" # SUBTRACT LINK32 /pdb:none !ENDIF @@ -88,6 +120,7 @@ LINK32=link.exe # Name "test - Win32 Release" # Name "test - Win32 Debug" +# Name "test - Win32 DebugPython" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" From afdaa4d0d848ec7242cf5b5f1d4d8a00e1639e20 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 4 Mar 2001 15:55:35 +0000 Subject: [PATCH 021/369] Rolled in const_cast from Dragon fork [SVN r9416] --- src/classes.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/classes.cpp b/src/classes.cpp index 625d67b7..c609eeef 100644 --- a/src/classes.cpp +++ b/src/classes.cpp @@ -7,8 +7,9 @@ // producing this work. // // Revision History: -// Mar 03 01 added: pickle safety measures (Ralf W. Grosse-Kunstleve) -// Mar 03 01 bug fix: use bound_function::create() (instead of new bound_function) +// 04 Mar 01 Rolled in const_cast from Dragon fork (Dave Abrahams) +// 03 Mar 01 added: pickle safety measures (Ralf W. Grosse-Kunstleve) +// 03 Mar 01 bug fix: use bound_function::create() (instead of new bound_function) #include #include @@ -881,7 +882,7 @@ namespace { PyObject *globals = PyEval_GetGlobals(); if (globals != NULL) { - PyObject *module_name = PyDict_GetItemString(globals, "__name__"); + PyObject *module_name = PyDict_GetItemString(globals, const_cast("__name__")); if (module_name != NULL) name_space.set_item(module_key, module_name); } From a3f822b7d3b24fa9d179e68bfe7cc93093fe368d Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 4 Mar 2001 15:56:07 +0000 Subject: [PATCH 022/369] Documentation for pickle support. [SVN r9417] --- doc/index.html | 2 +- doc/pickle.html | 223 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 doc/pickle.html diff --git a/doc/index.html b/doc/index.html index 9ddd65d3..4550be5c 100644 --- a/doc/index.html +++ b/doc/index.html @@ -116,7 +116,7 @@ among others.
  • Advanced Topics
      -
    1. Pickling +
    2. Pickle Support
    3. class_builder<> diff --git a/doc/pickle.html b/doc/pickle.html new file mode 100644 index 00000000..0e64d6fc --- /dev/null +++ b/doc/pickle.html @@ -0,0 +1,223 @@ + + + BPL Pickle Support + + + +c++boost.gif (8819 bytes) + + +
      +

      BPL Pickle Support

      + +Pickle is a Python module for object serialization, also known +as persistence, marshalling, or flattening. + +

      +It is often necessary to save and restore the contents of an object to +a file. One approach to this problem is to write a pair of functions +that read and write data from a file in a special format. A powerful +alternative approach is to use Python's pickle module. Exploiting +Python's ability for introspection, the pickle module recursively +converts nearly arbitrary Python objects into a stream of bytes that +can be written to a file. + +

      +The Boost Python Library supports the pickle module by emulating the +interface implemented by Jim Fulton's ExtensionClass module that is +included in the ZOPE distribution +(http://www.zope.org/). +This interface is similar to that for regular Python classes as +described in detail in the Python Library Reference for pickle: + +

      + http://www.python.org/doc/current/lib/module-pickle.html +
      + +
      +

      The BPL Pickle Interface

      + +At the user level, the BPL pickle interface involves three special +methods: + +
      +
      +__getinitargs__ +
      + When an instance of a BPL extension class is pickled, the pickler + tests if the instance has a __getinitargs__ method. This method must + return a Python tuple. When the instance is restored by the + unpickler, the contents of this tuple are used as the arguments for + the class constructor. + +

      + If __getinitargs__ is not defined, the class constructor will be + called without arguments. + +

      +

      +__getstate__ + +
      + When an instance of a BPL extension class is pickled, the pickler + tests if the instance has a __getstate__ method. This method should + return a Python object representing the state of the instance. + +

      + If __getstate__ is not defined, the instance's __dict__ is pickled + (if it is not empty). + +

      +

      +__setstate__ + +
      + When an instance of a BPL extension class is restored by the + unpickler, it is first constructed using the result of + __getinitargs__ as arguments (see above). Subsequently the unpickler + tests if the new instance has a __setstate__ method. If so, this + method is called with the result of __getstate__ (a Python object) as + the argument. + +

      + If __setstate__ is not defined, the result of __getstate__ must be + a Python dictionary. The items of this dictionary are added to + the instance's __dict__. +

      + +If both __getstate__ and __setstate__ are defined, the Python object +returned by __getstate__ need not be a dictionary. The __getstate__ and +__setstate__ methods can do what they want. + +
      +

      Pitfalls and Safety Guards

      + +In BPL extension modules with many extension classes, providing +complete pickle support for all classes would be a significant +overhead. In general complete pickle support should only be implemented +for extension classes that will eventually be pickled. However, the +author of a BPL extension module might not anticipate correctly which +classes need support for pickle. Unfortunately, the pickle protocol +described above has two important pitfalls that the end user of a BPL +extension module might not be aware of: + +
      +
      +Pitfall 1: +Both __getinitargs__ and __getstate__ are not defined. + +
      + In this situation the unpickler calls the class constructor without + arguments and then adds the __dict__ that was pickled by default to + that of the new instance. + +

      + However, most C++ classes wrapped with the BPL will have member data + that are not restored correctly by this procedure. To alert the user + to this problem, a safety guard is provided. If both __getinitargs__ + and __getstate__ are not defined, the BPL tests if the class has an + attribute __dict_defines_state__. An exception is raised if this + attribute is not defined: + +

      +    RuntimeError: Incomplete pickle support (__dict_defines_state__ not set)
      +
      + + In the rare cases where this is not the desired behavior, the safety + guard can deliberately be disabled. The corresponding C++ code for + this is, e.g.: + +
      +    class_builder py_your_class(your_module, "your_class");
      +    py_your_class.dict_defines_state();
      +
      + + It is also possible to override the safety guard at the Python level. + E.g.: + +
      +    import your_bpl_module
      +    class your_class(your_bpl_module.your_class):
      +      __dict_defines_state__ = 1
      +
      + +

      +

      +Pitfall 2: +__getstate__ is defined and the instance's __dict__ is not empty. + +
      + The author of a BPL extension class might provide a __getstate__ + method without considering the possibilities that: + +

      +

        +
      • + his class is used as a base class. Most likely the __dict__ of + instances of the derived class needs to be pickled in order to + restore the instances correctly. + +

        +

      • + the user adds items to the instance's __dict__ directly. Again, + the __dict__ of the instance then needs to be pickled. +
      +

      + + To alert the user to this highly unobvious problem, a safety guard is + provided. If __getstate__ is defined and the instance's __dict__ is + not empty, the BPL tests if the class has an attribute + __getstate_manages_dict__. An exception is raised if this attribute + is not defined: + +

      +    RuntimeError: Incomplete pickle support (__getstate_manages_dict__ not set)
      +
      + + To resolve this problem, it should first be established that the + __getstate__ and __setstate__ methods manage the instances's __dict__ + correctly. Note that this can be done both at the C++ and the Python + level. Finally, the safety guard should intentionally be overridden. + E.g. in C++: + +
      +    class_builder py_your_class(your_module, "your_class");
      +    py_your_class.getstate_manages_dict();
      +
      + + In Python: + +
      +    import your_bpl_module
      +    class your_class(your_bpl_module.your_class):
      +      __getstate_manages_dict__ = 1
      +      def __getstate__(self):
      +        # your code here
      +      def __setstate__(self, state):
      +        # your code here
      +
      +
      + +
      +

      Practical Advice

      + +
        +
      • + Avoid using __getstate__ if the instance can also be reconstructed + by way of __getinitargs__. This automatically avoids Pitfall 2. + +

        +

      • + If __getstate__ is required, include the instance's __dict__ in the + Python object that is returned. +
      + +
      +
      +Author: Ralf W. Grosse-Kunstleve, March 2001 +
      + From af6cfd0ea8b5c854e66ecc8540f8c3fb54860e54 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 4 Mar 2001 15:56:38 +0000 Subject: [PATCH 023/369] std::complex<> fixes for MSVC [SVN r9418] --- src/conversions.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/conversions.cpp b/src/conversions.cpp index 369f197a..88e30048 100644 --- a/src/conversions.cpp +++ b/src/conversions.cpp @@ -7,7 +7,8 @@ // producing this work. // // Revision History: -// Mar 03 01 added: converters for [plain] char (Ralf W. Grosse-Kunstleve) +// 04 Mar 01 std::complex<> fixes for MSVC (Dave Abrahams) +// 03 Mar 01 added: converters for [plain] char (Ralf W. Grosse-Kunstleve) #include #include @@ -47,6 +48,19 @@ void handle_exception() } } +namespace detail { + + void expect_complex(PyObject* p) + { + if (!PyComplex_Check(p)) + { + PyErr_SetString(PyExc_TypeError, "expected a complex number"); + throw boost::python::argument_error(); + } + } + +} // namespace boost::python::detail + }} // namespace boost::python BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE From f6ba5a41da56aabcd0c337b1bd3fcaf36923d889 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 4 Mar 2001 15:57:47 +0000 Subject: [PATCH 024/369] Use PyObject_INIT() instead of trying to hand-initialize [SVN r9419] --- src/extension_class.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/extension_class.cpp b/src/extension_class.cpp index 47862ec7..f71976b9 100644 --- a/src/extension_class.cpp +++ b/src/extension_class.cpp @@ -7,7 +7,7 @@ // producing this work. // // Revision History: -// Mar 01 01 Use PyObject_INIT() instead of trying to hand-initialize (David Abrahams) +// 04 Mar 01 Use PyObject_INIT() instead of trying to hand-initialize (David Abrahams) #include #include @@ -463,7 +463,9 @@ operator_dispatcher::create(const ref& object, const ref& self) free_list = result->m_free_list_link; result->m_object = object; result->m_self = self; - Py_INCREF(result); + + PyObject* result_as_pyobject = result; + PyObject_INIT(result_as_pyobject, &type_obj); return result; } From 405710e635cce91ce42a0bd82ba4925cc82dc4dc Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 4 Mar 2001 15:59:52 +0000 Subject: [PATCH 025/369] Changed name of extension module so it would work with DebugPython, eliminated useless test that aggravated MSVC [SVN r9420] --- test/comprehensive.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/test/comprehensive.cpp b/test/comprehensive.cpp index 592b0ebd..57edd687 100644 --- a/test/comprehensive.cpp +++ b/test/comprehensive.cpp @@ -5,6 +5,10 @@ // // The author gratefully acknowleges the support of Dragon Systems, Inc., in // producing this work. + +// Revision History: +// 04 Mar 01 Changed name of extension module so it would work with DebugPython, +// eliminated useless test that aggravated MSVC (David Abrahams) #include "comprehensive.hpp" #include #include // used for portability on broken compilers @@ -818,7 +822,14 @@ namespace bpl_test { // Test plain char converters. char get_plain_char() { return 'x'; } std::string use_plain_char(char c) { return std::string(3, c); } - std::string use_const_plain_char(const char c) { return std::string(5, c); } + + // This doesn't test anything but the compiler, since it has the same signature as the above. + // Since MSVC is broken and gets the signature wrong, we'll skip it. + std::string use_const_plain_char( +#ifndef BOOST_MSVC6_OR_EARLIER + const +#endif + char c) { return std::string(5, c); } // Test std::complex converters. std::complex dpolar(double rho, double theta) { @@ -1091,18 +1102,18 @@ PyObject* raw(const boost::python::tuple& args, const boost::python::dictionary& void init_module() { - boost::python::module_builder test("test"); - init_module(test); + boost::python::module_builder boost_python_test("boost_python_test"); + init_module(boost_python_test); // Just for giggles, add a raw metaclass. - test.add(new boost::python::meta_class); + boost_python_test.add(new boost::python::meta_class); } extern "C" #ifdef _WIN32 __declspec(dllexport) #endif -void inittest() +void initboost_python_test() { try { bpl_test::init_module(); From 7208104122237e24eafd16f471ebc6eedf289e6b Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 4 Mar 2001 16:02:46 +0000 Subject: [PATCH 026/369] Changed name of extension module so it would work with DebugPython, fixed exception message checking to work with Python 2.0 [SVN r9421] --- test/comprehensive.py | 44 ++++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/test/comprehensive.py b/test/comprehensive.py index 3c7f3c61..c8033575 100644 --- a/test/comprehensive.py +++ b/test/comprehensive.py @@ -7,6 +7,15 @@ r''' // The author gratefully acknowleges the support of Dragon Systems, Inc., in // producing this work. +// Revision History: +// 04 Mar 01 Changed name of extension module so it would work with DebugPython, +// fixed exception message checking to work with Python 2.0 +// (Dave Abrahams) + +Load up the extension module + + >>> from boost_python_test import * + Automatic checking of the number and type of arguments. Foo's constructor takes a single long parameter. @@ -17,9 +26,9 @@ a single long parameter. >>> try: ext = Foo('foo') ... except TypeError, err: - ... assert re.match( - ... '(illegal argument type for built-in operation)|(an integer is required)', str(err)) - ... else: print 'no exception' + ... assert_integer_expected(err) + ... else: + ... print 'no exception' >>> ext = Foo(1) @@ -209,7 +218,7 @@ Polymorphism also works: Pickling tests: >>> world.__module__ - 'test' + 'boost_python_test' >>> world.__safe_for_unpickling__ 1 >>> world.__reduce__() @@ -697,10 +706,11 @@ Testing interaction between callbacks, base declarations, and overloading >>> c = CallbackTest() >>> c.testCallback(1) 2 - >>> c.testCallback('foo') - Traceback (innermost last): - File "", line 1, in ? - TypeError: illegal argument type for built-in operation + + >>> try: c.testCallback('foo') + ... except TypeError, err: assert_integer_expected(err) + ... else: print 'no exception' + >>> c.callback(1) 2 >>> c.callback('foo') @@ -719,10 +729,11 @@ Testing interaction between callbacks, base declarations, and overloading -1 >>> r.callback('foo') 'foo 1' - >>> r.testCallback('foo') - Traceback (innermost last): - File "", line 1, in ? - TypeError: illegal argument type for built-in operation + + >>> try: r.testCallback('foo') + ... except TypeError, err: assert_integer_expected(err) + ... else: print 'no exception' + >>> r.testCallback(1) -1 >>> testCallback(r, 1) @@ -1145,8 +1156,15 @@ test methodologies for wrapping functions that return a pointer '6.35' ''' +#' + +def assert_integer_expected(err): + """Handle a common error report which appears differently in Python 1.5.x and 2.0""" + assert isinstance(err, TypeError) + message = str(err) + assert (message == "illegal argument type for built-in operation" + or message == "an integer is required") -from test import * import string import re import sys From 03dd2883f71fd8753148a3493ff4a70f909bd4f4 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 4 Mar 2001 17:39:14 +0000 Subject: [PATCH 027/369] file name change: test.so -> boost_python_test.so [SVN r9426] --- build/Makefile.linux_gcc | 8 ++++---- build/Makefile.mingw32 | 16 ++++++++-------- build/Makefile.tru64_cxx | 8 ++++---- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/build/Makefile.linux_gcc b/build/Makefile.linux_gcc index 3e8f1041..7021e221 100644 --- a/build/Makefile.linux_gcc +++ b/build/Makefile.linux_gcc @@ -79,7 +79,7 @@ DEPOBJ= $(OBJ) comprehensive.o abstract.o \ .SUFFIXES: .o .cpp -all: libbpl.a test.so abstract.so \ +all: libbpl.a boost_python_test.so abstract.so \ getting_started1.so getting_started2.so getting_started3.so \ getting_started4.so getting_started5.so @@ -111,8 +111,8 @@ libbpl.a: $(OBJ) rm -f libbpl.a ar r libbpl.a $(OBJ) -test.so: $(OBJ) comprehensive.o - $(LD) $(LDOPTS) $(OBJ) comprehensive.o -o test.so -lm +boost_python_test.so: $(OBJ) comprehensive.o + $(LD) $(LDOPTS) $(OBJ) comprehensive.o -o boost_python_test.so -lm abstract.so: $(OBJ) abstract.o $(LD) $(LDOPTS) $(OBJ) abstract.o -o abstract.so @@ -146,7 +146,7 @@ test: clean: rm -f $(OBJ) libbpl.a libbpl.a.input - rm -f comprehensive.o test.so + rm -f comprehensive.o boost_python_test.so rm -f abstract.o abstract.so rm -f getting_started1.o getting_started1.so rm -f getting_started2.o getting_started2.so diff --git a/build/Makefile.mingw32 b/build/Makefile.mingw32 index 2d86efcd..7c5f2c52 100644 --- a/build/Makefile.mingw32 +++ b/build/Makefile.mingw32 @@ -31,8 +31,8 @@ # Could this be fixed with compiler options? # -fhuge-objects looks interesting, but requires recompiling the C++ library. # (what exactly does that mean?) -# -fvtable-thunks eliminates the compiler warning, but "import test" still -# causes a crash. +# -fvtable-thunks eliminates the compiler warning, +# but "import boost_python_test" still causes a crash. BOOST_UNIX= /net/cci/rwgk/boost BOOST_WIN= "L:\boost" @@ -82,7 +82,7 @@ $(BPL_EXA)/test_getting_started4.py \ $(BPL_EXA)/test_getting_started5.py DEFS= \ -test \ +boost_python_test \ abstract \ getting_started1 \ getting_started2 \ @@ -96,7 +96,7 @@ OBJ = classes.o conversions.o extension_class.o functions.o \ .SUFFIXES: .o .cpp -all: libbpl.a test.pyd abstract.pyd \ +all: libbpl.a boost_python_test.pyd abstract.pyd \ getting_started1.pyd getting_started2.pyd getting_started3.pyd \ getting_started4.pyd getting_started5.pyd @@ -143,10 +143,10 @@ libbpl.a: $(OBJ) DLLWRAPOPTS= -s --driver-name g++ -s --entry _DllMainCRTStartup@12 --target=i386-mingw32 -test.pyd: $(OBJ) comprehensive.o +boost_python_test.pyd: $(OBJ) comprehensive.o dllwrap $(DLLWRAPOPTS) \ - --dllname test.pyd \ - --def test.def \ + --dllname boost_python_test.pyd \ + --def boost_python_test.def \ $(OBJ) comprehensive.o $(PYLIB) abstract.pyd: $(OBJ) abstract.o @@ -199,7 +199,7 @@ test: clean: rm -f $(OBJ) libbpl.a libbpl.a.input - rm -f comprehensive.o test.pyd + rm -f comprehensive.o boost_python_test.pyd rm -f abstract.o abstract.pyd rm -f getting_started1.o getting_started1.pyd rm -f getting_started2.o getting_started2.pyd diff --git a/build/Makefile.tru64_cxx b/build/Makefile.tru64_cxx index 7b932bd3..2b417944 100644 --- a/build/Makefile.tru64_cxx +++ b/build/Makefile.tru64_cxx @@ -79,7 +79,7 @@ DEPOBJ= $(OBJ) comprehensive.o abstract.o \ .SUFFIXES: .o .cpp -all: libbpl.a test.so abstract.so \ +all: libbpl.a boost_python_test.so abstract.so \ getting_started1.so getting_started2.so getting_started3.so \ getting_started4.so getting_started5.so @@ -115,8 +115,8 @@ libbpl.a: $(OBJ) rm -f libbpl.a.input ar r libbpl.a $(OBJ) -test.so: $(OBJ) comprehensive.o - $(LD) $(LDOPTS) $(OBJ) comprehensive.o -o test.so -lm +boost_python_test.so: $(OBJ) comprehensive.o + $(LD) $(LDOPTS) $(OBJ) comprehensive.o -o boost_python_test.so -lm abstract.so: $(OBJ) abstract.o $(LD) $(LDOPTS) $(OBJ) abstract.o -o abstract.so @@ -150,7 +150,7 @@ test: clean: rm -f $(OBJ) libbpl.a libbpl.a.input - rm -f comprehensive.o test.so + rm -f comprehensive.o boost_python_test.so rm -f abstract.o abstract.so rm -f getting_started1.o getting_started1.so rm -f getting_started2.o getting_started2.so From 5ad51c36fb5bc0d3055977409512e099a0e79a38 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 5 Mar 2001 03:43:10 +0000 Subject: [PATCH 028/369] Turned off "enable minimal rebuild", which causes INTERNAL COMPILER ERRORs [SVN r9437] --- build/bpl_static.dsp | 4 ++-- build/example1/example1.dsp | 4 ++-- build/rwgk1/rwgk1.dsp | 4 ++-- build/test/test.dsp | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/bpl_static.dsp b/build/bpl_static.dsp index 92af59c7..ca70236d 100644 --- a/build/bpl_static.dsp +++ b/build/bpl_static.dsp @@ -65,7 +65,7 @@ LIB32=link.exe -lib # PROP Intermediate_Dir "Debug" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W4 /WX /Gm /GR /GX /Zi /Od /I "..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W4 /WX /Gm- /GR /GX /Zi /Od /I "..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe @@ -88,7 +88,7 @@ LIB32=link.exe -lib # PROP Intermediate_Dir "DebugPython" # PROP Target_Dir "" # ADD BASE CPP /nologo /MDd /W4 /WX /Gm /GR /GX /Zi /Od /I "..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W4 /WX /Gm /GR /GX /Zi /Od /I "..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "BOOST_DEBUG_PYTHON" /FR /YX /FD /GZ /EHs /c +# ADD CPP /nologo /MDd /W4 /WX /Gm- /GR /GX /Zi /Od /I "..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "BOOST_DEBUG_PYTHON" /FR /YX /FD /GZ /EHs /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe diff --git a/build/example1/example1.dsp b/build/example1/example1.dsp index dcff3f55..4d95aa97 100644 --- a/build/example1/example1.dsp +++ b/build/example1/example1.dsp @@ -70,7 +70,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "_DEBUG" @@ -97,7 +97,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 1 # PROP Target_Dir "" # ADD BASE CPP /nologo /MDd /W3 /Gm /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /EHs /c +# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /EHs /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "_DEBUG" diff --git a/build/rwgk1/rwgk1.dsp b/build/rwgk1/rwgk1.dsp index daf736b3..67476984 100644 --- a/build/rwgk1/rwgk1.dsp +++ b/build/rwgk1/rwgk1.dsp @@ -69,7 +69,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm- /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "_DEBUG" @@ -96,7 +96,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 1 # PROP Target_Dir "" # ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm- /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "_DEBUG" diff --git a/build/test/test.dsp b/build/test/test.dsp index 0816bf1e..4bd2822a 100644 --- a/build/test/test.dsp +++ b/build/test/test.dsp @@ -71,7 +71,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /GZ /Zm200 /c +# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /GZ /Zm200 /c # SUBTRACT CPP /Fr # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 @@ -100,7 +100,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 1 # PROP Target_Dir "" # ADD BASE CPP /nologo /MDd /W3 /Gm /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /GZ /Zm200 /c -# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /Zm200 /EHs /c +# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /Zm200 /EHs /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "_DEBUG" From 7d29c6a0f79680e5a0512b396dc4c0691a2a5482 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 5 Mar 2001 03:44:46 +0000 Subject: [PATCH 029/369] tests for null pointer <=> None conversions [SVN r9438] --- test/comprehensive.cpp | 24 +++++++++++++++++++++++- test/comprehensive.py | 15 +++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/test/comprehensive.cpp b/test/comprehensive.cpp index 57edd687..3d173310 100644 --- a/test/comprehensive.cpp +++ b/test/comprehensive.cpp @@ -242,6 +242,23 @@ boost::shared_ptr Baz::create_foo() return boost::shared_ptr(new DerivedFromFoo(0)); } +// Used to check conversion to None +boost::shared_ptr foo_factory(bool create) +{ + return boost::shared_ptr(create ? new DerivedFromFoo(0) : 0); +} + +// Used to check conversion from None +bool foo_ptr_is_null(Foo* p) +{ + return p == 0; +} + +bool foo_shared_ptr_is_null(boost::shared_ptr p) +{ + return p.get() == 0; +} + // We can accept smart pointer parameters int Baz::get_foo_value(boost::shared_ptr foo) { @@ -408,7 +425,7 @@ static int testUpcast(Base* b) static std::auto_ptr derived1Factory(int i) { - return std::auto_ptr(new Derived1(i)); + return std::auto_ptr(i < 0 ? 0 : new Derived1(i)); } static std::auto_ptr derived2Factory(int i) @@ -1081,6 +1098,11 @@ void init_module(boost::python::module_builder& m) m.def(fpolar, "fpolar"); m.def(freal, "freal"); m.def(fimag, "fimag"); + + // Test new null-pointer<->None conversions + m.def(foo_factory, "foo_factory"); + m.def(foo_ptr_is_null, "foo_ptr_is_null"); + m.def(foo_shared_ptr_is_null, "foo_shared_ptr_is_null"); } PyObject* raw(const boost::python::tuple& args, const boost::python::dictionary& keywords) diff --git a/test/comprehensive.py b/test/comprehensive.py index c8033575..c1424d25 100644 --- a/test/comprehensive.py +++ b/test/comprehensive.py @@ -73,6 +73,21 @@ We can subclass Foo. >>> b.call_pure() 'not pure anymore!' +None corresponds to a NULL pointer or smart pointer + >>> f = foo_factory(1) + >>> f.add_len('xxx') + 1000 + >>> foo_factory(0) is None + 1 + >>> foo_ptr_is_null(None) + 1 + >>> foo_ptr_is_null(f) + 0 + >>> foo_shared_ptr_is_null(None) + 1 + >>> foo_shared_ptr_is_null(f) + 0 + If no __init__ function is defined, the one from the base class takes effect, just like in a Python class. From a559a371b1c839e7189afa3aa7c8b8da9890d17e Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 5 Mar 2001 03:48:38 +0000 Subject: [PATCH 030/369] enable null pointer <=> None conversions [SVN r9439] --- .../boost/python/detail/extension_class.hpp | 82 +++++++++++++++---- src/gen_extclass.py | 82 +++++++++++++++---- 2 files changed, 130 insertions(+), 34 deletions(-) diff --git a/include/boost/python/detail/extension_class.hpp b/include/boost/python/detail/extension_class.hpp index bf43ec5c..987d753e 100644 --- a/include/boost/python/detail/extension_class.hpp +++ b/include/boost/python/detail/extension_class.hpp @@ -22,6 +22,7 @@ # include # include # include +# include namespace boost { namespace python { @@ -133,6 +134,26 @@ class class_registry static std::vector static_derived_class_info; }; +template +struct is_null_helper +{ + template + static bool test(Ptr x) { return x == 0; } +}; + +template <> +struct is_null_helper +{ + template + static bool test(const Ptr& x) { return x.get() == 0; } +}; + +template +bool is_null(const Ptr& x) +{ + return is_null_helper<(is_pointer::value)>::test(x); +}; + }}} // namespace boost::python::detail BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE @@ -178,9 +199,9 @@ class python_extension_class_converters new boost::python::detail::instance_value_holder(result.get(), x))); return result.release(); } - - // Convert to T* - friend T* from_python(PyObject* obj, boost::python::type) + + friend + T* non_null_from_python(PyObject* obj, boost::python::type) { // downcast to an extension_instance, then find the actual T boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj); @@ -201,9 +222,18 @@ class python_extension_class_converters throw boost::python::argument_error(); } - // Convert to PtrType, where PtrType can be dereferenced to obtain a T. + // Convert to T* + friend T* from_python(PyObject* obj, boost::python::type) + { + if (obj == Py_None) + return 0; + else + return non_null_from_python(obj, boost::python::type()); + } + + // Extract from obj a mutable reference to the PtrType object which is holding a T. template - static PtrType& ptr_from_python(PyObject* obj, boost::python::type) + static PtrType& smart_ptr_reference(PyObject* obj, boost::python::type) { // downcast to an extension_instance, then find the actual T boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj); @@ -220,9 +250,27 @@ class python_extension_class_converters throw boost::python::argument_error(); } + // Extract from obj a constant reference to the PtrType object which is holding a T. + // If obj is None, the reference denotes a default-constructed PtrType template - static PyObject* ptr_to_python(PtrType x) + static const PtrType& smart_ptr_value(PyObject* obj, boost::python::type) { + if (obj == Py_None) + { + static PtrType null_ptr; + return null_ptr; + } + return smart_ptr_reference(obj, boost::python::type()); + } + + template + static PyObject* smart_ptr_to_python(PtrType x) + { + if (boost::python::detail::is_null(x)) + { + return boost::python::detail::none(); + } + boost::python::reference result(create_instance()); result->add_implementation( std::auto_ptr( @@ -254,7 +302,7 @@ class python_extension_class_converters // Convert to T& friend T& from_python(PyObject* p, boost::python::type) - { return *boost::python::detail::check_non_null(from_python(p, boost::python::type())); } + { return *boost::python::detail::check_non_null(non_null_from_python(p, boost::python::type())); } // Convert to const T& friend const T& from_python(PyObject* p, boost::python::type) @@ -265,28 +313,28 @@ class python_extension_class_converters { return from_python(p, boost::python::type()); } friend std::auto_ptr& from_python(PyObject* p, boost::python::type&>) - { return ptr_from_python(p, boost::python::type >()); } + { return smart_ptr_reference(p, boost::python::type >()); } - friend std::auto_ptr& from_python(PyObject* p, boost::python::type >) - { return ptr_from_python(p, boost::python::type >()); } + friend const std::auto_ptr& from_python(PyObject* p, boost::python::type >) + { return smart_ptr_value(p, boost::python::type >()); } friend const std::auto_ptr& from_python(PyObject* p, boost::python::type&>) - { return ptr_from_python(p, boost::python::type >()); } + { return smart_ptr_value(p, boost::python::type >()); } friend PyObject* to_python(std::auto_ptr x) - { return ptr_to_python(x); } + { return smart_ptr_to_python(x); } friend boost::shared_ptr& from_python(PyObject* p, boost::python::type&>) - { return ptr_from_python(p, boost::python::type >()); } + { return smart_ptr_reference(p, boost::python::type >()); } - friend boost::shared_ptr& from_python(PyObject* p, boost::python::type >) - { return ptr_from_python(p, boost::python::type >()); } + friend const boost::shared_ptr& from_python(PyObject* p, boost::python::type >) + { return smart_ptr_value(p, boost::python::type >()); } friend const boost::shared_ptr& from_python(PyObject* p, boost::python::type&>) - { return ptr_from_python(p, boost::python::type >()); } + { return smart_ptr_value(p, boost::python::type >()); } friend PyObject* to_python(boost::shared_ptr x) - { return ptr_to_python(x); } + { return smart_ptr_to_python(x); } }; // Convert T to_python, instantiated on demand and only if there isn't a diff --git a/src/gen_extclass.py b/src/gen_extclass.py index 7c378d45..2d261289 100644 --- a/src/gen_extclass.py +++ b/src/gen_extclass.py @@ -27,6 +27,7 @@ def gen_extclass(args): # include # include # include +# include namespace boost { namespace python { @@ -138,6 +139,26 @@ class class_registry static std::vector static_derived_class_info; }; +template +struct is_null_helper +{ + template + static bool test(Ptr x) { return x == 0; } +}; + +template <> +struct is_null_helper +{ + template + static bool test(const Ptr& x) { return x.get() == 0; } +}; + +template +bool is_null(const Ptr& x) +{ + return is_null_helper<(is_pointer::value)>::test(x); +}; + }}} // namespace boost::python::detail BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE @@ -183,9 +204,9 @@ class python_extension_class_converters new boost::python::detail::instance_value_holder(result.get(), x))); return result.release(); } - - // Convert to T* - friend T* from_python(PyObject* obj, boost::python::type) + + friend + T* non_null_from_python(PyObject* obj, boost::python::type) { // downcast to an extension_instance, then find the actual T boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj); @@ -206,9 +227,18 @@ class python_extension_class_converters throw boost::python::argument_error(); } - // Convert to PtrType, where PtrType can be dereferenced to obtain a T. + // Convert to T* + friend T* from_python(PyObject* obj, boost::python::type) + { + if (obj == Py_None) + return 0; + else + return non_null_from_python(obj, boost::python::type()); + } + + // Extract from obj a mutable reference to the PtrType object which is holding a T. template - static PtrType& ptr_from_python(PyObject* obj, boost::python::type) + static PtrType& smart_ptr_reference(PyObject* obj, boost::python::type) { // downcast to an extension_instance, then find the actual T boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj); @@ -225,9 +255,27 @@ class python_extension_class_converters throw boost::python::argument_error(); } + // Extract from obj a constant reference to the PtrType object which is holding a T. + // If obj is None, the reference denotes a default-constructed PtrType template - static PyObject* ptr_to_python(PtrType x) + static const PtrType& smart_ptr_value(PyObject* obj, boost::python::type) { + if (obj == Py_None) + { + static PtrType null_ptr; + return null_ptr; + } + return smart_ptr_reference(obj, boost::python::type()); + } + + template + static PyObject* smart_ptr_to_python(PtrType x) + { + if (boost::python::detail::is_null(x)) + { + return boost::python::detail::none(); + } + boost::python::reference result(create_instance()); result->add_implementation( std::auto_ptr( @@ -259,7 +307,7 @@ class python_extension_class_converters // Convert to T& friend T& from_python(PyObject* p, boost::python::type) - { return *boost::python::detail::check_non_null(from_python(p, boost::python::type())); } + { return *boost::python::detail::check_non_null(non_null_from_python(p, boost::python::type())); } // Convert to const T& friend const T& from_python(PyObject* p, boost::python::type) @@ -270,28 +318,28 @@ class python_extension_class_converters { return from_python(p, boost::python::type()); } friend std::auto_ptr& from_python(PyObject* p, boost::python::type&>) - { return ptr_from_python(p, boost::python::type >()); } + { return smart_ptr_reference(p, boost::python::type >()); } - friend std::auto_ptr& from_python(PyObject* p, boost::python::type >) - { return ptr_from_python(p, boost::python::type >()); } + friend const std::auto_ptr& from_python(PyObject* p, boost::python::type >) + { return smart_ptr_value(p, boost::python::type >()); } friend const std::auto_ptr& from_python(PyObject* p, boost::python::type&>) - { return ptr_from_python(p, boost::python::type >()); } + { return smart_ptr_value(p, boost::python::type >()); } friend PyObject* to_python(std::auto_ptr x) - { return ptr_to_python(x); } + { return smart_ptr_to_python(x); } friend boost::shared_ptr& from_python(PyObject* p, boost::python::type&>) - { return ptr_from_python(p, boost::python::type >()); } + { return smart_ptr_reference(p, boost::python::type >()); } - friend boost::shared_ptr& from_python(PyObject* p, boost::python::type >) - { return ptr_from_python(p, boost::python::type >()); } + friend const boost::shared_ptr& from_python(PyObject* p, boost::python::type >) + { return smart_ptr_value(p, boost::python::type >()); } friend const boost::shared_ptr& from_python(PyObject* p, boost::python::type&>) - { return ptr_from_python(p, boost::python::type >()); } + { return smart_ptr_value(p, boost::python::type >()); } friend PyObject* to_python(boost::shared_ptr x) - { return ptr_to_python(x); } + { return smart_ptr_to_python(x); } }; // Convert T to_python, instantiated on demand and only if there isn't a From 1edec9ff89141b4624e8824f7b806369d70c8fe1 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 5 Mar 2001 14:41:57 +0000 Subject: [PATCH 031/369] no message [SVN r9443] --- build/build.opt | Bin 80384 -> 86528 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/build/build.opt b/build/build.opt index 9cdea95b7eef30bf876fd69fc7e9971cd8f4a6f9..5086795feff7997de1d0b50d82b2404da330c819 100644 GIT binary patch literal 86528 zcmca`Uhu)fjZzO8(10BSGsD0CoD6J8;!F$-42&?o00YCn|NsAkxG);Tu3%tb_&*AU zObGn_|Np-N0|Nsy0|NsK0|Nsq0|PkD*%=rZI2afhI2jlixEL51xEUbv&C9^Rz{kMA zz|X+IAi%)DAjrVLAjH7HAk4tPAi}`FAPQ9{&cMJR!N9;E$-uxM#lXNI&A`AQ!@$5G z%fP@O$H2fK4^`*Sz`&ryz`&r)z`&rwz`&r&z`&r!z`&r+z`&rvz`&r%z`&pdRjb3m zz@W>(z@W##z@X2-z+k|@z+lM0z+l9{z+lY4z+eJZXU4$5V9vn6V8Ot^V9CJ1V8y_| zV9mh5V8g(`V9UV3V8_6~V9&t7;K0DZ;K;zh-~`p@!oa}b%D}+j#=yYf&cMLn!N9=a z$-uzi#lXPe&A`Cm!@$7c%fP_k2UXw9z`zj5z`zj1z`zj9z`zi~z`zj7z`zj3z`zjB zz`zi}z`zj6z`zj2z`zg<)f3CWz!1m4z!1;Cz>vVez>vtmz>vhiz>v(qz>vbgz>vzo zz>vnkz>vvYfz>vwnz>vkjz>v+rz>vehz>o_yC!c|Vp@4ybp^$-rp@@Njp_qYz zp@e~fp_GAvp^Slnp&Y6X6u(sr3=Gu_3=B043=Fjl3=DM)3=H)Q3=9omx92nDGn6nW zFt{@0F_bVAF;s%GG0|9zffb(Lk;@8f1}MDhZ&P1-fDyU82xrJ=C}PNFC}t>NNMuN6 zNM%r92xcf@NMtAhhXposki`@jm>5Bs4U|4XG_o8nHmDo}CsuIW7ct~Blrt1Fq=Lf{ zmmXZ=0t`%ypu7XhE5zE*12PPhS-|Nng&~un1RM$=VNx+40}~@Ce}e1=VPf=)ffPaQ zXJlXn=X;it)Z!8iXRDZ`{QTmQn4HX{;+TTUl8pSkn55FooRk=lJebf+DJ}rj0$fQ2 zIq}6Mi6xoInt1dfRKYZ|7L})G8*1Uv16B|NCSjU5QY#X33vyBo4e;oLsfmFxV7fu& z8Z(0=0}}&N5vYa&;cJWx41A0X3}#FW4BJ2<0>z+E1YuJq28NxCkdl#+fuR8;whOAB zxq&k%H9fPqB(QB7&j>2DL2QtZKw${NfBygf|MLI; z{~$RK-p|CqFbx#e4V>ZmMcKs#iOH#EoS;BrW?*GtWDqC@nFxwCSh${rhAqfsQ2zV( z|9?HmKe;G1H4l`#K_-B_%Ul8~lR+`52(2SQW`Qu+MGd@Q+ZB8> z^D>=@z$s+&Q9&Cc-u zKV#`xGyt+0gdw(b1f>?|mlh?bLNtN0+W-H|1T?X^WG3e1r^|!Gor!^&;s1XYtXg1h z1(){F5G#d;7>9FyUP)1YPBAFBKn)*|L9C?)po9pjl0k(6)YC`~b}vdS$jD4C7G(sr zmRP{Hvw<~%6jd=XFnBRS>VFU)2*TY)lv<14B6z z1H)-XNRtBHm?I1f3{BAH26F>vNNPoiLP&mojyMa*L68vSD4hg#xdsyh!wG0cftkeI zz~Y*cSpo}kCQ$8-HT)17SY1++O4H52Ar5NM{r}HUwulkZ=4)kww2eTjVIdAmqqYnT z4O1Bz7$(C*oXx2yzq~jV)c67=PmsloWoYT+EXWuT1_d2+18ZPuYEdPqsR+^`3(CLc z_;m=lB$gy5B^IYDxMU`#7bWH*Yi1;%nKdLaDJKp3*%;gr0kVa)E zBczcB@(~C_e8m!$nOcr)3k#^R29kqgkYW%92{1SC1%q>m0yN3OLJ(Xq5^x|}P-=31 zQ3}j935Ngw69{PG49~1eEJ|@oEHZ+|I1j`B{~hHMnHU&AF*<>nf#EAOfg#8Epa1{s zGng0{BAFni(t|hsjQ{^LGH@_ByW}Tlhv%g*GRUwnH2nJizaA9%utF8mhm-=f%E5Ik z0|RT3BttQ%RR?OMf`Wj7f#JoR4o2k$CQ$#g;V0CDzu+<-s(_&a)E}*fmk1H+6W1_q^K28OA{3=Fy@3=9S(3=D=P3=E|u3=ES>7#P-;Ffgny zVPM!^!oYB^gn@yjl!1Z0l!1Yxlz}0vl!2kDl!0MFDFefiQU-=&r3?(`N*Ng5mNGDW zC}m*ySjxcQSjNE6TE@U|v5bL1qMU&trksIcWjO=GnQ{h(kL3&uIu#5IdKC-|W)%z! zu@wvqy%h`$eH9E02P+sDu2nEFysKbf(5Pf!aI9otNUmgHSW?NraIlhr;cX=YgJ~55 zLs%69Lr)b0!)<5>&7qosVOliIMdeoec~OyFeYgMg|70Mg|7$Mg|7cMg|7Y zMg|6-Mg|7oMh1r2jSLL88yOgsniv?on-~~6niv?mniv=+H!(2mYhqw{+{D1}q=|t+ zvYCNFu9<-$rI~@DznOtyW-|lBnq~%u_00?n8=4syZZ|V9+-+uHc-G9oAkxCXpx?s4 zVA8_CP}{=5P}jo1u)BqU;dKiGgJ3HIgLEqcgMBLlgHtO5gL5kbgIg;DLv||zLtZNb zLw+j*Lw73!!T43AqG7zElF7=+pw7=+sx81&m17&6)z7&_Y+7`odS7oeT`$I~f>QyBHYQyBHWax)>N#x)>Pzx)>M& zx)>PhyBHW6yBHXnx)>Oyb}=yA>0)5G*Tujf-Oa$@*v-HY*Ui9?(9OV**v-ID(#^oI zx0``se>VdIQx5}!Mh^o+a1R4RK@S5%Q4a${aSsDSTMq-nnH~m)b3F_U-+LGse)cdh z{OVy~;O%8#i0oxxi0)-zXzyiU=Q+;FgpJCe{}qBbo_60{BLypZ*=@` zbo>w6JQ$@0Q3(8pj{k8eq_f;e0CoEZk>f_4G8zJ-Awbg*;9y{8@b&TXVPfD6Ni8mM zE-flcRdlh6DK1KmNh~fXOEv>hp(U9)Fj_CUpkOO#xg%)hZ$N5MT7FS(VqS8pf{{W% zeo+Zw&AOn45+F|{_?fbS)*1gu&}DnhzyO+=XZXAaJR->elLM&(VbH+dS3GjR@yPu{ zlLOf&zzDIAWiP6IAUQ#(92*unA*dWT7P%KtKM0`7f!q(mAU}xWk(0t92O4dWMUw-$ zlNIU~Y;wX-IVCLmM4*cZRj|mh;gMs9nu)Ftu$Z6w|)4?NW zh(it(W+rHIpfKZr`T?69%$??F`at3!4Dy5M`=8~YC4e_rY{6+4Bo4wLIcYp{N;u>| zdX@3Wf#gT=Xb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S0iBLx1lLe~FPFzPdmj{i|3 zL`TgS4S}H(0@(Inhcjd{ecgC|2CLmC5UuRBN|Hmm{N{|&Mmgt4hX7t;m_K=(g; zG6XPqGQ=|^F%*DpEQanq&jjzt2PwplwAhj4-g2OE{Cl#Sb9=>^3K^?qnT-{2+M4_N4KPxr4M59HEaR{JT3Q+?g(R{-&I{wQ5 zABP8xosN$GGBAve{}L{fMpcZ4z-S1JhQMeDjE2By2#kinXb6mkz-R~z&JY+K{~et1 zGU}?)5THj0IL?6_9426smtUfg3^^1nCpE=RBpJ(DkPMKqLShv|PI@F(HT;N23=JGG zw=gguojM5`KO7zZ1D&ahwq6l5RyVr-lYs%-8qd-7pY$kIM(r34fzc2c4S~@R7!85Z z5Eu=C(GVC7fzc2cj3F>O{x=w7Wzu z0~aK;-HY-|3!o}kIYeB%!ci7L;!($(l3KvXAj076l3I|Omy(*7T z=jNxB=A`0N#g&|&mzJ51-%1Y1NB@t>!6L$*dNy$tmB7iwEa|`l|O7L06lbfGXTv|X#8GB}O zD*mLwnM~OC{H1xB$@wWnWMPhiNQPIs?l$e)Jgw1@psU;ctDTF=4 zm6%jqQk0mCH+Z>0DpHdY2_)U*{JgT%qTDAW0i6LX0xhae3$WD?Zg8^xm`Fd71*Auv!OFgpG>P$55R?`Q}Nd{0*PL6oYAjhXFWPL5d(VpCFICVTIhV4q^{s zUqhk}3v$^DRt@wt2|6e}z}cxZGbaU_KI2nhDfA61 zH#oW>xd`M*M94sAK+&g{ab_A&fq)}5fu!&TG)Mu|K59=a^97|ALvE)BP3sopnSw^z zxx>gH1ewrIO)f!9NJCvn%^7IOXe-esLX<D&7#J9M85kIdwLb=Ayb6dw*bm{6PI56Yf$as^4Z_5j zkOxu(J%8SrA%`K6p_rkVA&eoDA(f$=L4kq9^Y=-%zY@uQ*!+(qf!SpEQDuq$2&+JL(d<{s*?_6KR}!bpID<6D(4IjPCzJ z3y{(MUzJG7V|4!)V%BeT{}+4$baek0sGTy3M?+vV1cqV=jL!cI#aJ74^JoZACj>_4 zf2b3Vqo$08z)%bU*!aH$Xy6-l3>&g)odYC+KKhSSwFpQx+!&;>f5ryTEy18cRKyrD z!2xo_h&yBexd(MlASpk;xFjC3HzXcpF^Tg7pmT(ZQZrKXiZjbntrbwXh|zx?1$ABB zq@w)n)I8n9(vp1Lf|4T4jUGZE`{5o3&jElu3-LC{^+b3UGV%^m{E~Ihc@+|EAU`2S z!Eq)7kTQtZL9ADx%b^(tp}#;*dc(@Arw@)VNO}i}QF~edYpwv57FbdZNEm0hf+R=h z1dtCCL?7|zCGyxi;!h;w0iDAHImip&fk&jCLPzYmQ$!zRMdHClM4nqmR02-qFE2_gfHs-%JCFE*Z6eR4B<^rlBF?}h_ViF< zXKaW)p^)%iCr;3zbOd66*fUzNS%AtRJ#hK}Oi6x~)1d}g>myZBDIB$IJ>rEG4e$CI0M8Vo!%9 zYSSk%CkqpK3MXlYOT&(q#+PG>If0m*U3*kKla}~HJ&9bs!c&w8s<%Ps+~Nxw>sO)G64A&5Vt^bi>KsuihbR{I(o=u0 z2g;-=R19MV3@VN^g9a5ro4J6Bq7U*yh2bOXP(E~?1t7Jo1>U?|5p z!jb_wEI`YaSiw7dsbv}qXsHkb10y3w5DS8)E#NDX^sxJnkpWFv1|&WRdjoxcItv2> z1K2T0Q4jGdJOuy$XJCMwX*;_9CkERwub`ZOSP%tWn}fbBcy#>_-R>M6UH?Pm#bu-G ze-Qf_QK~Y$7uJrh|A7{9qw9a5MH)HBuOkuK$5%u+jBDm>Fzz z{ZBITkp!dbe{kI^Kf3-0GxK0y{{z|oo5}{8|0Dg@-qH0x!*y(E)L+9t1R5C_7@8Ou z824}E=n&@U_-}l1 zNn%N6GH5gz8d{^{zeObq1G|M6wAXWV|0iU{Gsg4*7vzdA_oDpL0%)HUq7tcO7AWPtK3HSe=^`4LMcwnO(kw?Z%Srz3E|CPqx(O>7o&~t z|3odGNB4hXIh=WP|0hOKjlMJp@7&tx`0wcWZ*Z_v(CGe8(5TEP9t{CpA>hK0%8XgnM3bQVhmc1{ ziP1OSEo>Sm@r6TJcJVul8txKbMf)1RnRjsMRqkP2$1=sj;3Bn8yg^p z><|g*A?#?-904fA(L;KFby`t=F7)swo=(I>so*Vqhb02x03`$MTFG?BQ@wb;uuO;TC z5ArhQ2zfs9FH0@T$xloHrOd${b!2)FIqMB>5AG%}2Ho=W2e-fevoKbJ+ZBk`2&91# zkJhq?ha4YTl3G-Z)Kqaa)Iqdc9KqcUP*G}UWmTM;SX2^UP*N0Mk`HSE6_=z~S%FUE z28pAXGO#Tjb3=SBo&VgF1(A^sS^z_uZdO(qsW~a}nR&$}iFwJX$iZP`r+^~__4M=x zv`t7Lq$o>FPRNPLiQL5GWH_i36F)_X3DiCzH93Lw4AlfhS=MvQ&qper-175b^$m{P z1|3DYpX5axK zTwVG9LIa<623>%G0t@G@4j@So)=IXDDap^zK^Z?SNCqD^4;@l9GKf#nOUcP$kY!+C zU}a!*-~?TOP?Vpe>kMmja4;}B@WMo$ic%A^VKPh%3=N_#i6x1k5h4ZO%;LnH%=En6 z)Vvay3RVV&0|Ji8$*IM~3SpV~IpEV%VUlbN3j)H$dYEfbyTuC1T!vPVflFYKqlvIVJN`O!v-b>h5(Q|L4F#=qalDL1V+#Q!xAW?LZcxtLPB8l{J#+r(WBlR4FN16P|w^r zdj2Pta2XXE4S~@R7!85Z5Eu=C;T!^N42%q%3>BuTBNlnht($q+TFFXXVR?xJ=vT|6#pu)hw z!rUY^(FC!G*oXnN8XRK33xtA`YB-k{!|pyT2A!6xR&C_yYGm$c?5t~O?q;fMXy{^~ z>*!|aq-$W{Xy9yV;AZLKYF5j@09|~}02&+vEwcpSKmY&#fBFCae~=sq-)CfC*u}`e zz&^m?a+869;WacQU^JA=fCv}xWFvHvAO^A|AOZGgiCUwYAkrx$GDf=DwN1qD!wzP=x%uCKGO-YUM zb@lZRill0oTw;RcBbEUU6Oi9QafD2R*dVNoEliw)LSjI}^nR}4dd>j>R4H6Q83=^` zK?8+(fCFU-BLl-$P$|fOpg{ow!V1_k5oi+#Ct z7(|e0ko!Pb8y+IayIerWxyN9f+)kC`0;-2V_yRKngEkLV)D`Tzj?)(`FZilIf=!^*w@=TB^E=@|1GhCo&ReE z={w?HPCmN+7u4RfvKn3gi!WV`uKy*jkQ!b8TZFa;$SIKuX=il(Z+>10XjSm&`rrIK eP?roe#4)=5cXa(P+7jc@^}nFZF^WfS2mk=&D+65s literal 80384 zcmca`Uhu)fjZzO8(10BSGsD0CoD6J8;!F$-42&?o00YCn|NsAkxG);Tu3%tb_&*AU zObGn_|Np-N0|Nsy0|NsK0|Nsq0|PkD*%=rZI2afhI2jlixEL51xEUbv&C9^Rz{kMA zz|X+IAi%)DAjrVLAjH7HAk4tPAi}`FAPQ9{&cMJR!N9;E$-uxM#lXNI&A`AQ!@$5G z%fP@O$H2fK4^`*Sz`&ryz`&r)z`&rwz`&r&z`&r!z`&r+z`&rvz`&r%z`&pdRjb3m zz@W>(z@W##z@X2-z+k|@z+lM0z+l9{z+lY4z+eJZXU4$5V9vn6V8Ot^V9CJ1V8y_| zV9mh5V8g(`V9UV3V8_6~V9&t7;K0DZ;K;zh-~`p@!oa}b%D}+j#=yYf&cMLn!N9=a z$-uzi#lXPe&A`Cm!@$7c%fP_k2UXw9z`zj5z`zj1z`zj9z`zi~z`zj7z`zj3z`zjB zz`zi}z`zj6z`zj2z`zg<)f3CWz!1m4z!1;Cz>vVez>vtmz>vhiz>v(qz>vbgz>vzo zz>vnkz>vvYfz>vwnz>vkjz>v+rz>vehz>o_yC!c|Vp@4ybp^$-rp@@Njp_qYz zp@e~fp_GAvp^Slnp&Y6X6u(sr3=Gu_3=B043=Fjl3=DM)3=H)Q3=9omx92nDGn6nW zFt{@0F_bVAF;s%GG0|9zffb(Lk;@8f1~eopN*q~ofDyU82xrJ=C}PNFC}t>NNMuN6 zNM%r92xcf@NMtAhhXposki`@jm>5Bs4U|4XG_o8nHmDo}CsuIW7ct~Blrt1Fq=Lf{ zmmXZ=0t`%ypu7XhE5zE*12PPhS-|Nng&~un1RM$=VNx+40}~@Ce}e1=VPf=)ffPaQ zXJlXn=X;it)Z!8iXRDZ`{QTmQn4HX{;+TTUl8pSkn55FooRk=lJebf+DJ}rj0$fQ2 zIq}6Mi6xoInt1dfRKYZ|7L})G8*1Uv16B|NCSjU5QY#X33vyBo4e;oLsfmFxV7fKp z^OLetlS>q|bQIuBO&zR86&EGPWaed-#HW?!C6{F8=jkOE6o8aE`TGZl#Q1nR1;+$L zhIsh<#W;m}`nbe|xCV#BxVSony2FG)3gaQ1c#v$oi=K;*PpyKUktrzXVHiEWW>kah zwX#adk55j_$r&t;HU^cmFgJrUJDkJ7z%c4)>Lm|j15i;S0m^C$x(eZ$dB#QxE~!bS z=>g!J2+DOJtd(pPQ<9&b1J9wLBwLUS$)}J^Yh)0gqL-4B!ytrd7%28cP=te0b5awF zK~)d9er9E0bl`N(&nqd)&(U=TDF@lg!NBOi3lnuJN=*b+N#OP%69Yqos7qo=Vo7B| zs)BE3abiwpdR}g79;iYBt6*hdI3VDdoSa%*tPqx&pOXm6S1^Ow7#I%ldgdtvB&Me- zxE2-VgX%M|HdzLS1Hzs;IjQN1ISQV6#U(|h;2a6l*~7qaK-96QD6vw(DZex?rC7nW zA~`iRB^6YYf=%dUU^pP=mXn`YqTrI6mtT~dn4{odkXn?O2UpU^z;HkWswA^4GbL3a zsZt>-wFp$hg3V9^yCSbFF()%c!6mb}Aip>h+5PtCm&RUgYBQhz;HkiA{AVcn4GQPoROLg5B$jt z3vd2>sxmMfknqdTOU}NFOv*_Ghg$)% zdkA@Y3MgPb^GZ_FQ;QT_u!b8EN~VI+118l7@H05Oq!y&+ zrKIMesNyLAS&)-jmYRc48GBlJie5%R0d9l%lM;(lp_MXzl^l8bd8zo7aF-M%CZ{GP zCTHVw6fdl5FUD`0aB4+KYF=?>eqMZXPGT_u)x7zjf~6$Ch=4ktocz3WNP7gIBe}s= zrV=oWzq}~1ARZE9_&vjul9^mWgtf($#kt^QkI!)&$@zI{nd$hH@FthVmlP#tmJsj( zZ*gv7QAvD3NfCbc^A_i1CZ`hi0DD1YZfY(*mvMsXDMGGF163M?ZQ}y9)KUpJT@ci+ zL$oLHW(U69)RK(+6k=?KMghLe#hsZ~Qj`p;FYpBj2VvXziZj#m5=%;p2qwtnd{8^R zg0PXi#hH2OIjJT2dH5rqBQv)kzo-PC2e=`&5r|VRSfa%nVx=XSIhiGu_}#=+P?-v9 zsTAXL6(^`Q-Ta=oXT9lfXOrVq$f>;_4ZZQ%{ zy!@aPPFzkdO3X_qB8PG%CKZFqX}nR&Sx^b;T&Cg+6CO}GPB`d<@{_tS3>rfOVVGH<@h%XS`!5d~ax`P`bBPC815z`J85l;x zU^EQqod%deT}(Fcus^6r48jpi3=E(w3mVo3Wn&Q50p(NZ)Bs2g2n#baFl>j4gVccV zA1EKx1p%o6VVHR!c^E#yz`!sKT3mqCfbbb61_llA*epyH0|QJQ$XJjX5XNO5NEb*u zNDT<%QwLHDG84;iC#aK!+FqmH0MF?7AM(I5Ekk;U4qA?m|AAW7u-rL1{s$_fM#uj~ z$N%#4K!bar0uwUSGdliqGxpc z4|DQsbo_60{BLxuir!;YqxMlh&2ca=Gx+*=`7kkXhNKpkIF}Zcr7F5uftMO278jHy zo5ds+7lf8%=D=vsa=5La<&L10zX7R5X`od#dC92?MhXG>MJ0qa>w*S3M#ujk>*PU0 z9WXq)l#Y5Mt)t_AqwD_|7#K#^|BbHy8(sgGoH4ro4|#>-==wk0%Q3k}*Z+YQ!Sar- z|3euC8eRW~5*(xJ|FA3x=N(=DhqR1-bp0P}yau$G2-L>~t^EVx(e;1SAIE`(^(Z|W zwxpy1Z2Pan88R927*fFdqCxoW0ZCw3>?2t(w@NQA)ek5cG z4p4oE&?6t7UzA;3keHmRpbp+!pl+pLqEJwj588XJQLHJD1m7~Qkd~Q~TFeuiUs{x$ zssJ*km=CsV8zRRI-v13@bAcUzsfEWQH8CZ%2%;b2FeIfo1PHkjq76c#d2n?9_vrp_ z8XgZYy8nB0|96Q3`cCH2^`E2bKS$Sp20I0f?*GPIi8Q+Z8~tE{(f!|`)--gf>*)S( zq`(;6{|!wQqx-*c&wq{X{{{~&z{YGx_kWL$Cz3LrII4DNr5DFJkaJ%JZ1VC;6hKFU z73JsTq^8($Bty@FWMDu#=@CPj2uvCBk&z4x@Z%bZ)c`pZl33N?5lhhc;pq4u_&6}| za$Q<&S|6fIDZ$kklt3SuAG9lNK}(}Y&wm8P8fa2!bpJOf6h_DYM#uj~$Nxsh|F9mz zIXeC~I{t^}aMjWAztQnO%t?dM@xRgWztQs_N6%Yi7+PahqhpKIkFSJRkUPEPke23Q zxq5;RAq}}xg@eI40J5%+fKDldPWYV`(EBDp>n0gNmk=?4Sg%+?om~*?H<$$)1dza@ z8GIoINEv>u1e`_K0O(v910w@BgL6n?QF>~LXGv-<9{=EVF-Vetn?OpSwxTSIWMtri zgtmK8erW+z1*H5&SpbPg9dk-*0V9J5@>%|%t2`1j^HPgY45X$)!e{^UWR|2BC6?q9 zI6s}Yq_iN1h=Zkx+q*{8G%yF`oHcw0JPVO@tTZtPh7-H#jHt7~!OL|CACApU)Okll z-uA$glUYo}9RtK(4M1G)MKrM}vm_%owInl{s1v@4Ia!>a=u_-@K&z4o2Qx7z1`%LTvu6@IOrA5Duk3Q;5jI90iqxjyV?r#SQ2Vo>Zcuo7i1x z#9zEX%<=Wa9YiRaoS#>gS_HmfgqXWBsJN$$Jvp@ubW%L-o)9tD7Z6@-MeMa5L|=pe zDijE(IKHIPw6xSB!U~DKwT0MgN{G8XhlmsRh(C9Y$O~nNye)wvIkC6|{|y2hpbJ#+ zE0HWIO3W(;oec!dr18ZCsmb{D2tr~DssX=RevlK0QYnJ&68r{>z%MT&%5?tX#9ZRa zAxMJ_nZ!DvOMEdz)NLlC_rD;Hb|k9dM_hYobpQA0{_mtxy!T&Gv92bvtwzrMFW|di zKpoFfJQ@O{Aut*OqaiRF0;3@?VnV=+nUNVZ7GA-q&+tN|9yA0$V*Ebp(a{hX=^+4{ z|C50qzJX=-j|V1+KKF-Lmjp}~?s-2p1_p+gtdn&!6?Bsolpy!KDrBVQddV3nnME4vdV2a01Ue8zT@$VxFMe$H!Lu&;Tu3k}To<_8~ zZkc+lrV_|yFIc6}F5!-W&I+Ygq=E`f$dn~W=^Ivdq)AQ01g03wE_fK=oW2AZGepAz z4+8*D%Tct-3sQga3xGTKVCi4f%wlGt0UN9X@W=l`&bg^teuL9_Gd{9h`T zGA}(`cKoTk-f`I{MKZHj*$;H3~J`x+` zcMvAVgglTU==t-`3^@#m48;t^3}FnJ45iM9Cnkv8_5t!0VnA334QTMu@z*Hg&D|y zuRvE`gHJ9*1PF9g41HPvYpwtlF<4R!NEm0hf+V4KjLr#w#|h9!{CSBy_Kx@y$#{|z zb8?arle6(JE+zF8I%3bABKjaJA~&KCdE_FghpZ8KLL=en1j6T%5pgslKjK_90&9W= z!RaL)d|P=cfnz9%Iq8m=)3XR4aYx)4XGEU1Na`VT#EoDRc_Jj?GeG&15{pygAq%+i zXR*=yUonqzAHDwpTn!)%pc9^w;sl)?N1$9F_9#{^Q0+jd;1EQ;nk%EA0QdOg==eW+ zgpQ8?kB{-g(GVC7fzc2c4S~@R z7YR_m0jD`T2A+U$}2RPq? z&TZY$MgF<1UQCQEpxI1N-j}d#9L@h^#>c3((GVDlApl$dBg24nJ|pN#NVN3@j11i1 znbOo^z2t%dP>F#u#|jk_POT^bt;5OBiwCQQspU;8%}XxH%+G`CMw=3W>PKIg4i$zU z?*!#TCvc!Vv^x+P7&u^ut}-w%GNSo|fdNA~#u1hb$YB905m~`Ie6fTIS*EdomI`4p zjFCYQb?p*%|6wT0fW!x3Z=ml_XJKGq06PXL>LFf*hv5JJ3=DbDlU70Jtb!sQvD^jc zIu($z(e*!xuscIX*Z)8#uF+TPKsF%|y+4--g`?|#Qj<&Y-C8=j{wKK-X|=%U`X7w_ z&7L1y8Z{LcmpjYEK1Hu1+8Aiz2=CB z(}?+sGt=`DOG=AU2`r5u{^n%f;>^7CoYa#1JOa!9AU8qatJL5f1iX1=^!!)o+Hv%5 z7T!=J{vKLlZ(8Oe<^T<1Zs{If|AW$&A?Nc0@1_ov( zMnj*{n3N2;o8o3L$LpAR>r~(P4rPVUCXf#ut|)mSiS_ zsyk?CF*2YHO=Aq~LIV$Nz#2o@==d*aK%K6ehC$=oqx(NW$$79{#A6fPH@vMso&lQW_oqMH!9YO)iTsDN4*NAuwRbTb!F%R1#lMLSXkb zu@}jWj{lC1|67LW}xAcBFxg(06InW2;+mm!rQkD-L27$QtG3A%p>c{G(6jgvr% zp!e^9n3Q5t?Wfc}bp4dr&&9yZ06xeJZYan!I0rO}Uky6F#L6lqKOS_}i3aqj9tABO z1vpbv$Jr_de2!mCPG(Xubirs$aZz#%NOL@F`7dZaFi5GBzkhH@jE|>Na7;jCh=;#l zj8mwmk4sF5Yj8-6i>p(pJ4_g)Fdo8*2g$~}=(+g#)GFv1nIb!K)X}sHX=8&S7}7)3 z(V*#boU5uqlLsKIm24GLlAoW0lFtf~!DpC3v!0Pbe2QL5P7VW(69#dvNS0+_U|?ln zbl?On)h)`;(RBtzKFC%M21W;7n5a`xYGO7_hKYfpLDVI&BoTD3l7eq$abiwpdR}g7 zUI|PED+9v;0mtOz)Z$`=u+03NM9^LUm?Rqm!vS8;JcWS7^i%~`(CI5M8CeE~1Hzs; zIjQN1ISQV6#U(|h;9UeT`5p#_1EP*aMTwOPPWh#IDa8t|70IcoDXA$i6}=1$2gKZR z@)JuGTvGG$i*gfl6#NTPixTtTO8OWW4v0XNWR_*7q$(s;Dnz9g<-^QS1G^%xEHNiD zMZqPrxFEkc6WRU!2m?IxQY#XZOB8}qi%WChzMsIra6lYlgD2D&up5vKnaIF!fDfX^ zzbv&VEhoPmX8$Axh692Sso;{t|_Rp1N;!#(7Y5>o#G4(2RQxm6?{{3 z^NYZ@zJVfAm4V@agkOGMa(-S(W?pGxQcfy3+zOE0L&(!pKmqHSSCX2ZTBP8DHQb0$ zG8L3AV5Xq^dm6}!fTGN@%$(Hp)D&z9;4diDAc2Ce+mw;v0I!RWkAh!*iGmv_b-+T* ziIL%eBuK_HFS8^wF(|;O~ zxEo#nJG%ZCl{7OBUK@H@ve5qv!vjFX$dU|8MmCKkNhg zqw9ZBDsFPt|8j`9c!h)7CZl*X1V%$(Gz3ONU^E0qLtw;&!07pZBPOaxJvtf!7$LyM z02%;9KKE;MDvfqiX+v_-a)?f)At&`AlBSIfM(6)V=l{@WvPS3sM(6+X^FWh(p!GDP z^MCkmPvR~qN=#0L+}4MC_6lh`D&D!6(fuE|cE)gw&i`?UfTm?e@Bd28Lz#paJ^u$j z?aK+e*|4NI1>Y<=UoLow3GDhq++`MLeo|IuZb1${!+48Q(^894^O95XpQto?{txbO d9^L-|?l{5D>=`}(XK=3DAKgze8ZXpH0|0G)Qbqs( From 2e145ea9163340ef7f4ab94cf7bb3ddbc74d511d Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 5 Mar 2001 23:41:37 +0000 Subject: [PATCH 032/369] Use file name "libboost_python.a"; rename makefiles. [SVN r9449] --- build/{Makefile.linux_gcc => linux_gcc.mak} | 10 +++++----- build/{Makefile.mingw32 => mingw32.mak} | 10 +++++----- build/{Makefile.tru64_cxx => tru64_cxx.mak} | 16 ++++++++-------- 3 files changed, 18 insertions(+), 18 deletions(-) rename build/{Makefile.linux_gcc => linux_gcc.mak} (96%) rename build/{Makefile.mingw32 => mingw32.mak} (96%) rename build/{Makefile.tru64_cxx => tru64_cxx.mak} (93%) diff --git a/build/Makefile.linux_gcc b/build/linux_gcc.mak similarity index 96% rename from build/Makefile.linux_gcc rename to build/linux_gcc.mak index 7021e221..a07bb5da 100644 --- a/build/Makefile.linux_gcc +++ b/build/linux_gcc.mak @@ -79,7 +79,7 @@ DEPOBJ= $(OBJ) comprehensive.o abstract.o \ .SUFFIXES: .o .cpp -all: libbpl.a boost_python_test.so abstract.so \ +all: libboost_python.a boost_python_test.so abstract.so \ getting_started1.so getting_started2.so getting_started3.so \ getting_started4.so getting_started5.so @@ -107,9 +107,9 @@ unlink: fi; \ done -libbpl.a: $(OBJ) - rm -f libbpl.a - ar r libbpl.a $(OBJ) +libboost_python.a: $(OBJ) + rm -f libboost_python.a + ar r libboost_python.a $(OBJ) boost_python_test.so: $(OBJ) comprehensive.o $(LD) $(LDOPTS) $(OBJ) comprehensive.o -o boost_python_test.so -lm @@ -145,7 +145,7 @@ test: $(PYEXE) test_getting_started5.py clean: - rm -f $(OBJ) libbpl.a libbpl.a.input + rm -f $(OBJ) libboost_python.a libboost_python.a.input rm -f comprehensive.o boost_python_test.so rm -f abstract.o abstract.so rm -f getting_started1.o getting_started1.so diff --git a/build/Makefile.mingw32 b/build/mingw32.mak similarity index 96% rename from build/Makefile.mingw32 rename to build/mingw32.mak index 7c5f2c52..014af132 100644 --- a/build/Makefile.mingw32 +++ b/build/mingw32.mak @@ -96,7 +96,7 @@ OBJ = classes.o conversions.o extension_class.o functions.o \ .SUFFIXES: .o .cpp -all: libbpl.a boost_python_test.pyd abstract.pyd \ +all: libboost_python.a boost_python_test.pyd abstract.pyd \ getting_started1.pyd getting_started2.pyd getting_started3.pyd \ getting_started4.pyd getting_started5.pyd @@ -136,9 +136,9 @@ rmdefs: rm $$def.def; \ done -libbpl.a: $(OBJ) - del libbpl.a - ar r libbpl.a $(OBJ) +libboost_python.a: $(OBJ) + del libboost_python.a + ar r libboost_python.a $(OBJ) DLLWRAPOPTS= -s --driver-name g++ -s --entry _DllMainCRTStartup@12 --target=i386-mingw32 @@ -198,7 +198,7 @@ test: $(PYEXE) test_getting_started5.py clean: - rm -f $(OBJ) libbpl.a libbpl.a.input + rm -f $(OBJ) libboost_python.a libboost_python.a.input rm -f comprehensive.o boost_python_test.pyd rm -f abstract.o abstract.pyd rm -f getting_started1.o getting_started1.pyd diff --git a/build/Makefile.tru64_cxx b/build/tru64_cxx.mak similarity index 93% rename from build/Makefile.tru64_cxx rename to build/tru64_cxx.mak index 2b417944..3fd584b7 100644 --- a/build/Makefile.tru64_cxx +++ b/build/tru64_cxx.mak @@ -79,7 +79,7 @@ DEPOBJ= $(OBJ) comprehensive.o abstract.o \ .SUFFIXES: .o .cpp -all: libbpl.a boost_python_test.so abstract.so \ +all: libboost_python.a boost_python_test.so abstract.so \ getting_started1.so getting_started2.so getting_started3.so \ getting_started4.so getting_started5.so @@ -107,13 +107,13 @@ unlink: fi; \ done -libbpl.a: $(OBJ) - rm -f libbpl.a +libboost_python.a: $(OBJ) + rm -f libboost_python.a cd cxx_repository; \ - ls -1 > ../libbpl.a.input; \ - ar r ../libbpl.a -input ../libbpl.a.input - rm -f libbpl.a.input - ar r libbpl.a $(OBJ) + ls -1 > ../libboost_python.a.input; \ + ar r ../libboost_python.a -input ../libboost_python.a.input + rm -f libboost_python.a.input + ar r libboost_python.a $(OBJ) boost_python_test.so: $(OBJ) comprehensive.o $(LD) $(LDOPTS) $(OBJ) comprehensive.o -o boost_python_test.so -lm @@ -149,7 +149,7 @@ test: $(PYEXE) test_getting_started5.py clean: - rm -f $(OBJ) libbpl.a libbpl.a.input + rm -f $(OBJ) libboost_python.a libboost_python.a.input rm -f comprehensive.o boost_python_test.so rm -f abstract.o abstract.so rm -f getting_started1.o getting_started1.so From 149cc499ede69475159d5a120c3213597c9d410a Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 5 Mar 2001 23:46:43 +0000 Subject: [PATCH 033/369] Remove spurious ";" [SVN r9450] --- include/boost/python/detail/extension_class.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/python/detail/extension_class.hpp b/include/boost/python/detail/extension_class.hpp index 987d753e..4afffcae 100644 --- a/include/boost/python/detail/extension_class.hpp +++ b/include/boost/python/detail/extension_class.hpp @@ -152,7 +152,7 @@ template bool is_null(const Ptr& x) { return is_null_helper<(is_pointer::value)>::test(x); -}; +} }}} // namespace boost::python::detail From fdff5e33b3745a4768caf0145d57d3cce7f1a668 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 6 Mar 2001 00:02:01 +0000 Subject: [PATCH 034/369] temp file for branching [SVN r9451] --- src/x_class_builder.cpp | 118 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 src/x_class_builder.cpp diff --git a/src/x_class_builder.cpp b/src/x_class_builder.cpp new file mode 100644 index 00000000..cf81a3f7 --- /dev/null +++ b/src/x_class_builder.cpp @@ -0,0 +1,118 @@ +# include +namespace python = boost::python; +# include // MSVC6.0SP4 does not know std::fprintf +# include // MSVC6.0SP4 does not know std::strcmp + +namespace { + + PyObject *get_module_dict(const char *module_name) + { + python::ref module_obj(PyImport_ImportModule((char*) module_name)); + PyObject *module_dict = PyModule_GetDict(module_obj.get()); + if (module_dict == 0) throw python::import_error(); + return module_dict; + } +} + +namespace boost { namespace python { namespace detail { + +#ifndef SPECIAL_PYCVTSOBJECT + +void *import_converters(const std::string& module_name, + const std::string& klass_name, + const std::string& attribute_name) +{ + static std::string err; + PyObject *module_dict + = get_module_dict(const_cast(module_name.c_str())); + PyObject *klass + = PyDict_GetItemString(module_dict, const_cast(klass_name.c_str())); + if (klass == 0) { + err = std::string("module ") + module_name + " has no attribute " + + klass_name; + PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); + throw python::import_error(); + } + python::ref c_obj(PyObject_GetAttrString(klass, + const_cast(attribute_name.c_str())), ref::null_ok); + if (c_obj.get() == 0) { + err = std::string("object ") + module_name + "." + klass_name + + " has no attribute " + attribute_name; + PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); + throw python::import_error(); + } + if (! PyCObject_Check(c_obj.get())) { + err = std::string("object ") + module_name + "." + klass_name + "." + + attribute_name + " is not a PyCObject"; + PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); + throw python::import_error(); + } + return PyCObject_AsVoidPtr(c_obj.get()); +} + +#else + +PyObject *new_import_converters(const std::string& module_name, + const std::string& klass_name, + const std::string& attribute_name) +{ + static std::string err; + PyObject *module_dict + = get_module_dict(const_cast(module_name.c_str())); + PyObject *klass + = PyDict_GetItemString(module_dict, const_cast(klass_name.c_str())); + if (klass == 0) { + err = std::string("module ") + module_name + " has no attribute " + + klass_name; + PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); + throw python::import_error(); + } + python::ref cvts_obj(PyObject_GetAttrString(klass, + const_cast(attribute_name.c_str())), ref::null_ok); + if (cvts_obj.get() == 0) { + err = std::string("object ") + module_name + "." + klass_name + + " has no attribute " + attribute_name; + PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); + throw python::import_error(); + } + // Weak point: direct access to ob_type->tp_name + if (strcmp(cvts_obj->ob_type->tp_name, "PyCvtsObject") != 0) { + err = std::string("object ") + module_name + "." + klass_name + "." + + attribute_name + " is not a PyCvtsObject"; + PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); + throw python::import_error(); + } + return cvts_obj.release(); +} + +#endif // SPECIAL_PYCVTSOBJECT + +void check_export_converters_api(const int importing_major, + const int importing_minor, + const int imported_major, + const int imported_minor) +{ + if (importing_major != imported_major) { + // Python uses fprintf(stderr, ...) for API warnings. + fprintf(stderr, + "Fatal: EXPORT_CONVERTERS_API mismatch:" + " Importing module = %d.%d" + " Imported module = %d.%d\n", + importing_major, importing_minor, + imported_major, imported_minor); + PyErr_SetString(PyExc_RuntimeError, + "Fatal: EXPORT_CONVERTERS_API mismatch"); + throw import_error(); + } + if (importing_minor != imported_minor) { + // Python uses fprintf(stderr, ...) for API warnings. + fprintf(stderr, + "Warning: EXPORT_CONVERTERS_API mismatch:" + " Importing module = %d.%d" + " Imported module = %d.%d\n", + importing_major, importing_minor, + imported_major, imported_minor); + } +} + +}}} // namespace boost::python::detail From f49141f71ede423a1ae6f52f85f3a5b054c869e9 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 6 Mar 2001 00:04:28 +0000 Subject: [PATCH 035/369] temp file removed after branching [SVN r9452] --- src/x_class_builder.cpp | 118 ---------------------------------------- 1 file changed, 118 deletions(-) delete mode 100644 src/x_class_builder.cpp diff --git a/src/x_class_builder.cpp b/src/x_class_builder.cpp deleted file mode 100644 index cf81a3f7..00000000 --- a/src/x_class_builder.cpp +++ /dev/null @@ -1,118 +0,0 @@ -# include -namespace python = boost::python; -# include // MSVC6.0SP4 does not know std::fprintf -# include // MSVC6.0SP4 does not know std::strcmp - -namespace { - - PyObject *get_module_dict(const char *module_name) - { - python::ref module_obj(PyImport_ImportModule((char*) module_name)); - PyObject *module_dict = PyModule_GetDict(module_obj.get()); - if (module_dict == 0) throw python::import_error(); - return module_dict; - } -} - -namespace boost { namespace python { namespace detail { - -#ifndef SPECIAL_PYCVTSOBJECT - -void *import_converters(const std::string& module_name, - const std::string& klass_name, - const std::string& attribute_name) -{ - static std::string err; - PyObject *module_dict - = get_module_dict(const_cast(module_name.c_str())); - PyObject *klass - = PyDict_GetItemString(module_dict, const_cast(klass_name.c_str())); - if (klass == 0) { - err = std::string("module ") + module_name + " has no attribute " - + klass_name; - PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); - throw python::import_error(); - } - python::ref c_obj(PyObject_GetAttrString(klass, - const_cast(attribute_name.c_str())), ref::null_ok); - if (c_obj.get() == 0) { - err = std::string("object ") + module_name + "." + klass_name - + " has no attribute " + attribute_name; - PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); - throw python::import_error(); - } - if (! PyCObject_Check(c_obj.get())) { - err = std::string("object ") + module_name + "." + klass_name + "." - + attribute_name + " is not a PyCObject"; - PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); - throw python::import_error(); - } - return PyCObject_AsVoidPtr(c_obj.get()); -} - -#else - -PyObject *new_import_converters(const std::string& module_name, - const std::string& klass_name, - const std::string& attribute_name) -{ - static std::string err; - PyObject *module_dict - = get_module_dict(const_cast(module_name.c_str())); - PyObject *klass - = PyDict_GetItemString(module_dict, const_cast(klass_name.c_str())); - if (klass == 0) { - err = std::string("module ") + module_name + " has no attribute " - + klass_name; - PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); - throw python::import_error(); - } - python::ref cvts_obj(PyObject_GetAttrString(klass, - const_cast(attribute_name.c_str())), ref::null_ok); - if (cvts_obj.get() == 0) { - err = std::string("object ") + module_name + "." + klass_name - + " has no attribute " + attribute_name; - PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); - throw python::import_error(); - } - // Weak point: direct access to ob_type->tp_name - if (strcmp(cvts_obj->ob_type->tp_name, "PyCvtsObject") != 0) { - err = std::string("object ") + module_name + "." + klass_name + "." - + attribute_name + " is not a PyCvtsObject"; - PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); - throw python::import_error(); - } - return cvts_obj.release(); -} - -#endif // SPECIAL_PYCVTSOBJECT - -void check_export_converters_api(const int importing_major, - const int importing_minor, - const int imported_major, - const int imported_minor) -{ - if (importing_major != imported_major) { - // Python uses fprintf(stderr, ...) for API warnings. - fprintf(stderr, - "Fatal: EXPORT_CONVERTERS_API mismatch:" - " Importing module = %d.%d" - " Imported module = %d.%d\n", - importing_major, importing_minor, - imported_major, imported_minor); - PyErr_SetString(PyExc_RuntimeError, - "Fatal: EXPORT_CONVERTERS_API mismatch"); - throw import_error(); - } - if (importing_minor != imported_minor) { - // Python uses fprintf(stderr, ...) for API warnings. - fprintf(stderr, - "Warning: EXPORT_CONVERTERS_API mismatch:" - " Importing module = %d.%d" - " Imported module = %d.%d\n", - importing_major, importing_minor, - imported_major, imported_minor); - } -} - -}}} // namespace boost::python::detail From 23725680c9b8ab8068e26b46512936d260fb95df Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 6 Mar 2001 00:05:41 +0000 Subject: [PATCH 036/369] temp file before branching [SVN r9453] --- include/boost/python/x_class_builder.hpp | 361 +++++++++++++++++++++++ 1 file changed, 361 insertions(+) create mode 100644 include/boost/python/x_class_builder.hpp diff --git a/include/boost/python/x_class_builder.hpp b/include/boost/python/x_class_builder.hpp new file mode 100644 index 00000000..4b3da600 --- /dev/null +++ b/include/boost/python/x_class_builder.hpp @@ -0,0 +1,361 @@ +#ifndef X_CLASS_BUILDER_HPP +# define X_CLASS_BUILDER_HPP + +# include + +//QUESTIONMARK +// Do we really need the special PyCvtsObject? +// Is there a better way of creating the special PyCvtsObject? +// My solution adds a lot of code including several reinterpret_cast. +//#define SPECIAL_PYCVTSOBJECT + +namespace boost { namespace python { + struct import_error : error_already_set {}; + struct export_error : error_already_set {}; +}} + +namespace boost { namespace python { namespace detail { + +// Concept: throw exception if api_major is changed +// show warning on stderr if api_minor is changed +const int EXPORT_CONVERTERS_API_MAJOR = 1; +const int EXPORT_CONVERTERS_API_MINOR = 1; +const std::string converters_attribute_name = "__converters__"; +#ifndef SPECIAL_PYCVTSOBJECT +void *import_converters(const std::string& module_name, + const std::string& klass_name, + const std::string& attribute_name); +#else +PyObject *new_import_converters(const std::string& module_name, + const std::string& klass_name, + const std::string& attribute_name); +#endif +void check_export_converters_api(const int importing_major, + const int importing_minor, + const int imported_major, + const int imported_minor); + +}}} + +// forward declaration +namespace boost { namespace python { namespace detail { +template class import_extension_class; +}}} + +BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE + +//QUESTIONMARK +// This class is a look-alike of class python_extension_class_converters. +// Is there a way to ensure that the siblings stay in sync? +template +class python_import_extension_class_converters +{ + public: + + friend python_import_extension_class_converters py_extension_class_converters(boost::python::type) + { + return python_import_extension_class_converters(); + } + + PyObject* to_python(const T& x) const + { + return boost::python::detail::import_extension_class::get_converters()->to_python(x); + } + + friend T* from_python(PyObject* obj, boost::python::type) + { + return boost::python::detail::import_extension_class::get_converters()->Tptr_from_python(obj); + } + + // Convert to const T* + friend const T* from_python(PyObject* p, boost::python::type) + { return from_python(p, boost::python::type()); } + + // Convert to const T* const& + friend const T* from_python(PyObject* p, boost::python::type) + { return from_python(p, boost::python::type()); } + + // Convert to T* const& + friend T* from_python(PyObject* p, boost::python::type) + { return from_python(p, boost::python::type()); } + + // Convert to T& + friend T& from_python(PyObject* p, boost::python::type) + { return *boost::python::detail::check_non_null(from_python(p, boost::python::type())); } + + // Convert to const T& + friend const T& from_python(PyObject* p, boost::python::type) + { return from_python(p, boost::python::type()); } + + // Convert to T + friend const T& from_python(PyObject* p, boost::python::type) + { return from_python(p, boost::python::type()); } + + friend std::auto_ptr& from_python(PyObject* p, boost::python::type&>) { + return boost::python::detail::import_extension_class::get_converters()->auto_ptr_from_python(p); + } + + friend std::auto_ptr& from_python(PyObject* p, boost::python::type >) { + return boost::python::detail::import_extension_class::get_converters()->auto_ptr_from_python(p); + } + + friend const std::auto_ptr& from_python(PyObject* p, boost::python::type&>) { + return boost::python::detail::import_extension_class::get_converters()->auto_ptr_from_python(p); + } + + friend PyObject* to_python(std::auto_ptr x) { + return boost::python::detail::import_extension_class::get_converters()->to_python(x); + } + + friend boost::shared_ptr& from_python(PyObject* p, boost::python::type&>) { + return boost::python::detail::import_extension_class::get_converters()->shared_ptr_from_python(p); + } + + friend boost::shared_ptr& from_python(PyObject* p, boost::python::type >) { + return boost::python::detail::import_extension_class::get_converters()->shared_ptr_from_python(p); + } + + friend const boost::shared_ptr& from_python(PyObject* p, boost::python::type&>) { + return boost::python::detail::import_extension_class::get_converters()->shared_ptr_from_python(p); + } + + friend PyObject* to_python(boost::shared_ptr x) { + return boost::python::detail::import_extension_class::get_converters()->to_python(x); + } +}; + +BOOST_PYTHON_END_CONVERSION_NAMESPACE + +namespace boost { namespace python { + +BOOST_PYTHON_IMPORT_CONVERSION(python_import_extension_class_converters); + +// A pointer to this class is exported/imported via the Python API. +// All functions are virtual. This is, what we really export/import +// is essentially just a pointer to a vtbl. +template +struct export_converters_base +{ + virtual const int get_api_major() const { + return detail::EXPORT_CONVERTERS_API_MAJOR; } + virtual const int get_api_minor() const { + return detail::EXPORT_CONVERTERS_API_MINOR; } + virtual PyObject *to_python(const T& x) = 0; + virtual PyObject *to_python(std::auto_ptr x) = 0; + virtual PyObject *to_python(boost::shared_ptr x) = 0; + virtual T* Tptr_from_python(PyObject* obj) = 0; + virtual std::auto_ptr& auto_ptr_from_python(PyObject *obj) = 0; + virtual boost::shared_ptr& shared_ptr_from_python(PyObject *obj) = 0; +}; + +// Converters to be used if T is not copyable. +template +struct export_ptr_converters : export_converters_base +{ + virtual PyObject *to_python(const T& x) { + PyErr_SetString(PyExc_RuntimeError, + "to_python(const T&) converter not exported"); + throw import_error(); + } + virtual PyObject *to_python(std::auto_ptr x) { + return BOOST_PYTHON_CONVERSION::to_python(x); + } + virtual PyObject *to_python(boost::shared_ptr x) { + return BOOST_PYTHON_CONVERSION::to_python(x); + } + virtual T* Tptr_from_python(PyObject* obj) { + return BOOST_PYTHON_CONVERSION::from_python(obj, boost::python::type()); + } + virtual std::auto_ptr& auto_ptr_from_python(PyObject *obj) { + return BOOST_PYTHON_CONVERSION::python_extension_class_converters::ptr_from_python(obj, boost::python::type >()); + } + virtual boost::shared_ptr& shared_ptr_from_python(PyObject *obj) { + return BOOST_PYTHON_CONVERSION::python_extension_class_converters::ptr_from_python(obj, boost::python::type >()); + } +}; + +// The addditional to_python() converter that can be used if T is copyable. +template +struct export_converters : export_ptr_converters +{ + virtual PyObject *to_python(const T& x) { + BOOST_PYTHON_CONVERSION::python_extension_class_converters cv; + return cv.to_python(x); + } +}; + +namespace detail { + +//QUESTIONMARK +// A stripped-down, modified version of class extension_class. +// Would it make sense to establish a formal relationship +// between the two classes? +template +class import_extension_class + : public python_import_extension_class_converters +{ + public: + inline import_extension_class(const char *module, const char* klass) { + m_module = module; + m_klass = klass; + } + + static boost::python::export_converters_base* get_converters(); + + private: + static std::string m_module; + static std::string m_klass; + static boost::python::export_converters_base* imported_converters; +}; + +template std::string import_extension_class::m_module; +template std::string import_extension_class::m_klass; +template +boost::python::export_converters_base* +import_extension_class::imported_converters = 0; + +#ifdef SPECIAL_PYCVTSOBJECT + +// A special PyObject for passing pointers to export_converters_base +template +struct PyCvtsObject { + PyObject_HEAD + export_converters_base* cvts; +}; + +template +void DEL_PyCvtsObject(PyCvtsObject* self) { PyMem_DEL(self); } + +template +PyObject *create_PyCvtsObject(export_converters_base* cvts) +{ + static char PyCvtsObject_Type__doc__[] = + "Boost Python Library (BPL) converters objects to be exported from\n" + "one extension module to another."; + + static PyTypeObject PyCvtsObject_Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /*ob_size*/ + "PyCvtsObject", /*tp_name*/ + sizeof(PyCvtsObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor)(static_cast*)> + (DEL_PyCvtsObject)), /*tp_dealloc*/ + (printfunc)0, /*tp_print*/ + (getattrfunc)0, /*tp_getattr*/ + (setattrfunc)0, /*tp_setattr*/ + (cmpfunc)0, /*tp_compare*/ + (reprfunc)0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + (hashfunc)0, /*tp_hash*/ + (ternaryfunc)0, /*tp_call*/ + (reprfunc)0, /*tp_str*/ + + /* Space for future expansion */ + 0L,0L,0L,0L, + PyCvtsObject_Type__doc__ /* Documentation string */ + }; + + PyCvtsObject* self = PyObject_NEW(PyCvtsObject, &PyCvtsObject_Type); + if (self == 0) throw export_error(); + self->cvts = cvts; + return reinterpret_cast(self); +} + +#endif // SPECIAL_PYCVTSOBJECT + +template +boost::python::export_converters_base* +import_extension_class::get_converters() { + if (imported_converters == 0) { +#ifndef SPECIAL_PYCVTSOBJECT + void *cobject + = import_converters(m_module, m_klass, converters_attribute_name); + imported_converters + = static_cast*>(cobject); +#else + ref cvts_obj( + new_import_converters(m_module, m_klass, converters_attribute_name)); + PyCvtsObject* cvts = reinterpret_cast*>(cvts_obj.get()); + imported_converters = cvts->cvts; +#endif + check_export_converters_api( + EXPORT_CONVERTERS_API_MAJOR, + EXPORT_CONVERTERS_API_MINOR, + imported_converters->get_api_major(), + imported_converters->get_api_minor()); + } + return imported_converters; +} + +}}} // namespace boost::python::detail + +namespace boost { namespace python { + +//QUESTIONMARK +// A stripped-down, modified version of class class_builder. +// Would it make sense to establish a formal relationship +// between the two classes? +template +class import_class_builder + : python_import_extension_class_converters +{ + public: + import_class_builder(const char *module, const char* klass) + : m_class(new detail::import_extension_class(module, klass)) + { } + private: + + //QUESTIONMARK + //reference > m_class; + boost::shared_ptr > m_class; +}; + +}} // namespace boost::python + +namespace boost { namespace python { + +// A class_builder that exports the converter functions. +template , + class C = export_converters > +class x_class_builder + : public class_builder +{ + private: + static C export_cvts; + + public: + x_class_builder(module_builder& module, const char* name) + : class_builder(module, name) { +#ifndef SPECIAL_PYCVTSOBJECT + add( + ref(PyCObject_FromVoidPtr(reinterpret_cast(&export_cvts), NULL)), + const_cast(detail::converters_attribute_name.c_str())); +#else + add(ref(detail::create_PyCvtsObject(&export_cvts)), + const_cast(detail::converters_attribute_name.c_str())); +#endif + } +}; + +template +C x_class_builder::export_cvts; + +//QUESTIONMARK +// Is there a better way of making it easy for the end-user +// to choose between x_class_builder and xptr_class_builder? +template , + class C = export_ptr_converters > +class xptr_class_builder : public x_class_builder +{ + public: + xptr_class_builder(module_builder& module, const char* name) + : x_class_builder(module, name) { } +}; + +}} // namespace boost::python + +#endif // X_CLASS_BUILDER_HPP From 5b13e75fa585d73753627a2f4df1cb2c8fa2128e Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 6 Mar 2001 00:06:55 +0000 Subject: [PATCH 037/369] temp file removed after branching. [SVN r9454] --- include/boost/python/x_class_builder.hpp | 361 ----------------------- 1 file changed, 361 deletions(-) delete mode 100644 include/boost/python/x_class_builder.hpp diff --git a/include/boost/python/x_class_builder.hpp b/include/boost/python/x_class_builder.hpp deleted file mode 100644 index 4b3da600..00000000 --- a/include/boost/python/x_class_builder.hpp +++ /dev/null @@ -1,361 +0,0 @@ -#ifndef X_CLASS_BUILDER_HPP -# define X_CLASS_BUILDER_HPP - -# include - -//QUESTIONMARK -// Do we really need the special PyCvtsObject? -// Is there a better way of creating the special PyCvtsObject? -// My solution adds a lot of code including several reinterpret_cast. -//#define SPECIAL_PYCVTSOBJECT - -namespace boost { namespace python { - struct import_error : error_already_set {}; - struct export_error : error_already_set {}; -}} - -namespace boost { namespace python { namespace detail { - -// Concept: throw exception if api_major is changed -// show warning on stderr if api_minor is changed -const int EXPORT_CONVERTERS_API_MAJOR = 1; -const int EXPORT_CONVERTERS_API_MINOR = 1; -const std::string converters_attribute_name = "__converters__"; -#ifndef SPECIAL_PYCVTSOBJECT -void *import_converters(const std::string& module_name, - const std::string& klass_name, - const std::string& attribute_name); -#else -PyObject *new_import_converters(const std::string& module_name, - const std::string& klass_name, - const std::string& attribute_name); -#endif -void check_export_converters_api(const int importing_major, - const int importing_minor, - const int imported_major, - const int imported_minor); - -}}} - -// forward declaration -namespace boost { namespace python { namespace detail { -template class import_extension_class; -}}} - -BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE - -//QUESTIONMARK -// This class is a look-alike of class python_extension_class_converters. -// Is there a way to ensure that the siblings stay in sync? -template -class python_import_extension_class_converters -{ - public: - - friend python_import_extension_class_converters py_extension_class_converters(boost::python::type) - { - return python_import_extension_class_converters(); - } - - PyObject* to_python(const T& x) const - { - return boost::python::detail::import_extension_class::get_converters()->to_python(x); - } - - friend T* from_python(PyObject* obj, boost::python::type) - { - return boost::python::detail::import_extension_class::get_converters()->Tptr_from_python(obj); - } - - // Convert to const T* - friend const T* from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to const T* const& - friend const T* from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to T* const& - friend T* from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to T& - friend T& from_python(PyObject* p, boost::python::type) - { return *boost::python::detail::check_non_null(from_python(p, boost::python::type())); } - - // Convert to const T& - friend const T& from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to T - friend const T& from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - friend std::auto_ptr& from_python(PyObject* p, boost::python::type&>) { - return boost::python::detail::import_extension_class::get_converters()->auto_ptr_from_python(p); - } - - friend std::auto_ptr& from_python(PyObject* p, boost::python::type >) { - return boost::python::detail::import_extension_class::get_converters()->auto_ptr_from_python(p); - } - - friend const std::auto_ptr& from_python(PyObject* p, boost::python::type&>) { - return boost::python::detail::import_extension_class::get_converters()->auto_ptr_from_python(p); - } - - friend PyObject* to_python(std::auto_ptr x) { - return boost::python::detail::import_extension_class::get_converters()->to_python(x); - } - - friend boost::shared_ptr& from_python(PyObject* p, boost::python::type&>) { - return boost::python::detail::import_extension_class::get_converters()->shared_ptr_from_python(p); - } - - friend boost::shared_ptr& from_python(PyObject* p, boost::python::type >) { - return boost::python::detail::import_extension_class::get_converters()->shared_ptr_from_python(p); - } - - friend const boost::shared_ptr& from_python(PyObject* p, boost::python::type&>) { - return boost::python::detail::import_extension_class::get_converters()->shared_ptr_from_python(p); - } - - friend PyObject* to_python(boost::shared_ptr x) { - return boost::python::detail::import_extension_class::get_converters()->to_python(x); - } -}; - -BOOST_PYTHON_END_CONVERSION_NAMESPACE - -namespace boost { namespace python { - -BOOST_PYTHON_IMPORT_CONVERSION(python_import_extension_class_converters); - -// A pointer to this class is exported/imported via the Python API. -// All functions are virtual. This is, what we really export/import -// is essentially just a pointer to a vtbl. -template -struct export_converters_base -{ - virtual const int get_api_major() const { - return detail::EXPORT_CONVERTERS_API_MAJOR; } - virtual const int get_api_minor() const { - return detail::EXPORT_CONVERTERS_API_MINOR; } - virtual PyObject *to_python(const T& x) = 0; - virtual PyObject *to_python(std::auto_ptr x) = 0; - virtual PyObject *to_python(boost::shared_ptr x) = 0; - virtual T* Tptr_from_python(PyObject* obj) = 0; - virtual std::auto_ptr& auto_ptr_from_python(PyObject *obj) = 0; - virtual boost::shared_ptr& shared_ptr_from_python(PyObject *obj) = 0; -}; - -// Converters to be used if T is not copyable. -template -struct export_ptr_converters : export_converters_base -{ - virtual PyObject *to_python(const T& x) { - PyErr_SetString(PyExc_RuntimeError, - "to_python(const T&) converter not exported"); - throw import_error(); - } - virtual PyObject *to_python(std::auto_ptr x) { - return BOOST_PYTHON_CONVERSION::to_python(x); - } - virtual PyObject *to_python(boost::shared_ptr x) { - return BOOST_PYTHON_CONVERSION::to_python(x); - } - virtual T* Tptr_from_python(PyObject* obj) { - return BOOST_PYTHON_CONVERSION::from_python(obj, boost::python::type()); - } - virtual std::auto_ptr& auto_ptr_from_python(PyObject *obj) { - return BOOST_PYTHON_CONVERSION::python_extension_class_converters::ptr_from_python(obj, boost::python::type >()); - } - virtual boost::shared_ptr& shared_ptr_from_python(PyObject *obj) { - return BOOST_PYTHON_CONVERSION::python_extension_class_converters::ptr_from_python(obj, boost::python::type >()); - } -}; - -// The addditional to_python() converter that can be used if T is copyable. -template -struct export_converters : export_ptr_converters -{ - virtual PyObject *to_python(const T& x) { - BOOST_PYTHON_CONVERSION::python_extension_class_converters cv; - return cv.to_python(x); - } -}; - -namespace detail { - -//QUESTIONMARK -// A stripped-down, modified version of class extension_class. -// Would it make sense to establish a formal relationship -// between the two classes? -template -class import_extension_class - : public python_import_extension_class_converters -{ - public: - inline import_extension_class(const char *module, const char* klass) { - m_module = module; - m_klass = klass; - } - - static boost::python::export_converters_base* get_converters(); - - private: - static std::string m_module; - static std::string m_klass; - static boost::python::export_converters_base* imported_converters; -}; - -template std::string import_extension_class::m_module; -template std::string import_extension_class::m_klass; -template -boost::python::export_converters_base* -import_extension_class::imported_converters = 0; - -#ifdef SPECIAL_PYCVTSOBJECT - -// A special PyObject for passing pointers to export_converters_base -template -struct PyCvtsObject { - PyObject_HEAD - export_converters_base* cvts; -}; - -template -void DEL_PyCvtsObject(PyCvtsObject* self) { PyMem_DEL(self); } - -template -PyObject *create_PyCvtsObject(export_converters_base* cvts) -{ - static char PyCvtsObject_Type__doc__[] = - "Boost Python Library (BPL) converters objects to be exported from\n" - "one extension module to another."; - - static PyTypeObject PyCvtsObject_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, /*ob_size*/ - "PyCvtsObject", /*tp_name*/ - sizeof(PyCvtsObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)(static_cast*)> - (DEL_PyCvtsObject)), /*tp_dealloc*/ - (printfunc)0, /*tp_print*/ - (getattrfunc)0, /*tp_getattr*/ - (setattrfunc)0, /*tp_setattr*/ - (cmpfunc)0, /*tp_compare*/ - (reprfunc)0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - (hashfunc)0, /*tp_hash*/ - (ternaryfunc)0, /*tp_call*/ - (reprfunc)0, /*tp_str*/ - - /* Space for future expansion */ - 0L,0L,0L,0L, - PyCvtsObject_Type__doc__ /* Documentation string */ - }; - - PyCvtsObject* self = PyObject_NEW(PyCvtsObject, &PyCvtsObject_Type); - if (self == 0) throw export_error(); - self->cvts = cvts; - return reinterpret_cast(self); -} - -#endif // SPECIAL_PYCVTSOBJECT - -template -boost::python::export_converters_base* -import_extension_class::get_converters() { - if (imported_converters == 0) { -#ifndef SPECIAL_PYCVTSOBJECT - void *cobject - = import_converters(m_module, m_klass, converters_attribute_name); - imported_converters - = static_cast*>(cobject); -#else - ref cvts_obj( - new_import_converters(m_module, m_klass, converters_attribute_name)); - PyCvtsObject* cvts = reinterpret_cast*>(cvts_obj.get()); - imported_converters = cvts->cvts; -#endif - check_export_converters_api( - EXPORT_CONVERTERS_API_MAJOR, - EXPORT_CONVERTERS_API_MINOR, - imported_converters->get_api_major(), - imported_converters->get_api_minor()); - } - return imported_converters; -} - -}}} // namespace boost::python::detail - -namespace boost { namespace python { - -//QUESTIONMARK -// A stripped-down, modified version of class class_builder. -// Would it make sense to establish a formal relationship -// between the two classes? -template -class import_class_builder - : python_import_extension_class_converters -{ - public: - import_class_builder(const char *module, const char* klass) - : m_class(new detail::import_extension_class(module, klass)) - { } - private: - - //QUESTIONMARK - //reference > m_class; - boost::shared_ptr > m_class; -}; - -}} // namespace boost::python - -namespace boost { namespace python { - -// A class_builder that exports the converter functions. -template , - class C = export_converters > -class x_class_builder - : public class_builder -{ - private: - static C export_cvts; - - public: - x_class_builder(module_builder& module, const char* name) - : class_builder(module, name) { -#ifndef SPECIAL_PYCVTSOBJECT - add( - ref(PyCObject_FromVoidPtr(reinterpret_cast(&export_cvts), NULL)), - const_cast(detail::converters_attribute_name.c_str())); -#else - add(ref(detail::create_PyCvtsObject(&export_cvts)), - const_cast(detail::converters_attribute_name.c_str())); -#endif - } -}; - -template -C x_class_builder::export_cvts; - -//QUESTIONMARK -// Is there a better way of making it easy for the end-user -// to choose between x_class_builder and xptr_class_builder? -template , - class C = export_ptr_converters > -class xptr_class_builder : public x_class_builder -{ - public: - xptr_class_builder(module_builder& module, const char* name) - : x_class_builder(module, name) { } -}; - -}} // namespace boost::python - -#endif // X_CLASS_BUILDER_HPP From 2d568b1c0fd9b786d93b10e5f96a9118ce865274 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 6 Mar 2001 01:13:35 +0000 Subject: [PATCH 038/369] Fixed a bug which prevented auto_ptr values from being converted to_python [SVN r9455] --- include/boost/python/detail/extension_class.hpp | 14 ++++++++++---- src/gen_extclass.py | 16 +++++++++++----- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/include/boost/python/detail/extension_class.hpp b/include/boost/python/detail/extension_class.hpp index 4afffcae..125f1eed 100644 --- a/include/boost/python/detail/extension_class.hpp +++ b/include/boost/python/detail/extension_class.hpp @@ -9,6 +9,10 @@ // This file automatically generated for 10-argument constructors by // gen_extclass.python +// Revision History: +// 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_ @@ -250,10 +254,12 @@ class python_extension_class_converters throw boost::python::argument_error(); } - // Extract from obj a constant reference to the PtrType object which is holding a T. - // If obj is None, the reference denotes a default-constructed PtrType + // 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 - static const PtrType& smart_ptr_value(PyObject* obj, boost::python::type) + static PtrType& smart_ptr_value(PyObject* obj, boost::python::type) { if (obj == Py_None) { @@ -315,7 +321,7 @@ class python_extension_class_converters friend std::auto_ptr& from_python(PyObject* p, boost::python::type&>) { return smart_ptr_reference(p, boost::python::type >()); } - friend const std::auto_ptr& from_python(PyObject* p, boost::python::type >) + friend std::auto_ptr from_python(PyObject* p, boost::python::type >) { return smart_ptr_value(p, boost::python::type >()); } friend const std::auto_ptr& from_python(PyObject* p, boost::python::type&>) diff --git a/src/gen_extclass.py b/src/gen_extclass.py index 2d261289..8de8a1ae 100644 --- a/src/gen_extclass.py +++ b/src/gen_extclass.py @@ -14,6 +14,10 @@ def gen_extclass(args): // This file automatically generated for %d-argument constructors by // gen_extclass.python +// Revision History: +// 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_ @@ -157,7 +161,7 @@ template bool is_null(const Ptr& x) { return is_null_helper<(is_pointer::value)>::test(x); -}; +} }}} // namespace boost::python::detail @@ -255,10 +259,12 @@ class python_extension_class_converters throw boost::python::argument_error(); } - // Extract from obj a constant reference to the PtrType object which is holding a T. - // If obj is None, the reference denotes a default-constructed PtrType + // 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 - static const PtrType& smart_ptr_value(PyObject* obj, boost::python::type) + static PtrType& smart_ptr_value(PyObject* obj, boost::python::type) { if (obj == Py_None) { @@ -320,7 +326,7 @@ class python_extension_class_converters friend std::auto_ptr& from_python(PyObject* p, boost::python::type&>) { return smart_ptr_reference(p, boost::python::type >()); } - friend const std::auto_ptr& from_python(PyObject* p, boost::python::type >) + friend std::auto_ptr from_python(PyObject* p, boost::python::type >) { return smart_ptr_value(p, boost::python::type >()); } friend const std::auto_ptr& from_python(PyObject* p, boost::python::type&>) From b0d6d40c2a800159cacbe796f96c069ec503fc2a Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 6 Mar 2001 01:14:47 +0000 Subject: [PATCH 039/369] Suppress warnings under Cygwin with Python 2.0 [SVN r9456] --- include/boost/python/detail/wrap_python.hpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/include/boost/python/detail/wrap_python.hpp b/include/boost/python/detail/wrap_python.hpp index d5b75374..b7a47513 100644 --- a/include/boost/python/detail/wrap_python.hpp +++ b/include/boost/python/detail/wrap_python.hpp @@ -16,9 +16,13 @@ // 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 + #ifdef _DEBUG # ifndef BOOST_DEBUG_PYTHON # undef _DEBUG // Don't let Python force the debug library just because we're debugging. @@ -37,9 +41,11 @@ typedef int pid_t; # define WORD_BIT 32 # define hypot _hypot # include -# define HAVE_CLOCK -# define HAVE_STRFTIME -# define HAVE_STRERROR +# 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 From dd0e42cf7252e41d3c3e1c5d5854d614c446d57a Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 6 Mar 2001 02:44:32 +0000 Subject: [PATCH 040/369] temp files before branching [SVN r9457] --- example/dvect.cpp | 68 ++++++++++++++++++++++++++++++++++ example/dvect.h | 32 ++++++++++++++++ example/ivect.cpp | 68 ++++++++++++++++++++++++++++++++++ example/ivect.h | 32 ++++++++++++++++ example/noncopyable.h | 14 +++++++ example/noncopyable_export.cpp | 23 ++++++++++++ example/noncopyable_import.cpp | 41 ++++++++++++++++++++ example/tst_dvect.py | 16 ++++++++ example/tst_ivect.py | 16 ++++++++ example/tst_noncopyable.py | 8 ++++ 10 files changed, 318 insertions(+) create mode 100644 example/dvect.cpp create mode 100644 example/dvect.h create mode 100644 example/ivect.cpp create mode 100644 example/ivect.h create mode 100644 example/noncopyable.h create mode 100644 example/noncopyable_export.cpp create mode 100644 example/noncopyable_import.cpp create mode 100644 example/tst_dvect.py create mode 100644 example/tst_ivect.py create mode 100644 example/tst_noncopyable.py diff --git a/example/dvect.cpp b/example/dvect.cpp new file mode 100644 index 00000000..47f70d3b --- /dev/null +++ b/example/dvect.cpp @@ -0,0 +1,68 @@ +#include "ivect.h" +#include "dvect.h" +#include +namespace python = boost::python; + +namespace { + + vects::ivect dvect_as_ivect(const vects::dvect& dv) + { + vects::ivect iv(dv.size()); + vects::ivect::iterator iviter = iv.begin(); + for (int i = 0; i < dv.size(); i++) iviter[i] = static_cast(dv[i]); + return iv; + } + + boost::python::tuple ivect_as_tuple(const vects::ivect& iv) + { + return iv.as_tuple(); + } + + std::auto_ptr auto_ptr_ivect(const vects::dvect& dv) + { + return std::auto_ptr(new vects::ivect(dvect_as_ivect(dv))); + } + + boost::shared_ptr shared_ptr_ivect(const vects::dvect& dv) + { + return boost::shared_ptr(new vects::ivect(dvect_as_ivect(dv))); + } + + boost::python::tuple auto_ptr_ivect_as_tuple(std::auto_ptr& iv) + { + return iv->as_tuple(); + } + + boost::python::tuple shared_ptr_ivect_as_tuple(boost::shared_ptr& iv) + { + return iv->as_tuple(); + } +} + +extern "C" +DL_EXPORT(void) +initdvect() +{ + try + { + python::module_builder this_module("dvect"); + + python::x_class_builder dvect_class(this_module, "dvect"); + + python::import_class_builder ivect_class("ivect", "ivect"); + + dvect_class.def(python::constructor()); + dvect_class.def(&vects::dvect::as_tuple, "as_tuple"); + dvect_class.def(dvect_as_ivect, "as_ivect"); + + this_module.def(ivect_as_tuple, "ivect_as_tuple"); + dvect_class.def(auto_ptr_ivect, "auto_ptr_ivect"); + dvect_class.def(shared_ptr_ivect, "shared_ptr_ivect"); + this_module.def(auto_ptr_ivect_as_tuple, "auto_ptr_ivect_as_tuple"); + this_module.def(shared_ptr_ivect_as_tuple, "shared_ptr_ivect_as_tuple"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/dvect.h b/example/dvect.h new file mode 100644 index 00000000..8ffe7b50 --- /dev/null +++ b/example/dvect.h @@ -0,0 +1,32 @@ +#ifndef DVECT_H +#define DVECT_H + +#include +#include + +namespace vects { + + struct dvect : public std::vector + { + dvect() : std::vector() {} + dvect(size_t n) : std::vector(n) {} + dvect(boost::python::tuple tuple) : std::vector(tuple.size()) + { + std::vector::iterator v_it = begin(); + for (int i = 0; i < tuple.size(); i++) + v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), + boost::python::type()); + } + + boost::python::tuple as_tuple() const + { + boost::python::tuple t(size()); + for (int i = 0; i < size(); i++) + t.set_item(i, + boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i]))); + return t; + } + }; +} + +#endif // DVECT_H diff --git a/example/ivect.cpp b/example/ivect.cpp new file mode 100644 index 00000000..dfd90fc9 --- /dev/null +++ b/example/ivect.cpp @@ -0,0 +1,68 @@ +#include "ivect.h" +#include "dvect.h" +#include +namespace python = boost::python; + +namespace { + + vects::dvect ivect_as_dvect(const vects::ivect& iv) + { + vects::dvect dv(iv.size()); + vects::dvect::iterator dviter = dv.begin(); + for (int i = 0; i < iv.size(); i++) dviter[i] = static_cast(iv[i]); + return dv; + } + + boost::python::tuple dvect_as_tuple(const vects::dvect& dv) + { + return dv.as_tuple(); + } + + std::auto_ptr auto_ptr_dvect(const vects::ivect& iv) + { + return std::auto_ptr(new vects::dvect(ivect_as_dvect(iv))); + } + + boost::shared_ptr shared_ptr_dvect(const vects::ivect& iv) + { + return boost::shared_ptr(new vects::dvect(ivect_as_dvect(iv))); + } + + boost::python::tuple auto_ptr_dvect_as_tuple(std::auto_ptr& dv) + { + return dv->as_tuple(); + } + + boost::python::tuple shared_ptr_dvect_as_tuple(boost::shared_ptr& dv) + { + return dv->as_tuple(); + } +} + +extern "C" +DL_EXPORT(void) +initivect() +{ + try + { + python::module_builder this_module("ivect"); + + python::x_class_builder ivect_class(this_module, "ivect"); + + python::import_class_builder dvect_class("dvect", "dvect"); + + ivect_class.def(python::constructor()); + ivect_class.def(&vects::ivect::as_tuple, "as_tuple"); + ivect_class.def(ivect_as_dvect, "as_dvect"); + + this_module.def(dvect_as_tuple, "dvect_as_tuple"); + ivect_class.def(auto_ptr_dvect, "auto_ptr_dvect"); + ivect_class.def(shared_ptr_dvect, "shared_ptr_dvect"); + this_module.def(auto_ptr_dvect_as_tuple, "auto_ptr_dvect_as_tuple"); + this_module.def(shared_ptr_dvect_as_tuple, "shared_ptr_dvect_as_tuple"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/ivect.h b/example/ivect.h new file mode 100644 index 00000000..a0187307 --- /dev/null +++ b/example/ivect.h @@ -0,0 +1,32 @@ +#ifndef IVECT_H +#define IVECT_H + +#include +#include + +namespace vects { + + struct ivect : public std::vector + { + ivect() : std::vector() {} + ivect(size_t n) : std::vector(n) {} + ivect(boost::python::tuple tuple) : std::vector(tuple.size()) + { + std::vector::iterator v_it = begin(); + for (int i = 0; i < tuple.size(); i++) + v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), + boost::python::type()); + } + + boost::python::tuple as_tuple() const + { + boost::python::tuple t(size()); + for (int i = 0; i < size(); i++) + t.set_item(i, + boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i]))); + return t; + } + }; +} + +#endif // IVECT_H diff --git a/example/noncopyable.h b/example/noncopyable.h new file mode 100644 index 00000000..de7b3672 --- /dev/null +++ b/example/noncopyable.h @@ -0,0 +1,14 @@ +#ifndef NONCOPYABLE_H +#define NONCOPYABLE_H + +class store +{ + private: + store(const store&) { } // Disable the copy constructor. + int number; + public: + store(const int i) : number(i) { } + int recall() const { return number; } +}; + +#endif // NONCOPYABLE_H diff --git a/example/noncopyable_export.cpp b/example/noncopyable_export.cpp new file mode 100644 index 00000000..31cbe7c8 --- /dev/null +++ b/example/noncopyable_export.cpp @@ -0,0 +1,23 @@ +#include +namespace python = boost::python; + +#include "noncopyable.h" + +extern "C" +DL_EXPORT(void) +initnoncopyable_export() +{ + try + { + python::module_builder this_module("noncopyable_export"); + + python::xptr_class_builder store_class(this_module, "store"); + + store_class.def(python::constructor()); + store_class.def(&store::recall, "recall"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/noncopyable_import.cpp b/example/noncopyable_import.cpp new file mode 100644 index 00000000..f2b2c6d0 --- /dev/null +++ b/example/noncopyable_import.cpp @@ -0,0 +1,41 @@ +#include +namespace python = boost::python; + +#include "noncopyable.h" + +namespace { // Avoid cluttering the global namespace. + + // A function with store objects as both input and output parameters. + // Because the copy constructor is disabled, we cannot pass a store + // object by value. Instead, we pass a smart pointer. + std::auto_ptr add_stores(const store& s1, const store& s2) + { + int sum = s1.recall() + s2.recall(); + std::auto_ptr ss = std::auto_ptr(new store(sum)); + return ss; + } +} + +extern "C" +DL_EXPORT(void) +initnoncopyable_import() +{ + try + { + python::module_builder this_module("noncopyable_import"); + + python::import_class_builder + dvect_class("noncopyable_export", "store"); + + // Imagine all the additional classes with member functions + // that have store objects as input and output parameters. + // Lots and lots of them. + // However, to keep this example simple, we only define a + // module-level function. + this_module.def(add_stores, "add_stores"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/tst_dvect.py b/example/tst_dvect.py new file mode 100644 index 00000000..563f0ad5 --- /dev/null +++ b/example/tst_dvect.py @@ -0,0 +1,16 @@ +import dvect +print dvect.dvect.__converters__ +dv = dvect.dvect((1,2,3,4,5)) +print dv +print dv.as_tuple() +iv = dv.as_ivect() +print iv +print iv.as_tuple() +print dvect.ivect_as_tuple(iv) +aiv = dv.auto_ptr_ivect() +print aiv +siv = dv.shared_ptr_ivect() +print dvect.auto_ptr_ivect_as_tuple(aiv) +print dvect.ivect_as_tuple(aiv) +print dvect.shared_ptr_ivect_as_tuple(siv) +print dvect.ivect_as_tuple(siv) diff --git a/example/tst_ivect.py b/example/tst_ivect.py new file mode 100644 index 00000000..58bc323f --- /dev/null +++ b/example/tst_ivect.py @@ -0,0 +1,16 @@ +import ivect +print ivect.ivect.__converters__ +iv = ivect.ivect((1,2,3,4,5)) +print iv +print iv.as_tuple() +dv = iv.as_dvect() +print dv +print dv.as_tuple() +print ivect.dvect_as_tuple(dv) +adv = iv.auto_ptr_dvect() +print adv +sdv = iv.shared_ptr_dvect() +print ivect.auto_ptr_dvect_as_tuple(adv) +print ivect.dvect_as_tuple(adv) +print ivect.shared_ptr_dvect_as_tuple(sdv) +print ivect.dvect_as_tuple(sdv) diff --git a/example/tst_noncopyable.py b/example/tst_noncopyable.py new file mode 100644 index 00000000..913df039 --- /dev/null +++ b/example/tst_noncopyable.py @@ -0,0 +1,8 @@ +import noncopyable_export +import noncopyable_import +s1 = noncopyable_export.store(1) +print s1.recall() +s2 = noncopyable_export.store(2) +print s2.recall() +s3 = noncopyable_import.add_stores(s1, s2) +print s3.recall() From 53d2398e0654b67463c4326b7dc8ba134d925711 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 6 Mar 2001 02:45:39 +0000 Subject: [PATCH 041/369] remove temp files after branching. [SVN r9459] --- example/dvect.cpp | 68 ---------------------------------- example/dvect.h | 32 ---------------- example/ivect.cpp | 68 ---------------------------------- example/ivect.h | 32 ---------------- example/noncopyable.h | 14 ------- example/noncopyable_export.cpp | 23 ------------ example/noncopyable_import.cpp | 41 -------------------- example/tst_dvect.py | 16 -------- example/tst_ivect.py | 16 -------- example/tst_noncopyable.py | 8 ---- 10 files changed, 318 deletions(-) delete mode 100644 example/dvect.cpp delete mode 100644 example/dvect.h delete mode 100644 example/ivect.cpp delete mode 100644 example/ivect.h delete mode 100644 example/noncopyable.h delete mode 100644 example/noncopyable_export.cpp delete mode 100644 example/noncopyable_import.cpp delete mode 100644 example/tst_dvect.py delete mode 100644 example/tst_ivect.py delete mode 100644 example/tst_noncopyable.py diff --git a/example/dvect.cpp b/example/dvect.cpp deleted file mode 100644 index 47f70d3b..00000000 --- a/example/dvect.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "ivect.h" -#include "dvect.h" -#include -namespace python = boost::python; - -namespace { - - vects::ivect dvect_as_ivect(const vects::dvect& dv) - { - vects::ivect iv(dv.size()); - vects::ivect::iterator iviter = iv.begin(); - for (int i = 0; i < dv.size(); i++) iviter[i] = static_cast(dv[i]); - return iv; - } - - boost::python::tuple ivect_as_tuple(const vects::ivect& iv) - { - return iv.as_tuple(); - } - - std::auto_ptr auto_ptr_ivect(const vects::dvect& dv) - { - return std::auto_ptr(new vects::ivect(dvect_as_ivect(dv))); - } - - boost::shared_ptr shared_ptr_ivect(const vects::dvect& dv) - { - return boost::shared_ptr(new vects::ivect(dvect_as_ivect(dv))); - } - - boost::python::tuple auto_ptr_ivect_as_tuple(std::auto_ptr& iv) - { - return iv->as_tuple(); - } - - boost::python::tuple shared_ptr_ivect_as_tuple(boost::shared_ptr& iv) - { - return iv->as_tuple(); - } -} - -extern "C" -DL_EXPORT(void) -initdvect() -{ - try - { - python::module_builder this_module("dvect"); - - python::x_class_builder dvect_class(this_module, "dvect"); - - python::import_class_builder ivect_class("ivect", "ivect"); - - dvect_class.def(python::constructor()); - dvect_class.def(&vects::dvect::as_tuple, "as_tuple"); - dvect_class.def(dvect_as_ivect, "as_ivect"); - - this_module.def(ivect_as_tuple, "ivect_as_tuple"); - dvect_class.def(auto_ptr_ivect, "auto_ptr_ivect"); - dvect_class.def(shared_ptr_ivect, "shared_ptr_ivect"); - this_module.def(auto_ptr_ivect_as_tuple, "auto_ptr_ivect_as_tuple"); - this_module.def(shared_ptr_ivect_as_tuple, "shared_ptr_ivect_as_tuple"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/dvect.h b/example/dvect.h deleted file mode 100644 index 8ffe7b50..00000000 --- a/example/dvect.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef DVECT_H -#define DVECT_H - -#include -#include - -namespace vects { - - struct dvect : public std::vector - { - dvect() : std::vector() {} - dvect(size_t n) : std::vector(n) {} - dvect(boost::python::tuple tuple) : std::vector(tuple.size()) - { - std::vector::iterator v_it = begin(); - for (int i = 0; i < tuple.size(); i++) - v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), - boost::python::type()); - } - - boost::python::tuple as_tuple() const - { - boost::python::tuple t(size()); - for (int i = 0; i < size(); i++) - t.set_item(i, - boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i]))); - return t; - } - }; -} - -#endif // DVECT_H diff --git a/example/ivect.cpp b/example/ivect.cpp deleted file mode 100644 index dfd90fc9..00000000 --- a/example/ivect.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "ivect.h" -#include "dvect.h" -#include -namespace python = boost::python; - -namespace { - - vects::dvect ivect_as_dvect(const vects::ivect& iv) - { - vects::dvect dv(iv.size()); - vects::dvect::iterator dviter = dv.begin(); - for (int i = 0; i < iv.size(); i++) dviter[i] = static_cast(iv[i]); - return dv; - } - - boost::python::tuple dvect_as_tuple(const vects::dvect& dv) - { - return dv.as_tuple(); - } - - std::auto_ptr auto_ptr_dvect(const vects::ivect& iv) - { - return std::auto_ptr(new vects::dvect(ivect_as_dvect(iv))); - } - - boost::shared_ptr shared_ptr_dvect(const vects::ivect& iv) - { - return boost::shared_ptr(new vects::dvect(ivect_as_dvect(iv))); - } - - boost::python::tuple auto_ptr_dvect_as_tuple(std::auto_ptr& dv) - { - return dv->as_tuple(); - } - - boost::python::tuple shared_ptr_dvect_as_tuple(boost::shared_ptr& dv) - { - return dv->as_tuple(); - } -} - -extern "C" -DL_EXPORT(void) -initivect() -{ - try - { - python::module_builder this_module("ivect"); - - python::x_class_builder ivect_class(this_module, "ivect"); - - python::import_class_builder dvect_class("dvect", "dvect"); - - ivect_class.def(python::constructor()); - ivect_class.def(&vects::ivect::as_tuple, "as_tuple"); - ivect_class.def(ivect_as_dvect, "as_dvect"); - - this_module.def(dvect_as_tuple, "dvect_as_tuple"); - ivect_class.def(auto_ptr_dvect, "auto_ptr_dvect"); - ivect_class.def(shared_ptr_dvect, "shared_ptr_dvect"); - this_module.def(auto_ptr_dvect_as_tuple, "auto_ptr_dvect_as_tuple"); - this_module.def(shared_ptr_dvect_as_tuple, "shared_ptr_dvect_as_tuple"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/ivect.h b/example/ivect.h deleted file mode 100644 index a0187307..00000000 --- a/example/ivect.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef IVECT_H -#define IVECT_H - -#include -#include - -namespace vects { - - struct ivect : public std::vector - { - ivect() : std::vector() {} - ivect(size_t n) : std::vector(n) {} - ivect(boost::python::tuple tuple) : std::vector(tuple.size()) - { - std::vector::iterator v_it = begin(); - for (int i = 0; i < tuple.size(); i++) - v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), - boost::python::type()); - } - - boost::python::tuple as_tuple() const - { - boost::python::tuple t(size()); - for (int i = 0; i < size(); i++) - t.set_item(i, - boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i]))); - return t; - } - }; -} - -#endif // IVECT_H diff --git a/example/noncopyable.h b/example/noncopyable.h deleted file mode 100644 index de7b3672..00000000 --- a/example/noncopyable.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef NONCOPYABLE_H -#define NONCOPYABLE_H - -class store -{ - private: - store(const store&) { } // Disable the copy constructor. - int number; - public: - store(const int i) : number(i) { } - int recall() const { return number; } -}; - -#endif // NONCOPYABLE_H diff --git a/example/noncopyable_export.cpp b/example/noncopyable_export.cpp deleted file mode 100644 index 31cbe7c8..00000000 --- a/example/noncopyable_export.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include -namespace python = boost::python; - -#include "noncopyable.h" - -extern "C" -DL_EXPORT(void) -initnoncopyable_export() -{ - try - { - python::module_builder this_module("noncopyable_export"); - - python::xptr_class_builder store_class(this_module, "store"); - - store_class.def(python::constructor()); - store_class.def(&store::recall, "recall"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/noncopyable_import.cpp b/example/noncopyable_import.cpp deleted file mode 100644 index f2b2c6d0..00000000 --- a/example/noncopyable_import.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include -namespace python = boost::python; - -#include "noncopyable.h" - -namespace { // Avoid cluttering the global namespace. - - // A function with store objects as both input and output parameters. - // Because the copy constructor is disabled, we cannot pass a store - // object by value. Instead, we pass a smart pointer. - std::auto_ptr add_stores(const store& s1, const store& s2) - { - int sum = s1.recall() + s2.recall(); - std::auto_ptr ss = std::auto_ptr(new store(sum)); - return ss; - } -} - -extern "C" -DL_EXPORT(void) -initnoncopyable_import() -{ - try - { - python::module_builder this_module("noncopyable_import"); - - python::import_class_builder - dvect_class("noncopyable_export", "store"); - - // Imagine all the additional classes with member functions - // that have store objects as input and output parameters. - // Lots and lots of them. - // However, to keep this example simple, we only define a - // module-level function. - this_module.def(add_stores, "add_stores"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/tst_dvect.py b/example/tst_dvect.py deleted file mode 100644 index 563f0ad5..00000000 --- a/example/tst_dvect.py +++ /dev/null @@ -1,16 +0,0 @@ -import dvect -print dvect.dvect.__converters__ -dv = dvect.dvect((1,2,3,4,5)) -print dv -print dv.as_tuple() -iv = dv.as_ivect() -print iv -print iv.as_tuple() -print dvect.ivect_as_tuple(iv) -aiv = dv.auto_ptr_ivect() -print aiv -siv = dv.shared_ptr_ivect() -print dvect.auto_ptr_ivect_as_tuple(aiv) -print dvect.ivect_as_tuple(aiv) -print dvect.shared_ptr_ivect_as_tuple(siv) -print dvect.ivect_as_tuple(siv) diff --git a/example/tst_ivect.py b/example/tst_ivect.py deleted file mode 100644 index 58bc323f..00000000 --- a/example/tst_ivect.py +++ /dev/null @@ -1,16 +0,0 @@ -import ivect -print ivect.ivect.__converters__ -iv = ivect.ivect((1,2,3,4,5)) -print iv -print iv.as_tuple() -dv = iv.as_dvect() -print dv -print dv.as_tuple() -print ivect.dvect_as_tuple(dv) -adv = iv.auto_ptr_dvect() -print adv -sdv = iv.shared_ptr_dvect() -print ivect.auto_ptr_dvect_as_tuple(adv) -print ivect.dvect_as_tuple(adv) -print ivect.shared_ptr_dvect_as_tuple(sdv) -print ivect.dvect_as_tuple(sdv) diff --git a/example/tst_noncopyable.py b/example/tst_noncopyable.py deleted file mode 100644 index 913df039..00000000 --- a/example/tst_noncopyable.py +++ /dev/null @@ -1,8 +0,0 @@ -import noncopyable_export -import noncopyable_import -s1 = noncopyable_export.store(1) -print s1.recall() -s2 = noncopyable_export.store(2) -print s2.recall() -s3 = noncopyable_import.add_stores(s1, s2) -print s3.recall() From 116b3db1d1b6ebbaab7aca99401b6a8dd332d613 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 6 Mar 2001 20:55:09 +0000 Subject: [PATCH 042/369] Fixed typo in use of "PYTHON_LIB" [SVN r9467] --- build/como.mak | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build/como.mak b/build/como.mak index c6f340a5..581eefea 100644 --- a/build/como.mak +++ b/build/como.mak @@ -1,5 +1,7 @@ # Revision History: +# 06 Mar 01 Fixed typo in use of "PYTHON_LIB" (Dave Abrahams) # 04 Mar 01 Changed library name to libboost_python.a (David Abrahams) + LIBSRC = \ classes.cpp \ conversions.cpp \ @@ -33,7 +35,7 @@ endif [ -s $@ ] || rm -f $@ example1: example1.o libboost_python.a - como-dyn-link -o ../example/hellomodule.$(MODULE_EXTENSION) $(PYHTON_LIB) example1.o -L. -lboost_python + como-dyn-link -o ../example/hellomodule.$(MODULE_EXTENSION) $(PYTHON_LIB) example1.o -L. -lboost_python python ../example/test_example1.py example1.o: ../example/example1.cpp From 617bcdac9f81d1486c585158b9c7694f2f5c48fd Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 7 Mar 2001 03:39:31 +0000 Subject: [PATCH 043/369] Major doc updates [SVN r9470] --- doc/building.html | 195 +++++++++++++++++++++++++++++-------- doc/comparisons.html | 61 +++++++----- doc/enums.html | 43 +++++--- doc/example1.html | 112 ++++++--------------- doc/exporting_classes.html | 144 +++++++++++++++++++++++++++ doc/extending.html | 4 +- doc/index.html | 91 +++++++++-------- doc/inheritance.html | 26 ++--- doc/overloading.html | 6 +- doc/overriding.html | 98 +++++++++++-------- doc/pickle.html | 28 +++--- doc/pointers.html | 4 +- doc/special.html | 28 +++--- doc/under-the-hood.html | 4 +- 14 files changed, 551 insertions(+), 293 deletions(-) create mode 100644 doc/exporting_classes.html diff --git a/doc/building.html b/doc/building.html index 4ac2343c..6627bbe8 100644 --- a/doc/building.html +++ b/doc/building.html @@ -1,44 +1,157 @@ - - - Building an Extension Module - + + + + + Building an Extension Module +
      -

      - c++boost.gif (8819 bytes)Building an Extension Module -

      -

      - Right now, the only supported configuration is one in which the BPL - source files are statically linked with the source for your extension - module. You may first build them into a library and link it with your - extension module source, but the effect is the same as compiling all - the source files together. Some users have successfully built the - sources into a shared library, and support for a shared library - build is planned, but not yet implemented. The BPL source files are: -

      -
      -extclass.cpp
      -functions.cpp
      -init_function.cpp
      -module.cpp
      -newtypes.cpp
      -objects.cpp
      -py.cpp
      -subclass.cpp
      -         
      -
      -

      - Next: Enums - Previous: A Peek Under the Hood - Up: Top -

      - © Copyright David Abrahams 2000. 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. -

      - Updated: Nov 26, 2000 +

      c++boost.gif (8819 bytes)Building an + Extension Module

      + +

      The build process for Boost is currently undergoing some evolution, + and, it is to be hoped, improvement. The following facts may help: + +

        +
      • + Makefiles for various platforms reside in the Boost subdirectory + libs/python/build: + +
          +
        • como.mak (Comeau C++ on Linux) + +
        • linux_gcc.mak (GCC on + Linux/Unix) + +
        • gcc.mak (older makefile for GCC + on Linux/Unix. Deprecated.) + +
        • mingw32.mak + (highly-specialized makefile for mingw32 (Win32-targeted) GCC. Read + the header comment). + +
        • tru64_cxx.mak (Compaq + Alpha). +
        +
        + +
      • + A project workspace for Microsoft Visual Studio is provided at libs/python/build/build.dsw. The + include paths for this project may need to be changed for your + installation. They currently assume that python has been installed at + c:\tools\python. Three configurations of all targets are + supported: + +
          +
        • Release (optimization, -DNDEBUG) + +
        • Debug (no optimization -D_DEBUG) + +
        • DebugPython (no optimization, -D_DEBUG + -DBOOST_DEBUG_PYTHON) +
        + +

        When extension modules are built with Visual C++ using + -D_DEBUG, Python defaults to force linking with a + special debugging version of the Python DLL. Since this debug DLL + isn't supplied with the default Python installation for Windows, + Boost.Python uses boost/python/detail/wrap_python.hpp + to temporarily undefine _DEBUG when Python.h is + #included. + +

        If you want the extra runtime checks available with the debugging + version of the library, #define BOOST_DEBUG_PYTHON to + re-enable library forcing, and link with the DebugPython version of + boost_python.lib. You'll need to get the debugging version + of the Python executable (python_d.exe) and DLL + (python20_d.dll or python15_d.dll). The Python + sources include project files for building these. If you download them, change the name of the + top-level directory to src, and install it under + c:\tools\python, the workspace supplied by Boost.Python will + be able to use it without modification. Just open + c:\tools\python\src\pcbuild\pcbuild.dsw and invoke "build + all" to generate all the debugging targets. + +

        If you do not #define BOOST_DEBUG_PYTHON, be sure that + any source files #include <boost/python/detail/wrap_python.hpp> + instead of the usual Python.h, or you will have link + incompatibilities.
        +
        + + +

      • + The makefiles and Visual Studio project can all build at least the + following: + +
          +
        • The boost_python library for static linking with your + extension module. On the various Unices, this library will be + called libboost_python.a. On Win32 platforms, the library + will be called boost_python.lib. + +
        • A comprehensive test of Boost.Python features. This test builds + a Boost.Python extension module, then runs Python to import the + module, and runs a series of tests on it using doctest. Source code for the module + and tests is available in the Boost subdirectory + libs/python/test.
          + + +
        • Various examples from the Boost subdirectory + libs/python/example. Which examples are built currently + depends on the platform. The most up-to-date examples are + getting_startedn.cpp from Ralf W. + Grosse-Kunstleve. All these examples include a doctest modeled + on the comprehensive test above.
          +
          + +
        + +
      • + If your platform isn't directly supported, you can build a static + library from the following source files (in the Boost subdirectory + libs/python/src), or compile them directly and link the + resulting objects into your extension module: + + +
      + +

      Next: Wrapping Enums Previous: A Peek Under the Hood Up: Top + +

      © Copyright David Abrahams 2000. 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. + +

      Updated: Mar 6, 2001

      diff --git a/doc/comparisons.html b/doc/comparisons.html index 336220fb..6f082d51 100644 --- a/doc/comparisons.html +++ b/doc/comparisons.html @@ -6,13 +6,14 @@

      c++boost.gif (8819 bytes)Comparisons with + src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">
      + Comparisons with Other Systems

      CXX

      - Like BPL, CXX attempts to + Like Boost.Python, CXX attempts to provide a C++-oriented interface to Python. In most cases, as with the boost library, it relieves the user from worrying about reference-counts. Both libraries automatically convert thrown C++ @@ -40,9 +41,15 @@

      As far as I can tell, CXX enables one to write what is essentially idiomatic Python code in C++, manipulating Python objects through the - same fully-generic interfaces we use in Python. While you're hardly programming directly to the ``bare - metal'' with CXX, it basically presents a ``C++-ized'' - version of the Python 'C' API. + same fully-generic interfaces we use in Python. While you're hardly + programming directly to the ``bare metal'' with CXX, it basically + presents a ``C++-ized'' version of the Python 'C' API. Some fraction of + that capability is available in Boost.Python through boost/python/objects.hpp, + which provides C++ objects corresponding to Python lists, tuples, + strings, and dictionaries, and through boost/python/callback.hpp, + which allows you to call back into python with C++ arguments.

      Paul F. Dubois, the original @@ -65,7 +72,7 @@ that.''
      -Paul Dubois languages. Swig relies on a parser to read your source code and produce additional source code files which can be compiled into a Python (or Perl or Tcl) extension module. It has been successfully used to create - many Python extension modules. Like BPL, SWIG is trying to allow an + many Python extension modules. Like Boost.Python, SWIG is trying to allow an existing interface to be wrapped with little or no change to the existing code. The documentation says ``SWIG parses a form of ANSI C syntax that has been extended with a number of special directives. As a @@ -78,15 +85,15 @@ that.''
      -Paul Dubois couldnt handle templates, didnt do func overloading properly etc. For ANSI C libraries this was fine. But for usual C++ code this was a problem. Simple things work. But for anything very complicated (or - realistic), one had to write code by hand. I believe BPL doesn't have + realistic), one had to write code by hand. I believe Boost.Python doesn't have this problem[sic]... IMHO overloaded functions are very important to wrap correctly.''
      -Prabhu Ramachandran

      - By contrast, BPL doesn't attempt to parse C++ - the problem is simply + By contrast, Boost.Python doesn't attempt to parse C++ - the problem is simply too complex to do correctly. Technically, one does - write code by hand to use BPL. The goal, however, has been to make + write code by hand to use Boost.Python. The goal, however, has been to make that code nearly as simple as listing the names of the classes and member functions you want to expose in Python. @@ -95,7 +102,7 @@ that.''
      -Paul Dubois SIP is a system similar to SWIG, though seemingly more - C++-oriented. The author says that like BPL, SIP supports overriding + C++-oriented. The author says that like Boost.Python, SIP supports overriding extension class member functions in Python subclasses. It appears to have been designed specifically to directly support some features of PyQt/PyKDE, which is its primary client. Documentation is almost @@ -113,7 +120,7 @@ that.''
      -Paul Dubois to a wide range of computer languages, including Common Lisp, C++, C, Modula-3, and Python. ILU can parse the ISL to generate a C++ language header file describing the interface, of which the user is expected to - provide an implementation. Unlike BPL, this means that the system + provide an implementation. Unlike Boost.Python, this means that the system imposes implementation details on your C++ code at the deepest level. It is worth noting that some of the C++ names generated by ILU are supposed to be reserved to the C++ implementation. It is unclear from the @@ -148,7 +155,7 @@ an inheritance relationship?

      Zope ExtensionClasses

      - ExtensionClasses in Zope use the same underlying mechanism as BPL + ExtensionClasses in Zope use the same underlying mechanism as Boost.Python to support subclassing of extension types in Python, including multiple-inheritance. Both systems support pickling/unpickling of extension class instances in very similar ways. Both systems rely on the @@ -158,31 +165,35 @@ an inheritance relationship?

      The major differences are:

        +
      • Zope is entirely 'C' language-based. It doesn't require a C++ + compiler, so it's much more portable than Boost.Python, which stresses + the limits of even some modern C++ implementations. +
      • - BPL lifts the burden on the user to parse and convert function + Boost.Python lifts the burden on the user to parse and convert function argument types. Zope provides no such facility.
      • - BPL lifts the burden on the user to maintain Python + Boost.Python lifts the burden on the user to maintain Python reference-counts.
      • - BPL supports function overloading; Zope does not. + Boost.Python supports function overloading; Zope does not.
      • - BPL supplies a simple mechanism for exposing read-only and + Boost.Python supplies a simple mechanism for exposing read-only and read/write access to data members of the wrapped C++ type as Python attributes.
      • Writing a Zope ExtensionClass is significantly more complex than - exposing a C++ class to python using BPL (mostly a summary of the + exposing a C++ class to python using Boost.Python (mostly a summary of the previous 4 items). A Zope Example illustrates the differences.
      • Zope's ExtensionClasses are specifically motivated by ``the need for a - C-based persistence mechanism''. BPL's are motivated by the desire + C-based persistence mechanism''. Boost.Python's are motivated by the desire to simply reflect a C++ API into Python with as little modification as possible.
      • - The following Zope restriction does not apply to BPL: ``At most one + The following Zope restriction does not apply to Boost.Python: ``At most one base extension direct or indirect super class may define C data members. If an extension subclass inherits from multiple base extension classes, then all but one must be mix-in classes that @@ -191,21 +202,21 @@ an inheritance relationship? Zope requires use of the somewhat funky inheritedAttribute (search for ``inheritedAttribute'' on this page) - method to access base class methods. In BPL, base class methods can + method to access base class methods. In Boost.Python, base class methods can be accessed in the usual way by writing ``BaseClass.method''.
      • Zope supplies some creative but esoteric idioms such as - Acquisition. No specific support for this is built into BPL. + Acquisition. No specific support for this is built into Boost.Python.
      • Zope's ComputedAttribute support is designed to be used from Python. The analogous feature of - BPL can be used from C++ or Python. The feature is arguably - easier to use in BPL. + Boost.Python can be used from C++ or Python. The feature is arguably + easier to use in Boost.Python.

      - Next: A Simple Example Using BPL + Next: A Simple Example Using Boost.Python Previous: A Brief Introduction to writing Python Extension Modules Up: Top

      @@ -215,6 +226,6 @@ an inheritance relationship? express or implied warranty, and with no claim as to its suitability for any purpose.

      - Updated: Nov 26, 2000 + Updated: Mar 6, 2001

      diff --git a/doc/enums.html b/doc/enums.html index 04138ff1..32d61447 100644 --- a/doc/enums.html +++ b/doc/enums.html @@ -6,7 +6,8 @@

      c++boost.gif (8819 bytes)Wrapping enums + src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">
      + Wrapping enums

      Because there is in general no way to deduce that a value of arbitrary type T @@ -17,24 +18,39 @@ enums). Once you have done that, you can write some simple from_python() and to_python() functions.

      If you are satisfied with a Python int as a way to represent your enum -values, we provide a shorthand for these functions. You just need to -instantiate boost::python::enum_as_int_converters<EnumType> where +values, we provide a shorthand for these functions. You just need to cause +boost::python::enum_as_int_converters<EnumType> to be +instantiated, where EnumType is your enumerated type. There are two convenient ways to do this:

        -
      1. +
      2. Explicit instantiation: + +
        +  template class boost::python::enum_as_int_converters<my_enum>;
        +
        + +Some buggy C++ implementations require a class to be instantiated in the same +namespace in which it is defined. In that case, the simple incantation above becomes: + +
            ...
         } // close my_namespace
        +
         // drop into namespace python and explicitly instantiate
        -BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
        -  template class enum_as_int_converters;
        -BOOST_PYTHON_END_CONVERSION_NAMESPACE
        +namespace boost { namespace python {
        +  template class enum_as_int_converters<my_enum_type>;
        +}} // namespace boost::python
        +
         namespace my_namespace { // re-open my_namespace
            ...
         
        -
      3. +
        +
        +
      4. If you have such an implementation, you may find this technique more convenient +
         // instantiate as base class in any namespace
         struct EnumTypeConverters
             : boost::python::enum_as_int_converters<EnumType>
        @@ -71,7 +87,8 @@ BOOST_PYTHON_END_CONVERSION_NAMESPACE
          long type.
         
         You may also want to add a bunch of lines like this to your module
        -initialization:
        +initialization. These bind the corresponding enum values to the appropriate
        +names so they can be used from Python:
         
         
         mymodule.add(boost::python::to_python(enum_value_1), "enum_value_1");
        @@ -83,12 +100,12 @@ You can also add these to an extension class definition, if your enum happens to
         be local to a class and you want the analogous interface in Python:
         
         
        -my_class.add(boost::python::to_python(enum_value_1), "enum_value_1");
        -my_class.add(boost::python::to_python(enum_value_2), "enum_value_2");
        +my_class_builder.add(boost::python::to_python(enum_value_1), "enum_value_1");
        +my_class_builder.add(boost::python::to_python(enum_value_2), "enum_value_2");
         ...
         

        - Next: Pointers + Next: Pointers and Smart Pointers Previous: Building an Extension Module Up: Top

        @@ -98,6 +115,6 @@ my_class.add(boost::python::to_python(enum_value_2), "enum_value_2"); is'' without express or implied warranty, and with no claim as to its suitability for any purpose.

        - Updated: Nov 26, 2000 + Updated: Mar 6, 2001

      diff --git a/doc/example1.html b/doc/example1.html index 655f3d6a..402cc7a6 100644 --- a/doc/example1.html +++ b/doc/example1.html @@ -18,104 +18,56 @@
       #include <string>
       
      -namespace hello {
      -  class world
      -  {
      -   public:
      -      world(int);
      -      ~world();
      -      std::string greet() const { return "hi, world"; }
      -    ...
      -  };
      -  std::size_t length(const world& x) { return std::strlen(x.greet()); }
      +namespace { // Avoid cluttering the global namespace.
      +
      +  // A couple of simple C++ functions that we want to expose to Python.
      +  std::string greet() { return "hello, world"; }
      +  int square(int number) { return number * number; }
       }
       
       

      - Here is the C++ code for a python module called hello - which exposes the API using: + Here is the C++ code for a python module called getting_started1 + which exposes the API.

       #include <boost/python/class_builder.hpp>
      -// Python requires an exported function called init<module-name> in every
      -// extension module. This is where we build the module contents.
      -extern "C"
      -#ifdef _WIN32
      -__declspec(dllexport)
      -#endif
      -void inithello()
      +namespace python = boost::python;
      +
      +BOOST_PYTHON_MODULE_INIT(getting_started1)
       {
      -    try
      -    {
      -       // create an object representing this extension module
      -       boost::python::module_builder m("hello");
      -       // Create the Python type object for our extension class
      -       boost::python::class_builder<hello::world> world_class(m, "world");
      -       // Add the __init__ function
      -       world_class.def(boost::python::constructor<int>());
      -       // Add a regular member function
      -       world_class.def(&hello::world::get, "get");
      -       // Add a regular function to the module
      -       m.def(hello::length, "length");
      -    }
      -    catch(...)
      -    {
      -       boost::python::handle_exception();    // Deal with the exception for Python
      -    }
      +  try
      +  {
      +    // Create an object representing this extension module.
      +    python::module_builder this_module("getting_started1");
      +
      +    // Add regular functions to the module.
      +    this_module.def(greet, "greet");
      +    this_module.def(square, "square");
      +  }
      +  catch(...)
      +  {
      +    python::handle_exception(); // Deal with the exception for Python
      +  }
       }
      -// Win32 DLL boilerplate
      -#if defined(_WIN32)
      -#include <windows.h>
      -extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID)
      -{
      -    return 1;
      -}
      -#endif // _WIN32
       

      That's it! If we build this shared library and put it on our - PYTHONPATH we can now access our C++ class and function from + PYTHONPATH we can now access our C++ functions from Python.

      ->>> import hello
      ->>> hi_world = hello.world(3)
      ->>> hi_world.greet()
      -'hi, world'
      ->>> hello.length(hi_world)
      -9
      +>>> import getting_started1
      +>>> print getting_started1.greet()
      +hello, world
      +>>> number = 11
      +>>> print number, '*', number, '=', getting_started1.square(number)
      +11 * 11 = 121
       
      -

      - We can even make a subclass of hello.world: -

      -
      ->>> class my_subclass(hello.world):
      -...     def greet(self):
      -...         return 'hello, world'
      -...
      ->>> y = my_subclass(4)
      ->>> y.greet()
      -'hello, world'
      -
      -
      -

      - Pretty cool! You can't do that with an ordinary Python extension type! -

      -
      ->>> hello.length(y)
      -9
      -
      -
      -

      - Of course, you may now have a slightly empty feeling in the pit of - your little pythonic stomach. Perhaps you feel your subclass deserves - to have a length() of 12? If so, read on... -

      - Next: Overridable virtual functions + Next: Exporting Classes Previous: Comparisons with other systems Up: Top

      @@ -125,6 +77,6 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) express or implied warranty, and with no claim as to its suitability for any purpose.

      - Updated: Nov 26, 2000 + Updated: Mar 6, 2000 diff --git a/doc/exporting_classes.html b/doc/exporting_classes.html new file mode 100644 index 00000000..e5932e70 --- /dev/null +++ b/doc/exporting_classes.html @@ -0,0 +1,144 @@ + + + Exporting Classes + +

      +

      + + +

      +

      + Exporting Classes +

      +

      + Now let's expose a C++ class to Python: + +

      +#include <iostream>
      +#include <string>
      +
      +namespace { // Avoid cluttering the global namespace.
      +
      +  // A friendly class.
      +  class hello
      +  {
      +    public:
      +      hello(const std::string& country) { this->country = country; }
      +      std::string greet() const { return "Hello from " + country; }
      +    private:
      +      std::string country;
      +  };
      +
      +  // A function taking a hello object as an argument.
      +  std::string invite(const hello& w) {
      +    return w.greet() + "! Please come soon!";
      +  }
      +}
      +
      +

      + To expose the class, we use a class_builder in addition to the + module_builder from the previous example. Class member functions + are exposed by using the def() member function on the + class_builder: +

      +#include <boost/python/class_builder.hpp>
      +namespace python = boost::python;
      +
      +BOOST_PYTHON_MODULE_INIT(getting_started2)
      +{
      +  try
      +  {
      +    // Create an object representing this extension module.
      +    python::module_builder this_module("getting_started2");
      +
      +    // Create the Python type object for our extension class.
      +    python::class_builder<hello> hello_class(this_module, "hello");
      +
      +    // Add the __init__ function.
      +    hello_class.def(python::constructor<std::string>());
      +    // Add a regular member function.
      +    hello_class.def(&hello::greet, "greet");
      +
      +    // Add invite() as a regular function to the module.
      +    this_module.def(invite, "invite");
      +
      +    // Even better, invite() can also be made a member of hello_class!!!
      +    hello_class.def(invite, "invite");
      +  }
      +  catch(...)
      +  {
      +    python::handle_exception(); // Deal with the exception for Python
      +  }
      +}
      +
      +

      +Now we can use the class normally from Python: + +

      +>>> from getting_started2 import *
      +>>> hi = hello('California')
      +>>> hi.greet()
      +'Hello from California'
      +>>> invite(hi)
      +'Hello from California! Please come soon!'
      +>>> hi.invite()
      +'Hello from California! Please come soon!'
      +
      + +Notes:
        +
      • We expose the class' constructor by calling def() on the + class_builder with an argument whose type is + constructor<params>, where params + matches the list of constructor argument types: + + +
      • Regular member functions are defined by calling def() with a + member function pointer and its Python name: + +
      • Any function added to a class whose initial argument matches the class (or +any base) will act like a member function in Python. +
      +

      + We can even make a subclass of hello.world: + +

      +>>> class wordy(hello):
      +...     def greet(self):
      +...         return hello.greet(self) + ', where the weather is fine'
      +...
      +>>> hi2 = wordy('Florida')
      +>>> hi2.greet()
      +'Hello from Florida, where the weather is fine'
      +>>> invite(hi2)
      +'Hello from Florida! Please come soon!'
      +
      +

      + Pretty cool! You can't do that with an ordinary Python extension type! + + Of course, you may now have a slightly empty feeling in the pit of + your little pythonic stomach. Perhaps you wanted to see the following + wordy invitation: + +

      +'Hello from Florida, where the weather is fine! Please come soon!'
      +
      + + After all, invite calls hello::greet(), and you + reimplemented that in your Python subclass, wordy. If so, read on... + +

      + Next: Overridable virtual functions + Previous: A Simple Example Up: + Top +

      + © Copyright David Abrahams 2000. 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. +

      + Updated: Mar 6, 2001 +

      + diff --git a/doc/extending.html b/doc/extending.html index c4a3a5e4..8839ab43 100644 --- a/doc/extending.html +++ b/doc/extending.html @@ -56,10 +56,10 @@ sublcassing the extension type. Aside from being tedious, it's not really the same as having a true class, because there's no way for the user to override a method of the extension type which is called from the - extension module. BPL solves this problem by taking advantage of Python's metaclass feature to provide objects which look, walk, and hiss almost exactly - like regular Python classes. BPL classes are actually cleaner than + like regular Python classes. Boost.Python classes are actually cleaner than Python classes in some subtle ways; a more detailed discussion will follow (someday).

      Next: Comparisons with Other Systems Up: - The Boost Python Library (BPL) + The Boost Python Library (Boost.Python)

      c++boost.gif (8819 bytes)The Boost Python Library (BPL) + align="center" height="86">
      The Boost Python Library (Boost.Python)

      Synopsis

      @@ -15,9 +15,9 @@ href="http://www.python.org">Python
      such that the Python interface is very similar to the C++ interface. It is designed to be minimally intrusive on your C++ design. In most cases, you should not have to alter - your C++ classes in any way in order to use them with BPL. The system + your C++ classes in any way in order to use them with Boost.Python. The system should simply ``reflect'' your C++ classes and functions into - Python. The major features of BPL include support for: + Python. The major features of Boost.Python include support for:

    Documentation is a major ongoing project; assistance is greatly - appreciated! In the meantime, useful examples of every BPL feature should + appreciated! In the meantime, useful examples of every Boost.Python feature should be evident in the regression test files test/comprehensive.[py/hpp/the boost mailing list.

    - © Copyright David Abrahams 2000. Permission to copy, use, modify, + © Copyright David Abrahams 2001. 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.

    - Updated: Nov 26, 2000 + Updated: Mar 6, 2001 diff --git a/doc/inheritance.html b/doc/inheritance.html index d11899c8..cd95c744 100644 --- a/doc/inheritance.html +++ b/doc/inheritance.html @@ -12,10 +12,10 @@

    Inheritance in Python

    - BPL extension classes support single and multiple-inheritance in + Boost.Python extension classes support single and multiple-inheritance in Python, just like regular Python classes. You can arbitrarily mix built-in Python classes with extension classes in a derived class' - tuple of bases. Whenever a BPL extension class is among the bases for a + tuple of bases. Whenever a Boost.Python extension class is among the bases for a new class in Python, the result is an extension class:

    @@ -37,7 +37,7 @@
     
     

    Reflecting C++ Inheritance Relationships

    - BPL also allows us to represent C++ inheritance relationships so that + Boost.Python also allows us to represent C++ inheritance relationships so that wrapped derived classes may be passed where values, pointers, or references to a base class are expected as arguments. The declare_base member function of @@ -76,11 +76,7 @@ int get_derived_x(const Derived& d) { // namespace alias for code brevity namespace python = boost::python; -extern "C" -#ifdef _WIN32 -__declspec(dllexport) -#endif -void initmy_module() +BOOST_PYTHON_MODULE_INIT(my_module) {     try     { @@ -115,11 +111,19 @@ void initmy_module() >>> derived = Derived() >>> get_name(base) 'Base' -

    objects of wrapped class Derived may be passed where Base is expected
    +
    +
    +objects of wrapped class Derived may be passed where Base is expected +
    +
     >>> get_name(derived) 
     'Derived'
    -
    objects of wrapped class Derived can be passed where Derived is -expected but where type information has been lost.
    +
    +
    +objects of wrapped class Derived can be passed where Derived is +expected but where type information has been lost. +
    +
     >>> get_derived_x(derived_as_base()) 
     -1
     
    diff --git a/doc/overloading.html b/doc/overloading.html index 6979efd0..242e023f 100644 --- a/doc/overloading.html +++ b/doc/overloading.html @@ -29,7 +29,7 @@ private: }; ... -void initoverload_demo() +BOOST_PYTHON_MODULE_INIT(overload_demo) {     try     { @@ -144,12 +144,12 @@ namespace scope as Python member functions. Previous: Overridable Virtual Functions Up: Top

    - © Copyright David Abrahams 2000. Permission to copy, use, modify, + © Copyright David Abrahams 2001. 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.

    - Updated: Nov 26, 2000 + Updated: Mar 6, 2001 diff --git a/doc/overriding.html b/doc/overriding.html index ae629580..7b28add1 100644 --- a/doc/overriding.html +++ b/doc/overriding.html @@ -9,7 +9,7 @@

    Overridable Virtual Functions

    - In the previous example we exposed a simple + In the previous example we exposed a simple C++ class in Python and showed that we could write a subclass. We even redefined one of the functions in our derived class. Now we will learn how to make the function behave virtually when called from C++. @@ -17,16 +17,17 @@

    Example

    -

    In this example, it is assumed that world::greet() is a virtual +

    In this example, it is assumed that hello::greet() is a virtual member function:

    -class world
    +class hello
     {
      public:
    -    world(int);
    -    virtual ~world();
    -    virtual std::string greet() const { return "hi, world"; }
    +    hello(const std::string& country) { this->country = country; }
    +    virtual std::string greet() const { return "Hello from " + country; }
    +    virtual ~hello(); // Good practice 
    +    ...
     };
     
    @@ -37,21 +38,28 @@ class world
      -
    1. A PyObject* data member that holds a - reference to the corresponding Python object. +
    2. A PyObject* data member (usually + called self) that holds a pointer to the Python object corresponding + to our C++ hello instance. -
    3. A constructor for each exposed constructor of the - base class which stores an additional initial PyObject* argument - in the data member described above. +
    4. For each exposed constructor of the + base class T, a constructor which takes the same parameters preceded by an initial + PyObject* argument. The initial argument should be stored in the self data + member described above. + +
    5. If the class being wrapped is ever returned by + value from a wrapped function, be sure you do the same for the + T's copy constructor: you'll need a constructor taking arguments + (PyObject*, const T&).
    6. An implementation of each virtual function you may wish to override in Python which uses - boost::python::callback<return-type>::call_method() to call + callback<return-type>::call_method(self, "name", args...) to call the Python override.
    7. For each non-pure virtual function meant to be overridable from Python, a static member function (or a free function) taking - a reference or pointer to the base type as the first parameter and which + a reference or pointer to the T as the first parameter and which forwards any additional parameters neccessary to the default implementation of the virtual function. See also this note if the base class virtual function is private. @@ -59,52 +67,60 @@ class world
    -struct world_callback : world
    +struct hello_callback : hello
     {
    -    world_callback(PyObject* self, int x) // 2
    -        : world(x),
    -          m_self(self) {}
    +    // hello constructor storing initial self_ parameter
    +    hello_callback(PyObject* self_, const std::string& x) // 2
    +        : hello(x), self(self_) {}
     
    -    std::string greet() const // 3
    -        { return boost::python::callback<std::string>::call_method(m_self, "get"); }
    +    // In case hello is returned by-value from a wrapped function
    +    hello_callback(PyObject* self_, const hello& x) // 3
    +        : hello(x), self(self_) {}
     
    -    static std::string default_get(const hello::world& self) const // 4
    -        { return self.world::greet(); }
    +    // Override greet to call back into Python
    +    std::string greet() const // 4
    +        { return boost::python::callback<std::string>::call_method(m_self, "greet"); }
    +
    +    // Supplies the default implementation of greet
    +    static std::string default_greet(const hello& self) const // 5
    +        { return self.hello::greet(); }
      private:
         PyObject* m_self; // 1
     };
     

    - Finally, we add world_callback to the - class_builder<> declaration in our module initialization + Finally, we add hello_callback to the + class_builder<> declaration in our module initialization function, and when we define the function, we must tell py_cpp about the default implementation:

     // Create the Python type object for our extension class
    -boost::python::class_builder<hello::world,world_callback> world_class(hello, "world");
    +"hello_class">Python type object for our extension class
    +boost::python::class_builder<hello,hello_callback> hello_class(hello, "hello");
     // Add a virtual member function
    -world_class.def(&world::get, "get", &world_callback::default_get);
    +hello_class.def(&hello::greet, "greet", &hello_callback::default_greet);
     

    - Now our subclass of hello.world behaves as expected: + Now our Python subclass of hello behaves as expected:

    ->>> class my_subclass(hello.world):
    +>>> class wordy(hello):
     ...     def greet(self):
    -...         return 'hello, world'
    +...         return hello.greet(self) + ', where the weather is fine'
     ...
    ->>> hello.length(my_subclass())
    -12
    +>>> hi2 = wordy('Florida')
    +>>> hi2.greet()
    +'Hello from Florida, where the weather is fine'
    +>>> invite(hi2)
    +'Hello from Florida, where the weather is fine! Please come soon!'
     
    -

    *You may ask, "Why do we need this derived class? This could have been designed so that everything gets done right - inside of hello::world." One of the goals of py_cpp is to be + inside of hello." One of the goals of py_cpp is to be minimally intrusive on an existing C++ design. In principle, it should be possible to expose the interface for a 3rd party library without changing it. To unintrusively hook into the virtual functions so that a Python @@ -117,10 +133,10 @@ world_class.def(&world::get, "get", &world_callback::default_get) deal with than a virtual function with a default implementation. First of all, you obviously don't need to supply a default implementation. Secondly, you don't need to call - def() on the extension_class<> instance + def() on the extension_class<> instance for the virtual function. In fact, you wouldn't want to: if the corresponding attribute on the Python class stays undefined, you'll get an - AttributeError in Python when you try to call the function, + AttributeError in Python when you try to call the function, indicating that it should have been implemented. For example:

    @@ -132,11 +148,7 @@ struct baz_callback {
         int pure(int x) { boost::python::callback<int>::call_method(m_self, "pure", x); }
     };
     
    -extern "C"
    -#ifdef _WIN32
    -__declspec(dllexport)
    -#endif
    -initfoobar()
    +BOOST_PYTHON_MODULE_INIT(foobar)
     {
         try
         {
    @@ -182,14 +194,14 @@ href="http://cs.calvin.edu/c++/C++Standard-Nov97/basic.html#basic.def.odr">ODR
           Next: Function Overloading
    -      Previous: A Simple Example Using py_cpp
    +      Previous: Exporting Classes
           Up: Top
         

    - © Copyright David Abrahams 2000. Permission to copy, use, modify, + © Copyright David Abrahams 2001. 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.

    - Updated: Nov 26, 2000 + Updated: Mar 6, 2001 diff --git a/doc/pickle.html b/doc/pickle.html index 0e64d6fc..7b559e68 100644 --- a/doc/pickle.html +++ b/doc/pickle.html @@ -1,6 +1,6 @@ - BPL Pickle Support + Boost.Python Pickle Support @@ -11,7 +11,7 @@


    -

    BPL Pickle Support

    +

    Boost.Python Pickle Support

    Pickle is a Python module for object serialization, also known as persistence, marshalling, or flattening. @@ -39,16 +39,16 @@ described in detail in the Python Library Reference for pickle:

    -

    The BPL Pickle Interface

    +

    The Boost.Python Pickle Interface

    -At the user level, the BPL pickle interface involves three special +At the user level, the Boost.Python pickle interface involves three special methods:
    __getinitargs__
    - When an instance of a BPL extension class is pickled, the pickler + When an instance of a Boost.Python extension class is pickled, the pickler tests if the instance has a __getinitargs__ method. This method must return a Python tuple. When the instance is restored by the unpickler, the contents of this tuple are used as the arguments for @@ -63,7 +63,7 @@ methods: __getstate__
    - When an instance of a BPL extension class is pickled, the pickler + When an instance of a Boost.Python extension class is pickled, the pickler tests if the instance has a __getstate__ method. This method should return a Python object representing the state of the instance. @@ -76,7 +76,7 @@ methods: __setstate__
    - When an instance of a BPL extension class is restored by the + When an instance of a Boost.Python extension class is restored by the unpickler, it is first constructed using the result of __getinitargs__ as arguments (see above). Subsequently the unpickler tests if the new instance has a __setstate__ method. If so, this @@ -96,13 +96,13 @@ __setstate__ methods can do what they want.

    Pitfalls and Safety Guards

    -In BPL extension modules with many extension classes, providing +In Boost.Python extension modules with many extension classes, providing complete pickle support for all classes would be a significant overhead. In general complete pickle support should only be implemented for extension classes that will eventually be pickled. However, the -author of a BPL extension module might not anticipate correctly which +author of a Boost.Python extension module might not anticipate correctly which classes need support for pickle. Unfortunately, the pickle protocol -described above has two important pitfalls that the end user of a BPL +described above has two important pitfalls that the end user of a Boost.Python extension module might not be aware of:
    @@ -116,10 +116,10 @@ Both __getinitargs__ and __getstate__ are not defined. that of the new instance.

    - However, most C++ classes wrapped with the BPL will have member data + However, most C++ classes wrapped with Boost.Python will have member data that are not restored correctly by this procedure. To alert the user to this problem, a safety guard is provided. If both __getinitargs__ - and __getstate__ are not defined, the BPL tests if the class has an + and __getstate__ are not defined, Boost.Python tests if the class has an attribute __dict_defines_state__. An exception is raised if this attribute is not defined: @@ -151,7 +151,7 @@ Both __getinitargs__ and __getstate__ are not defined. __getstate__ is defined and the instance's __dict__ is not empty.

    - The author of a BPL extension class might provide a __getstate__ + The author of a Boost.Python extension class might provide a __getstate__ method without considering the possibilities that:

    @@ -170,7 +170,7 @@ __getstate__ is defined and the instance's __dict__ is not empty. To alert the user to this highly unobvious problem, a safety guard is provided. If __getstate__ is defined and the instance's __dict__ is - not empty, the BPL tests if the class has an attribute + not empty, Boost.Python tests if the class has an attribute __getstate_manages_dict__. An exception is raised if this attribute is not defined: diff --git a/doc/pointers.html b/doc/pointers.html index e26cea02..fdbee797 100644 --- a/doc/pointers.html +++ b/doc/pointers.html @@ -13,7 +13,7 @@

    In general, raw pointers passed to or returned from functions are problematic -for BPL because pointers have too many potential meanings. Is it an iterator? +for Boost.Python because pointers have too many potential meanings. Is it an iterator? A pointer to a single element? An array? When used as a return value, is the caller expected to manage (delete) the pointed-to object or is the pointer really just a reference? If the latter, what happens to Python references to the @@ -46,7 +46,7 @@ const Foo& f_wrapper() { return *f(); } my_module.def(f_wrapper, "f");

    -Foo must have a public copy constructor for this technique to work, since BPL +Foo must have a public copy constructor for this technique to work, since Boost.Python converts const T& values to_python by copying the T value into a new extension instance. diff --git a/doc/special.html b/doc/special.html index 50cee505..0caa1924 100644 --- a/doc/special.html +++ b/doc/special.html @@ -12,7 +12,7 @@ Overview

    - BPL supports all of the standard special method names supported by real Python class instances except __complex__ (more on the reasons my_class.def(boost::python::constructor<...>()) - (see section "A Simple Example Using BPL").

    + (see section "A Simple Example Using Boost.Python").

    __del__(self)
    @@ -104,7 +104,7 @@ std::string to_string(Foo const& f) boost::python::class_builder<Foo> foo_class(my_module, "Foo"); foo_class.def(&to_string, "__str__"); - Note that BPL also supports automatic wrapping of + Note that Boost.Python also supports automatic wrapping of __str__ and __cmp__. This is explained in the next section and the Table of Automatically Wrapped Methods. @@ -117,7 +117,7 @@ foo_class.def(&to_string, "__str__"); href="http://www.python.org/doc/current/ref/numeric-types.html">numeric protocols. This is the same basic technique used to expose to_string() as __str__() above, and is covered in detail below. BPL also supports + href="#numeric_manual">covered in detail below. Boost.Python also supports automatic wrapping of numeric operators whenever they have already been defined in C++. @@ -174,7 +174,7 @@ a = i + b; bignum_class.def(boost::python::operators<boost::python::op_add>(), boost::python::right_operand<int>()); bignum_class.def(boost::python::operators<boost::python::op_add>(), boost::python::left_operand<int>()); - BPL uses overloading to register several variants of the same + Boost.Python uses overloading to register several variants of the same operation (more on this in the context of coercion). Again, several operators can be exported at once:
    @@ -283,13 +283,13 @@ bignum_class.def(&rmod,  "__rmod__");
           coercion functions can be difficult if many type combinations must be
           supported. 
           

    - BPL solves this problem the same way that C++ does: with overloading. This technique drastically simplifies the code neccessary to support operators: you just register - operators for all desired type combinations, and BPL automatically + operators for all desired type combinations, and Boost.Python automatically ensures that the correct function is called in each case; there is no need for user-defined coercion functions. To enable operator - overloading, BPL provides a standard coercion which is implicitly + overloading, Boost.Python provides a standard coercion which is implicitly registered whenever automatic operator wrapping is used.

    If you wrap all operator functions manually, but still want to use @@ -370,7 +370,7 @@ bignum_class.def((ternary_function2)&power, "__pow__"); In the second variant, however, BigNum appears only as second argument, and in the last one it's the third argument. These functions - must be presented to BPL such that that the BigNum + must be presented to Boost.Python such that that the BigNum argument appears in first position:

    @@ -397,7 +397,7 @@ Note that "__rrpow__" is an extension not present in plain Python.
     
     

    Table of Automatically Wrapped Methods

    - BPL can automatically wrap the following special methods: @@ -772,13 +772,13 @@ KeyError: 2

    Customized Attribute Access

    - Just like built-in Python classes, BPL extension classes support special the usual attribute access methods __getattr__, __setattr__, and __delattr__. Because writing these functions can be tedious in the common case where the attributes being accessed are - known statically, BPL checks the special names + known statically, Boost.Python checks the special names

    • @@ -794,7 +794,7 @@ KeyError: 2 following shows how we can implement a ``computed attribute'' in Python:
      ->>> class Range(AnyBPLExtensionClass):
      +>>> class Range(AnyBoost.PythonExtensionClass):
       ...    def __init__(self, start, end):
       ...        self.start = start
       ...        self.end = end
      @@ -810,7 +810,7 @@ KeyError: 2
                Direct Access to Data Members
             
             

      - BPL uses the special + Boost.Python uses the special __xxxattr__<name>__ functionality described above to allow direct access to data members through the following special functions on class_builder<> and diff --git a/doc/under-the-hood.html b/doc/under-the-hood.html index 902804d3..733f0f54 100644 --- a/doc/under-the-hood.html +++ b/doc/under-the-hood.html @@ -22,7 +22,7 @@ "example1.html#add_world_class">add it to the module it goes into the module's dictionary to be looked up under the name "world".

      - BPL uses C++'s template argument deduction mechanism to determine the + Boost.Python uses C++'s template argument deduction mechanism to determine the types of arguments to functions (except constructors, for which we must provide an argument list because they can't be named in C++). Then, it calls the appropriate @@ -48,7 +48,7 @@ the top of your module's init function, then def the member functions later to avoid problems with inter-class dependencies.

      - Next: Building a Module with BPL + Next: Building a Module with Boost.Python Previous: Special Method and Operator Support Up: Top

      From 00cea4ff83e2d64c3273fab652171cf4ca192a88 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 7 Mar 2001 03:40:47 +0000 Subject: [PATCH 044/369] Added getting_started targets [SVN r9471] --- build/build.dsw | 34 ++++++++++++++++++++++++++++++++++ build/build.opt | Bin 86528 -> 116224 bytes 2 files changed, 34 insertions(+) diff --git a/build/build.dsw b/build/build.dsw index f4ee1a11..8de38493 100644 --- a/build/build.dsw +++ b/build/build.dsw @@ -30,6 +30,40 @@ Package=<4> ############################################################################### +Project: "getting_started1"=.\getting_started1\getting_started1.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name bpl_static + End Project Dependency +}}} + +############################################################################### + +Project: "getting_started2"=.\getting_started2\getting_started2.dsp - Package Owner=<4> + +Package=<5> +{{{ + begin source code control + getting_started2 + .\getting_started2 + end source code control +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name bpl_static + End Project Dependency +}}} + +############################################################################### + Project: "rwgk1"=.\rwgk1\rwgk1.dsp - Package Owner=<4> Package=<5> diff --git a/build/build.opt b/build/build.opt index 5086795feff7997de1d0b50d82b2404da330c819..89eb84a706504d37bff9685be4808fda8baf9b81 100644 GIT binary patch literal 116224 zcmca`Uhu)fjZzO8(10BSGsD0CoD6J8;!F$-42&?o00YCn|NsAkxG);Tu3}(d_&*AU zObGn_|Np-N0|Nsy0|NsK0|Nsq0|PkD*%=rZI2afhI2jlixEL51xEUbv&C9^Rz{kMA zz|X+IAi%)DAjrVLAjH7HAk4tPAi}`FAPQ9{&cMJR!N9;E$-uxM#lXNI&A`AQ!@$5G z%fP@O$H2fK4^(z@W##z@X2-z+k|@z+lM0z+l9{z+lY4z+eJZXU4$5V9vn6V8Ot^V9CJ1V8y_| zV9mh5V8g(`V9UV3V8_6~V9&t7;K0DZ;K;zh;Kabd;LO0l;KIPb;L50|P@M0|P@60|P@c0|P?} z0|P@UR8Kks149M_14AYQ149-A14A|g149l214AwY14AAI14BLo1497=14AJL149u5 z14A(b149V|14AhT149`D14B6j149J^14AX$JWxE>FfcIGGB7aIF)%RHGcYhTfZd+Y zkk3%UpuphDkjGHMPz2Ti%E`oGF$Pw6en&1VumLn?y;Loh=LLn1>7I4rQ5gCwZHz{Cj3Y@l=rqLHLDA=7H=6VPf=) zffPaQXJlXn=XaKp)Z!8iXRDZ`{QTmQn4HX{;+TTUl8pSkn55FooRk=lJebf+DJ}rj z0$fQ2Iq}6Mi6xoInt1dfRKYZ|7L})G8*1Uv16B|NCSjU5QY#X33vyBo4e;oLsfmFx zV7dj;Q%g!R^U^`?Eh~hEf)gs8gN9V)j%%dNInlmsioPNPx3)WJQ+6AUT64>g% zhO5T{Kng$@)W!v=gEoJlOb7*%2eF_us3{C?+nhan_AHV(xS>X@`$0Vv3wSo2B`&=%pe*WlUeV8jX*XJZV9N*Ph`CbD}_ON zQR^KBaQy=k2Vsz9Ao?Em^Z-N*|7$gSbg6LZy1`-B|fw&<0Hi&_QL1G{-h`s}2 zAYqUghzp|cf*42`BnIMw=zAar5(bHZxFGsIh=GJbVjwPz2C-rIO~wJxP!gC68V9?f z!o>p`QveGvFff2?Wyo+1Ob9&Q2H|jkYG4SHfq~%%!*50=1|Eh3&#y8V{6mED1gOQ# zOpJy;rOBBoi3-m7dBypk7#NvAtp%9+?~DJGUl8D`1&t|y#{Q7q0V}&46XK1dA+!_0%J0nsNI7#OBOryW3QK==$31A_*%tOKb5VVF9Q zu^=@djLSTbdXRRI8W6^(4x|=jCbp4I^x;1Akvc=zNFDm9;^_F_;7;qKWzpb@A5bP7 z#Um#KM#uj~$Nxsh{{~kXJQC}~kyGN1`VT?anRi00<@%T$Nxs_bXeLLrH58p;9y{8@b&TXVPfD6 zNi8mME-flcRdlh6DK1KmNh~fXOEv>hp(U9)Fj_CUpkOO#xg%)hZ$N5MT7FS(VqS8p zf{{W%eo+Zw&AQMzh0*ap;FdAJu(cfvV+pH9@K^y#Um#KM#uj~$Nxsh|3+3B zPiY-N3;iRf#2xi1CDwebJyY5+7D#U}6N7p`bGYkk_o^)1wHIgzi5MX2@qKWhesg{ElaE zX2^%`LeFQ&VTfn&WXNMk1MhVQX~Bjy7(lC+K{i7$HZ|yC+8_a_{hkZ~44w?}3`ql2}d(Sh$JMuva@nbm#CPvVrL(qapkPGmuhRB+NDA3^r;PV9__NOvbFeEbMf?bgc zKGguEh%lCd?tcf_4Z?(VFfjOn6oC$B058B~Wx!a+$myJuSX>;InOe?jqhIM!4*HCVrUePoDdit{~aCw9UcE2TxIY`tP@90i9703 zPzZqfr=#P)qvOAzv;f1PGy!6R=+W`t(edArSPzc+d9*F&I0tg(E5;b0b~5g>AkoL) z7)Vi!VUvJOUVe!}a(-S(QGQNNYKol*HmeyJz(-UPs~B>~B(bXDr%PgJ;DEV>fdT2j zOYo@Z==k3VTdz1;UQ)Nb1hv0L@yH2*(ec00@xRgWKkAmDqjeJL;W=_j+)x$ zz)c_}P+L(J9WpX-K|?$VOXoXnC+{Lbeo zNGwUt$Vn|r#cL@~PG&I??&nP|BP!6iGxJJ{k~311v+?;6|omo=BDQ2Q^8xDlbK9Z@Pi9(!d?Rv z3WQbhC6%V7r4|uZ$eUjPse%X;;Jn4TiA5#x1tkRPDsD){QB<0TFH|@PJB**`x`ihv zpO`eklUABXL|)}cPAo3LpXE79DnW@0U(L=BQbJUk7AYx8%qs?+`9qxY#GK6Zyxi2h z5~7sz7boTtS58QxyCc51AT=3(KnOyjktmlynpZ?Ln}|)3#HBRilM&&(OjIL=$Ye%j z(~ro82X$MB#8+1&wE+pYhe@p3h$uyfZBp_Q*<2*1jY4E2kk|s1s74?W?Gz%KeMC0q zh;JPd(^98P#5975>yHfPMjdet6jFOF#P*r!+C(I_aYsa}p2$WF zAEbW|sdw?Uu!w2B65U87Vl;p{%_edhA;dSeNNKJR-*6Hktwly+dynX56Om;%kwX+j zb@GU)e~Ij76Wit^wiF<~h9cZkB(i=Yrj{VN&?B;qKvXqL+*l*welc-fdtw`|)E=E6 zrj8}tSR$@(K|=8ly7wJlaZOycPkh6i=xUJY3Wad%ow(s=B3jVIwIGP>Xc1k>k=XeF zIg;?;ED<$7alK07#yE)W#t_?IB)<1dR0EiZaamFu=Y)Ih#Ef?n(^?{_uS;ydlRC{N z;u|Z(HO8 z#=yYvhLs&@KLBJG07(1=t5mX8Oi6xzPH_xml^&GRORY!+DR{{`SvONbH(5amvVK+} zBQ+-{-&z66%P+Q8$S>AQ&Pd5D(ooma(}y6?!NBU8a8)V!$siFlrBIh6sRJpBhYA~7 zE1+=oic0e|qSbZF)MGW3KpP8w!#6O9!L-1`0356!MUd?aAdkFZWd)0Z*hARYkf;NB z4dH*h2?V4R5(*#|L^~)924}>AT=s%h13gWGE=mk=b}G%xNr9%%_!L+QeZ$HPj#x-8 z0(lYb?5OX2q==y&mmVpy7Ur6FScP702i|AQzqF3G!xfF%Cl@mm)93p<|naHJcM6MU0(v0lr`hU=t zNTj`vkV=4vDu&n;NnA=JJ{b|t%fzkJAa0w<==y)ywppY!LSofML@7e-It*eL&JeMB ziO3a}L~p1XUH=c>HcrIaAtD!>lG^GZW@RU0`O|p@MkZ!P9)>Uf|NjSd6JU4(Xfr&cxI3za>fXabUJhDQ-kl_LoGsw%# z`V0&p3}TOBx`zPl{=*`Ma)xwufqPey^Hq4y8M>@Q(R zWdPm12$CWN3o$S;@-Z+l@G~$l5Nm%L$N~)z!N35sKb;|!p@g9XeDh^GLp<0mi3~*y zAa|wU2^B2{CPr2U1_o{t?5_q{Z37~RwciM$7z?RI#{HKwLFTA{2nGh&{EsB$@P5lo;qx8j&h7M~&h3B=h0og1U~UI$0eE5u%to2j0S*46PE;XA@`b_5 z;T{H$_=D6FF_kkIJqekM0!>yxW@JDtglBQbJ4hWw2gviNQy(Cam#l-&wLe3bp8iibRmrzkIw(#J}{5?oq^=+vLj{FAEYWEqUIQ#|3OaM#2q|I z?0#P2wrCT-&77n?v4nS!kIw%XEj~Gn@Ln94~t25zxRld<+{pXwLx>L?8Lb zsuHUpXvmbY0kpyc#6pY>6C4;vjI=`rj(bq&0+RCci%a4mdqUztP9$+&0CXaGQEEnN zUU6nws=TToJjxxqsSWIsIIz+?X)&qBNnay=2A zg^aj^6u)F0bY6u-8^}+H(QgS%Pb0QCK)epp@Cr0B#xMx|1#;3GR$e`QaC||W4icmG zbO6>|0m}DSQVmELXSjkSN90_9Ao!r;_$1Kwnp6U3xf8Jzng?`BJLH&ue8-^^vzDGC zFF%jKT?<4X|5#p>SO6{0@Sk8VoLW%=Dz@_T;=uufUo|&aO)8a+$|rW9ixae#oPeE( z^@jzx2LnkQUf~6;WG>0f&m&+rH)J~kAyq_Ow8B@MnVy$eQd&ePkOedIGE3rNF2o;g zLiG}b$kPzeuVd9DaF4(O-_;NRqYuQOZ z{WLQ#Jtws!KM#NO62HWsA9SThJS4f|H6NH;>oZ};U12HiNt`oOalW^0OwB8zt#|#rQ%}4yqIMFlm zM0P2OYYG!Lzfas@^MpG@#N7lyO!t+@+X6sy;e<;SqFRC=qXfScWC6|9&Is*dJn;M~d4`PY z8V!Nb5Eu=C(GVC7fzc2cQX$aDz`)SNz`)SVz`)SLz`)STz`)SPz`)SXz`)SKz`)SS zz`)SOz`)SWz`)SMz`)SUz`)SQz`)SYz`!tpfq`Kn0|Ub(1_p-73=9lY7#J9)GB7Yq zV_;yI&cMJhgMoqJ-~a#rXE87^%w}LkLUmVtp`9RmZydIkoD4Gatn z8yOfFHZd?TY-V6!*uucTuobFyI|Bp54h9B>oeT^NyBHW4b~7+A>|tPF*vr7cu#bU( zVLw#eK?VkfLktWIhZz_cjxaDV9A#i&IL5%haGZgG;RFK%!$}4PhEog-45t|w7|t*- zFq~yzU^vIXz;K>{f#CuJ1H(lI28K%v3=Ef{=7CyJ*BBTWt}`$&++bi}xXHl4aEpO~ z;Wh&U!yN_&hPw<54EGoq816GLFg##jV0Z}C2RgfAATVtGr(Ak!Nl9j2dVFz7Vo^zI ziXrNnMiF#r^i`n*^edq2hZ_%FY6@zDLe7GQEW{&l_BZ+p(M_l;MA2;{v_KSkN;lGZ z-^G>1)(XXy#d-yaB^i2&1)$^qK&Obu#DLa5A}IuM<1y{SDvVfM3Oy(s+u}+BAxUyT zA+IhSM!}?l9_H{Ag|w&>J+MeTy&H3d=u6gN6ok+frRaxP5X`Hf3XVW31t}pahCm9T z?id!QToAuVftZB_q%Q0sdbtbX#j8Xt)gf|jmdIHtBGy)swA6vRmO(1P1m)M02 zB}IvO#cBCPx$z}MiJ2t?7UL1W_J-IAeqyGOiM&pps8w6Uu2&*vnFFayCwPmAo02AK zAy|H1T4p-_6`8~=Atz^ImAFZ4B367+`zCu*mMjsq2m>;6PAF3ly?TuBx)>totO>9C zAZ|vVs0HT4E;%Ch++XnK(nIWeTf%Eih+OAKpits8XVpd?$Y`q~ViyjFt9)_%1BH|Pw5*wJr z#W0asos^oJ$a0O?G(%ioC#Ri6M5CUlW%xvuaKvr2<0rbULTopVxRsH_W_04au0%C( zi0t+eS0)gyaf#_p6H~Gf+fg8;pdh~MMohPX$VLM(y(l7k@FexSiAx;B?UEv5On~?{ zAkhN?wCTSS-TO@@Tz3=Gfg-hsOwzJ^;#(uc?l>WOOBadFN#aH(U^{aObT^6XeG}1K zC%$1ye2IipoiSMP6*kmR=c0oi-lW=dJ*d8-+dr?Vgj}ke~Ky<$vRD%*O zGKlJl5ZenPc7&1WUMaB_6EP}HTvwlP+nw0q3R1`Di5Oudy4yfZqlZ-Y5!?7AqPQU< zwuo$j5ZRa{qP;*;TZZT+0}By!k}=u>!zZN!q;AtI{fPSju~k*C~{(76ZC!VvC!5IY`BM9&VCs7BNr0`bGL zkZuDq30hq>ibq3WGz3ONU^E0qLjW@b{xdSNF$pj*jPC!$44YAr(GVC7fzc2c4S~@R z7!85Z5Eu=C(GVDJA%JWDuMz5YO7#7|MuhhNqUlH9Q;3j8+W!mL4NKJiUqbsZjp)4N z*T`A{+m2r&lpVhypCL9bgHjUuE=okOfH$#%G!VQ$W(WrbWNR{LlP)CcK`g{AGwAzA z(E^98Yg<4eitXl?AsL9E;DQ7kC@n!JUC?*)5=df5I)}yn+X0#fDJd<;A>zJtVwYl% zym=7fXE_M3+!|dKm6u$JbSLlVswn(>bw^i4A*U8n*NqdqVPd4LiXwU;JF&~BMps3_ zSCovdigHN>okWz1TELI4ipont3lbtXNfEJCgXlHvL~gevZbxBeUJ2o4H8fcjMf}zj z;?_?M z=>0DvEyhRvI~oFr5b$IOVDMy!M+lI};$mQ8K)$zt80~97ibOyJ1A{X|4nrbCF+(v! z7(*sQDnmJg0z)`MCPN-W3PV0aIYbd2Qi%-vw}H%q+V8@U%8}0gw$EAcBFxg(06InW2;+mm!rQkD-L27$QtGDME(*S3suAfCvT#*!nLS2Ck%n z9MJ6#C7H<#42%qDt3enU;G@0C1qGm$Cn&o_p<)3ra1{FD*(=MVNpT79ax! z(C-=mg&n$}5d#AQBWqE4dN$SUWdW@zqn0N?xfJAX7-nH$U;tZybp02;1J?+jiZ#0a z3v)3}a$-(SQetv8{&kq6r(&Tl>l!^33(HzJB2S{GJ!^LKzDx| z{JYNZees|23j$oVJPZsBoD2*M%&_hv0|Ns)6i)#4i5VCe5};V_zq|qi1A`ezDM$*Y zZj?rZ*=SgdhQ(k^1B?u;44_SM|Nk>Ga5FeN=M=l;qy*>WCn1drf%A0(d{hX+g$xxz z*x+F#2orr&%n-XUXt0c-Bp!C`x*l{W550Q{6&@Y`3q~8DBx4YBbo?*1A{CU>NB4h* zXXY6jDS)>agR&=d=nQSdpNqjcpeR4fy(qu50ICAAgc>dF;Z%n)u8vbBQdz^uAOx{D zHMs=Qw};wK#6?P@k%q)RRaW(Hx*1qDer`M@Zy{$xaK^K;f=F0d zl~fj_+JF}Gf>w`OSp_AQholylC}`Pf>gegkz!6xNK17p#N@_`BW{!SpMM-L2ab|vA zJosW4P`8;%iO9&v5??CXL!RH95{pv@x5o~U=P{SmqRg_?6vN@{IitbtxfA5YoHKN( z3n{G2fe*aVGubX z2ayxGLF8mOsDp@`qEzITpO2J`-175btp5B0VBg_myOE@GzT^rOB>LJI0gO(qHuvW5FOi6xz4$4qOL2^=Q zW=;xpbi&9WK1DAjCx-$3YXt{q$oc}*BK-V@-hblqXREY)Tt;nF&ies#K6!X>XKNJ2;N3%+EP6kJmC@{4j4a}@kR*A?f%mGm(%91wvj$t=rENmWRyRESC~ z%7>Yu26jbWSz=CRih@gKaY24@CbBE~5e9hXrB);+mna0K7MJG0eLsPL;ea^A22ZFl zU^gHeGLeDd03SpRs2!D-lMmjT3<`xw3=9VZAyUC5iOJat&Kar6@W7wUz;J*cA{&~Q zl3IkUQ=Ea}0H>fg%o&pM3 z&%Bb<^wc5+7p&n%gp#SCbOAF3-QUwdRs*Qq798XpLxfflG}FOGgLdq)g(sFI zXBaXtKo~|ahB1s`!oaYBiGd*i*U-E;kt% z7+yo&3!|Z2q;LUGVnJs%Vj!!zVnD;oJw_|l6OJiTBG7et!LC@7#x*oZMOFo5t$ zXxOj~aM<)QFfh!6CK4D8~Ixb%4VJ2rFX?6X&3i7|?LNpKG|Db3g!93KviY0^xtqKw%l+Kv}}b zz_1lm3Nj#QP=J820`^P3`_$YIQtkF7_Nds0*Qul8D!vr z11WRiOLnN1R6rRAgr7k}gK>aE<0Gilhh`ozC=Ck@gJjr-2uNr^rUhX&Gumn>s)bMl z0|NsHb3-!|!vKd6C^Wc11Oo#DjD~Uub>Z0Y*b-<(RfI*3BbRF>MI^dGzjL~(#pekt;lN(z@W##z@X2-z+k|@z+lM0z+l9{z+lY4z+eJZXU4$5V9vn6V8Ot^V9CJ1V8y_| zV9mh5V8g(`V9UV3V8_6~V9&t7;K0DZ;K;zh-~`p@!oa}b%D}+j#=yYf&cMLn!N9=a z$-uzi#lXPe&A`Cm!@$7c%fP_k2UXw9z`zj5z`zj1z`zj9z`zi~z`zj7z`zj3z`zjB zz`zi}z`zj6z`zj2z`zg<)f3CWz!1m4z!1;Cz>vVez>vtmz>vhiz>v(qz>vbgz>vzo zz>vnkz>vvYfz>vwnz>vkjz>v+rz>vehz>o_yC!c|Vp@4ybp^$-rp@@Njp_qYz zp@e~fp_GAvp^Slnp&Y6X6u(sr3=Gu_3=B043=Fjl3=DM)3=H)Q3=9omx92nDGn6nW zFt{@0F_bVAF;s%GG0|9zffb(Lk;@8f1}MDhZ&P1-fDyU82xrJ=C}PNFC}t>NNMuN6 zNM%r92xcf@NMtAhhXposki`@jm>5Bs4U|4XG_o8nHmDo}CsuIW7ct~Blrt1Fq=Lf{ zmmXZ=0t`%ypu7XhE5zE*12PPhS-|Nng&~un1RM$=VNx+40}~@Ce}e1=VPf=)ffPaQ zXJlXn=X;it)Z!8iXRDZ`{QTmQn4HX{;+TTUl8pSkn55FooRk=lJebf+DJ}rj0$fQ2 zIq}6Mi6xoInt1dfRKYZ|7L})G8*1Uv16B|NCSjU5QY#X33vyBo4e;oLsfmFxV7fu& z8Z(0=0}}&N5vYa&;cJWx41A0X3}#FW4BJ2<0>z+E1YuJq28NxCkdl#+fuR8;whOAB zxq&k%H9fPqB(QB7&j>2DL2QtZKw${NfBygf|MLI; z{~$RK-p|CqFbx#e4V>ZmMcKs#iOH#EoS;BrW?*GtWDqC@nFxwCSh${rhAqfsQ2zV( z|9?HmKe;G1H4l`#K_-B_%Ul8~lR+`52(2SQW`Qu+MGd@Q+ZB8> z^D>=@z$s+&Q9&Cc-u zKV#`xGyt+0gdw(b1f>?|mlh?bLNtN0+W-H|1T?X^WG3e1r^|!Gor!^&;s1XYtXg1h z1(){F5G#d;7>9FyUP)1YPBAFBKn)*|L9C?)po9pjl0k(6)YC`~b}vdS$jD4C7G(sr zmRP{Hvw<~%6jd=XFnBRS>VFU)2*TY)lv<14B6z z1H)-XNRtBHm?I1f3{BAH26F>vNNPoiLP&mojyMa*L68vSD4hg#xdsyh!wG0cftkeI zz~Y*cSpo}kCQ$8-HT)17SY1++O4H52Ar5NM{r}HUwulkZ=4)kww2eTjVIdAmqqYnT z4O1Bz7$(C*oXx2yzq~jV)c67=PmsloWoYT+EXWuT1_d2+18ZPuYEdPqsR+^`3(CLc z_;m=lB$gy5B^IYDxMU`#7bWH*Yi1;%nKdLaDJKp3*%;gr0kVa)E zBczcB@(~C_e8m!$nOcr)3k#^R29kqgkYW%92{1SC1%q>m0yN3OLJ(Xq5^x|}P-=31 zQ3}j935Ngw69{PG49~1eEJ|@oEHZ+|I1j`B{~hHMnHU&AF*<>nf#EAOfg#8Epa1{s zGng0{BAFni(t|hsjQ{^LGH@_ByW}Tlhv%g*GRUwnH2nJizaA9%utF8mhm-=f%E5Ik z0|RT3BttQ%RR?OMf`Wj7f#JoR4o2k$CQ$#g;V0CDzu+<-s(_&a)E}*fmk1H+6W1_q^K28OA{3=Fy@3=9S(3=D=P3=E|u3=ES>7#P-;Ffgny zVPM!^!oYB^gn@yjl!1Z0l!1Yxlz}0vl!2kDl!0MFDFefiQU-=&r3?(`N*Ng5mNGDW zC}m*ySjxcQSjNE6TE@U|v5bL1qMU&trksIcWjO=GnQ{h(kL3&uIu#5IdKC-|W)%z! zu@wvqy%h`$eH9E02P+sDu2nEFysKbf(5Pf!aI9otNUmgHSW?NraIlhr;cX=YgJ~55 zLs%69Lr)b0!)<5>&7qosVOliIMdeoec~OyFeYgMg|70Mg|7$Mg|7cMg|7Y zMg|6-Mg|7oMh1r2jSLL88yOgsniv?on-~~6niv?mniv=+H!(2mYhqw{+{D1}q=|t+ zvYCNFu9<-$rI~@DznOtyW-|lBnq~%u_00?n8=4syZZ|V9+-+uHc-G9oAkxCXpx?s4 zVA8_CP}{=5P}jo1u)BqU;dKiGgJ3HIgLEqcgMBLlgHtO5gL5kbgIg;DLv||zLtZNb zLw+j*Lw73!!T43AqG7zElF7=+pw7=+sx81&m17&6)z7&_Y+7`odS7oeT`$I~f>QyBHYQyBHWax)>N#x)>Pzx)>M& zx)>PhyBHW6yBHXnx)>Oyb}=yA>0)5G*Tujf-Oa$@*v-HY*Ui9?(9OV**v-ID(#^oI zx0``se>VdIQx5}!Mh^o+a1R4RK@S5%Q4a${aSsDSTMq-nnH~m)b3F_U-+LGse)cdh z{OVy~;O%8#i0oxxi0)-zXzyiU=Q+;FgpJCe{}qBbo_60{BLypZ*=@` zbo>w6JQ$@0Q3(8pj{k8eq_f;e0CoEZk>f_4G8zJ-Awbg*;9y{8@b&TXVPfD6Ni8mM zE-flcRdlh6DK1KmNh~fXOEv>hp(U9)Fj_CUpkOO#xg%)hZ$N5MT7FS(VqS8pf{{W% zeo+Zw&AOn45+F|{_?fbS)*1gu&}DnhzyO+=XZXAaJR->elLM&(VbH+dS3GjR@yPu{ zlLOf&zzDIAWiP6IAUQ#(92*unA*dWT7P%KtKM0`7f!q(mAU}xWk(0t92O4dWMUw-$ zlNIU~Y;wX-IVCLmM4*cZRj|mh;gMs9nu)Ftu$Z6w|)4?NW zh(it(W+rHIpfKZr`T?69%$??F`at3!4Dy5M`=8~YC4e_rY{6+4Bo4wLIcYp{N;u>| zdX@3Wf#gT=Xb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S0iBLx1lLe~FPFzPdmj{i|3 zL`TgS4S}H(0@(Inhcjd{ecgC|2CLmC5UuRBN|Hmm{N{|&Mmgt4hX7t;m_K=(g; zG6XPqGQ=|^F%*DpEQanq&jjzt2PwplwAhj4-g2OE{Cl#Sb9=>^3K^?qnT-{2+M4_N4KPxr4M59HEaR{JT3Q+?g(R{-&I{wQ5 zABP8xosN$GGBAve{}L{fMpcZ4z-S1JhQMeDjE2By2#kinXb6mkz-R~z&JY+K{~et1 zGU}?)5THj0IL?6_9426smtUfg3^^1nCpE=RBpJ(DkPMKqLShv|PI@F(HT;N23=JGG zw=gguojM5`KO7zZ1D&ahwq6l5RyVr-lYs%-8qd-7pY$kIM(r34fzc2c4S~@R7!85Z z5Eu=C(GVC7fzc2cj3F>O{x=w7Wzu z0~aK;-HY-|3!o}kIYeB%!ci7L;!($(l3KvXAj076l3I|Omy(*7T z=jNxB=A`0N#g&|&mzJ51-%1Y1NB@t>!6L$*dNy$tmB7iwEa|`l|O7L06lbfGXTv|X#8GB}O zD*mLwnM~OC{H1xB$@wWnWMPhiNQPIs?l$e)Jgw1@psU;ctDTF=4 zm6%jqQk0mCH+Z>0DpHdY2_)U*{JgT%qTDAW0i6LX0xhae3$WD?Zg8^xm`Fd71*Auv!OFgpG>P$55R?`Q}Nd{0*PL6oYAjhXFWPL5d(VpCFICVTIhV4q^{s zUqhk}3v$^DRt@wt2|6e}z}cxZGbaU_KI2nhDfA61 zH#oW>xd`M*M94sAK+&g{ab_A&fq)}5fu!&TG)Mu|K59=a^97|ALvE)BP3sopnSw^z zxx>gH1ewrIO)f!9NJCvn%^7IOXe-esLX<D&7#J9M85kIdwLb=Ayb6dw*bm{6PI56Yf$as^4Z_5j zkOxu(J%8SrA%`K6p_rkVA&eoDA(f$=L4kq9^Y=-%zY@uQ*!+(qf!SpEQDuq$2&+JL(d<{s*?_6KR}!bpID<6D(4IjPCzJ z3y{(MUzJG7V|4!)V%BeT{}+4$baek0sGTy3M?+vV1cqV=jL!cI#aJ74^JoZACj>_4 zf2b3Vqo$08z)%bU*!aH$Xy6-l3>&g)odYC+KKhSSwFpQx+!&;>f5ryTEy18cRKyrD z!2xo_h&yBexd(MlASpk;xFjC3HzXcpF^Tg7pmT(ZQZrKXiZjbntrbwXh|zx?1$ABB zq@w)n)I8n9(vp1Lf|4T4jUGZE`{5o3&jElu3-LC{^+b3UGV%^m{E~Ihc@+|EAU`2S z!Eq)7kTQtZL9ADx%b^(tp}#;*dc(@Arw@)VNO}i}QF~edYpwv57FbdZNEm0hf+R=h z1dtCCL?7|zCGyxi;!h;w0iDAHImip&fk&jCLPzYmQ$!zRMdHClM4nqmR02-qFE2_gfHs-%JCFE*Z6eR4B<^rlBF?}h_ViF< zXKaW)p^)%iCr;3zbOd66*fUzNS%AtRJ#hK}Oi6x~)1d}g>myZBDIB$IJ>rEG4e$CI0M8Vo!%9 zYSSk%CkqpK3MXlYOT&(q#+PG>If0m*U3*kKla}~HJ&9bs!c&w8s<%Ps+~Nxw>sO)G64A&5Vt^bi>KsuihbR{I(o=u0 z2g;-=R19MV3@VN^g9a5ro4J6Bq7U*yh2bOXP(E~?1t7Jo1>U?|5p z!jb_wEI`YaSiw7dsbv}qXsHkb10y3w5DS8)E#NDX^sxJnkpWFv1|&WRdjoxcItv2> z1K2T0Q4jGdJOuy$XJCMwX*;_9CkERwub`ZOSP%tWn}fbBcy#>_-R>M6UH?Pm#bu-G ze-Qf_QK~Y$7uJrh|A7{9qw9a5MH)HBuOkuK$5%u+jBDm>Fzz z{ZBITkp!dbe{kI^Kf3-0GxK0y{{z|oo5}{8|0Dg@-qH0x!*y(E)L+9t1R5C_7@8Ou z824}E=n&@U_-}l1 zNn%N6GH5gz8d{^{zeObq1G|M6wAXWV|0iU{Gsg4*7vzdA_oDpL0%)HUq7tcO7AWPtK3HSe=^`4LMcwnO(kw?Z%Srz3E|CPqx(O>7o&~t z|3odGNB4hXIh=WP|0hOKjlMJp@7&tx`0wcWZ*Z_v(CGe8(5TEP9t{CpA>hK0%8XgnM3bQVhmc1{ ziP1OSEo>Sm@r6TJcJVul8txKbMf)1RnRjsMRqkP2$1=sj;3Bn8yg^p z><|g*A?#?-904fA(L;KFby`t=F7)swo=(I>so*Vqhb02x03`$MTFG?BQ@wb;uuO;TC z5ArhQ2zfs9FH0@T$xloHrOd${b!2)FIqMB>5AG%}2Ho=W2e-fevoKbJ+ZBk`2&91# zkJhq?ha4YTl3G-Z)Kqaa)Iqdc9KqcUP*G}UWmTM;SX2^UP*N0Mk`HSE6_=z~S%FUE z28pAXGO#Tjb3=SBo&VgF1(A^sS^z_uZdO(qsW~a}nR&$}iFwJX$iZP`r+^~__4M=x zv`t7Lq$o>FPRNPLiQL5GWH_i36F)_X3DiCzH93Lw4AlfhS=MvQ&qper-175b^$m{P z1|3DYpX5axK zTwVG9LIa<623>%G0t@G@4j@So)=IXDDap^zK^Z?SNCqD^4;@l9GKf#nOUcP$kY!+C zU}a!*-~?TOP?Vpe>kMmja4;}B@WMo$ic%A^VKPh%3=N_#i6x1k5h4ZO%;LnH%=En6 z)Vvay3RVV&0|Ji8$*IM~3SpV~IpEV%VUlbN3j)H$dYEfbyTuC1T!vPVflFYKqlvIVJN`O!v-b>h5(Q|L4F#=qalDL1V+#Q!xAW?LZcxtLPB8l{J#+r(WBlR4FN16P|w^r zdj2Pta2XXE4S~@R7!85Z5Eu=C;T!^N42%q%3>BuTBNlnht($q+TFFXXVR?xJ=vT|6#pu)hw z!rUY^(FC!G*oXnN8XRK33xtA`YB-k{!|pyT2A!6xR&C_yYGm$c?5t~O?q;fMXy{^~ z>*!|aq-$W{Xy9yV;AZLKYF5j@09|~}02&+vEwcpSKmY&#fBFCae~=sq-)CfC*u}`e zz&^m?a+869;WacQU^JA=fCv}xWFvHvAO^A|AOZGgiCUwYAkrx$GDf=DwN1qD!wzP=x%uCKGO-YUM zb@lZRill0oTw;RcBbEUU6Oi9QafD2R*dVNoEliw)LSjI}^nR}4dd>j>R4H6Q83=^` zK?8+(fCFU-BLl-$P$|fOpg{ow!V1_k5oi+#Ct z7(|e0ko!Pb8y+IayIerWxyN9f+)kC`0;-2V_yRKngEkLV)D`Tzj?)(`FZilIf=!^*w@=TB^E=@|1GhCo&ReE z={w?HPCmN+7u4RfvKn3gi!WV`uKy*jkQ!b8TZFa;$SIKuX=il(Z+>10XjSm&`rrIK eP?roe#4)=5cXa(P+7jc@^}nFZF^WfS2mk=&D+65s From 98b31ed07389a28079818dc2806674e5da1f2137 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 7 Mar 2001 03:53:14 +0000 Subject: [PATCH 045/369] use BOOST_PYTHON_MODULE_INIT, update getting_started2 for better documentation [SVN r9472] --- example/getting_started1.cpp | 4 +--- example/getting_started2.cpp | 33 ++++++++++++++++---------------- example/getting_started3.cpp | 4 +--- example/getting_started4.cpp | 4 +--- example/getting_started5.cpp | 4 +--- example/test_getting_started2.py | 26 +++++++++++++++++-------- 6 files changed, 38 insertions(+), 37 deletions(-) diff --git a/example/getting_started1.cpp b/example/getting_started1.cpp index 9679a2a4..7a8e9087 100644 --- a/example/getting_started1.cpp +++ b/example/getting_started1.cpp @@ -12,9 +12,7 @@ namespace python = boost::python; // Python requires an exported function called init in every // extension module. This is where we build the module contents. -extern "C" -DL_EXPORT(void) -initgetting_started1() +BOOST_PYTHON_MODULE_INIT(getting_started1) { try { diff --git a/example/getting_started2.cpp b/example/getting_started2.cpp index 82b4a6df..72b04105 100644 --- a/example/getting_started2.cpp +++ b/example/getting_started2.cpp @@ -1,29 +1,28 @@ #include #include -#include -namespace python = boost::python; namespace { // Avoid cluttering the global namespace. // A friendly class. - class world + class hello { + public: + hello(const std::string& country) { this->country = country; } + std::string greet() const { return "Hello from " + country; } private: std::string country; - public: - world(const std::string& country) { this->country = country; } - std::string greet() const { return "Hello from " + country + "!"; } }; - // A function taking a world object as an argument. - std::string invite(const world& w) { - return w.greet() + " Please come soon!"; + // A function taking a hello object as an argument. + std::string invite(const hello& w) { + return w.greet() + "! Please come soon!"; } } -extern "C" -DL_EXPORT(void) -initgetting_started2() +#include +namespace python = boost::python; + +BOOST_PYTHON_MODULE_INIT(getting_started2) { try { @@ -31,18 +30,18 @@ initgetting_started2() python::module_builder this_module("getting_started2"); // Create the Python type object for our extension class. - python::class_builder world_class(this_module, "world"); + python::class_builder hello_class(this_module, "hello"); // Add the __init__ function. - world_class.def(python::constructor()); + hello_class.def(python::constructor()); // Add a regular member function. - world_class.def(&world::greet, "greet"); + hello_class.def(&hello::greet, "greet"); // Add invite() as a regular function to the module. this_module.def(invite, "invite"); - // Even better, invite() can also be made a member of world_class!!! - world_class.def(invite, "invite"); + // Even better, invite() can also be made a member of hello_class!!! + hello_class.def(invite, "invite"); } catch(...) { diff --git a/example/getting_started3.cpp b/example/getting_started3.cpp index 7e827249..799f5cac 100644 --- a/example/getting_started3.cpp +++ b/example/getting_started3.cpp @@ -91,9 +91,7 @@ namespace { // Avoid cluttering the global namespace. } } -extern "C" -DL_EXPORT(void) -initgetting_started3() +BOOST_PYTHON_MODULE_INIT(getting_started3) { try { diff --git a/example/getting_started4.cpp b/example/getting_started4.cpp index 0c7bd7ee..199ef7a9 100644 --- a/example/getting_started4.cpp +++ b/example/getting_started4.cpp @@ -74,9 +74,7 @@ namespace { // Avoid cluttering the global namespace. } } -extern "C" -DL_EXPORT(void) -initgetting_started4() +BOOST_PYTHON_MODULE_INIT(getting_started4) { try { diff --git a/example/getting_started5.cpp b/example/getting_started5.cpp index c9f1ce36..be033224 100644 --- a/example/getting_started5.cpp +++ b/example/getting_started5.cpp @@ -103,9 +103,7 @@ BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE BOOST_PYTHON_END_CONVERSION_NAMESPACE -extern "C" -DL_EXPORT(void) -initgetting_started5() +BOOST_PYTHON_MODULE_INIT(getting_started5) { try { diff --git a/example/test_getting_started2.py b/example/test_getting_started2.py index 09215816..49cf765d 100644 --- a/example/test_getting_started2.py +++ b/example/test_getting_started2.py @@ -1,11 +1,21 @@ -r'''>>> import getting_started2 - >>> w = getting_started2.world('California') - >>> print w.greet() - Hello from California! - >>> print getting_started2.invite(w) - Hello from California! Please come soon! - >>> print w.invite() - Hello from California! Please come soon! +r'''>>> from getting_started2 import * + >>> hi = hello('California') + >>> hi.greet() + 'Hello from California' + >>> invite(hi) + 'Hello from California! Please come soon!' + >>> hi.invite() + 'Hello from California! Please come soon!' + + >>> class wordy(hello): + ... def greet(self): + ... return hello.greet(self) + ', where the weather is fine' + ... + >>> hi2 = wordy('Florida') + >>> hi2.greet() + 'Hello from Florida, where the weather is fine' + >>> invite(hi2) + 'Hello from Florida! Please come soon!' ''' def run(args = None): From 041409d71570d18cd25351936c4f817db47cd520 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 7 Mar 2001 03:53:56 +0000 Subject: [PATCH 046/369] use BOOST_PYTHON_MODULE_INIT [SVN r9473] --- test/comprehensive.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/test/comprehensive.cpp b/test/comprehensive.cpp index 3d173310..7699b01f 100644 --- a/test/comprehensive.cpp +++ b/test/comprehensive.cpp @@ -1131,11 +1131,7 @@ void init_module() boost_python_test.add(new boost::python::meta_class); } -extern "C" -#ifdef _WIN32 -__declspec(dllexport) -#endif -void initboost_python_test() +BOOST_PYTHON_MODULE_INIT(boost_python_test) { try { bpl_test::init_module(); From a350b666faafe048311aabcc7d9baa48732fce72 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 7 Mar 2001 03:56:25 +0000 Subject: [PATCH 047/369] Added BOOST_PYTHON_MODULE_INIT [SVN r9475] --- include/boost/python/detail/config.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/boost/python/detail/config.hpp b/include/boost/python/detail/config.hpp index 3207f7c6..9792695e 100644 --- a/include/boost/python/detail/config.hpp +++ b/include/boost/python/detail/config.hpp @@ -57,4 +57,10 @@ # define BOOST_CSTD_ std # endif +#ifdef _WIN32 +# define BOOST_PYTHON_MODULE_INIT(name) extern "C" __declspec(dllexport) void init##name() +#else +# define BOOST_PYTHON_MODULE_INIT(name) extern "C" void init##name() +#endif + #endif // CONFIG_DWA052200_H_ From 5759ce9ba0ad80126051762d56492ce0a33b5239 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 7 Mar 2001 22:27:22 +0000 Subject: [PATCH 048/369] no message [SVN r9482] --- build/getting_started1/getting_started1.dsp | 136 ++++++++++++++++++++ build/getting_started2/getting_started2.dsp | 135 +++++++++++++++++++ 2 files changed, 271 insertions(+) create mode 100644 build/getting_started1/getting_started1.dsp create mode 100644 build/getting_started2/getting_started2.dsp diff --git a/build/getting_started1/getting_started1.dsp b/build/getting_started1/getting_started1.dsp new file mode 100644 index 00000000..a41eb057 --- /dev/null +++ b/build/getting_started1/getting_started1.dsp @@ -0,0 +1,136 @@ +# Microsoft Developer Studio Project File - Name="getting_started1" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=getting_started1 - Win32 DebugPython +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "getting_started1.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "getting_started1.mak" CFG="getting_started1 - Win32 DebugPython" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "getting_started1 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "getting_started1 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "getting_started1 - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "getting_started1 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /libpath:"c:\tools\python\libs" + +!ELSEIF "$(CFG)" == "getting_started1 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /GR /GX /ZI /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs" + +!ELSEIF "$(CFG)" == "getting_started1 - Win32 DebugPython" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "DebugPython" +# PROP BASE Intermediate_Dir "DebugPython" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "DebugPython" +# PROP Intermediate_Dir "DebugPython" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /pdb:"DebugPython/boost_python_test_d.pdb" /debug /machine:I386 /out:"DebugPython/getting_started1_d.dll" /pdbtype:sept /libpath:"c:\tools\python\src\PCbuild" +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "getting_started1 - Win32 Release" +# Name "getting_started1 - Win32 Debug" +# Name "getting_started1 - Win32 DebugPython" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\example\getting_started1.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/build/getting_started2/getting_started2.dsp b/build/getting_started2/getting_started2.dsp new file mode 100644 index 00000000..284bab21 --- /dev/null +++ b/build/getting_started2/getting_started2.dsp @@ -0,0 +1,135 @@ +# Microsoft Developer Studio Project File - Name="getting_started2" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=getting_started2 - Win32 DebugPython +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "getting_started2.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "getting_started2.mak" CFG="getting_started2 - Win32 DebugPython" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "getting_started2 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "getting_started2 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "getting_started2 - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "getting_started2" +# PROP Scc_LocalPath "." +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "getting_started2 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /libpath:"c:\tools\python\libs" + +!ELSEIF "$(CFG)" == "getting_started2 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs" + +!ELSEIF "$(CFG)" == "getting_started2 - Win32 DebugPython" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "getting_started2___Win32_DebugPython" +# PROP BASE Intermediate_Dir "getting_started2___Win32_DebugPython" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "getting_started2___Win32_DebugPython" +# PROP Intermediate_Dir "getting_started2___Win32_DebugPython" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /D "BOOST_DEBUG_PYTHON" /FR /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"DebugPython/getting_started2_d.dll" /pdbtype:sept /libpath:"c:\tools\python\src\pcbuild" + +!ENDIF + +# Begin Target + +# Name "getting_started2 - Win32 Release" +# Name "getting_started2 - Win32 Debug" +# Name "getting_started2 - Win32 DebugPython" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\example\getting_started2.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project From 945344b3cd440b9260b2536cb2b3c3f9e0c24714 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 7 Mar 2001 23:31:32 +0000 Subject: [PATCH 049/369] *** empty log message *** [SVN r9483] --- doc/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/index.html b/doc/index.html index 5a64bf62..c6e0722e 100644 --- a/doc/index.html +++ b/doc/index.html @@ -97,7 +97,7 @@ among others.

    • The members of the boost mailing list and the Python community supplied invaluable early feedback. In particular, Ron Clarke, Mark Evans, - Anton Gluck, Chuck Ingold, Prabhu Ramachandran,n and Barry Scott took the + Anton Gluck, Chuck Ingold, Prabhu Ramachandran, and Barry Scott took the brave step of trying to use Boost.Python while it was still in early stages of development. From bdbd9a0f5fcd711bd3fbca0477914fbf9c741348 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 8 Mar 2001 01:32:12 +0000 Subject: [PATCH 050/369] class_builder -> class_builder<your_class> [SVN r9484] --- doc/pickle.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/pickle.html b/doc/pickle.html index 7b559e68..ef3d8d0d 100644 --- a/doc/pickle.html +++ b/doc/pickle.html @@ -132,7 +132,7 @@ Both __getinitargs__ and __getstate__ are not defined. this is, e.g.:
      -    class_builder py_your_class(your_module, "your_class");
      +    class_builder<your_class> py_your_class(your_module, "your_class");
           py_your_class.dict_defines_state();
       
      @@ -185,7 +185,7 @@ __getstate__ is defined and the instance's __dict__ is not empty. E.g. in C++:
      -    class_builder py_your_class(your_module, "your_class");
      +    class_builder<your_class> py_your_class(your_module, "your_class");
           py_your_class.getstate_manages_dict();
       
      From a55948071695439f870126c1d686d4aeac4df8b3 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 8 Mar 2001 03:01:29 +0000 Subject: [PATCH 051/369] py_cpp => Boost.Python [SVN r9485] --- doc/overriding.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/overriding.html b/doc/overriding.html index 7b28add1..b29bf0e6 100644 --- a/doc/overriding.html +++ b/doc/overriding.html @@ -92,7 +92,7 @@ struct hello_callback : hello

      Finally, we add hello_callback to the class_builder<> declaration in our module initialization - function, and when we define the function, we must tell py_cpp about the default + function, and when we define the function, we must tell Boost.Python about the default implementation:

      @@ -120,7 +120,7 @@ hello_class.def(&hello::greet, "greet", &hello_callback::default_gree
           

      *You may ask, "Why do we need this derived class? This could have been designed so that everything gets done right - inside of hello." One of the goals of py_cpp is to be + inside of hello." One of the goals of Boost.Python is to be minimally intrusive on an existing C++ design. In principle, it should be possible to expose the interface for a 3rd party library without changing it. To unintrusively hook into the virtual functions so that a Python From 33ea0dbdeeadd3b4ad77f223843276d9a08867f6 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 9 Mar 2001 02:40:06 +0000 Subject: [PATCH 052/369] temp file before branching [SVN r9515] --- doc/cross_module_dependencies.html | 253 +++++++++++++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 doc/cross_module_dependencies.html diff --git a/doc/cross_module_dependencies.html b/doc/cross_module_dependencies.html new file mode 100644 index 00000000..3d416bf5 --- /dev/null +++ b/doc/cross_module_dependencies.html @@ -0,0 +1,253 @@ + + + Cross-extension-module dependencies + + + +c++boost.gif (8819 bytes) + + +


      +

      Cross-extension-module dependencies

      + +It is good programming practice to organize large projects as modules +that interact with each other via well defined interfaces. With +Boost.Python it is possible to reflect this organization at the C++ +level at the Python level. This is, each logical C++ module can be +organized as a separate Python extension module. + +

      +At first sight this might seem natural and straightforward. However, it +is a fairly complex problem to establish cross-extension-module +dependencies while maintaining the same ease of use Boost.Python +provides for classes that are wrapped in the same extension module. To +a large extent this complexity can be hidden from the author of a +Boost.Python extension module, but not entirely. + +

      The recipe

      + +Suppose there is an extension module that exposes certain instances of +the C++ std::vector template library such that it can be used from +Python in the following manner: + +
      +import std_vector
      +v = std_vector.double([1, 2, 3, 4])
      +v.push_back(5)
      +v.size()
      +
      + +Suppose the std_vector module is done well and reflects all C++ +functions that are useful at the Python level, for all C++ built-in +data types (std_vector.int, std_vector.long, etc.). + +

      +Suppose further that there is statistic module with a C++ class that +has constructors or member functions that use or return a std::vector. +For example: + +

      +class xy {
      +  private:
      +    std::vector<double> m_x;
      +    std::vector<double> m_y;
      +  public:
      +    xy(const std::vector<double>& x, const std::vector<double>& y) : m_x(x), m_y(y) {}
      +    const std::vector<double>& x() const { return m_x; }
      +    const std::vector<double>& y() const { return m_y; }
      +    double correlation();
      +}
      +
      + +What is more natural then reusing the std_vector extension module to +expose these constructors or functions to Python? + +

      +Unfortunately, what seems natural needs a little work in both the +std_vector and the statistics module. + +

      +In the std_vector extension module, std::vector<double> needs to be +exposed to Python with the x_class_builder<> template instead of the +regular class_builder<>. For example: + +

      +  x_class_builder<std::vector<double> > v_double(std_vector_module, "double");
      +
      + +In the extension module that wraps class xy we need to use +the import_class_builder<> template: + +
      +  import_class_builder<std::vector<double> > v_double("std_vector", "double");
      +
      + +That is all. All the properties that are defined for std_vector.double +in the std_vector Boost.Python module will be available for the +returned objects of xy.x() and xy.y(). Similarly, the constructor for +xy will accept objects that were created by the std_vector module. + +

      Non-copyable types

      + +The x_class_builder<T> instantiates template functions that invoke the +copy constructor of T. For a T that is non-copyable this will result in +compile-time error messages. In such a case, another variety of the +class_builder<>, the xptr_class_builder<> must be used. +For example: + +
      +xptr_class_builder<store> py_store(your_module, "store");
      +
      + +The corresponding import_class_builder<> does not need any special +attention: + +
      +import_class_builder<store> py_store("noncopyable_export", "store");
      +
      + +

      Python module search path

      + +The std_vector and statistics modules can now be used in the following +way: + +
      +import std_vector
      +import statistics
      +x = std_vector.double([1, 2, 3, 4])
      +y = std_vector.double([2, 4, 6, 8])
      +xy = statistics.xy(x, y)
      +xy.correlation()
      +
      + +In this example it is clear that Python has to be able to find both the +std_vector and the statistics extension module. In other words, both +extension modules need to be in the Python module search path +(sys.path). + +

      +The situation is not always that obvious. Suppose the statistics +module has a random function that returns a vector of random +numbers with a given length: + +

      +import statistics
      +x = statistics.random(5)
      +y = statistics.random(5)
      +xy = statistics.xy(x, y)
      +xy.correlation()
      +
      + +A naive user will not easily anticipate that the std_vector module is +used to pass the x and y vectors around. If the std_vector module is in +the Python module search path, this form of ignorance is of no harm. +On the contrary, we are glad that we do not have to bother the user +with details like this. + +

      +If the std_vector module is not in the Python module search path, a +Python exception will be raised: + +

      +Traceback (innermost last):
      +  File "foo.py", line 2, in ?
      +    x = statistics.random(5)
      +ImportError: No module named std_vector
      +
      + +As is the case with any system of a non-trivial complexity, it is +important that the setup is consistent and complete. + +

      Two-way module dependencies

      + +Boost.Python supports two-way module dependencies. This is best +illustrated by a simple example. + +

      +Suppose there is a module ivect that implements vectors of integers, +and a similar module dvect that implements vectors of doubles. We want +to be able do convert an integer vector to a double vector and vice +versa. For example: + +

      +import ivect
      +iv = ivect.ivect((1,2,3,4,5))
      +dv = iv.as_dvect()
      +
      + +The last expression will implicitly import the dvect module in order to +enable the conversion of the C++ representation of dvect to a Python +object. The analogous is possible for a dvect: + +
      +import dvect
      +dv = dvect.dvect((1,2,3,4,5))
      +iv = dv.as_ivect()
      +
      + +Now the ivect module is imported implicitly. + +

      +Note that the two-way dependencies are possible because the +dependencies are resolved only when needed. This is, the initialization +of the ivect module does not rely on the dvect module, and vice versa. +Only if as_dvect() or as_ivect() is actually invoked will the +corresponding module be implicitly imported. This also means that, for +example, the dvect module does not have to be available at all if +as_dvect() is never used. + +

      Clarification of compile-time and link-time dependencies

      + +Boost.Python's support for resolving cross-module dependencies at +runtime does not imply that compile-time dependencies are eliminated. +For example, the statistics extension module in the example above will +need to #include <vector>. This is immediately obvious from the +definition of class xy. + +

      +If a library is wrapped that consists of both header files and compiled +components (e.g. libdvect.a, dvect.lib, etc.), both the Boost.Python +extension module with the x_class_wrapper<> and the module with the +import_class_wrapper<> need to be linked against the object library. +Ideally one would build a shared library (e.g. libdvect.so, dvect.dll, +etc.). However, this introduces the issue of getting the search path +for the dynamic loading configured correctly. For small libraries it is +therefore often more convenient to ignore the fact that the object +files are loaded into memory more than once. + +

      +The main purpose of Boost.Python's support for resolving cross-module +dependencies at runtime is to allow for a modular system layout. With +this support it is straightforward to reflect C++ code organization at +the Python level. Without the cross-module support, a multi-purpose +module like std_vector would be impractical because the entire wrapper +code would somehow have to be duplicated in all extension modules that +use it, making them harder to maintain and harder to build. + +

      +Finally, there is an important psychological component. If a group of +classes is lumped together with many others in a huge module, the +authors will have difficulties in being identified with their work. +The situation is much more transparent if the work is represented by +a module with a recognizable name. This is not just a question of +strong egos, but also of getting credit and funding. + +

      Why not use the x_class_builder universally?

      + +There is some overhead associated with the Boost.Python cross-module +support. Depending on the platform, the code generated by +x_class_builder<> is roughly 10%-20% larger than that generated by +class_builder<>. For a large extension module with many wrapped +classes, this could mean a significant difference. Therefore the +general recommendation is to use x_class_wrapper<> only for classes +that are likely to be used as function arguments or return values in +other modules. + +
      +
      +Author: Ralf W. Grosse-Kunstleve, March 2001 +
      + From a6b0fa546a1d0f0cfc08068ebaa9bfad3c7c8b9a Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 9 Mar 2001 02:41:16 +0000 Subject: [PATCH 053/369] temp file removed after branching. [SVN r9516] --- doc/cross_module_dependencies.html | 253 ----------------------------- 1 file changed, 253 deletions(-) delete mode 100644 doc/cross_module_dependencies.html diff --git a/doc/cross_module_dependencies.html b/doc/cross_module_dependencies.html deleted file mode 100644 index 3d416bf5..00000000 --- a/doc/cross_module_dependencies.html +++ /dev/null @@ -1,253 +0,0 @@ - - - Cross-extension-module dependencies - - - -c++boost.gif (8819 bytes) - - -
      -

      Cross-extension-module dependencies

      - -It is good programming practice to organize large projects as modules -that interact with each other via well defined interfaces. With -Boost.Python it is possible to reflect this organization at the C++ -level at the Python level. This is, each logical C++ module can be -organized as a separate Python extension module. - -

      -At first sight this might seem natural and straightforward. However, it -is a fairly complex problem to establish cross-extension-module -dependencies while maintaining the same ease of use Boost.Python -provides for classes that are wrapped in the same extension module. To -a large extent this complexity can be hidden from the author of a -Boost.Python extension module, but not entirely. - -

      The recipe

      - -Suppose there is an extension module that exposes certain instances of -the C++ std::vector template library such that it can be used from -Python in the following manner: - -
      -import std_vector
      -v = std_vector.double([1, 2, 3, 4])
      -v.push_back(5)
      -v.size()
      -
      - -Suppose the std_vector module is done well and reflects all C++ -functions that are useful at the Python level, for all C++ built-in -data types (std_vector.int, std_vector.long, etc.). - -

      -Suppose further that there is statistic module with a C++ class that -has constructors or member functions that use or return a std::vector. -For example: - -

      -class xy {
      -  private:
      -    std::vector<double> m_x;
      -    std::vector<double> m_y;
      -  public:
      -    xy(const std::vector<double>& x, const std::vector<double>& y) : m_x(x), m_y(y) {}
      -    const std::vector<double>& x() const { return m_x; }
      -    const std::vector<double>& y() const { return m_y; }
      -    double correlation();
      -}
      -
      - -What is more natural then reusing the std_vector extension module to -expose these constructors or functions to Python? - -

      -Unfortunately, what seems natural needs a little work in both the -std_vector and the statistics module. - -

      -In the std_vector extension module, std::vector<double> needs to be -exposed to Python with the x_class_builder<> template instead of the -regular class_builder<>. For example: - -

      -  x_class_builder<std::vector<double> > v_double(std_vector_module, "double");
      -
      - -In the extension module that wraps class xy we need to use -the import_class_builder<> template: - -
      -  import_class_builder<std::vector<double> > v_double("std_vector", "double");
      -
      - -That is all. All the properties that are defined for std_vector.double -in the std_vector Boost.Python module will be available for the -returned objects of xy.x() and xy.y(). Similarly, the constructor for -xy will accept objects that were created by the std_vector module. - -

      Non-copyable types

      - -The x_class_builder<T> instantiates template functions that invoke the -copy constructor of T. For a T that is non-copyable this will result in -compile-time error messages. In such a case, another variety of the -class_builder<>, the xptr_class_builder<> must be used. -For example: - -
      -xptr_class_builder<store> py_store(your_module, "store");
      -
      - -The corresponding import_class_builder<> does not need any special -attention: - -
      -import_class_builder<store> py_store("noncopyable_export", "store");
      -
      - -

      Python module search path

      - -The std_vector and statistics modules can now be used in the following -way: - -
      -import std_vector
      -import statistics
      -x = std_vector.double([1, 2, 3, 4])
      -y = std_vector.double([2, 4, 6, 8])
      -xy = statistics.xy(x, y)
      -xy.correlation()
      -
      - -In this example it is clear that Python has to be able to find both the -std_vector and the statistics extension module. In other words, both -extension modules need to be in the Python module search path -(sys.path). - -

      -The situation is not always that obvious. Suppose the statistics -module has a random function that returns a vector of random -numbers with a given length: - -

      -import statistics
      -x = statistics.random(5)
      -y = statistics.random(5)
      -xy = statistics.xy(x, y)
      -xy.correlation()
      -
      - -A naive user will not easily anticipate that the std_vector module is -used to pass the x and y vectors around. If the std_vector module is in -the Python module search path, this form of ignorance is of no harm. -On the contrary, we are glad that we do not have to bother the user -with details like this. - -

      -If the std_vector module is not in the Python module search path, a -Python exception will be raised: - -

      -Traceback (innermost last):
      -  File "foo.py", line 2, in ?
      -    x = statistics.random(5)
      -ImportError: No module named std_vector
      -
      - -As is the case with any system of a non-trivial complexity, it is -important that the setup is consistent and complete. - -

      Two-way module dependencies

      - -Boost.Python supports two-way module dependencies. This is best -illustrated by a simple example. - -

      -Suppose there is a module ivect that implements vectors of integers, -and a similar module dvect that implements vectors of doubles. We want -to be able do convert an integer vector to a double vector and vice -versa. For example: - -

      -import ivect
      -iv = ivect.ivect((1,2,3,4,5))
      -dv = iv.as_dvect()
      -
      - -The last expression will implicitly import the dvect module in order to -enable the conversion of the C++ representation of dvect to a Python -object. The analogous is possible for a dvect: - -
      -import dvect
      -dv = dvect.dvect((1,2,3,4,5))
      -iv = dv.as_ivect()
      -
      - -Now the ivect module is imported implicitly. - -

      -Note that the two-way dependencies are possible because the -dependencies are resolved only when needed. This is, the initialization -of the ivect module does not rely on the dvect module, and vice versa. -Only if as_dvect() or as_ivect() is actually invoked will the -corresponding module be implicitly imported. This also means that, for -example, the dvect module does not have to be available at all if -as_dvect() is never used. - -

      Clarification of compile-time and link-time dependencies

      - -Boost.Python's support for resolving cross-module dependencies at -runtime does not imply that compile-time dependencies are eliminated. -For example, the statistics extension module in the example above will -need to #include <vector>. This is immediately obvious from the -definition of class xy. - -

      -If a library is wrapped that consists of both header files and compiled -components (e.g. libdvect.a, dvect.lib, etc.), both the Boost.Python -extension module with the x_class_wrapper<> and the module with the -import_class_wrapper<> need to be linked against the object library. -Ideally one would build a shared library (e.g. libdvect.so, dvect.dll, -etc.). However, this introduces the issue of getting the search path -for the dynamic loading configured correctly. For small libraries it is -therefore often more convenient to ignore the fact that the object -files are loaded into memory more than once. - -

      -The main purpose of Boost.Python's support for resolving cross-module -dependencies at runtime is to allow for a modular system layout. With -this support it is straightforward to reflect C++ code organization at -the Python level. Without the cross-module support, a multi-purpose -module like std_vector would be impractical because the entire wrapper -code would somehow have to be duplicated in all extension modules that -use it, making them harder to maintain and harder to build. - -

      -Finally, there is an important psychological component. If a group of -classes is lumped together with many others in a huge module, the -authors will have difficulties in being identified with their work. -The situation is much more transparent if the work is represented by -a module with a recognizable name. This is not just a question of -strong egos, but also of getting credit and funding. - -

      Why not use the x_class_builder universally?

      - -There is some overhead associated with the Boost.Python cross-module -support. Depending on the platform, the code generated by -x_class_builder<> is roughly 10%-20% larger than that generated by -class_builder<>. For a large extension module with many wrapped -classes, this could mean a significant difference. Therefore the -general recommendation is to use x_class_wrapper<> only for classes -that are likely to be used as function arguments or return values in -other modules. - -
      -
      -Author: Ralf W. Grosse-Kunstleve, March 2001 -
      - From 55321b87785ef71e51669bc562211dc534884032 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 9 Mar 2001 18:59:59 +0000 Subject: [PATCH 054/369] HTML 4.0 Strict fixes. [SVN r9530] --- doc/pickle.html | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/doc/pickle.html b/doc/pickle.html index ef3d8d0d..49f5c605 100644 --- a/doc/pickle.html +++ b/doc/pickle.html @@ -1,15 +1,15 @@ - - - Boost.Python Pickle Support - - + + +Boost.Python Pickle Support + +
      c++boost.gif (8819 bytes) -

      Boost.Python Pickle Support

      @@ -28,15 +28,14 @@ can be written to a file.

      The Boost Python Library supports the pickle module by emulating the interface implemented by Jim Fulton's ExtensionClass module that is -included in the ZOPE distribution -(http://www.zope.org/). +included in the +ZOPE +distribution. This interface is similar to that for regular Python classes as -described in detail in the Python Library Reference for pickle: - -

      - http://www.python.org/doc/current/lib/module-pickle.html -
      +described in detail in the +Python Library Reference for pickle.

      The Boost.Python Pickle Interface

      @@ -220,4 +219,4 @@ __getstate__ is defined and the instance's __dict__ is not empty.
      Author: Ralf W. Grosse-Kunstleve, March 2001
      - +
      From 494f12090f4090d1678f7f2b5fb06130e9814fca Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 9 Mar 2001 19:02:12 +0000 Subject: [PATCH 055/369] Use only one

      (although the validator did not complain). [SVN r9531] --- doc/pickle.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/pickle.html b/doc/pickle.html index 49f5c605..3ec8c928 100644 --- a/doc/pickle.html +++ b/doc/pickle.html @@ -38,7 +38,7 @@ described in detail in the >Python Library Reference for pickle.
      -

      The Boost.Python Pickle Interface

      +

      The Boost.Python Pickle Interface

      At the user level, the Boost.Python pickle interface involves three special methods: @@ -93,7 +93,7 @@ returned by __getstate__ need not be a dictionary. The __getstate__ and __setstate__ methods can do what they want.
      -

      Pitfalls and Safety Guards

      +

      Pitfalls and Safety Guards

      In Boost.Python extension modules with many extension classes, providing complete pickle support for all classes would be a significant @@ -202,7 +202,7 @@ __getstate__ is defined and the instance's __dict__ is not empty.
      -

      Practical Advice

      +

      Practical Advice

      • From 585063f6e18a37e90febc4409595f99f8d35c3f8 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 9 Mar 2001 20:04:56 +0000 Subject: [PATCH 056/369] Small enhancements. [SVN r9532] --- doc/pickle.html | 136 +++++++++++++++++++++++++++--------------------- 1 file changed, 77 insertions(+), 59 deletions(-) diff --git a/doc/pickle.html b/doc/pickle.html index 3ec8c928..39cb07dc 100644 --- a/doc/pickle.html +++ b/doc/pickle.html @@ -45,81 +45,87 @@ methods:
        -__getinitargs__ +__getinitargs__
        - When an instance of a Boost.Python extension class is pickled, the pickler - tests if the instance has a __getinitargs__ method. This method must - return a Python tuple. When the instance is restored by the + When an instance of a Boost.Python extension class is pickled, the + pickler tests if the instance has a __getinitargs__ method. + This method must return a Python tuple (it is most convenient to use + a boost::python::tuple). When the instance is restored by the unpickler, the contents of this tuple are used as the arguments for the class constructor.

        - If __getinitargs__ is not defined, the class constructor will be - called without arguments. + If __getinitargs__ is not defined, the class constructor + will be called without arguments.

        -__getstate__ +__getstate__
        - When an instance of a Boost.Python extension class is pickled, the pickler - tests if the instance has a __getstate__ method. This method should - return a Python object representing the state of the instance. + When an instance of a Boost.Python extension class is pickled, the + pickler tests if the instance has a __getstate__ method. + This method should return a Python object representing the state of + the instance.

        - If __getstate__ is not defined, the instance's __dict__ is pickled - (if it is not empty). + If __getstate__ is not defined, the instance's + __dict__ is pickled (if it is not empty).

        -__setstate__ +__setstate__
        When an instance of a Boost.Python extension class is restored by the unpickler, it is first constructed using the result of - __getinitargs__ as arguments (see above). Subsequently the unpickler - tests if the new instance has a __setstate__ method. If so, this - method is called with the result of __getstate__ (a Python object) as - the argument. + __getinitargs__ as arguments (see above). Subsequently the + unpickler tests if the new instance has a __setstate__ + method. If so, this method is called with the result of + __getstate__ (a Python object) as the argument.

        - If __setstate__ is not defined, the result of __getstate__ must be - a Python dictionary. The items of this dictionary are added to - the instance's __dict__. + If __setstate__ is not defined, the result of + __getstate__ must be a Python dictionary. The items of this + dictionary are added to the instance's __dict__. +

        -If both __getstate__ and __setstate__ are defined, the Python object -returned by __getstate__ need not be a dictionary. The __getstate__ and -__setstate__ methods can do what they want. +If both __getstate__ and __setstate__ are defined, +the Python object returned by __getstate__ need not be a +dictionary. The __getstate__ and __setstate__ methods +can do what they want.

        Pitfalls and Safety Guards

        -In Boost.Python extension modules with many extension classes, providing -complete pickle support for all classes would be a significant -overhead. In general complete pickle support should only be implemented -for extension classes that will eventually be pickled. However, the -author of a Boost.Python extension module might not anticipate correctly which -classes need support for pickle. Unfortunately, the pickle protocol -described above has two important pitfalls that the end user of a Boost.Python -extension module might not be aware of: +In Boost.Python extension modules with many extension classes, +providing complete pickle support for all classes would be a +significant overhead. In general complete pickle support should only be +implemented for extension classes that will eventually be pickled. +However, the author of a Boost.Python extension module might not +anticipate correctly which classes need support for pickle. +Unfortunately, the pickle protocol described above has two important +pitfalls that the end user of a Boost.Python extension module might not +be aware of:
        Pitfall 1: -Both __getinitargs__ and __getstate__ are not defined. +Both __getinitargs__ and __getstate__ are not defined.
        In this situation the unpickler calls the class constructor without - arguments and then adds the __dict__ that was pickled by default to - that of the new instance. + arguments and then adds the __dict__ that was pickled by + default to that of the new instance.

        - However, most C++ classes wrapped with Boost.Python will have member data - that are not restored correctly by this procedure. To alert the user - to this problem, a safety guard is provided. If both __getinitargs__ - and __getstate__ are not defined, Boost.Python tests if the class has an - attribute __dict_defines_state__. An exception is raised if this + However, most C++ classes wrapped with Boost.Python will have member + data that are not restored correctly by this procedure. To alert the + user to this problem, a safety guard is provided. If both + __getinitargs__ and __getstate__ are not defined, + Boost.Python tests if the class has an attribute + __dict_defines_state__. An exception is raised if this attribute is not defined:

        @@ -147,41 +153,44 @@ Both __getinitargs__ and __getstate__ are not defined.
         

        Pitfall 2: -__getstate__ is defined and the instance's __dict__ is not empty. +__getstate__ is defined and the instance's __dict__ is not empty.
        - The author of a Boost.Python extension class might provide a __getstate__ - method without considering the possibilities that: + The author of a Boost.Python extension class might provide a + __getstate__ method without considering the possibilities + that:

        • - his class is used as a base class. Most likely the __dict__ of - instances of the derived class needs to be pickled in order to - restore the instances correctly. + his class is used in Python as a base class. Most likely the + __dict__ of instances of the derived class needs to be + pickled in order to restore the instances correctly.

        • - the user adds items to the instance's __dict__ directly. Again, - the __dict__ of the instance then needs to be pickled. + the user adds items to the instance's __dict__ directly. + Again, the __dict__ of the instance then needs to be + pickled. +

        To alert the user to this highly unobvious problem, a safety guard is - provided. If __getstate__ is defined and the instance's __dict__ is - not empty, Boost.Python tests if the class has an attribute - __getstate_manages_dict__. An exception is raised if this attribute - is not defined: + provided. If __getstate__ is defined and the instance's + __dict__ is not empty, Boost.Python tests if the class has + an attribute __getstate_manages_dict__. An exception is + raised if this attribute is not defined:

             RuntimeError: Incomplete pickle support (__getstate_manages_dict__ not set)
         
        To resolve this problem, it should first be established that the - __getstate__ and __setstate__ methods manage the instances's __dict__ - correctly. Note that this can be done both at the C++ and the Python - level. Finally, the safety guard should intentionally be overridden. - E.g. in C++: + __getstate__ and __setstate__ methods manage the + instances's __dict__ correctly. Note that this can be done + both at the C++ and the Python level. Finally, the safety guard + should intentionally be overridden. E.g. in C++:
             class_builder<your_class> py_your_class(your_module, "your_class");
        @@ -206,15 +215,24 @@ __getstate__ is defined and the instance's __dict__ is not empty.
         
         
        • - Avoid using __getstate__ if the instance can also be reconstructed - by way of __getinitargs__. This automatically avoids Pitfall 2. + Avoid using __getstate__ if the instance can also be + reconstructed by way of __getinitargs__. This automatically + avoids Pitfall 2.

        • - If __getstate__ is required, include the instance's __dict__ in the - Python object that is returned. + If __getstate__ is required, include the instance's + __dict__ in the Python object that is returned. +
        +
        +

        Example

        + +An example that shows how to provide pickle support is available in the +boost/lib/python/example directory +(getting_started3.cpp). +
        Author: Ralf W. Grosse-Kunstleve, March 2001 From f5416ebce07b914ed6fd83754f414e53bd2b5563 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 10 Mar 2001 00:36:03 +0000 Subject: [PATCH 057/369] Fixed some doc bugs and improved an example [SVN r9533] --- doc/overriding.html | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/overriding.html b/doc/overriding.html index b29bf0e6..0fc7a2e6 100644 --- a/doc/overriding.html +++ b/doc/overriding.html @@ -142,6 +142,7 @@ hello_class.def(&hello::greet, "greet", &hello_callback::default_gree
         struct baz {
             virtual int pure(int) = 0;
        +    int calls_pure(int x) { return pure(x) + 1000; }
         };
         
         struct baz_callback {
        @@ -154,7 +155,7 @@ BOOST_PYTHON_MODULE_INIT(foobar)
             {
                boost::python::module_builder foobar("foobar");
                boost::python::class_builder<baz,baz_callback> baz_class("baz");
        -       baz_class.def(&baz::pure, "pure");
        +       baz_class.def(&baz::calls_pure, "calls_pure");
             }
             catch(...)
             {
        @@ -173,12 +174,18 @@ BOOST_PYTHON_MODULE_INIT(foobar)
         Traceback (innermost last):
           File "<stdin>", line 1, in ?
         AttributeError: pure
        +>>> x.calls_pure(1)
        +Traceback (innermost last):
        +  File "<stdin>", line 1, in ?
        +AttributeError: pure
         >>> class mumble(baz):
         ...    def pure(self, x): return x + 1
         ...
         >>> y = mumble()
         >>> y.pure(99)
         100
        +>>> y.calls_pure(99)
        +1100
         

      Private Non-Pure Virtual Functions

      @@ -192,6 +199,7 @@ this limited way without breaking binary compatibility (though it will certainly break the ODR). +

      Next: Function Overloading Previous: Exporting Classes From 678fa006de24673b654fc057a165e79a2108a734 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 10 Mar 2001 08:23:37 +0000 Subject: [PATCH 058/369] Copyright notice & minor fixes. [SVN r9536] --- doc/pickle.html | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/doc/pickle.html b/doc/pickle.html index 39cb07dc..842112d3 100644 --- a/doc/pickle.html +++ b/doc/pickle.html @@ -8,7 +8,7 @@ c++boost.gif (8819 bytes) + width="277" height="86">


      Boost.Python Pickle Support

      @@ -229,12 +229,17 @@ Both __getinitargs__ and __getstate__ are not defined.

      Example

      -An example that shows how to provide pickle support is available in the +An example that shows how to configure pickle support is available in the boost/lib/python/example directory (getting_started3.cpp).
      -
      -Author: Ralf W. Grosse-Kunstleve, March 2001 -
      +© Copyright Ralf W. Grosse-Kunstleve 2001. 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. + +

      +Updated: March 10, 2001 From 14acb1af8c1ef20c1a49ea1a2901e6b49817f2e2 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 10 Mar 2001 19:09:10 +0000 Subject: [PATCH 059/369] Fix bugs (m_self => self) [SVN r9539] --- doc/overriding.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/overriding.html b/doc/overriding.html index 0fc7a2e6..66c3610c 100644 --- a/doc/overriding.html +++ b/doc/overriding.html @@ -79,13 +79,13 @@ struct hello_callback : hello // Override greet to call back into Python std::string greet() const // 4 - { return boost::python::callback<std::string>::call_method(m_self, "greet"); } + { return boost::python::callback<std::string>::call_method(self, "greet"); } // Supplies the default implementation of greet static std::string default_greet(const hello& self) const // 5 { return self.hello::greet(); } private: - PyObject* m_self; // 1 + PyObject* self; // 1 };

    • From 7dc8fab961c798a832c959096462f901c8ec48f7 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 11 Mar 2001 21:29:31 +0000 Subject: [PATCH 060/369] 11 Mar 01 std::string *MAY* include nulls (Alex Martelli) [SVN r9544] --- src/conversions.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/conversions.cpp b/src/conversions.cpp index 88e30048..9445c7f3 100644 --- a/src/conversions.cpp +++ b/src/conversions.cpp @@ -7,6 +7,7 @@ // producing this work. // // Revision History: +// 11 Mar 01 std::string *MAY* include nulls (Alex Martelli) // 04 Mar 01 std::complex<> fixes for MSVC (Dave Abrahams) // 03 Mar 01 added: converters for [plain] char (Ralf W. Grosse-Kunstleve) @@ -149,7 +150,7 @@ int from_python(PyObject* p, boost::python::type type) PyObject* to_python(unsigned int i) { - return integer_to_python(i); + return integer_to_python(i); } unsigned int from_python(PyObject* p, boost::python::type type) @@ -169,7 +170,7 @@ float from_python(PyObject* p, boost::python::type) PyObject* to_python(unsigned short i) { - return integer_to_python(i); + return integer_to_python(i); } unsigned short from_python(PyObject* p, boost::python::type type) @@ -197,7 +198,7 @@ char from_python(PyObject* p, boost::python::type) PyObject* to_python(unsigned char i) { - return integer_to_python(i); + return integer_to_python(i); } unsigned char from_python(PyObject* p, boost::python::type type) @@ -207,7 +208,7 @@ unsigned char from_python(PyObject* p, boost::python::type type) PyObject* to_python(signed char i) { - return integer_to_python(i); + return integer_to_python(i); } signed char from_python(PyObject* p, boost::python::type type) @@ -243,12 +244,15 @@ const char* from_python(PyObject* p, boost::python::type) PyObject* to_python(const std::string& s) { - return PyString_FromString(s.c_str()); + return PyString_FromStringAndSize(s.data(), s.size()); } std::string from_python(PyObject* p, boost::python::type) { - return std::string(from_python(p, boost::python::type())); + char* buffer = 0; + int length = 0; + int rc = PyString_AsStringAndSize(p, &buffer, &length); + return std::string(buffer, length); } bool from_python(PyObject* p, boost::python::type) From ed34cd45f1da43539e40e8b9d51e360312c422c0 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 12 Mar 2001 19:32:40 +0000 Subject: [PATCH 061/369] Python 1.5.2 fixes [SVN r9546] --- src/conversions.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/conversions.cpp b/src/conversions.cpp index 9445c7f3..1bc923b1 100644 --- a/src/conversions.cpp +++ b/src/conversions.cpp @@ -7,6 +7,7 @@ // producing this work. // // Revision History: +// 12 Mar 01 Python 1.5.2 fixes (Ralf W. Grosse-Kunstleve) // 11 Mar 01 std::string *MAY* include nulls (Alex Martelli) // 04 Mar 01 std::complex<> fixes for MSVC (Dave Abrahams) // 03 Mar 01 added: converters for [plain] char (Ralf W. Grosse-Kunstleve) @@ -249,10 +250,7 @@ PyObject* to_python(const std::string& s) std::string from_python(PyObject* p, boost::python::type) { - char* buffer = 0; - int length = 0; - int rc = PyString_AsStringAndSize(p, &buffer, &length); - return std::string(buffer, length); + return std::string(PyString_AsString(p), PyString_Size(p)); } bool from_python(PyObject* p, boost::python::type) From ff04d9f03c85e173a0d6084d20ef3f2416b699c7 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 12 Mar 2001 19:34:14 +0000 Subject: [PATCH 062/369] Minute enhancement. [SVN r9547] --- doc/overriding.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/overriding.html b/doc/overriding.html index 66c3610c..af458d79 100644 --- a/doc/overriding.html +++ b/doc/overriding.html @@ -82,8 +82,8 @@ struct hello_callback : hello { return boost::python::callback<std::string>::call_method(self, "greet"); } // Supplies the default implementation of greet - static std::string default_greet(const hello& self) const // 5 - { return self.hello::greet(); } + static std::string default_greet(const hello& self_) const // 5 + { return self_.hello::greet(); } private: PyObject* self; // 1 }; From 012b4025a48e056da251b58eb50c402079740894 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 13 Mar 2001 00:01:06 +0000 Subject: [PATCH 063/369] temp files before branching [SVN r9549] --- example/pickle1.cpp | 57 +++++++++++++++++++ example/pickle2.cpp | 80 ++++++++++++++++++++++++++ example/pickle3.cpp | 121 ++++++++++++++++++++++++++++++++++++++++ example/test_pickle1.py | 31 ++++++++++ example/test_pickle2.py | 45 +++++++++++++++ example/test_pickle3.py | 38 +++++++++++++ 6 files changed, 372 insertions(+) create mode 100644 example/pickle1.cpp create mode 100644 example/pickle2.cpp create mode 100644 example/pickle3.cpp create mode 100644 example/test_pickle1.py create mode 100644 example/test_pickle2.py create mode 100644 example/test_pickle3.py diff --git a/example/pickle1.cpp b/example/pickle1.cpp new file mode 100644 index 00000000..2f786f69 --- /dev/null +++ b/example/pickle1.cpp @@ -0,0 +1,57 @@ +/* + This example shows how to make an Extension Class "pickleable". + For more information refer to boost/libs/python/doc/pickle.html. + */ + +#include + +#include +namespace python = boost::python; + +namespace { // Avoid cluttering the global namespace. + + // A friendly class. + class world + { + private: + std::string country; + int secret_number; + public: + world(const std::string& country) : secret_number(0) { + this->country = country; + } + std::string greet() const { return "Hello from " + country + "!"; } + std::string get_country() const { return country; } + }; + + // Support for pickle. + python::ref world_getinitargs(const world& w) { + python::tuple result(1); + result.set_item(0, w.get_country()); + return result.reference(); + } +} + +BOOST_PYTHON_MODULE_INIT(pickle1) +{ + try + { + // Create an object representing this extension module. + python::module_builder this_module("pickle1"); + + // Create the Python type object for our extension class. + python::class_builder world_class(this_module, "world"); + + // Add the __init__ function. + world_class.def(python::constructor()); + // Add a regular member function. + world_class.def(&world::greet, "greet"); + + // Support for pickle. + world_class.def(world_getinitargs, "__getinitargs__"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/pickle2.cpp b/example/pickle2.cpp new file mode 100644 index 00000000..c33776a0 --- /dev/null +++ b/example/pickle2.cpp @@ -0,0 +1,80 @@ +/* + This example shows how to make an Extension Class "pickleable". + For more information refer to boost/libs/python/doc/pickle.html. + */ + +#include + +#include +namespace python = boost::python; + +namespace { // Avoid cluttering the global namespace. + + // A friendly class. + class world + { + public: + world(const std::string& country) : secret_number(0) { + this->country = country; + } + std::string greet() const { return "Hello from " + country + "!"; } + std::string get_country() const { return country; } + void set_secret_number(int number) { secret_number = number; } + int get_secret_number() const { return secret_number; } + private: + std::string country; + int secret_number; + }; + + // Support for pickle. + python::ref world_getinitargs(const world& w) { + python::tuple result(1); + result.set_item(0, w.get_country()); + return result.reference(); // returning the reference avoids the copying. + } + + python::ref world_getstate(const world& w) { + python::tuple result(1); + result.set_item(0, w.get_secret_number()); + return result.reference(); // returning the reference avoids the copying. + } + + void world_setstate(world& w, python::tuple state) { + if (state.size() != 1) { + PyErr_SetString(PyExc_ValueError, + "Unexpected argument in call to __setstate__."); + throw python::error_already_set(); + } + int number = state[0].get(); + if (number != 42) + w.set_secret_number(number); + } +} + +BOOST_PYTHON_MODULE_INIT(pickle2) +{ + try + { + // Create an object representing this extension module. + python::module_builder this_module("pickle2"); + + // Create the Python type object for our extension class. + python::class_builder world_class(this_module, "world"); + + // Add the __init__ function. + world_class.def(python::constructor()); + // Add a regular member function. + world_class.def(&world::greet, "greet"); + world_class.def(&world::get_secret_number, "get_secret_number"); + world_class.def(&world::set_secret_number, "set_secret_number"); + + // Support for pickle. + world_class.def(world_getinitargs, "__getinitargs__"); + world_class.def(world_getstate, "__getstate__"); + world_class.def(world_setstate, "__setstate__"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/pickle3.cpp b/example/pickle3.cpp new file mode 100644 index 00000000..19ddec43 --- /dev/null +++ b/example/pickle3.cpp @@ -0,0 +1,121 @@ +/* + This example shows how to make an Extension Class "pickleable". + For more information refer to boost/libs/python/doc/pickle.html. + */ + +#include + +#include +namespace python = boost::python; + +namespace { // Avoid cluttering the global namespace. + + // A friendly class. + class world + { + public: + world(const std::string& country) : secret_number(0) { + this->country = country; + } + std::string greet() const { return "Hello from " + country + "!"; } + std::string get_country() const { return country; } + void set_secret_number(int number) { secret_number = number; } + int get_secret_number() const { return secret_number; } + private: + std::string country; + int secret_number; + }; + + // Support for pickle. + python::ref world_getinitargs(const world& w) { + python::tuple result(1); + result.set_item(0, w.get_country()); + return result.reference(); // returning the reference avoids the copying. + } + + python::ref world_getstate(python::tuple const & args, + python::dictionary const & keywords); + + PyObject* world_setstate(python::tuple const & args, + python::dictionary const & keywords); +} + +BOOST_PYTHON_MODULE_INIT(pickle3) +{ + try + { + // Create an object representing this extension module. + python::module_builder this_module("pickle3"); + + // Create the Python type object for our extension class. + python::class_builder world_class(this_module, "world"); + + // Add the __init__ function. + world_class.def(python::constructor()); + // Add a regular member function. + world_class.def(&world::greet, "greet"); + world_class.def(&world::get_secret_number, "get_secret_number"); + world_class.def(&world::set_secret_number, "set_secret_number"); + + // Support for pickle. + world_class.def(world_getinitargs, "__getinitargs__"); + world_class.def_raw(world_getstate, "__getstate__"); + world_class.def_raw(world_setstate, "__setstate__"); + world_class.getstate_manages_dict(); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} + +namespace { + + python::ref world_getstate(python::tuple const & args, + python::dictionary const & keywords) + { + if(args.size() != 1 || keywords.size() != 0) { + PyErr_SetString(PyExc_TypeError, "wrong number of arguments"); + throw boost::python::argument_error(); + } + const world& w = args[0].get(); + python::ref mydict(args[0].getattr("__dict__")); + python::tuple result(2); + // store the object's __dict__ + result.set_item(0, mydict); + // store the internal state of the C++ object + result.set_item(1, w.get_secret_number()); + return result.reference(); // returning the reference avoids the copying. + } + + PyObject* world_setstate(python::tuple const & args, + python::dictionary const & keywords) + { + if(args.size() != 2 || keywords.size() != 0) { + PyErr_SetString(PyExc_TypeError, "wrong number of arguments"); + throw boost::python::argument_error(); + } + world& w = args[0].get(); + python::ref mydict(args[0].getattr("__dict__")); + const python::tuple& state(args[1].get()); + if (state.size() != 2) { + PyErr_SetString(PyExc_ValueError, + "Unexpected argument in call to __setstate__."); + throw python::error_already_set(); + } + // restore the object's __dict__ + python::dictionary odict(mydict.get()); + const python::dictionary& pdict(state[0].get()); + python::list pkeys(pdict.keys()); + for (int i = 0; i < pkeys.size(); i++) { + python::ref k(pkeys[i]); + //odict[k] = pdict[k]; // XXX memory leak! + odict[k] = pdict.get_item(k); // this does not leak. + } + // restore the internal state of the C++ object + int number = state[1].get(); + if (number != 42) + w.set_secret_number(number); + return python::detail::none(); + } +} diff --git a/example/test_pickle1.py b/example/test_pickle1.py new file mode 100644 index 00000000..05696d4a --- /dev/null +++ b/example/test_pickle1.py @@ -0,0 +1,31 @@ +r'''>>> import pickle1 + >>> import re + >>> import pickle + >>> pickle1.world.__module__ + 'pickle1' + >>> pickle1.world.__safe_for_unpickling__ + 1 + >>> pickle1.world.__reduce__() + 'world' + >>> assert re.match( + ... "\(, \('Hello',\)\)", + ... repr(pickle1.world('Hello').__reduce__())) + >>> + >>> wd = pickle1.world('California') + >>> pstr = pickle.dumps(wd) + >>> wl = pickle.loads(pstr) + >>> print wd.greet() + Hello from California! + >>> print wl.greet() + Hello from California! +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_pickle1 + doctest.testmod(test_pickle1) + +if __name__ == '__main__': + run() diff --git a/example/test_pickle2.py b/example/test_pickle2.py new file mode 100644 index 00000000..463befa6 --- /dev/null +++ b/example/test_pickle2.py @@ -0,0 +1,45 @@ +r'''>>> import pickle2 + >>> import re + >>> import pickle + >>> pickle2.world.__module__ + 'pickle2' + >>> pickle2.world.__safe_for_unpickling__ + 1 + >>> pickle2.world.__reduce__() + 'world' + >>> assert re.match( + ... "\(, \('Hello',\), \(0,\)\)", + ... repr(pickle2.world('Hello').__reduce__())) + >>> + >>> for number in (24, 42): + ... wd = pickle2.world('California') + ... wd.set_secret_number(number) + ... pstr = pickle.dumps(wd) + ... wl = pickle.loads(pstr) + ... print wd.greet(), wd.get_secret_number() + ... print wl.greet(), wl.get_secret_number() + Hello from California! 24 + Hello from California! 24 + Hello from California! 42 + Hello from California! 0 + +# Now show that the __dict__ is not taken care of. + >>> wd = pickle2.world('California') + >>> wd.x = 1 + >>> wd.__dict__ + {'x': 1} + >>> try: pstr = pickle.dumps(wd) + ... except RuntimeError, err: print err[0] + ... + Incomplete pickle support (__getstate_manages_dict__ not set) +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_pickle2 + doctest.testmod(test_pickle2) + +if __name__ == '__main__': + run() diff --git a/example/test_pickle3.py b/example/test_pickle3.py new file mode 100644 index 00000000..b964f1a2 --- /dev/null +++ b/example/test_pickle3.py @@ -0,0 +1,38 @@ +r'''>>> import pickle3 + >>> import re + >>> import pickle + >>> pickle3.world.__module__ + 'pickle3' + >>> pickle3.world.__safe_for_unpickling__ + 1 + >>> pickle3.world.__reduce__() + 'world' + >>> assert re.match( + ... "\(, \('Hello',\), \(\{\}, 0\)\)", + ... repr(pickle3.world('Hello').__reduce__())) + >>> + >>> for number in (24, 42): + ... wd = pickle3.world('California') + ... wd.set_secret_number(number) + ... wd.x = 2 * number + ... wd.y = 'y' * number + ... wd.z = 3. * number + ... pstr = pickle.dumps(wd) + ... wl = pickle.loads(pstr) + ... print wd.greet(), wd.get_secret_number(), wd.__dict__ + ... print wl.greet(), wl.get_secret_number(), wl.__dict__ + Hello from California! 24 {'z': 72.0, 'x': 48, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyy'} + Hello from California! 24 {'z': 72.0, 'x': 48, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyy'} + Hello from California! 42 {'z': 126.0, 'x': 84, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'} + Hello from California! 0 {'z': 126.0, 'x': 84, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'} +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_pickle3 + doctest.testmod(test_pickle3) + +if __name__ == '__main__': + run() From c979ab01af48fc814c42beb89f857d7db4e85068 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 13 Mar 2001 00:03:58 +0000 Subject: [PATCH 064/369] temp files removed after branching. [SVN r9551] --- example/pickle1.cpp | 57 ------------------- example/pickle2.cpp | 80 -------------------------- example/pickle3.cpp | 121 ---------------------------------------- example/test_pickle1.py | 31 ---------- example/test_pickle2.py | 45 --------------- example/test_pickle3.py | 38 ------------- 6 files changed, 372 deletions(-) delete mode 100644 example/pickle1.cpp delete mode 100644 example/pickle2.cpp delete mode 100644 example/pickle3.cpp delete mode 100644 example/test_pickle1.py delete mode 100644 example/test_pickle2.py delete mode 100644 example/test_pickle3.py diff --git a/example/pickle1.cpp b/example/pickle1.cpp deleted file mode 100644 index 2f786f69..00000000 --- a/example/pickle1.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - This example shows how to make an Extension Class "pickleable". - For more information refer to boost/libs/python/doc/pickle.html. - */ - -#include - -#include -namespace python = boost::python; - -namespace { // Avoid cluttering the global namespace. - - // A friendly class. - class world - { - private: - std::string country; - int secret_number; - public: - world(const std::string& country) : secret_number(0) { - this->country = country; - } - std::string greet() const { return "Hello from " + country + "!"; } - std::string get_country() const { return country; } - }; - - // Support for pickle. - python::ref world_getinitargs(const world& w) { - python::tuple result(1); - result.set_item(0, w.get_country()); - return result.reference(); - } -} - -BOOST_PYTHON_MODULE_INIT(pickle1) -{ - try - { - // Create an object representing this extension module. - python::module_builder this_module("pickle1"); - - // Create the Python type object for our extension class. - python::class_builder world_class(this_module, "world"); - - // Add the __init__ function. - world_class.def(python::constructor()); - // Add a regular member function. - world_class.def(&world::greet, "greet"); - - // Support for pickle. - world_class.def(world_getinitargs, "__getinitargs__"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/pickle2.cpp b/example/pickle2.cpp deleted file mode 100644 index c33776a0..00000000 --- a/example/pickle2.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - This example shows how to make an Extension Class "pickleable". - For more information refer to boost/libs/python/doc/pickle.html. - */ - -#include - -#include -namespace python = boost::python; - -namespace { // Avoid cluttering the global namespace. - - // A friendly class. - class world - { - public: - world(const std::string& country) : secret_number(0) { - this->country = country; - } - std::string greet() const { return "Hello from " + country + "!"; } - std::string get_country() const { return country; } - void set_secret_number(int number) { secret_number = number; } - int get_secret_number() const { return secret_number; } - private: - std::string country; - int secret_number; - }; - - // Support for pickle. - python::ref world_getinitargs(const world& w) { - python::tuple result(1); - result.set_item(0, w.get_country()); - return result.reference(); // returning the reference avoids the copying. - } - - python::ref world_getstate(const world& w) { - python::tuple result(1); - result.set_item(0, w.get_secret_number()); - return result.reference(); // returning the reference avoids the copying. - } - - void world_setstate(world& w, python::tuple state) { - if (state.size() != 1) { - PyErr_SetString(PyExc_ValueError, - "Unexpected argument in call to __setstate__."); - throw python::error_already_set(); - } - int number = state[0].get(); - if (number != 42) - w.set_secret_number(number); - } -} - -BOOST_PYTHON_MODULE_INIT(pickle2) -{ - try - { - // Create an object representing this extension module. - python::module_builder this_module("pickle2"); - - // Create the Python type object for our extension class. - python::class_builder world_class(this_module, "world"); - - // Add the __init__ function. - world_class.def(python::constructor()); - // Add a regular member function. - world_class.def(&world::greet, "greet"); - world_class.def(&world::get_secret_number, "get_secret_number"); - world_class.def(&world::set_secret_number, "set_secret_number"); - - // Support for pickle. - world_class.def(world_getinitargs, "__getinitargs__"); - world_class.def(world_getstate, "__getstate__"); - world_class.def(world_setstate, "__setstate__"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/pickle3.cpp b/example/pickle3.cpp deleted file mode 100644 index 19ddec43..00000000 --- a/example/pickle3.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - This example shows how to make an Extension Class "pickleable". - For more information refer to boost/libs/python/doc/pickle.html. - */ - -#include - -#include -namespace python = boost::python; - -namespace { // Avoid cluttering the global namespace. - - // A friendly class. - class world - { - public: - world(const std::string& country) : secret_number(0) { - this->country = country; - } - std::string greet() const { return "Hello from " + country + "!"; } - std::string get_country() const { return country; } - void set_secret_number(int number) { secret_number = number; } - int get_secret_number() const { return secret_number; } - private: - std::string country; - int secret_number; - }; - - // Support for pickle. - python::ref world_getinitargs(const world& w) { - python::tuple result(1); - result.set_item(0, w.get_country()); - return result.reference(); // returning the reference avoids the copying. - } - - python::ref world_getstate(python::tuple const & args, - python::dictionary const & keywords); - - PyObject* world_setstate(python::tuple const & args, - python::dictionary const & keywords); -} - -BOOST_PYTHON_MODULE_INIT(pickle3) -{ - try - { - // Create an object representing this extension module. - python::module_builder this_module("pickle3"); - - // Create the Python type object for our extension class. - python::class_builder world_class(this_module, "world"); - - // Add the __init__ function. - world_class.def(python::constructor()); - // Add a regular member function. - world_class.def(&world::greet, "greet"); - world_class.def(&world::get_secret_number, "get_secret_number"); - world_class.def(&world::set_secret_number, "set_secret_number"); - - // Support for pickle. - world_class.def(world_getinitargs, "__getinitargs__"); - world_class.def_raw(world_getstate, "__getstate__"); - world_class.def_raw(world_setstate, "__setstate__"); - world_class.getstate_manages_dict(); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} - -namespace { - - python::ref world_getstate(python::tuple const & args, - python::dictionary const & keywords) - { - if(args.size() != 1 || keywords.size() != 0) { - PyErr_SetString(PyExc_TypeError, "wrong number of arguments"); - throw boost::python::argument_error(); - } - const world& w = args[0].get(); - python::ref mydict(args[0].getattr("__dict__")); - python::tuple result(2); - // store the object's __dict__ - result.set_item(0, mydict); - // store the internal state of the C++ object - result.set_item(1, w.get_secret_number()); - return result.reference(); // returning the reference avoids the copying. - } - - PyObject* world_setstate(python::tuple const & args, - python::dictionary const & keywords) - { - if(args.size() != 2 || keywords.size() != 0) { - PyErr_SetString(PyExc_TypeError, "wrong number of arguments"); - throw boost::python::argument_error(); - } - world& w = args[0].get(); - python::ref mydict(args[0].getattr("__dict__")); - const python::tuple& state(args[1].get()); - if (state.size() != 2) { - PyErr_SetString(PyExc_ValueError, - "Unexpected argument in call to __setstate__."); - throw python::error_already_set(); - } - // restore the object's __dict__ - python::dictionary odict(mydict.get()); - const python::dictionary& pdict(state[0].get()); - python::list pkeys(pdict.keys()); - for (int i = 0; i < pkeys.size(); i++) { - python::ref k(pkeys[i]); - //odict[k] = pdict[k]; // XXX memory leak! - odict[k] = pdict.get_item(k); // this does not leak. - } - // restore the internal state of the C++ object - int number = state[1].get(); - if (number != 42) - w.set_secret_number(number); - return python::detail::none(); - } -} diff --git a/example/test_pickle1.py b/example/test_pickle1.py deleted file mode 100644 index 05696d4a..00000000 --- a/example/test_pickle1.py +++ /dev/null @@ -1,31 +0,0 @@ -r'''>>> import pickle1 - >>> import re - >>> import pickle - >>> pickle1.world.__module__ - 'pickle1' - >>> pickle1.world.__safe_for_unpickling__ - 1 - >>> pickle1.world.__reduce__() - 'world' - >>> assert re.match( - ... "\(, \('Hello',\)\)", - ... repr(pickle1.world('Hello').__reduce__())) - >>> - >>> wd = pickle1.world('California') - >>> pstr = pickle.dumps(wd) - >>> wl = pickle.loads(pstr) - >>> print wd.greet() - Hello from California! - >>> print wl.greet() - Hello from California! -''' - -def run(args = None): - if args is not None: - import sys - sys.argv = args - import doctest, test_pickle1 - doctest.testmod(test_pickle1) - -if __name__ == '__main__': - run() diff --git a/example/test_pickle2.py b/example/test_pickle2.py deleted file mode 100644 index 463befa6..00000000 --- a/example/test_pickle2.py +++ /dev/null @@ -1,45 +0,0 @@ -r'''>>> import pickle2 - >>> import re - >>> import pickle - >>> pickle2.world.__module__ - 'pickle2' - >>> pickle2.world.__safe_for_unpickling__ - 1 - >>> pickle2.world.__reduce__() - 'world' - >>> assert re.match( - ... "\(, \('Hello',\), \(0,\)\)", - ... repr(pickle2.world('Hello').__reduce__())) - >>> - >>> for number in (24, 42): - ... wd = pickle2.world('California') - ... wd.set_secret_number(number) - ... pstr = pickle.dumps(wd) - ... wl = pickle.loads(pstr) - ... print wd.greet(), wd.get_secret_number() - ... print wl.greet(), wl.get_secret_number() - Hello from California! 24 - Hello from California! 24 - Hello from California! 42 - Hello from California! 0 - -# Now show that the __dict__ is not taken care of. - >>> wd = pickle2.world('California') - >>> wd.x = 1 - >>> wd.__dict__ - {'x': 1} - >>> try: pstr = pickle.dumps(wd) - ... except RuntimeError, err: print err[0] - ... - Incomplete pickle support (__getstate_manages_dict__ not set) -''' - -def run(args = None): - if args is not None: - import sys - sys.argv = args - import doctest, test_pickle2 - doctest.testmod(test_pickle2) - -if __name__ == '__main__': - run() diff --git a/example/test_pickle3.py b/example/test_pickle3.py deleted file mode 100644 index b964f1a2..00000000 --- a/example/test_pickle3.py +++ /dev/null @@ -1,38 +0,0 @@ -r'''>>> import pickle3 - >>> import re - >>> import pickle - >>> pickle3.world.__module__ - 'pickle3' - >>> pickle3.world.__safe_for_unpickling__ - 1 - >>> pickle3.world.__reduce__() - 'world' - >>> assert re.match( - ... "\(, \('Hello',\), \(\{\}, 0\)\)", - ... repr(pickle3.world('Hello').__reduce__())) - >>> - >>> for number in (24, 42): - ... wd = pickle3.world('California') - ... wd.set_secret_number(number) - ... wd.x = 2 * number - ... wd.y = 'y' * number - ... wd.z = 3. * number - ... pstr = pickle.dumps(wd) - ... wl = pickle.loads(pstr) - ... print wd.greet(), wd.get_secret_number(), wd.__dict__ - ... print wl.greet(), wl.get_secret_number(), wl.__dict__ - Hello from California! 24 {'z': 72.0, 'x': 48, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyy'} - Hello from California! 24 {'z': 72.0, 'x': 48, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyy'} - Hello from California! 42 {'z': 126.0, 'x': 84, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'} - Hello from California! 0 {'z': 126.0, 'x': 84, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'} -''' - -def run(args = None): - if args is not None: - import sys - sys.argv = args - import doctest, test_pickle3 - doctest.testmod(test_pickle3) - -if __name__ == '__main__': - run() From 60b91ac6780ee9c7594892185377cebbde95652b Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Wed, 14 Mar 2001 15:11:55 +0000 Subject: [PATCH 065/369] 1.21.1 run up, including new download instructions and fix broken hyperlinks [SVN r9557] --- doc/building.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/building.html b/doc/building.html index 6627bbe8..2a8c9cae 100644 --- a/doc/building.html +++ b/doc/building.html @@ -57,7 +57,7 @@ special debugging version of the Python DLL. Since this debug DLL isn't supplied with the default Python installation for Windows, Boost.Python uses boost/python/detail/wrap_python.hpp + "../../../boost/python/detail/wrap_python.hpp">boost/python/detail/wrap_python.hpp to temporarily undefine _DEBUG when Python.h is #included. @@ -77,7 +77,7 @@

      If you do not #define BOOST_DEBUG_PYTHON, be sure that any source files #include <boost/python/detail/wrap_python.hpp> + "../../../boost/python/detail/wrap_python.hpp">boost/python/detail/wrap_python.hpp> instead of the usual Python.h, or you will have link incompatibilities.

      From c068a300f429a81a78c486579feda5418a8b22e8 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Thu, 15 Mar 2001 16:05:25 +0000 Subject: [PATCH 066/369] template file is not longer needed, causes "broken links" messages [SVN r9562] --- doc/template.html | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 doc/template.html diff --git a/doc/template.html b/doc/template.html deleted file mode 100644 index 1d0cd7a4..00000000 --- a/doc/template.html +++ /dev/null @@ -1,26 +0,0 @@ - - - The Title Of This Page - -

      -

      - c++boost.gif (8819 bytes)The Title Of This - Page -

      -

      -

      - Prev: Previous - Next: Next - Up: Top -

      - © Copyright David Abrahams 2000. 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. -

      - Updated: Nov 26, 2000 -

      - From 13b2e072d25cc3b7e11471afd3b8098a26c458ec Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 16 Mar 2001 21:56:41 +0000 Subject: [PATCH 067/369] Remove const qualifications that will confuse VC++'s buggy brain [SVN r9567] --- example/getting_started4.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/getting_started4.cpp b/example/getting_started4.cpp index 199ef7a9..cf6c2ff2 100644 --- a/example/getting_started4.cpp +++ b/example/getting_started4.cpp @@ -55,7 +55,7 @@ namespace { // Avoid cluttering the global namespace. // Function returning a vector_double object to Python. // - std::vector foo(const int n) + std::vector foo(int n) { std::vector vd(n); std::vector::iterator vditer = vd.begin(); @@ -65,7 +65,7 @@ namespace { // Avoid cluttering the global namespace. // Same as foo(), but avoid copying on return. // - std::auto_ptr > bar(const int n) + std::auto_ptr > bar(int n) { std::auto_ptr > vdptr(new std::vector(n)); std::vector::iterator vditer = vdptr->begin(); From 098eadefe0f4849d762d227c7df27fc6b82abffc Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 20 Mar 2001 02:07:39 +0000 Subject: [PATCH 068/369] temp file before branching [SVN r9599] --- include/boost/python/cross_module.hpp | 274 ++++++++++++++++++++++++++ src/cross_module.cpp | 77 ++++++++ 2 files changed, 351 insertions(+) create mode 100644 include/boost/python/cross_module.hpp create mode 100644 src/cross_module.cpp diff --git a/include/boost/python/cross_module.hpp b/include/boost/python/cross_module.hpp new file mode 100644 index 00000000..a6c32889 --- /dev/null +++ b/include/boost/python/cross_module.hpp @@ -0,0 +1,274 @@ +#ifndef CROSS_MODULE_HPP +# define CROSS_MODULE_HPP + +# include + +namespace boost { namespace python { + struct import_error : error_already_set {}; + struct export_error : error_already_set {}; +}} + +namespace boost { namespace python { namespace detail { + +// Concept: throw exception if api_major is changed +// show warning on stderr if api_minor is changed +const int export_converters_api_major = 2; +const int export_converters_api_minor = 1; +extern const char* converters_attribute_name; +void* import_converter_object(const std::string& module_name, + const std::string& py_class_name, + const std::string& attribute_name); +void check_export_converters_api(const int importing_major, + const int importing_minor, + const int imported_major, + const int imported_minor); + +}}} + +// forward declaration +namespace boost { namespace python { namespace detail { +template class import_extension_class; +}}} + +BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE + +//QUESTIONMARK +// This class is a look-alike of class python_extension_class_converters. +// Is there a formal way to ensure that the siblings stay in sync? +template +class python_import_extension_class_converters +{ + public: + + friend python_import_extension_class_converters py_extension_class_converters(boost::python::type) + { + return python_import_extension_class_converters(); + } + + PyObject* to_python(const T& x) const + { + return boost::python::detail::import_extension_class::get_converters()->to_python(x); + } + + friend T* from_python(PyObject* p, boost::python::type) + { + return boost::python::detail::import_extension_class::get_converters()->T_pointer_from_python(p); + } + + // Convert to const T* + friend const T* from_python(PyObject* p, boost::python::type) + { return from_python(p, boost::python::type()); } + + // Convert to const T* const& + friend const T* from_python(PyObject* p, boost::python::type) + { return from_python(p, boost::python::type()); } + + // Convert to T* const& + friend T* from_python(PyObject* p, boost::python::type) + { return from_python(p, boost::python::type()); } + + // Convert to T& + friend T& from_python(PyObject* p, boost::python::type) { + return boost::python::detail::import_extension_class::get_converters()->T_reference_from_python(p); + } + + // Convert to const T& + friend const T& from_python(PyObject* p, boost::python::type) + { return from_python(p, boost::python::type()); } + + // Convert to T + friend const T& from_python(PyObject* p, boost::python::type) + { return from_python(p, boost::python::type()); } + + friend std::auto_ptr& from_python(PyObject* p, boost::python::type&>) { + return boost::python::detail::import_extension_class::get_converters()->auto_ptr_reference_from_python(p); + } + + friend std::auto_ptr& from_python(PyObject* p, boost::python::type >) { + return boost::python::detail::import_extension_class::get_converters()->auto_ptr_value_from_python(p); + } + + friend const std::auto_ptr& from_python(PyObject* p, boost::python::type&>) { + return boost::python::detail::import_extension_class::get_converters()->auto_ptr_value_from_python(p); + } + + friend PyObject* to_python(std::auto_ptr x) { + return boost::python::detail::import_extension_class::get_converters()->to_python(x); + } + + friend boost::shared_ptr& from_python(PyObject* p, boost::python::type&>) { + return boost::python::detail::import_extension_class::get_converters()->shared_ptr_reference_from_python(p); + } + + friend boost::shared_ptr& from_python(PyObject* p, boost::python::type >) { + return boost::python::detail::import_extension_class::get_converters()->shared_ptr_value_from_python(p); + } + + friend const boost::shared_ptr& from_python(PyObject* p, boost::python::type&>) { + return boost::python::detail::import_extension_class::get_converters()->shared_ptr_value_from_python(p); + } + + friend PyObject* to_python(boost::shared_ptr x) { + return boost::python::detail::import_extension_class::get_converters()->to_python(x); + } +}; + +BOOST_PYTHON_END_CONVERSION_NAMESPACE + +namespace boost { namespace python { + +BOOST_PYTHON_IMPORT_CONVERSION(python_import_extension_class_converters); + +// A pointer to this class is exported/imported via the Python API. +// All functions are virtual. This is, what we really export/import +// is essentially just a pointer to a vtbl. +template +struct export_converter_object_base +{ + virtual const int get_api_major() const { + return detail::export_converters_api_major; } + virtual const int get_api_minor() const { + return detail::export_converters_api_minor; } + virtual PyObject* to_python(const T& x) = 0; + virtual PyObject* to_python(std::auto_ptr x) = 0; + virtual PyObject* to_python(boost::shared_ptr x) = 0; + virtual T* T_pointer_from_python(PyObject* obj) = 0; + virtual T& T_reference_from_python(PyObject* obj) = 0; + virtual std::auto_ptr& auto_ptr_reference_from_python(PyObject* obj) = 0; + virtual std::auto_ptr auto_ptr_value_from_python(PyObject* obj) = 0; + virtual boost::shared_ptr& shared_ptr_reference_from_python(PyObject* obj) = 0; + virtual boost::shared_ptr shared_ptr_value_from_python(PyObject* obj) = 0; +}; + +// Converters to be used if T is not copyable. +template +struct export_converter_object_noncopyable : export_converter_object_base +{ + virtual PyObject* to_python(const T& x) { + PyErr_SetString(PyExc_RuntimeError, + "to_python(const T&) converter not exported"); + throw import_error(); + } + virtual PyObject* to_python(std::auto_ptr x) { + return BOOST_PYTHON_CONVERSION::to_python(x); + } + virtual PyObject* to_python(boost::shared_ptr x) { + return BOOST_PYTHON_CONVERSION::to_python(x); + } + virtual T* T_pointer_from_python(PyObject* obj) { + return BOOST_PYTHON_CONVERSION::from_python(obj, boost::python::type()); + } + virtual T& T_reference_from_python(PyObject* obj) { + return BOOST_PYTHON_CONVERSION::from_python(obj, boost::python::type()); + } + virtual std::auto_ptr& auto_ptr_reference_from_python(PyObject* obj) { + return BOOST_PYTHON_CONVERSION::python_extension_class_converters::smart_ptr_reference(obj, boost::python::type >()); + } + virtual std::auto_ptr auto_ptr_value_from_python(PyObject* obj) { + return BOOST_PYTHON_CONVERSION::python_extension_class_converters::smart_ptr_value(obj, boost::python::type >()); + } + virtual boost::shared_ptr& shared_ptr_reference_from_python(PyObject* obj) { + return BOOST_PYTHON_CONVERSION::python_extension_class_converters::smart_ptr_reference(obj, boost::python::type >()); + } + virtual boost::shared_ptr shared_ptr_value_from_python(PyObject* obj) { + return BOOST_PYTHON_CONVERSION::python_extension_class_converters::smart_ptr_value(obj, boost::python::type >()); + } +}; + +// The addditional to_python() converter that can be used if T is copyable. +template +struct export_converter_object : export_converter_object_noncopyable +{ + virtual PyObject* to_python(const T& x) { + BOOST_PYTHON_CONVERSION::python_extension_class_converters cv; + return cv.to_python(x); + } +}; + +namespace detail { + +//QUESTIONMARK +// A stripped-down, modified version of class extension_class. +// Would it make sense to establish a formal relationship +// between the two classes? +template +class import_extension_class + : public python_import_extension_class_converters +{ + public: + inline import_extension_class(const char* module, const char* py_class) { + m_module = module; + m_py_class = py_class; + } + + static boost::python::export_converter_object_base* get_converters(); + + private: + static std::string m_module; + static std::string m_py_class; + static boost::python::export_converter_object_base* imported_converters; +}; + +template std::string import_extension_class::m_module; +template std::string import_extension_class::m_py_class; +template +boost::python::export_converter_object_base* +import_extension_class::imported_converters = 0; + +template +boost::python::export_converter_object_base* +import_extension_class::get_converters() { + if (imported_converters == 0) { + void* cobject + = import_converter_object(m_module, m_py_class, + converters_attribute_name); + imported_converters + = static_cast*>(cobject); + check_export_converters_api( + export_converters_api_major, + export_converters_api_minor, + imported_converters->get_api_major(), + imported_converters->get_api_minor()); + } + return imported_converters; +} + +}}} // namespace boost::python::detail + +namespace boost { namespace python { + +template +void export_converters(class_builder& cb) +{ + static export_converter_object export_cvts; + cb.add( + ref(PyCObject_FromVoidPtr(reinterpret_cast(&export_cvts), NULL)), + detail::converters_attribute_name); +} + +template +void export_converters_noncopyable(class_builder& cb) +{ + static export_converter_object_noncopyable export_cvts; + cb.add( + ref(PyCObject_FromVoidPtr(reinterpret_cast(&export_cvts), NULL)), + detail::converters_attribute_name); +} + +template +class import_converters + : python_import_extension_class_converters +{ + public: + import_converters(const char* module, const char* py_class) + : m_class(new detail::import_extension_class(module, py_class)) + { } + private: + //QUESTIONMARK + //reference > m_class; + boost::shared_ptr > m_class; +}; + +}} // namespace boost::python + +#endif // CROSS_MODULE_HPP diff --git a/src/cross_module.cpp b/src/cross_module.cpp new file mode 100644 index 00000000..c14acfda --- /dev/null +++ b/src/cross_module.cpp @@ -0,0 +1,77 @@ +# include +namespace python = boost::python; +# include // MSVC6.0SP4 does not know std::fprintf +# include // MSVC6.0SP4 does not know std::strcmp + +namespace { + + PyObject* get_module_dict(const char* module_name) + { + python::ref module_obj(PyImport_ImportModule((char*) module_name)); + PyObject* module_dict = PyModule_GetDict(module_obj.get()); + if (module_dict == 0) throw python::import_error(); + return module_dict; + } +} + +namespace boost { namespace python { namespace detail { + +const char* converters_attribute_name = "__converters__"; + +void* import_converter_object(const std::string& module_name, + const std::string& py_class_name, + const std::string& attribute_name) +{ + static std::string err; + PyObject* module_dict = get_module_dict(const_cast(module_name.c_str())); + PyObject* py_class = PyDict_GetItemString(module_dict, const_cast(py_class_name.c_str())); + if (py_class == 0) { + err = std::string("module ") + module_name + " has no attribute " + py_class_name; + PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); + throw python::import_error(); + } + python::ref c_obj(PyObject_GetAttrString(py_class, const_cast(attribute_name.c_str())), ref::null_ok); + if (c_obj.get() == 0) { + err = std::string("object ") + module_name + "." + py_class_name + + " has no attribute " + attribute_name; + PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); + throw python::import_error(); + } + if (! PyCObject_Check(c_obj.get())) { + err = std::string("object ") + module_name + "." + py_class_name + "." + + attribute_name + " is not a PyCObject"; + PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); + throw python::import_error(); + } + return PyCObject_AsVoidPtr(c_obj.get()); +} + +void check_export_converters_api(const int importing_major, + const int importing_minor, + const int imported_major, + const int imported_minor) +{ + if (importing_major != imported_major) { + // Python uses fprintf(stderr, ...) for API warnings. + fprintf(stderr, + "Fatal: export_converters_api mismatch:" + " Importing module = %d.%d" + " Imported module = %d.%d\n", + importing_major, importing_minor, + imported_major, imported_minor); + PyErr_SetString(PyExc_RuntimeError, + "Fatal: export_converters_api mismatch"); + throw import_error(); + } + if (importing_minor != imported_minor) { + // Python uses fprintf(stderr, ...) for API warnings. + fprintf(stderr, + "Warning: export_converters_api mismatch:" + " Importing module = %d.%d" + " Imported module = %d.%d\n", + importing_major, importing_minor, + imported_major, imported_minor); + } +} + +}}} // namespace boost::python::detail From db943b4109c71c61b7293bfcacb13becfe2d01db Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 20 Mar 2001 02:08:24 +0000 Subject: [PATCH 069/369] temp file removed after branching. [SVN r9600] --- include/boost/python/cross_module.hpp | 274 -------------------------- src/cross_module.cpp | 77 -------- 2 files changed, 351 deletions(-) delete mode 100644 include/boost/python/cross_module.hpp delete mode 100644 src/cross_module.cpp diff --git a/include/boost/python/cross_module.hpp b/include/boost/python/cross_module.hpp deleted file mode 100644 index a6c32889..00000000 --- a/include/boost/python/cross_module.hpp +++ /dev/null @@ -1,274 +0,0 @@ -#ifndef CROSS_MODULE_HPP -# define CROSS_MODULE_HPP - -# include - -namespace boost { namespace python { - struct import_error : error_already_set {}; - struct export_error : error_already_set {}; -}} - -namespace boost { namespace python { namespace detail { - -// Concept: throw exception if api_major is changed -// show warning on stderr if api_minor is changed -const int export_converters_api_major = 2; -const int export_converters_api_minor = 1; -extern const char* converters_attribute_name; -void* import_converter_object(const std::string& module_name, - const std::string& py_class_name, - const std::string& attribute_name); -void check_export_converters_api(const int importing_major, - const int importing_minor, - const int imported_major, - const int imported_minor); - -}}} - -// forward declaration -namespace boost { namespace python { namespace detail { -template class import_extension_class; -}}} - -BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE - -//QUESTIONMARK -// This class is a look-alike of class python_extension_class_converters. -// Is there a formal way to ensure that the siblings stay in sync? -template -class python_import_extension_class_converters -{ - public: - - friend python_import_extension_class_converters py_extension_class_converters(boost::python::type) - { - return python_import_extension_class_converters(); - } - - PyObject* to_python(const T& x) const - { - return boost::python::detail::import_extension_class::get_converters()->to_python(x); - } - - friend T* from_python(PyObject* p, boost::python::type) - { - return boost::python::detail::import_extension_class::get_converters()->T_pointer_from_python(p); - } - - // Convert to const T* - friend const T* from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to const T* const& - friend const T* from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to T* const& - friend T* from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to T& - friend T& from_python(PyObject* p, boost::python::type) { - return boost::python::detail::import_extension_class::get_converters()->T_reference_from_python(p); - } - - // Convert to const T& - friend const T& from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to T - friend const T& from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - friend std::auto_ptr& from_python(PyObject* p, boost::python::type&>) { - return boost::python::detail::import_extension_class::get_converters()->auto_ptr_reference_from_python(p); - } - - friend std::auto_ptr& from_python(PyObject* p, boost::python::type >) { - return boost::python::detail::import_extension_class::get_converters()->auto_ptr_value_from_python(p); - } - - friend const std::auto_ptr& from_python(PyObject* p, boost::python::type&>) { - return boost::python::detail::import_extension_class::get_converters()->auto_ptr_value_from_python(p); - } - - friend PyObject* to_python(std::auto_ptr x) { - return boost::python::detail::import_extension_class::get_converters()->to_python(x); - } - - friend boost::shared_ptr& from_python(PyObject* p, boost::python::type&>) { - return boost::python::detail::import_extension_class::get_converters()->shared_ptr_reference_from_python(p); - } - - friend boost::shared_ptr& from_python(PyObject* p, boost::python::type >) { - return boost::python::detail::import_extension_class::get_converters()->shared_ptr_value_from_python(p); - } - - friend const boost::shared_ptr& from_python(PyObject* p, boost::python::type&>) { - return boost::python::detail::import_extension_class::get_converters()->shared_ptr_value_from_python(p); - } - - friend PyObject* to_python(boost::shared_ptr x) { - return boost::python::detail::import_extension_class::get_converters()->to_python(x); - } -}; - -BOOST_PYTHON_END_CONVERSION_NAMESPACE - -namespace boost { namespace python { - -BOOST_PYTHON_IMPORT_CONVERSION(python_import_extension_class_converters); - -// A pointer to this class is exported/imported via the Python API. -// All functions are virtual. This is, what we really export/import -// is essentially just a pointer to a vtbl. -template -struct export_converter_object_base -{ - virtual const int get_api_major() const { - return detail::export_converters_api_major; } - virtual const int get_api_minor() const { - return detail::export_converters_api_minor; } - virtual PyObject* to_python(const T& x) = 0; - virtual PyObject* to_python(std::auto_ptr x) = 0; - virtual PyObject* to_python(boost::shared_ptr x) = 0; - virtual T* T_pointer_from_python(PyObject* obj) = 0; - virtual T& T_reference_from_python(PyObject* obj) = 0; - virtual std::auto_ptr& auto_ptr_reference_from_python(PyObject* obj) = 0; - virtual std::auto_ptr auto_ptr_value_from_python(PyObject* obj) = 0; - virtual boost::shared_ptr& shared_ptr_reference_from_python(PyObject* obj) = 0; - virtual boost::shared_ptr shared_ptr_value_from_python(PyObject* obj) = 0; -}; - -// Converters to be used if T is not copyable. -template -struct export_converter_object_noncopyable : export_converter_object_base -{ - virtual PyObject* to_python(const T& x) { - PyErr_SetString(PyExc_RuntimeError, - "to_python(const T&) converter not exported"); - throw import_error(); - } - virtual PyObject* to_python(std::auto_ptr x) { - return BOOST_PYTHON_CONVERSION::to_python(x); - } - virtual PyObject* to_python(boost::shared_ptr x) { - return BOOST_PYTHON_CONVERSION::to_python(x); - } - virtual T* T_pointer_from_python(PyObject* obj) { - return BOOST_PYTHON_CONVERSION::from_python(obj, boost::python::type()); - } - virtual T& T_reference_from_python(PyObject* obj) { - return BOOST_PYTHON_CONVERSION::from_python(obj, boost::python::type()); - } - virtual std::auto_ptr& auto_ptr_reference_from_python(PyObject* obj) { - return BOOST_PYTHON_CONVERSION::python_extension_class_converters::smart_ptr_reference(obj, boost::python::type >()); - } - virtual std::auto_ptr auto_ptr_value_from_python(PyObject* obj) { - return BOOST_PYTHON_CONVERSION::python_extension_class_converters::smart_ptr_value(obj, boost::python::type >()); - } - virtual boost::shared_ptr& shared_ptr_reference_from_python(PyObject* obj) { - return BOOST_PYTHON_CONVERSION::python_extension_class_converters::smart_ptr_reference(obj, boost::python::type >()); - } - virtual boost::shared_ptr shared_ptr_value_from_python(PyObject* obj) { - return BOOST_PYTHON_CONVERSION::python_extension_class_converters::smart_ptr_value(obj, boost::python::type >()); - } -}; - -// The addditional to_python() converter that can be used if T is copyable. -template -struct export_converter_object : export_converter_object_noncopyable -{ - virtual PyObject* to_python(const T& x) { - BOOST_PYTHON_CONVERSION::python_extension_class_converters cv; - return cv.to_python(x); - } -}; - -namespace detail { - -//QUESTIONMARK -// A stripped-down, modified version of class extension_class. -// Would it make sense to establish a formal relationship -// between the two classes? -template -class import_extension_class - : public python_import_extension_class_converters -{ - public: - inline import_extension_class(const char* module, const char* py_class) { - m_module = module; - m_py_class = py_class; - } - - static boost::python::export_converter_object_base* get_converters(); - - private: - static std::string m_module; - static std::string m_py_class; - static boost::python::export_converter_object_base* imported_converters; -}; - -template std::string import_extension_class::m_module; -template std::string import_extension_class::m_py_class; -template -boost::python::export_converter_object_base* -import_extension_class::imported_converters = 0; - -template -boost::python::export_converter_object_base* -import_extension_class::get_converters() { - if (imported_converters == 0) { - void* cobject - = import_converter_object(m_module, m_py_class, - converters_attribute_name); - imported_converters - = static_cast*>(cobject); - check_export_converters_api( - export_converters_api_major, - export_converters_api_minor, - imported_converters->get_api_major(), - imported_converters->get_api_minor()); - } - return imported_converters; -} - -}}} // namespace boost::python::detail - -namespace boost { namespace python { - -template -void export_converters(class_builder& cb) -{ - static export_converter_object export_cvts; - cb.add( - ref(PyCObject_FromVoidPtr(reinterpret_cast(&export_cvts), NULL)), - detail::converters_attribute_name); -} - -template -void export_converters_noncopyable(class_builder& cb) -{ - static export_converter_object_noncopyable export_cvts; - cb.add( - ref(PyCObject_FromVoidPtr(reinterpret_cast(&export_cvts), NULL)), - detail::converters_attribute_name); -} - -template -class import_converters - : python_import_extension_class_converters -{ - public: - import_converters(const char* module, const char* py_class) - : m_class(new detail::import_extension_class(module, py_class)) - { } - private: - //QUESTIONMARK - //reference > m_class; - boost::shared_ptr > m_class; -}; - -}} // namespace boost::python - -#endif // CROSS_MODULE_HPP diff --git a/src/cross_module.cpp b/src/cross_module.cpp deleted file mode 100644 index c14acfda..00000000 --- a/src/cross_module.cpp +++ /dev/null @@ -1,77 +0,0 @@ -# include -namespace python = boost::python; -# include // MSVC6.0SP4 does not know std::fprintf -# include // MSVC6.0SP4 does not know std::strcmp - -namespace { - - PyObject* get_module_dict(const char* module_name) - { - python::ref module_obj(PyImport_ImportModule((char*) module_name)); - PyObject* module_dict = PyModule_GetDict(module_obj.get()); - if (module_dict == 0) throw python::import_error(); - return module_dict; - } -} - -namespace boost { namespace python { namespace detail { - -const char* converters_attribute_name = "__converters__"; - -void* import_converter_object(const std::string& module_name, - const std::string& py_class_name, - const std::string& attribute_name) -{ - static std::string err; - PyObject* module_dict = get_module_dict(const_cast(module_name.c_str())); - PyObject* py_class = PyDict_GetItemString(module_dict, const_cast(py_class_name.c_str())); - if (py_class == 0) { - err = std::string("module ") + module_name + " has no attribute " + py_class_name; - PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); - throw python::import_error(); - } - python::ref c_obj(PyObject_GetAttrString(py_class, const_cast(attribute_name.c_str())), ref::null_ok); - if (c_obj.get() == 0) { - err = std::string("object ") + module_name + "." + py_class_name - + " has no attribute " + attribute_name; - PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); - throw python::import_error(); - } - if (! PyCObject_Check(c_obj.get())) { - err = std::string("object ") + module_name + "." + py_class_name + "." - + attribute_name + " is not a PyCObject"; - PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); - throw python::import_error(); - } - return PyCObject_AsVoidPtr(c_obj.get()); -} - -void check_export_converters_api(const int importing_major, - const int importing_minor, - const int imported_major, - const int imported_minor) -{ - if (importing_major != imported_major) { - // Python uses fprintf(stderr, ...) for API warnings. - fprintf(stderr, - "Fatal: export_converters_api mismatch:" - " Importing module = %d.%d" - " Imported module = %d.%d\n", - importing_major, importing_minor, - imported_major, imported_minor); - PyErr_SetString(PyExc_RuntimeError, - "Fatal: export_converters_api mismatch"); - throw import_error(); - } - if (importing_minor != imported_minor) { - // Python uses fprintf(stderr, ...) for API warnings. - fprintf(stderr, - "Warning: export_converters_api mismatch:" - " Importing module = %d.%d" - " Imported module = %d.%d\n", - importing_major, importing_minor, - imported_major, imported_minor); - } -} - -}}} // namespace boost::python::detail From 1f45a846c64420b56fb9da13d963f97035a18525 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 20 Mar 2001 02:13:28 +0000 Subject: [PATCH 070/369] VC++ 6.0 fixes and misc. other modifications. [SVN r9601] --- example/getting_started4.cpp | 9 ++++----- example/getting_started5.cpp | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/example/getting_started4.cpp b/example/getting_started4.cpp index cf6c2ff2..fe6a3421 100644 --- a/example/getting_started4.cpp +++ b/example/getting_started4.cpp @@ -15,7 +15,7 @@ namespace { // Avoid cluttering the global namespace. vector_double_wrapper(PyObject* self) : std::vector() {} - vector_double_wrapper(PyObject* self, const int n) + vector_double_wrapper(PyObject* self, int n) : std::vector(n) {} vector_double_wrapper(PyObject* self, python::tuple tuple) @@ -28,17 +28,16 @@ namespace { // Avoid cluttering the global namespace. } }; - double getitem(const std::vector& vd, const std::size_t key) { + double getitem(const std::vector& vd, std::size_t key) { return vd[key]; } - void setitem(std::vector& vd, const std::size_t key, - const double &d) { + void setitem(std::vector& vd, std::size_t key, double d) { std::vector::iterator vditer = vd.begin(); vditer[key] = d; } - void delitem(std::vector& vd, const std::size_t key) { + void delitem(std::vector& vd, std::size_t key) { std::vector::iterator vditer = vd.begin(); vd.erase(&vditer[key]); } diff --git a/example/getting_started5.cpp b/example/getting_started5.cpp index be033224..9e9e7c75 100644 --- a/example/getting_started5.cpp +++ b/example/getting_started5.cpp @@ -60,7 +60,7 @@ namespace { // Avoid cluttering the global namespace. std::vector VMIx; public: void add(const MillerIndex& MIx) { VMIx.push_back(MIx); } - MillerIndex get(const std::size_t i) const { return VMIx[i]; } + MillerIndex get(std::size_t i) const { return VMIx[i]; } }; } From 591eaeaafbaa53bce030c06af0198690886a915a Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 20 Mar 2001 02:16:08 +0000 Subject: [PATCH 071/369] VC++ 6.0 makefile; filemgr.py used by all ralf_grosse_kunstleve makefiles. [SVN r9602] --- build/filemgr.py | 122 ++++++++++++++++++++++++++++++++++++++++++++ build/vc60.mak | 129 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 251 insertions(+) create mode 100644 build/filemgr.py create mode 100644 build/vc60.mak diff --git a/build/filemgr.py b/build/filemgr.py new file mode 100644 index 00000000..51c87403 --- /dev/null +++ b/build/filemgr.py @@ -0,0 +1,122 @@ +bpl_src = "/libs/python/src" +bpl_tst = "/libs/python/test" +bpl_exa = "/libs/python/example" +files = ( +bpl_src + "/classes.cpp", +bpl_src + "/conversions.cpp", +bpl_src + "/extension_class.cpp", +bpl_src + "/functions.cpp", +bpl_src + "/init_function.cpp", +bpl_src + "/module_builder.cpp", +bpl_src + "/objects.cpp", +bpl_src + "/types.cpp", +bpl_src + "/cross_module.cpp", +bpl_tst + "/comprehensive.cpp", +bpl_tst + "/comprehensive.hpp", +bpl_tst + "/comprehensive.py", +bpl_tst + "/doctest.py", +bpl_exa + "/abstract.cpp", +bpl_exa + "/getting_started1.cpp", +bpl_exa + "/getting_started2.cpp", +bpl_exa + "/getting_started3.cpp", +bpl_exa + "/getting_started4.cpp", +bpl_exa + "/getting_started5.cpp", +bpl_exa + "/pickle1.cpp", +bpl_exa + "/pickle2.cpp", +bpl_exa + "/pickle3.cpp", +bpl_exa + "/test_abstract.py", +bpl_exa + "/test_getting_started1.py", +bpl_exa + "/test_getting_started2.py", +bpl_exa + "/test_getting_started3.py", +bpl_exa + "/test_getting_started4.py", +bpl_exa + "/test_getting_started5.py", +bpl_exa + "/test_pickle1.py", +bpl_exa + "/test_pickle2.py", +bpl_exa + "/test_pickle3.py", +bpl_exa + "/noncopyable.h", +bpl_exa + "/noncopyable_export.cpp", +bpl_exa + "/noncopyable_import.cpp", +bpl_exa + "/tst_noncopyable.py", +bpl_exa + "/ivect.h", +bpl_exa + "/ivect.cpp", +bpl_exa + "/dvect.h", +bpl_exa + "/dvect.cpp", +bpl_exa + "/tst_ivect.py", +bpl_exa + "/tst_dvect.py", +) + +defs = ( +"boost_python_test", +"abstract", +"getting_started1", +"getting_started2", +"getting_started3", +"getting_started4", +"getting_started5", +"pickle1", +"pickle2", +"pickle3", +"noncopyable_export", +"noncopyable_import", +"ivect", +"dvect", +) + +if (__name__ == "__main__"): + + import sys, os, string + + path = sys.argv[1] + mode = sys.argv[2] + if (not mode in ("softlinks", "unlink", "cp", "rm", "copy", "del")): + raise RuntimeError, \ + "usage: python filemgr.py path " + + translation_table = string.maketrans("/", "\\") + + if (mode == "copy"): + for fn in files: + fn = string.translate(fn, translation_table) + os.system("copy " + path + fn + " .") + + elif (mode == "cp"): + for fn in files: + os.system("cp " + path + fn + " .") + + elif (mode == "softlinks"): + for fn in files: + f = string.split(fn, "/")[-1] + if (os.access(f, os.F_OK)): + print "File exists: " + f + else: + os.system("ln -s " + path + os.sep + fn + " .") + + elif (mode in ("rm", "del")): + for fn in files: + flds = string.split(fn, "/") + try: os.unlink(flds[-1]) + except: pass + + elif (mode == "unlink"): + for fn in files: + f = string.split(fn, "/")[-1] + if (os.system("test -e " + f) == 0): + if (os.system("test -L " + f) == 0): + try: os.unlink(f) + except: pass + else: + print "Not a softlink: " + f + + if (mode in ("softlinks", "cp", "copy")): + for d in defs: + fn = d + ".def" + f = open(fn, "w") + f.write("EXPORTS\n") + f.write("\tinit" + d + "\n") + f.close() + + if (mode in ("unlink", "rm", "del")): + for d in defs: + fn = d + ".def" + try: os.unlink(fn) + except: pass diff --git a/build/vc60.mak b/build/vc60.mak new file mode 100644 index 00000000..a05d04f4 --- /dev/null +++ b/build/vc60.mak @@ -0,0 +1,129 @@ +# Usage: +# +# make copy Copy the sources and tests +# make Compile all sources +# make test Run doctest tests +# make clean Remove all object files +# make del Remove the sources and tests + +BOOST_WIN= "L:\boost" +BOOST_UNIX= /net/cci/rwgk/boost + +PYEXE= "C:\Program files\Python\python.exe" +PYINC= /I"C:\Program files\Python\include" +PYLIB= "C:\Program files\Python\libs\python15.lib" + +STDOPTS= /nologo /MD /GR /GX /FD /Zm200 +WARNOPTS= + +CPP= cl.exe +CPPOPTS= $(STLPORTINC) $(STLPORTOPTS) /I$(BOOST_WIN) $(PYINC) \ + $(STDOPTS) $(WARNOPTS) + +LD= link.exe +LDOPTS= /nologo /dll /incremental:no + +OBJ = classes.obj conversions.obj extension_class.obj functions.obj \ + init_function.obj module_builder.obj \ + objects.obj types.obj cross_module.obj + +.SUFFIXES: .obj .cpp + +all: libboost_python.a \ + boost_python_test.pyd \ + abstract.pyd \ + getting_started1.pyd getting_started2.pyd getting_started3.pyd \ + getting_started4.pyd getting_started5.pyd \ + pickle1.pyd pickle2.pyd pickle3.pyd \ + noncopyable_export.pyd noncopyable_import.pyd \ + ivect.pyd dvect.pyd + +libboost_python.a: $(OBJ) + +boost_python_test.pyd: $(OBJ) comprehensive.obj + $(LD) $(LDOPTS) $(OBJ) comprehensive.obj $(PYLIB) /export:initboost_python_test /out:"boost_python_test.pyd" + +abstract.pyd: $(OBJ) abstract.obj + $(LD) $(LDOPTS) $(OBJ) abstract.obj $(PYLIB) /export:initabstract /out:"abstract.pyd" + +getting_started1.pyd: $(OBJ) getting_started1.obj + $(LD) $(LDOPTS) $(OBJ) getting_started1.obj $(PYLIB) /export:initgetting_started1 /out:"getting_started1.pyd" + +getting_started2.pyd: $(OBJ) getting_started2.obj + $(LD) $(LDOPTS) $(OBJ) getting_started2.obj $(PYLIB) /export:initgetting_started2 /out:"getting_started2.pyd" + +getting_started3.pyd: $(OBJ) getting_started3.obj + $(LD) $(LDOPTS) $(OBJ) getting_started3.obj $(PYLIB) /export:initgetting_started3 /out:"getting_started3.pyd" + +getting_started4.pyd: $(OBJ) getting_started4.obj + $(LD) $(LDOPTS) $(OBJ) getting_started4.obj $(PYLIB) /export:initgetting_started4 /out:"getting_started4.pyd" + +getting_started5.pyd: $(OBJ) getting_started5.obj + $(LD) $(LDOPTS) $(OBJ) getting_started5.obj $(PYLIB) /export:initgetting_started5 /out:"getting_started5.pyd" + +pickle1.pyd: $(OBJ) pickle1.obj + $(LD) $(LDOPTS) $(OBJ) pickle1.obj $(PYLIB) /export:initpickle1 /out:"pickle1.pyd" + +pickle2.pyd: $(OBJ) pickle2.obj + $(LD) $(LDOPTS) $(OBJ) pickle2.obj $(PYLIB) /export:initpickle2 /out:"pickle2.pyd" + +pickle3.pyd: $(OBJ) pickle3.obj + $(LD) $(LDOPTS) $(OBJ) pickle3.obj $(PYLIB) /export:initpickle3 /out:"pickle3.pyd" + +noncopyable_export.pyd: $(OBJ) noncopyable_export.obj + $(LD) $(LDOPTS) $(OBJ) noncopyable_export.obj $(PYLIB) /export:initnoncopyable_export /out:"noncopyable_export.pyd" + +noncopyable_import.pyd: $(OBJ) noncopyable_import.obj + $(LD) $(LDOPTS) $(OBJ) noncopyable_import.obj $(PYLIB) /export:initnoncopyable_import /out:"noncopyable_import.pyd" + +ivect.pyd: $(OBJ) ivect.obj + $(LD) $(LDOPTS) $(OBJ) ivect.obj $(PYLIB) /export:initivect /out:"ivect.pyd" + +dvect.pyd: $(OBJ) dvect.obj + $(LD) $(LDOPTS) $(OBJ) dvect.obj $(PYLIB) /export:initdvect /out:"dvect.pyd" + +.cpp.obj: + $(CPP) $(CPPOPTS) /c $*.cpp + +test: + $(PYEXE) comprehensive.py --broken-auto-ptr + $(PYEXE) test_abstract.py + $(PYEXE) test_getting_started1.py + $(PYEXE) test_getting_started2.py + $(PYEXE) test_getting_started3.py + $(PYEXE) test_getting_started4.py + $(PYEXE) test_getting_started5.py + $(PYEXE) test_pickle1.py + $(PYEXE) test_pickle2.py + $(PYEXE) test_pickle3.py + +tst: + $(PYEXE) tst_noncopyable.py + $(PYEXE) tst_ivect.py + $(PYEXE) tst_dvect.py + +clean: + del *.obj + del *.lib + del *.exp + del *.idb + del *.pyd + del *.pyc + +softlinks: + python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) softlinks + +unlink: + python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) unlink + +cp: + python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) cp + +rm: + python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) rm + +copy: + python $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) copy + +del: + python $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) del From c4775a581edb6aaf6c7e9cde17c5e4a26be9f36d Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 21 Mar 2001 01:05:30 +0000 Subject: [PATCH 072/369] temp files before branching [SVN r9615] --- example/dvect_conversions.cpp | 51 +++++++++++++++++++++ example/dvect_defs.cpp | 13 ++++++ example/ivect_conversions.cpp | 51 +++++++++++++++++++++ example/ivect_defs.cpp | 13 ++++++ example/swap_iv_dv.sh | 1 + example/tst_dvect1.py | 23 ++++++++++ example/tst_dvect2.py | 85 +++++++++++++++++++++++++++++++++++ example/tst_ivect1.py | 23 ++++++++++ example/tst_ivect2.py | 85 +++++++++++++++++++++++++++++++++++ 9 files changed, 345 insertions(+) create mode 100644 example/dvect_conversions.cpp create mode 100644 example/dvect_defs.cpp create mode 100644 example/ivect_conversions.cpp create mode 100644 example/ivect_defs.cpp create mode 100644 example/swap_iv_dv.sh create mode 100644 example/tst_dvect1.py create mode 100644 example/tst_dvect2.py create mode 100644 example/tst_ivect1.py create mode 100644 example/tst_ivect2.py diff --git a/example/dvect_conversions.cpp b/example/dvect_conversions.cpp new file mode 100644 index 00000000..21527243 --- /dev/null +++ b/example/dvect_conversions.cpp @@ -0,0 +1,51 @@ + // basics first: const reference converters + boost::python::tuple const_dvect_reference_as_tuple(const vects::dvect& dv) + { + return dv.as_tuple(); + } + + // to_python smart pointer conversions + std::auto_ptr dvect_as_auto_ptr(const vects::dvect& dv) + { + return std::auto_ptr(new vects::dvect(dv)); + } + boost::shared_ptr dvect_as_shared_ptr(const vects::dvect& dv) + { + return boost::shared_ptr(new vects::dvect(dv)); + } + + // smart pointers passed by value + boost::python::ref auto_ptr_value_dvect_as_tuple(std::auto_ptr dv) + { + if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return dv->as_tuple().reference(); + } + boost::python::ref shared_ptr_value_dvect_as_tuple(boost::shared_ptr dv) + { + if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return dv->as_tuple().reference(); + } + + // smart pointers passed by reference + boost::python::ref auto_ptr_reference_dvect_as_tuple(std::auto_ptr& dv) + { + if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return dv->as_tuple().reference(); + } + boost::python::ref shared_ptr_reference_dvect_as_tuple(boost::shared_ptr& dv) + { + if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return dv->as_tuple().reference(); + } + + // smart pointers passed by const reference + boost::python::ref auto_ptr_const_reference_dvect_as_tuple(const std::auto_ptr& dv) + { + if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return dv->as_tuple().reference(); + } + boost::python::ref shared_ptr_const_reference_dvect_as_tuple(const boost::shared_ptr& dv) + { + if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return dv->as_tuple().reference(); + } diff --git a/example/dvect_defs.cpp b/example/dvect_defs.cpp new file mode 100644 index 00000000..2739b219 --- /dev/null +++ b/example/dvect_defs.cpp @@ -0,0 +1,13 @@ + this_module.def(dvect_as_auto_ptr, "dvect_as_auto_ptr"); + this_module.def(dvect_as_shared_ptr, "dvect_as_shared_ptr"); + + this_module.def(const_dvect_reference_as_tuple, "const_dvect_reference_as_tuple"); + + this_module.def(auto_ptr_value_dvect_as_tuple, "auto_ptr_value_dvect_as_tuple"); + this_module.def(shared_ptr_value_dvect_as_tuple, "shared_ptr_value_dvect_as_tuple"); + + this_module.def(auto_ptr_reference_dvect_as_tuple, "auto_ptr_reference_dvect_as_tuple"); + this_module.def(shared_ptr_reference_dvect_as_tuple, "shared_ptr_reference_dvect_as_tuple"); + + this_module.def(auto_ptr_const_reference_dvect_as_tuple, "auto_ptr_const_reference_dvect_as_tuple"); + this_module.def(shared_ptr_const_reference_dvect_as_tuple, "shared_ptr_const_reference_dvect_as_tuple"); diff --git a/example/ivect_conversions.cpp b/example/ivect_conversions.cpp new file mode 100644 index 00000000..4f59573d --- /dev/null +++ b/example/ivect_conversions.cpp @@ -0,0 +1,51 @@ + // basics first: const reference converters + boost::python::tuple const_ivect_reference_as_tuple(const vects::ivect& iv) + { + return iv.as_tuple(); + } + + // to_python smart pointer conversions + std::auto_ptr ivect_as_auto_ptr(const vects::ivect& iv) + { + return std::auto_ptr(new vects::ivect(iv)); + } + boost::shared_ptr ivect_as_shared_ptr(const vects::ivect& iv) + { + return boost::shared_ptr(new vects::ivect(iv)); + } + + // smart pointers passed by value + boost::python::ref auto_ptr_value_ivect_as_tuple(std::auto_ptr iv) + { + if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return iv->as_tuple().reference(); + } + boost::python::ref shared_ptr_value_ivect_as_tuple(boost::shared_ptr iv) + { + if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return iv->as_tuple().reference(); + } + + // smart pointers passed by reference + boost::python::ref auto_ptr_reference_ivect_as_tuple(std::auto_ptr& iv) + { + if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return iv->as_tuple().reference(); + } + boost::python::ref shared_ptr_reference_ivect_as_tuple(boost::shared_ptr& iv) + { + if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return iv->as_tuple().reference(); + } + + // smart pointers passed by const reference + boost::python::ref auto_ptr_const_reference_ivect_as_tuple(const std::auto_ptr& iv) + { + if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return iv->as_tuple().reference(); + } + boost::python::ref shared_ptr_const_reference_ivect_as_tuple(const boost::shared_ptr& iv) + { + if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return iv->as_tuple().reference(); + } diff --git a/example/ivect_defs.cpp b/example/ivect_defs.cpp new file mode 100644 index 00000000..811c243d --- /dev/null +++ b/example/ivect_defs.cpp @@ -0,0 +1,13 @@ + this_module.def(ivect_as_auto_ptr, "ivect_as_auto_ptr"); + this_module.def(ivect_as_shared_ptr, "ivect_as_shared_ptr"); + + this_module.def(const_ivect_reference_as_tuple, "const_ivect_reference_as_tuple"); + + this_module.def(auto_ptr_value_ivect_as_tuple, "auto_ptr_value_ivect_as_tuple"); + this_module.def(shared_ptr_value_ivect_as_tuple, "shared_ptr_value_ivect_as_tuple"); + + this_module.def(auto_ptr_reference_ivect_as_tuple, "auto_ptr_reference_ivect_as_tuple"); + this_module.def(shared_ptr_reference_ivect_as_tuple, "shared_ptr_reference_ivect_as_tuple"); + + this_module.def(auto_ptr_const_reference_ivect_as_tuple, "auto_ptr_const_reference_ivect_as_tuple"); + this_module.def(shared_ptr_const_reference_ivect_as_tuple, "shared_ptr_const_reference_ivect_as_tuple"); diff --git a/example/swap_iv_dv.sh b/example/swap_iv_dv.sh new file mode 100644 index 00000000..fc072bee --- /dev/null +++ b/example/swap_iv_dv.sh @@ -0,0 +1 @@ +sed 's/iv/xv/g' $1 | sed 's/dv/iv/g' | sed 's/xv/dv/g' diff --git a/example/tst_dvect1.py b/example/tst_dvect1.py new file mode 100644 index 00000000..12c53739 --- /dev/null +++ b/example/tst_dvect1.py @@ -0,0 +1,23 @@ +def f(): + import dvect + print dvect.dvect.__converters__ + dv = dvect.dvect((1,2,3,4,5)) + print dv + print dv.as_tuple() + iv = dv.as_ivect() + print iv + print iv.as_tuple() + print dvect.const_ivect_reference_as_tuple(iv) + aiv = dvect.ivect_as_auto_ptr(iv) + print dvect.const_ivect_reference_as_tuple(aiv) + siv = dvect.ivect_as_shared_ptr(iv) + print dvect.const_ivect_reference_as_tuple(siv) + print aiv.as_tuple() + print siv.as_tuple() + +if (__name__ == "__main__"): + import sys, string + n = 1 + if (len(sys.argv) > 1): n = string.atoi(sys.argv[1]) + for i in xrange(n): + f() diff --git a/example/tst_dvect2.py b/example/tst_dvect2.py new file mode 100644 index 00000000..868c107d --- /dev/null +++ b/example/tst_dvect2.py @@ -0,0 +1,85 @@ +def f(): + import dvect + import ivect + # + dv = dvect.dvect((1,2,3,4,5)) + iv = dv.as_ivect() + # + aiv = dvect.ivect_as_auto_ptr(iv) + print '1. auto_ptr_value_ivect_as_tuple' + print ivect.auto_ptr_value_ivect_as_tuple(aiv) + print '2. auto_ptr_value_ivect_as_tuple' + print ivect.auto_ptr_value_ivect_as_tuple(aiv) + # + adv = dvect.dvect_as_auto_ptr(dv) + print '1. auto_ptr_value_dvect_as_tuple' + print ivect.auto_ptr_value_dvect_as_tuple(adv) + print '2. auto_ptr_value_dvect_as_tuple' + print ivect.auto_ptr_value_dvect_as_tuple(adv) + # + siv = dvect.ivect_as_shared_ptr(iv) + print '1. shared_ptr_value_ivect_as_tuple' + print ivect.shared_ptr_value_ivect_as_tuple(siv) + print '2. shared_ptr_value_ivect_as_tuple' + print ivect.shared_ptr_value_ivect_as_tuple(siv) + # + sdv = dvect.dvect_as_shared_ptr(dv) + print '1. shared_ptr_value_dvect_as_tuple' + print ivect.shared_ptr_value_dvect_as_tuple(sdv) + print '2. shared_ptr_value_dvect_as_tuple' + print ivect.shared_ptr_value_dvect_as_tuple(sdv) + # + aiv = dvect.ivect_as_auto_ptr(iv) + print '1. auto_ptr_reference_ivect_as_tuple' + print ivect.auto_ptr_reference_ivect_as_tuple(aiv) + print '2. auto_ptr_reference_ivect_as_tuple' + print ivect.auto_ptr_reference_ivect_as_tuple(aiv) + # + adv = dvect.dvect_as_auto_ptr(dv) + print '1. auto_ptr_reference_dvect_as_tuple' + print ivect.auto_ptr_reference_dvect_as_tuple(adv) + print '2. auto_ptr_reference_dvect_as_tuple' + print ivect.auto_ptr_reference_dvect_as_tuple(adv) + # + siv = dvect.ivect_as_shared_ptr(iv) + print '1. shared_ptr_reference_ivect_as_tuple' + print ivect.shared_ptr_reference_ivect_as_tuple(siv) + print '2. shared_ptr_reference_ivect_as_tuple' + print ivect.shared_ptr_reference_ivect_as_tuple(siv) + # + sdv = dvect.dvect_as_shared_ptr(dv) + print '1. shared_ptr_reference_dvect_as_tuple' + print ivect.shared_ptr_reference_dvect_as_tuple(sdv) + print '2. shared_ptr_reference_dvect_as_tuple' + print ivect.shared_ptr_reference_dvect_as_tuple(sdv) + # + aiv = dvect.ivect_as_auto_ptr(iv) + print '1. auto_ptr_const_reference_ivect_as_tuple' + print ivect.auto_ptr_const_reference_ivect_as_tuple(aiv) + print '2. auto_ptr_const_reference_ivect_as_tuple' + print ivect.auto_ptr_const_reference_ivect_as_tuple(aiv) + # + adv = dvect.dvect_as_auto_ptr(dv) + print '1. auto_ptr_const_reference_dvect_as_tuple' + print ivect.auto_ptr_const_reference_dvect_as_tuple(adv) + print '2. auto_ptr_const_reference_dvect_as_tuple' + print ivect.auto_ptr_const_reference_dvect_as_tuple(adv) + # + siv = dvect.ivect_as_shared_ptr(iv) + print '1. shared_ptr_const_reference_ivect_as_tuple' + print ivect.shared_ptr_const_reference_ivect_as_tuple(siv) + print '2. shared_ptr_const_reference_ivect_as_tuple' + print ivect.shared_ptr_const_reference_ivect_as_tuple(siv) + # + sdv = dvect.dvect_as_shared_ptr(dv) + print '1. shared_ptr_const_reference_dvect_as_tuple' + print ivect.shared_ptr_const_reference_dvect_as_tuple(sdv) + print '2. shared_ptr_const_reference_dvect_as_tuple' + print ivect.shared_ptr_const_reference_dvect_as_tuple(sdv) + +if (__name__ == "__main__"): + import sys, string + n = 1 + if (len(sys.argv) > 1): n = string.atoi(sys.argv[1]) + for i in xrange(n): + f() diff --git a/example/tst_ivect1.py b/example/tst_ivect1.py new file mode 100644 index 00000000..62d3ecf4 --- /dev/null +++ b/example/tst_ivect1.py @@ -0,0 +1,23 @@ +def f(): + import ivect + print ivect.ivect.__converters__ + iv = ivect.ivect((1,2,3,4,5)) + print iv + print iv.as_tuple() + dv = iv.as_dvect() + print dv + print dv.as_tuple() + print ivect.const_dvect_reference_as_tuple(dv) + adv = ivect.dvect_as_auto_ptr(dv) + print ivect.const_dvect_reference_as_tuple(adv) + sdv = ivect.dvect_as_shared_ptr(dv) + print ivect.const_dvect_reference_as_tuple(sdv) + print adv.as_tuple() + print sdv.as_tuple() + +if (__name__ == "__main__"): + import sys, string + n = 1 + if (len(sys.argv) > 1): n = string.atoi(sys.argv[1]) + for i in xrange(n): + f() diff --git a/example/tst_ivect2.py b/example/tst_ivect2.py new file mode 100644 index 00000000..0db6903d --- /dev/null +++ b/example/tst_ivect2.py @@ -0,0 +1,85 @@ +def f(): + import ivect + import dvect + # + iv = ivect.ivect((1,2,3,4,5)) + dv = iv.as_dvect() + # + adv = ivect.dvect_as_auto_ptr(dv) + print '1. auto_ptr_value_dvect_as_tuple' + print dvect.auto_ptr_value_dvect_as_tuple(adv) + print '2. auto_ptr_value_dvect_as_tuple' + print dvect.auto_ptr_value_dvect_as_tuple(adv) + # + aiv = ivect.ivect_as_auto_ptr(iv) + print '1. auto_ptr_value_ivect_as_tuple' + print dvect.auto_ptr_value_ivect_as_tuple(aiv) + print '2. auto_ptr_value_ivect_as_tuple' + print dvect.auto_ptr_value_ivect_as_tuple(aiv) + # + sdv = ivect.dvect_as_shared_ptr(dv) + print '1. shared_ptr_value_dvect_as_tuple' + print dvect.shared_ptr_value_dvect_as_tuple(sdv) + print '2. shared_ptr_value_dvect_as_tuple' + print dvect.shared_ptr_value_dvect_as_tuple(sdv) + # + siv = ivect.ivect_as_shared_ptr(iv) + print '1. shared_ptr_value_ivect_as_tuple' + print dvect.shared_ptr_value_ivect_as_tuple(siv) + print '2. shared_ptr_value_ivect_as_tuple' + print dvect.shared_ptr_value_ivect_as_tuple(siv) + # + adv = ivect.dvect_as_auto_ptr(dv) + print '1. auto_ptr_reference_dvect_as_tuple' + print dvect.auto_ptr_reference_dvect_as_tuple(adv) + print '2. auto_ptr_reference_dvect_as_tuple' + print dvect.auto_ptr_reference_dvect_as_tuple(adv) + # + aiv = ivect.ivect_as_auto_ptr(iv) + print '1. auto_ptr_reference_ivect_as_tuple' + print dvect.auto_ptr_reference_ivect_as_tuple(aiv) + print '2. auto_ptr_reference_ivect_as_tuple' + print dvect.auto_ptr_reference_ivect_as_tuple(aiv) + # + sdv = ivect.dvect_as_shared_ptr(dv) + print '1. shared_ptr_reference_dvect_as_tuple' + print dvect.shared_ptr_reference_dvect_as_tuple(sdv) + print '2. shared_ptr_reference_dvect_as_tuple' + print dvect.shared_ptr_reference_dvect_as_tuple(sdv) + # + siv = ivect.ivect_as_shared_ptr(iv) + print '1. shared_ptr_reference_ivect_as_tuple' + print dvect.shared_ptr_reference_ivect_as_tuple(siv) + print '2. shared_ptr_reference_ivect_as_tuple' + print dvect.shared_ptr_reference_ivect_as_tuple(siv) + # + adv = ivect.dvect_as_auto_ptr(dv) + print '1. auto_ptr_const_reference_dvect_as_tuple' + print dvect.auto_ptr_const_reference_dvect_as_tuple(adv) + print '2. auto_ptr_const_reference_dvect_as_tuple' + print dvect.auto_ptr_const_reference_dvect_as_tuple(adv) + # + aiv = ivect.ivect_as_auto_ptr(iv) + print '1. auto_ptr_const_reference_ivect_as_tuple' + print dvect.auto_ptr_const_reference_ivect_as_tuple(aiv) + print '2. auto_ptr_const_reference_ivect_as_tuple' + print dvect.auto_ptr_const_reference_ivect_as_tuple(aiv) + # + sdv = ivect.dvect_as_shared_ptr(dv) + print '1. shared_ptr_const_reference_dvect_as_tuple' + print dvect.shared_ptr_const_reference_dvect_as_tuple(sdv) + print '2. shared_ptr_const_reference_dvect_as_tuple' + print dvect.shared_ptr_const_reference_dvect_as_tuple(sdv) + # + siv = ivect.ivect_as_shared_ptr(iv) + print '1. shared_ptr_const_reference_ivect_as_tuple' + print dvect.shared_ptr_const_reference_ivect_as_tuple(siv) + print '2. shared_ptr_const_reference_ivect_as_tuple' + print dvect.shared_ptr_const_reference_ivect_as_tuple(siv) + +if (__name__ == "__main__"): + import sys, string + n = 1 + if (len(sys.argv) > 1): n = string.atoi(sys.argv[1]) + for i in xrange(n): + f() From c7d7cec28190763156ebe44d950f830ffac07c77 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 21 Mar 2001 01:07:07 +0000 Subject: [PATCH 073/369] temp files removed after branching. [SVN r9616] --- example/dvect_conversions.cpp | 51 --------------------- example/dvect_defs.cpp | 13 ------ example/ivect_conversions.cpp | 51 --------------------- example/ivect_defs.cpp | 13 ------ example/swap_iv_dv.sh | 1 - example/tst_dvect1.py | 23 ---------- example/tst_dvect2.py | 85 ----------------------------------- example/tst_ivect1.py | 23 ---------- example/tst_ivect2.py | 85 ----------------------------------- 9 files changed, 345 deletions(-) delete mode 100644 example/dvect_conversions.cpp delete mode 100644 example/dvect_defs.cpp delete mode 100644 example/ivect_conversions.cpp delete mode 100644 example/ivect_defs.cpp delete mode 100644 example/swap_iv_dv.sh delete mode 100644 example/tst_dvect1.py delete mode 100644 example/tst_dvect2.py delete mode 100644 example/tst_ivect1.py delete mode 100644 example/tst_ivect2.py diff --git a/example/dvect_conversions.cpp b/example/dvect_conversions.cpp deleted file mode 100644 index 21527243..00000000 --- a/example/dvect_conversions.cpp +++ /dev/null @@ -1,51 +0,0 @@ - // basics first: const reference converters - boost::python::tuple const_dvect_reference_as_tuple(const vects::dvect& dv) - { - return dv.as_tuple(); - } - - // to_python smart pointer conversions - std::auto_ptr dvect_as_auto_ptr(const vects::dvect& dv) - { - return std::auto_ptr(new vects::dvect(dv)); - } - boost::shared_ptr dvect_as_shared_ptr(const vects::dvect& dv) - { - return boost::shared_ptr(new vects::dvect(dv)); - } - - // smart pointers passed by value - boost::python::ref auto_ptr_value_dvect_as_tuple(std::auto_ptr dv) - { - if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return dv->as_tuple().reference(); - } - boost::python::ref shared_ptr_value_dvect_as_tuple(boost::shared_ptr dv) - { - if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return dv->as_tuple().reference(); - } - - // smart pointers passed by reference - boost::python::ref auto_ptr_reference_dvect_as_tuple(std::auto_ptr& dv) - { - if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return dv->as_tuple().reference(); - } - boost::python::ref shared_ptr_reference_dvect_as_tuple(boost::shared_ptr& dv) - { - if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return dv->as_tuple().reference(); - } - - // smart pointers passed by const reference - boost::python::ref auto_ptr_const_reference_dvect_as_tuple(const std::auto_ptr& dv) - { - if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return dv->as_tuple().reference(); - } - boost::python::ref shared_ptr_const_reference_dvect_as_tuple(const boost::shared_ptr& dv) - { - if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return dv->as_tuple().reference(); - } diff --git a/example/dvect_defs.cpp b/example/dvect_defs.cpp deleted file mode 100644 index 2739b219..00000000 --- a/example/dvect_defs.cpp +++ /dev/null @@ -1,13 +0,0 @@ - this_module.def(dvect_as_auto_ptr, "dvect_as_auto_ptr"); - this_module.def(dvect_as_shared_ptr, "dvect_as_shared_ptr"); - - this_module.def(const_dvect_reference_as_tuple, "const_dvect_reference_as_tuple"); - - this_module.def(auto_ptr_value_dvect_as_tuple, "auto_ptr_value_dvect_as_tuple"); - this_module.def(shared_ptr_value_dvect_as_tuple, "shared_ptr_value_dvect_as_tuple"); - - this_module.def(auto_ptr_reference_dvect_as_tuple, "auto_ptr_reference_dvect_as_tuple"); - this_module.def(shared_ptr_reference_dvect_as_tuple, "shared_ptr_reference_dvect_as_tuple"); - - this_module.def(auto_ptr_const_reference_dvect_as_tuple, "auto_ptr_const_reference_dvect_as_tuple"); - this_module.def(shared_ptr_const_reference_dvect_as_tuple, "shared_ptr_const_reference_dvect_as_tuple"); diff --git a/example/ivect_conversions.cpp b/example/ivect_conversions.cpp deleted file mode 100644 index 4f59573d..00000000 --- a/example/ivect_conversions.cpp +++ /dev/null @@ -1,51 +0,0 @@ - // basics first: const reference converters - boost::python::tuple const_ivect_reference_as_tuple(const vects::ivect& iv) - { - return iv.as_tuple(); - } - - // to_python smart pointer conversions - std::auto_ptr ivect_as_auto_ptr(const vects::ivect& iv) - { - return std::auto_ptr(new vects::ivect(iv)); - } - boost::shared_ptr ivect_as_shared_ptr(const vects::ivect& iv) - { - return boost::shared_ptr(new vects::ivect(iv)); - } - - // smart pointers passed by value - boost::python::ref auto_ptr_value_ivect_as_tuple(std::auto_ptr iv) - { - if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return iv->as_tuple().reference(); - } - boost::python::ref shared_ptr_value_ivect_as_tuple(boost::shared_ptr iv) - { - if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return iv->as_tuple().reference(); - } - - // smart pointers passed by reference - boost::python::ref auto_ptr_reference_ivect_as_tuple(std::auto_ptr& iv) - { - if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return iv->as_tuple().reference(); - } - boost::python::ref shared_ptr_reference_ivect_as_tuple(boost::shared_ptr& iv) - { - if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return iv->as_tuple().reference(); - } - - // smart pointers passed by const reference - boost::python::ref auto_ptr_const_reference_ivect_as_tuple(const std::auto_ptr& iv) - { - if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return iv->as_tuple().reference(); - } - boost::python::ref shared_ptr_const_reference_ivect_as_tuple(const boost::shared_ptr& iv) - { - if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); - return iv->as_tuple().reference(); - } diff --git a/example/ivect_defs.cpp b/example/ivect_defs.cpp deleted file mode 100644 index 811c243d..00000000 --- a/example/ivect_defs.cpp +++ /dev/null @@ -1,13 +0,0 @@ - this_module.def(ivect_as_auto_ptr, "ivect_as_auto_ptr"); - this_module.def(ivect_as_shared_ptr, "ivect_as_shared_ptr"); - - this_module.def(const_ivect_reference_as_tuple, "const_ivect_reference_as_tuple"); - - this_module.def(auto_ptr_value_ivect_as_tuple, "auto_ptr_value_ivect_as_tuple"); - this_module.def(shared_ptr_value_ivect_as_tuple, "shared_ptr_value_ivect_as_tuple"); - - this_module.def(auto_ptr_reference_ivect_as_tuple, "auto_ptr_reference_ivect_as_tuple"); - this_module.def(shared_ptr_reference_ivect_as_tuple, "shared_ptr_reference_ivect_as_tuple"); - - this_module.def(auto_ptr_const_reference_ivect_as_tuple, "auto_ptr_const_reference_ivect_as_tuple"); - this_module.def(shared_ptr_const_reference_ivect_as_tuple, "shared_ptr_const_reference_ivect_as_tuple"); diff --git a/example/swap_iv_dv.sh b/example/swap_iv_dv.sh deleted file mode 100644 index fc072bee..00000000 --- a/example/swap_iv_dv.sh +++ /dev/null @@ -1 +0,0 @@ -sed 's/iv/xv/g' $1 | sed 's/dv/iv/g' | sed 's/xv/dv/g' diff --git a/example/tst_dvect1.py b/example/tst_dvect1.py deleted file mode 100644 index 12c53739..00000000 --- a/example/tst_dvect1.py +++ /dev/null @@ -1,23 +0,0 @@ -def f(): - import dvect - print dvect.dvect.__converters__ - dv = dvect.dvect((1,2,3,4,5)) - print dv - print dv.as_tuple() - iv = dv.as_ivect() - print iv - print iv.as_tuple() - print dvect.const_ivect_reference_as_tuple(iv) - aiv = dvect.ivect_as_auto_ptr(iv) - print dvect.const_ivect_reference_as_tuple(aiv) - siv = dvect.ivect_as_shared_ptr(iv) - print dvect.const_ivect_reference_as_tuple(siv) - print aiv.as_tuple() - print siv.as_tuple() - -if (__name__ == "__main__"): - import sys, string - n = 1 - if (len(sys.argv) > 1): n = string.atoi(sys.argv[1]) - for i in xrange(n): - f() diff --git a/example/tst_dvect2.py b/example/tst_dvect2.py deleted file mode 100644 index 868c107d..00000000 --- a/example/tst_dvect2.py +++ /dev/null @@ -1,85 +0,0 @@ -def f(): - import dvect - import ivect - # - dv = dvect.dvect((1,2,3,4,5)) - iv = dv.as_ivect() - # - aiv = dvect.ivect_as_auto_ptr(iv) - print '1. auto_ptr_value_ivect_as_tuple' - print ivect.auto_ptr_value_ivect_as_tuple(aiv) - print '2. auto_ptr_value_ivect_as_tuple' - print ivect.auto_ptr_value_ivect_as_tuple(aiv) - # - adv = dvect.dvect_as_auto_ptr(dv) - print '1. auto_ptr_value_dvect_as_tuple' - print ivect.auto_ptr_value_dvect_as_tuple(adv) - print '2. auto_ptr_value_dvect_as_tuple' - print ivect.auto_ptr_value_dvect_as_tuple(adv) - # - siv = dvect.ivect_as_shared_ptr(iv) - print '1. shared_ptr_value_ivect_as_tuple' - print ivect.shared_ptr_value_ivect_as_tuple(siv) - print '2. shared_ptr_value_ivect_as_tuple' - print ivect.shared_ptr_value_ivect_as_tuple(siv) - # - sdv = dvect.dvect_as_shared_ptr(dv) - print '1. shared_ptr_value_dvect_as_tuple' - print ivect.shared_ptr_value_dvect_as_tuple(sdv) - print '2. shared_ptr_value_dvect_as_tuple' - print ivect.shared_ptr_value_dvect_as_tuple(sdv) - # - aiv = dvect.ivect_as_auto_ptr(iv) - print '1. auto_ptr_reference_ivect_as_tuple' - print ivect.auto_ptr_reference_ivect_as_tuple(aiv) - print '2. auto_ptr_reference_ivect_as_tuple' - print ivect.auto_ptr_reference_ivect_as_tuple(aiv) - # - adv = dvect.dvect_as_auto_ptr(dv) - print '1. auto_ptr_reference_dvect_as_tuple' - print ivect.auto_ptr_reference_dvect_as_tuple(adv) - print '2. auto_ptr_reference_dvect_as_tuple' - print ivect.auto_ptr_reference_dvect_as_tuple(adv) - # - siv = dvect.ivect_as_shared_ptr(iv) - print '1. shared_ptr_reference_ivect_as_tuple' - print ivect.shared_ptr_reference_ivect_as_tuple(siv) - print '2. shared_ptr_reference_ivect_as_tuple' - print ivect.shared_ptr_reference_ivect_as_tuple(siv) - # - sdv = dvect.dvect_as_shared_ptr(dv) - print '1. shared_ptr_reference_dvect_as_tuple' - print ivect.shared_ptr_reference_dvect_as_tuple(sdv) - print '2. shared_ptr_reference_dvect_as_tuple' - print ivect.shared_ptr_reference_dvect_as_tuple(sdv) - # - aiv = dvect.ivect_as_auto_ptr(iv) - print '1. auto_ptr_const_reference_ivect_as_tuple' - print ivect.auto_ptr_const_reference_ivect_as_tuple(aiv) - print '2. auto_ptr_const_reference_ivect_as_tuple' - print ivect.auto_ptr_const_reference_ivect_as_tuple(aiv) - # - adv = dvect.dvect_as_auto_ptr(dv) - print '1. auto_ptr_const_reference_dvect_as_tuple' - print ivect.auto_ptr_const_reference_dvect_as_tuple(adv) - print '2. auto_ptr_const_reference_dvect_as_tuple' - print ivect.auto_ptr_const_reference_dvect_as_tuple(adv) - # - siv = dvect.ivect_as_shared_ptr(iv) - print '1. shared_ptr_const_reference_ivect_as_tuple' - print ivect.shared_ptr_const_reference_ivect_as_tuple(siv) - print '2. shared_ptr_const_reference_ivect_as_tuple' - print ivect.shared_ptr_const_reference_ivect_as_tuple(siv) - # - sdv = dvect.dvect_as_shared_ptr(dv) - print '1. shared_ptr_const_reference_dvect_as_tuple' - print ivect.shared_ptr_const_reference_dvect_as_tuple(sdv) - print '2. shared_ptr_const_reference_dvect_as_tuple' - print ivect.shared_ptr_const_reference_dvect_as_tuple(sdv) - -if (__name__ == "__main__"): - import sys, string - n = 1 - if (len(sys.argv) > 1): n = string.atoi(sys.argv[1]) - for i in xrange(n): - f() diff --git a/example/tst_ivect1.py b/example/tst_ivect1.py deleted file mode 100644 index 62d3ecf4..00000000 --- a/example/tst_ivect1.py +++ /dev/null @@ -1,23 +0,0 @@ -def f(): - import ivect - print ivect.ivect.__converters__ - iv = ivect.ivect((1,2,3,4,5)) - print iv - print iv.as_tuple() - dv = iv.as_dvect() - print dv - print dv.as_tuple() - print ivect.const_dvect_reference_as_tuple(dv) - adv = ivect.dvect_as_auto_ptr(dv) - print ivect.const_dvect_reference_as_tuple(adv) - sdv = ivect.dvect_as_shared_ptr(dv) - print ivect.const_dvect_reference_as_tuple(sdv) - print adv.as_tuple() - print sdv.as_tuple() - -if (__name__ == "__main__"): - import sys, string - n = 1 - if (len(sys.argv) > 1): n = string.atoi(sys.argv[1]) - for i in xrange(n): - f() diff --git a/example/tst_ivect2.py b/example/tst_ivect2.py deleted file mode 100644 index 0db6903d..00000000 --- a/example/tst_ivect2.py +++ /dev/null @@ -1,85 +0,0 @@ -def f(): - import ivect - import dvect - # - iv = ivect.ivect((1,2,3,4,5)) - dv = iv.as_dvect() - # - adv = ivect.dvect_as_auto_ptr(dv) - print '1. auto_ptr_value_dvect_as_tuple' - print dvect.auto_ptr_value_dvect_as_tuple(adv) - print '2. auto_ptr_value_dvect_as_tuple' - print dvect.auto_ptr_value_dvect_as_tuple(adv) - # - aiv = ivect.ivect_as_auto_ptr(iv) - print '1. auto_ptr_value_ivect_as_tuple' - print dvect.auto_ptr_value_ivect_as_tuple(aiv) - print '2. auto_ptr_value_ivect_as_tuple' - print dvect.auto_ptr_value_ivect_as_tuple(aiv) - # - sdv = ivect.dvect_as_shared_ptr(dv) - print '1. shared_ptr_value_dvect_as_tuple' - print dvect.shared_ptr_value_dvect_as_tuple(sdv) - print '2. shared_ptr_value_dvect_as_tuple' - print dvect.shared_ptr_value_dvect_as_tuple(sdv) - # - siv = ivect.ivect_as_shared_ptr(iv) - print '1. shared_ptr_value_ivect_as_tuple' - print dvect.shared_ptr_value_ivect_as_tuple(siv) - print '2. shared_ptr_value_ivect_as_tuple' - print dvect.shared_ptr_value_ivect_as_tuple(siv) - # - adv = ivect.dvect_as_auto_ptr(dv) - print '1. auto_ptr_reference_dvect_as_tuple' - print dvect.auto_ptr_reference_dvect_as_tuple(adv) - print '2. auto_ptr_reference_dvect_as_tuple' - print dvect.auto_ptr_reference_dvect_as_tuple(adv) - # - aiv = ivect.ivect_as_auto_ptr(iv) - print '1. auto_ptr_reference_ivect_as_tuple' - print dvect.auto_ptr_reference_ivect_as_tuple(aiv) - print '2. auto_ptr_reference_ivect_as_tuple' - print dvect.auto_ptr_reference_ivect_as_tuple(aiv) - # - sdv = ivect.dvect_as_shared_ptr(dv) - print '1. shared_ptr_reference_dvect_as_tuple' - print dvect.shared_ptr_reference_dvect_as_tuple(sdv) - print '2. shared_ptr_reference_dvect_as_tuple' - print dvect.shared_ptr_reference_dvect_as_tuple(sdv) - # - siv = ivect.ivect_as_shared_ptr(iv) - print '1. shared_ptr_reference_ivect_as_tuple' - print dvect.shared_ptr_reference_ivect_as_tuple(siv) - print '2. shared_ptr_reference_ivect_as_tuple' - print dvect.shared_ptr_reference_ivect_as_tuple(siv) - # - adv = ivect.dvect_as_auto_ptr(dv) - print '1. auto_ptr_const_reference_dvect_as_tuple' - print dvect.auto_ptr_const_reference_dvect_as_tuple(adv) - print '2. auto_ptr_const_reference_dvect_as_tuple' - print dvect.auto_ptr_const_reference_dvect_as_tuple(adv) - # - aiv = ivect.ivect_as_auto_ptr(iv) - print '1. auto_ptr_const_reference_ivect_as_tuple' - print dvect.auto_ptr_const_reference_ivect_as_tuple(aiv) - print '2. auto_ptr_const_reference_ivect_as_tuple' - print dvect.auto_ptr_const_reference_ivect_as_tuple(aiv) - # - sdv = ivect.dvect_as_shared_ptr(dv) - print '1. shared_ptr_const_reference_dvect_as_tuple' - print dvect.shared_ptr_const_reference_dvect_as_tuple(sdv) - print '2. shared_ptr_const_reference_dvect_as_tuple' - print dvect.shared_ptr_const_reference_dvect_as_tuple(sdv) - # - siv = ivect.ivect_as_shared_ptr(iv) - print '1. shared_ptr_const_reference_ivect_as_tuple' - print dvect.shared_ptr_const_reference_ivect_as_tuple(siv) - print '2. shared_ptr_const_reference_ivect_as_tuple' - print dvect.shared_ptr_const_reference_ivect_as_tuple(siv) - -if (__name__ == "__main__"): - import sys, string - n = 1 - if (len(sys.argv) > 1): n = string.atoi(sys.argv[1]) - for i in xrange(n): - f() From 4ec0b61de5ec0f677bb4ad7d6d6948bf8cbd00c4 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 21 Mar 2001 01:09:17 +0000 Subject: [PATCH 074/369] Now using BOOST_PYTHON_MODULE_INIT. [SVN r9617] --- example/abstract.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/example/abstract.cpp b/example/abstract.cpp index 41d34def..97e38c2e 100644 --- a/example/abstract.cpp +++ b/example/abstract.cpp @@ -21,9 +21,7 @@ struct Abstract_callback: Abstract PyObject * m_self; }; -extern "C" -DL_EXPORT(void) -initabstract() +BOOST_PYTHON_MODULE_INIT(abstract) { boost::python::module_builder a("abstract"); From f610e31a87aafbad86576d99c51c6c5347ca5c66 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 21 Mar 2001 01:15:53 +0000 Subject: [PATCH 075/369] temp files removed after branching. [SVN r9619] --- build/filemgr.py | 122 -------------------------------------------- build/vc60.mak | 129 ----------------------------------------------- 2 files changed, 251 deletions(-) delete mode 100644 build/filemgr.py delete mode 100644 build/vc60.mak diff --git a/build/filemgr.py b/build/filemgr.py deleted file mode 100644 index 51c87403..00000000 --- a/build/filemgr.py +++ /dev/null @@ -1,122 +0,0 @@ -bpl_src = "/libs/python/src" -bpl_tst = "/libs/python/test" -bpl_exa = "/libs/python/example" -files = ( -bpl_src + "/classes.cpp", -bpl_src + "/conversions.cpp", -bpl_src + "/extension_class.cpp", -bpl_src + "/functions.cpp", -bpl_src + "/init_function.cpp", -bpl_src + "/module_builder.cpp", -bpl_src + "/objects.cpp", -bpl_src + "/types.cpp", -bpl_src + "/cross_module.cpp", -bpl_tst + "/comprehensive.cpp", -bpl_tst + "/comprehensive.hpp", -bpl_tst + "/comprehensive.py", -bpl_tst + "/doctest.py", -bpl_exa + "/abstract.cpp", -bpl_exa + "/getting_started1.cpp", -bpl_exa + "/getting_started2.cpp", -bpl_exa + "/getting_started3.cpp", -bpl_exa + "/getting_started4.cpp", -bpl_exa + "/getting_started5.cpp", -bpl_exa + "/pickle1.cpp", -bpl_exa + "/pickle2.cpp", -bpl_exa + "/pickle3.cpp", -bpl_exa + "/test_abstract.py", -bpl_exa + "/test_getting_started1.py", -bpl_exa + "/test_getting_started2.py", -bpl_exa + "/test_getting_started3.py", -bpl_exa + "/test_getting_started4.py", -bpl_exa + "/test_getting_started5.py", -bpl_exa + "/test_pickle1.py", -bpl_exa + "/test_pickle2.py", -bpl_exa + "/test_pickle3.py", -bpl_exa + "/noncopyable.h", -bpl_exa + "/noncopyable_export.cpp", -bpl_exa + "/noncopyable_import.cpp", -bpl_exa + "/tst_noncopyable.py", -bpl_exa + "/ivect.h", -bpl_exa + "/ivect.cpp", -bpl_exa + "/dvect.h", -bpl_exa + "/dvect.cpp", -bpl_exa + "/tst_ivect.py", -bpl_exa + "/tst_dvect.py", -) - -defs = ( -"boost_python_test", -"abstract", -"getting_started1", -"getting_started2", -"getting_started3", -"getting_started4", -"getting_started5", -"pickle1", -"pickle2", -"pickle3", -"noncopyable_export", -"noncopyable_import", -"ivect", -"dvect", -) - -if (__name__ == "__main__"): - - import sys, os, string - - path = sys.argv[1] - mode = sys.argv[2] - if (not mode in ("softlinks", "unlink", "cp", "rm", "copy", "del")): - raise RuntimeError, \ - "usage: python filemgr.py path " - - translation_table = string.maketrans("/", "\\") - - if (mode == "copy"): - for fn in files: - fn = string.translate(fn, translation_table) - os.system("copy " + path + fn + " .") - - elif (mode == "cp"): - for fn in files: - os.system("cp " + path + fn + " .") - - elif (mode == "softlinks"): - for fn in files: - f = string.split(fn, "/")[-1] - if (os.access(f, os.F_OK)): - print "File exists: " + f - else: - os.system("ln -s " + path + os.sep + fn + " .") - - elif (mode in ("rm", "del")): - for fn in files: - flds = string.split(fn, "/") - try: os.unlink(flds[-1]) - except: pass - - elif (mode == "unlink"): - for fn in files: - f = string.split(fn, "/")[-1] - if (os.system("test -e " + f) == 0): - if (os.system("test -L " + f) == 0): - try: os.unlink(f) - except: pass - else: - print "Not a softlink: " + f - - if (mode in ("softlinks", "cp", "copy")): - for d in defs: - fn = d + ".def" - f = open(fn, "w") - f.write("EXPORTS\n") - f.write("\tinit" + d + "\n") - f.close() - - if (mode in ("unlink", "rm", "del")): - for d in defs: - fn = d + ".def" - try: os.unlink(fn) - except: pass diff --git a/build/vc60.mak b/build/vc60.mak deleted file mode 100644 index a05d04f4..00000000 --- a/build/vc60.mak +++ /dev/null @@ -1,129 +0,0 @@ -# Usage: -# -# make copy Copy the sources and tests -# make Compile all sources -# make test Run doctest tests -# make clean Remove all object files -# make del Remove the sources and tests - -BOOST_WIN= "L:\boost" -BOOST_UNIX= /net/cci/rwgk/boost - -PYEXE= "C:\Program files\Python\python.exe" -PYINC= /I"C:\Program files\Python\include" -PYLIB= "C:\Program files\Python\libs\python15.lib" - -STDOPTS= /nologo /MD /GR /GX /FD /Zm200 -WARNOPTS= - -CPP= cl.exe -CPPOPTS= $(STLPORTINC) $(STLPORTOPTS) /I$(BOOST_WIN) $(PYINC) \ - $(STDOPTS) $(WARNOPTS) - -LD= link.exe -LDOPTS= /nologo /dll /incremental:no - -OBJ = classes.obj conversions.obj extension_class.obj functions.obj \ - init_function.obj module_builder.obj \ - objects.obj types.obj cross_module.obj - -.SUFFIXES: .obj .cpp - -all: libboost_python.a \ - boost_python_test.pyd \ - abstract.pyd \ - getting_started1.pyd getting_started2.pyd getting_started3.pyd \ - getting_started4.pyd getting_started5.pyd \ - pickle1.pyd pickle2.pyd pickle3.pyd \ - noncopyable_export.pyd noncopyable_import.pyd \ - ivect.pyd dvect.pyd - -libboost_python.a: $(OBJ) - -boost_python_test.pyd: $(OBJ) comprehensive.obj - $(LD) $(LDOPTS) $(OBJ) comprehensive.obj $(PYLIB) /export:initboost_python_test /out:"boost_python_test.pyd" - -abstract.pyd: $(OBJ) abstract.obj - $(LD) $(LDOPTS) $(OBJ) abstract.obj $(PYLIB) /export:initabstract /out:"abstract.pyd" - -getting_started1.pyd: $(OBJ) getting_started1.obj - $(LD) $(LDOPTS) $(OBJ) getting_started1.obj $(PYLIB) /export:initgetting_started1 /out:"getting_started1.pyd" - -getting_started2.pyd: $(OBJ) getting_started2.obj - $(LD) $(LDOPTS) $(OBJ) getting_started2.obj $(PYLIB) /export:initgetting_started2 /out:"getting_started2.pyd" - -getting_started3.pyd: $(OBJ) getting_started3.obj - $(LD) $(LDOPTS) $(OBJ) getting_started3.obj $(PYLIB) /export:initgetting_started3 /out:"getting_started3.pyd" - -getting_started4.pyd: $(OBJ) getting_started4.obj - $(LD) $(LDOPTS) $(OBJ) getting_started4.obj $(PYLIB) /export:initgetting_started4 /out:"getting_started4.pyd" - -getting_started5.pyd: $(OBJ) getting_started5.obj - $(LD) $(LDOPTS) $(OBJ) getting_started5.obj $(PYLIB) /export:initgetting_started5 /out:"getting_started5.pyd" - -pickle1.pyd: $(OBJ) pickle1.obj - $(LD) $(LDOPTS) $(OBJ) pickle1.obj $(PYLIB) /export:initpickle1 /out:"pickle1.pyd" - -pickle2.pyd: $(OBJ) pickle2.obj - $(LD) $(LDOPTS) $(OBJ) pickle2.obj $(PYLIB) /export:initpickle2 /out:"pickle2.pyd" - -pickle3.pyd: $(OBJ) pickle3.obj - $(LD) $(LDOPTS) $(OBJ) pickle3.obj $(PYLIB) /export:initpickle3 /out:"pickle3.pyd" - -noncopyable_export.pyd: $(OBJ) noncopyable_export.obj - $(LD) $(LDOPTS) $(OBJ) noncopyable_export.obj $(PYLIB) /export:initnoncopyable_export /out:"noncopyable_export.pyd" - -noncopyable_import.pyd: $(OBJ) noncopyable_import.obj - $(LD) $(LDOPTS) $(OBJ) noncopyable_import.obj $(PYLIB) /export:initnoncopyable_import /out:"noncopyable_import.pyd" - -ivect.pyd: $(OBJ) ivect.obj - $(LD) $(LDOPTS) $(OBJ) ivect.obj $(PYLIB) /export:initivect /out:"ivect.pyd" - -dvect.pyd: $(OBJ) dvect.obj - $(LD) $(LDOPTS) $(OBJ) dvect.obj $(PYLIB) /export:initdvect /out:"dvect.pyd" - -.cpp.obj: - $(CPP) $(CPPOPTS) /c $*.cpp - -test: - $(PYEXE) comprehensive.py --broken-auto-ptr - $(PYEXE) test_abstract.py - $(PYEXE) test_getting_started1.py - $(PYEXE) test_getting_started2.py - $(PYEXE) test_getting_started3.py - $(PYEXE) test_getting_started4.py - $(PYEXE) test_getting_started5.py - $(PYEXE) test_pickle1.py - $(PYEXE) test_pickle2.py - $(PYEXE) test_pickle3.py - -tst: - $(PYEXE) tst_noncopyable.py - $(PYEXE) tst_ivect.py - $(PYEXE) tst_dvect.py - -clean: - del *.obj - del *.lib - del *.exp - del *.idb - del *.pyd - del *.pyc - -softlinks: - python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) softlinks - -unlink: - python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) unlink - -cp: - python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) cp - -rm: - python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) rm - -copy: - python $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) copy - -del: - python $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) del From 2a96c9f9eea85095c6c1ff889d3c264123e72945 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 21 Mar 2001 02:33:27 +0000 Subject: [PATCH 076/369] temp file before branching [SVN r9621] --- example/do_it_yourself_converters.cpp | 126 ++++++++++++++++++++++ example/simple_vector.cpp | 101 +++++++++++++++++ example/test_do_it_yourself_converters.py | 22 ++++ example/test_simple_vector.py | 35 ++++++ 4 files changed, 284 insertions(+) create mode 100644 example/do_it_yourself_converters.cpp create mode 100644 example/simple_vector.cpp create mode 100644 example/test_do_it_yourself_converters.py create mode 100644 example/test_simple_vector.py diff --git a/example/do_it_yourself_converters.cpp b/example/do_it_yourself_converters.cpp new file mode 100644 index 00000000..ad31f708 --- /dev/null +++ b/example/do_it_yourself_converters.cpp @@ -0,0 +1,126 @@ +/* + This example shows how to convert a class from and to native + Python objects, such as tuples. + + We do not want to expose the helper class MillerIndex as an + Extension Class. However, in order to simplify the wrapper code, + we want to define from_python() and to_python() functions for + class MillerIndex. + + Consider the alternatives: + + - Expose MillerIndex as an Extension Class. + We need a constructor MillerIndex(python::tuple). + Python function calls become more complex: + foo(MillerIndex((1,2,3)) instead of foo((1,2,3)) + We need a method such as MillerIndex().as_tuple(). + + - Define a wrapper function for each function that we + want to expose, e.g.: + void add(const IndexingSet& ixset, const python::tuple PyMIx) + + The first alternative introduces a new type that the user has to + deal with. Other modules using Miller indices might organize them in + different ways, for example to increase runtime efficiency for + important procedures. This means, the user has to know how to + convert between the different kinds of Miller index representations. + This can quickly become a nuisance. Relying on native Python data + structures minimizes the number of special types the user has to + learn and convert. Of course, this argument is only valid for + small and relatively simply classes. + + If there are many member functions with MillerIndex arguments, the + second alternative is impractical, and concentrating the conversion + mechanism in one central place is essential for code + maintainability. An added benefit is that more convenient (smarter) + conversion functions can be provided without cluttering the rest of + the wrapper code. + + */ + +#include +#include +#include +namespace python = boost::python; + +namespace { // Avoid cluttering the global namespace. + + // The helper class. + // + class MillerIndex { + public: + int v[3]; + }; + + // The main class. Imagine that there are MANY member functions + // like add() and get(). + // + class IndexingSet { + private: + std::vector VMIx; + public: + void add(const MillerIndex& MIx) { VMIx.push_back(MIx); } + MillerIndex get(std::size_t i) const { return VMIx[i]; } + }; +} + +BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE + + // Convert a Python tuple to a MillerIndex object. + // + MillerIndex from_python(PyObject* p, python::type) + { + python::tuple tup + = python::tuple(python::ref(p, python::ref::increment_count)); + if (tup.size() != 3) { + PyErr_SetString(PyExc_ValueError, + "expecting exactly 3 values in tuple."); + throw python::error_already_set(); + } + MillerIndex result; + for (int i = 0; i < 3; i++) + result.v[i] = from_python(tup[i].get(), python::type()); + return result; + } + + // Similar conversion for MillerIndex objects passed by value. + // Not actually used, but included to show the principle. + // + MillerIndex from_python(PyObject* p, python::type) + { + return from_python(p, python::type()); + } + + // Convert a MillerIndex object to a Python tuple. + // + PyObject* to_python(const MillerIndex& hkl) + { + python::tuple result(3); + for (int i = 0; i < 3; i++) + result.set_item(i, python::ref(to_python(hkl.v[i]))); + return result.reference().release(); + } + +BOOST_PYTHON_END_CONVERSION_NAMESPACE + +BOOST_PYTHON_MODULE_INIT(do_it_yourself_converters) +{ + try + { + // Create an object representing this extension module. + python::module_builder this_module("do_it_yourself_converters"); + + // Create the Python type object for our extension class. + python::class_builder ixset_class(this_module, "IndexingSet"); + + // Add the __init__ function. + ixset_class.def(python::constructor<>()); + // Add the member functions. + ixset_class.def(&IndexingSet::add, "add"); + ixset_class.def(&IndexingSet::get, "get"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/simple_vector.cpp b/example/simple_vector.cpp new file mode 100644 index 00000000..f18f2cad --- /dev/null +++ b/example/simple_vector.cpp @@ -0,0 +1,101 @@ +#include +namespace python = boost::python; + +namespace { // Avoid cluttering the global namespace. + + // A wrapper is used to define additional constructors. + // + struct vector_double_wrapper: std::vector + { + // Tell the compiler how to convert a base class object to + // this wrapper object. + vector_double_wrapper(PyObject*, const std::vector& vd) + : std::vector(vd) {} + + vector_double_wrapper(PyObject* self) + : std::vector() {} + + vector_double_wrapper(PyObject* self, int n) + : std::vector(n) {} + + vector_double_wrapper(PyObject* self, python::tuple tuple) + : std::vector(tuple.size()) + { + std::vector::iterator vd = begin(); + for (int i = 0; i < tuple.size(); i++) + vd[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), + python::type()); + } + }; + + double getitem(const std::vector& vd, std::size_t key) { + return vd[key]; + } + + void setitem(std::vector& vd, std::size_t key, double d) { + std::vector::iterator vditer = vd.begin(); + vditer[key] = d; + } + + void delitem(std::vector& vd, std::size_t key) { + std::vector::iterator vditer = vd.begin(); + vd.erase(&vditer[key]); + } + + // Convert vector_double to a regular Python tuple. + // + python::tuple as_tuple(const std::vector& vd) + { + python::tuple t(vd.size()); + for (int i = 0; i < vd.size(); i++) t.set_item(i, + python::ref(BOOST_PYTHON_CONVERSION::to_python(vd[i]))); + return t; + } + + // Function returning a vector_double object to Python. + // + std::vector foo(int n) + { + std::vector vd(n); + std::vector::iterator vditer = vd.begin(); + for (int i = 0; i < n; i++) vditer[i] = double(i); + return vd; + } + + // Same as foo(), but avoid copying on return. + // + std::auto_ptr > bar(int n) + { + std::auto_ptr > vdptr(new std::vector(n)); + std::vector::iterator vditer = vdptr->begin(); + for (int i = 0; i < n; i++) vditer[i] = double(10 * i); + return vdptr; + } +} + +BOOST_PYTHON_MODULE_INIT(simple_vector) +{ + try + { + python::module_builder this_module("simple_vector"); + + python::class_builder, vector_double_wrapper> + vector_double(this_module, "vector_double"); + + vector_double.def(python::constructor<>()); + vector_double.def(python::constructor()); + vector_double.def(python::constructor()); + vector_double.def(&std::vector::size, "__len__"); + vector_double.def(getitem, "__getitem__"); + vector_double.def(setitem, "__setitem__"); + vector_double.def(delitem, "__delitem__"); + vector_double.def(as_tuple, "as_tuple"); + + this_module.def(foo, "foo"); + this_module.def(bar, "bar"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/test_do_it_yourself_converters.py b/example/test_do_it_yourself_converters.py new file mode 100644 index 00000000..e256c614 --- /dev/null +++ b/example/test_do_it_yourself_converters.py @@ -0,0 +1,22 @@ +r'''>>> import do_it_yourself_converters + >>> ixset = do_it_yourself_converters.IndexingSet() + >>> ixset.add((1,2,3)) + >>> ixset.add((4,5,6)) + >>> ixset.add((7,8,9)) + >>> print ixset.get(0) + (1, 2, 3) + >>> print ixset.get(1) + (4, 5, 6) + >>> print ixset.get(2) + (7, 8, 9) +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_do_it_yourself_converters + doctest.testmod(test_do_it_yourself_converters) + +if __name__ == '__main__': + run() diff --git a/example/test_simple_vector.py b/example/test_simple_vector.py new file mode 100644 index 00000000..a19e205b --- /dev/null +++ b/example/test_simple_vector.py @@ -0,0 +1,35 @@ +r'''>>> import simple_vector + >>> v=simple_vector.vector_double() + >>> print v.as_tuple() + () + >>> v=simple_vector.vector_double(5) + >>> print v.as_tuple() + (0.0, 0.0, 0.0, 0.0, 0.0) + >>> print len(v) + 5 + >>> v=simple_vector.vector_double((3,4,5)) + >>> print v.as_tuple() + (3.0, 4.0, 5.0) + >>> print v[1] + 4.0 + >>> v[1] = 40 + >>> print v.as_tuple() + (3.0, 40.0, 5.0) + >>> del v[1] + >>> print v.as_tuple() + (3.0, 5.0) + >>> print simple_vector.foo(11).as_tuple() + (0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0) + >>> print simple_vector.bar(12).as_tuple() + (0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 110.0) +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_simple_vector + doctest.testmod(test_simple_vector) + +if __name__ == '__main__': + run() From 01bcd460dabfdd58d435dc020d0025ef3a23b914 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 21 Mar 2001 02:35:32 +0000 Subject: [PATCH 077/369] temp files removed after branching. [SVN r9623] --- example/do_it_yourself_converters.cpp | 126 ---------------------- example/simple_vector.cpp | 101 ----------------- example/test_do_it_yourself_converters.py | 22 ---- example/test_simple_vector.py | 35 ------ 4 files changed, 284 deletions(-) delete mode 100644 example/do_it_yourself_converters.cpp delete mode 100644 example/simple_vector.cpp delete mode 100644 example/test_do_it_yourself_converters.py delete mode 100644 example/test_simple_vector.py diff --git a/example/do_it_yourself_converters.cpp b/example/do_it_yourself_converters.cpp deleted file mode 100644 index ad31f708..00000000 --- a/example/do_it_yourself_converters.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - This example shows how to convert a class from and to native - Python objects, such as tuples. - - We do not want to expose the helper class MillerIndex as an - Extension Class. However, in order to simplify the wrapper code, - we want to define from_python() and to_python() functions for - class MillerIndex. - - Consider the alternatives: - - - Expose MillerIndex as an Extension Class. - We need a constructor MillerIndex(python::tuple). - Python function calls become more complex: - foo(MillerIndex((1,2,3)) instead of foo((1,2,3)) - We need a method such as MillerIndex().as_tuple(). - - - Define a wrapper function for each function that we - want to expose, e.g.: - void add(const IndexingSet& ixset, const python::tuple PyMIx) - - The first alternative introduces a new type that the user has to - deal with. Other modules using Miller indices might organize them in - different ways, for example to increase runtime efficiency for - important procedures. This means, the user has to know how to - convert between the different kinds of Miller index representations. - This can quickly become a nuisance. Relying on native Python data - structures minimizes the number of special types the user has to - learn and convert. Of course, this argument is only valid for - small and relatively simply classes. - - If there are many member functions with MillerIndex arguments, the - second alternative is impractical, and concentrating the conversion - mechanism in one central place is essential for code - maintainability. An added benefit is that more convenient (smarter) - conversion functions can be provided without cluttering the rest of - the wrapper code. - - */ - -#include -#include -#include -namespace python = boost::python; - -namespace { // Avoid cluttering the global namespace. - - // The helper class. - // - class MillerIndex { - public: - int v[3]; - }; - - // The main class. Imagine that there are MANY member functions - // like add() and get(). - // - class IndexingSet { - private: - std::vector VMIx; - public: - void add(const MillerIndex& MIx) { VMIx.push_back(MIx); } - MillerIndex get(std::size_t i) const { return VMIx[i]; } - }; -} - -BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE - - // Convert a Python tuple to a MillerIndex object. - // - MillerIndex from_python(PyObject* p, python::type) - { - python::tuple tup - = python::tuple(python::ref(p, python::ref::increment_count)); - if (tup.size() != 3) { - PyErr_SetString(PyExc_ValueError, - "expecting exactly 3 values in tuple."); - throw python::error_already_set(); - } - MillerIndex result; - for (int i = 0; i < 3; i++) - result.v[i] = from_python(tup[i].get(), python::type()); - return result; - } - - // Similar conversion for MillerIndex objects passed by value. - // Not actually used, but included to show the principle. - // - MillerIndex from_python(PyObject* p, python::type) - { - return from_python(p, python::type()); - } - - // Convert a MillerIndex object to a Python tuple. - // - PyObject* to_python(const MillerIndex& hkl) - { - python::tuple result(3); - for (int i = 0; i < 3; i++) - result.set_item(i, python::ref(to_python(hkl.v[i]))); - return result.reference().release(); - } - -BOOST_PYTHON_END_CONVERSION_NAMESPACE - -BOOST_PYTHON_MODULE_INIT(do_it_yourself_converters) -{ - try - { - // Create an object representing this extension module. - python::module_builder this_module("do_it_yourself_converters"); - - // Create the Python type object for our extension class. - python::class_builder ixset_class(this_module, "IndexingSet"); - - // Add the __init__ function. - ixset_class.def(python::constructor<>()); - // Add the member functions. - ixset_class.def(&IndexingSet::add, "add"); - ixset_class.def(&IndexingSet::get, "get"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/simple_vector.cpp b/example/simple_vector.cpp deleted file mode 100644 index f18f2cad..00000000 --- a/example/simple_vector.cpp +++ /dev/null @@ -1,101 +0,0 @@ -#include -namespace python = boost::python; - -namespace { // Avoid cluttering the global namespace. - - // A wrapper is used to define additional constructors. - // - struct vector_double_wrapper: std::vector - { - // Tell the compiler how to convert a base class object to - // this wrapper object. - vector_double_wrapper(PyObject*, const std::vector& vd) - : std::vector(vd) {} - - vector_double_wrapper(PyObject* self) - : std::vector() {} - - vector_double_wrapper(PyObject* self, int n) - : std::vector(n) {} - - vector_double_wrapper(PyObject* self, python::tuple tuple) - : std::vector(tuple.size()) - { - std::vector::iterator vd = begin(); - for (int i = 0; i < tuple.size(); i++) - vd[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), - python::type()); - } - }; - - double getitem(const std::vector& vd, std::size_t key) { - return vd[key]; - } - - void setitem(std::vector& vd, std::size_t key, double d) { - std::vector::iterator vditer = vd.begin(); - vditer[key] = d; - } - - void delitem(std::vector& vd, std::size_t key) { - std::vector::iterator vditer = vd.begin(); - vd.erase(&vditer[key]); - } - - // Convert vector_double to a regular Python tuple. - // - python::tuple as_tuple(const std::vector& vd) - { - python::tuple t(vd.size()); - for (int i = 0; i < vd.size(); i++) t.set_item(i, - python::ref(BOOST_PYTHON_CONVERSION::to_python(vd[i]))); - return t; - } - - // Function returning a vector_double object to Python. - // - std::vector foo(int n) - { - std::vector vd(n); - std::vector::iterator vditer = vd.begin(); - for (int i = 0; i < n; i++) vditer[i] = double(i); - return vd; - } - - // Same as foo(), but avoid copying on return. - // - std::auto_ptr > bar(int n) - { - std::auto_ptr > vdptr(new std::vector(n)); - std::vector::iterator vditer = vdptr->begin(); - for (int i = 0; i < n; i++) vditer[i] = double(10 * i); - return vdptr; - } -} - -BOOST_PYTHON_MODULE_INIT(simple_vector) -{ - try - { - python::module_builder this_module("simple_vector"); - - python::class_builder, vector_double_wrapper> - vector_double(this_module, "vector_double"); - - vector_double.def(python::constructor<>()); - vector_double.def(python::constructor()); - vector_double.def(python::constructor()); - vector_double.def(&std::vector::size, "__len__"); - vector_double.def(getitem, "__getitem__"); - vector_double.def(setitem, "__setitem__"); - vector_double.def(delitem, "__delitem__"); - vector_double.def(as_tuple, "as_tuple"); - - this_module.def(foo, "foo"); - this_module.def(bar, "bar"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/test_do_it_yourself_converters.py b/example/test_do_it_yourself_converters.py deleted file mode 100644 index e256c614..00000000 --- a/example/test_do_it_yourself_converters.py +++ /dev/null @@ -1,22 +0,0 @@ -r'''>>> import do_it_yourself_converters - >>> ixset = do_it_yourself_converters.IndexingSet() - >>> ixset.add((1,2,3)) - >>> ixset.add((4,5,6)) - >>> ixset.add((7,8,9)) - >>> print ixset.get(0) - (1, 2, 3) - >>> print ixset.get(1) - (4, 5, 6) - >>> print ixset.get(2) - (7, 8, 9) -''' - -def run(args = None): - if args is not None: - import sys - sys.argv = args - import doctest, test_do_it_yourself_converters - doctest.testmod(test_do_it_yourself_converters) - -if __name__ == '__main__': - run() diff --git a/example/test_simple_vector.py b/example/test_simple_vector.py deleted file mode 100644 index a19e205b..00000000 --- a/example/test_simple_vector.py +++ /dev/null @@ -1,35 +0,0 @@ -r'''>>> import simple_vector - >>> v=simple_vector.vector_double() - >>> print v.as_tuple() - () - >>> v=simple_vector.vector_double(5) - >>> print v.as_tuple() - (0.0, 0.0, 0.0, 0.0, 0.0) - >>> print len(v) - 5 - >>> v=simple_vector.vector_double((3,4,5)) - >>> print v.as_tuple() - (3.0, 4.0, 5.0) - >>> print v[1] - 4.0 - >>> v[1] = 40 - >>> print v.as_tuple() - (3.0, 40.0, 5.0) - >>> del v[1] - >>> print v.as_tuple() - (3.0, 5.0) - >>> print simple_vector.foo(11).as_tuple() - (0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0) - >>> print simple_vector.bar(12).as_tuple() - (0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 110.0) -''' - -def run(args = None): - if args is not None: - import sys - sys.argv = args - import doctest, test_simple_vector - doctest.testmod(test_simple_vector) - -if __name__ == '__main__': - run() From 5a40cec1edd9ee8ca1f8396f1c0ffd230c53822c Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 1 Apr 2001 13:47:25 +0000 Subject: [PATCH 078/369] temp file before branching [SVN r9689] --- build/irix_CC.mak | 167 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 build/irix_CC.mak diff --git a/build/irix_CC.mak b/build/irix_CC.mak new file mode 100644 index 00000000..91eb819e --- /dev/null +++ b/build/irix_CC.mak @@ -0,0 +1,167 @@ +# Usage: +# +# Create a new empty directory anywhere (preferably not in the boost tree). +# Copy this Makefile to that new directory and rename it to "Makefile" +# Set the BOOST pathname below. +# +# make softlinks Create softlinks to source code and tests +# make Compile all sources +# make test Run doctest tests +# make clean Remove all object files +# make unlink Remove softlinks + +BOOST= /net/cci/rwgk/boost + +#PYEXE= /usr/bin/python +#PYINC= -I/usr/include/python1.5 +PYEXE= /usr/local/Python-1.5.2/bin/python +PYINC= -I/usr/local/Python-1.5.2/include/python1.5 +#PYEXE= /usr/local/Python-2.0/bin/python +#PYINC= -I/usr/local/Python-2.0/include/python2.0 +STLPORTINC= -I/net/cci/xp/C++_C_headers + +STDOPTS= +WARNOPTS= -woff 1001,1234,1682 + +CPP= CC -LANG:std -n32 -mips4 +CPPOPTS= $(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \ + $(STDOPTS) $(WARNOPTS) -g +MAKEDEP= -M + +LD= CC -LANG:std -n32 -mips4 +LDOPTS= -shared -all + +OBJ = classes.o conversions.o extension_class.o functions.o \ + init_function.o module_builder.o \ + objects.o types.o cross_module.o +DEPOBJ= $(OBJ) \ + comprehensive.o \ + abstract.o \ + getting_started1.o getting_started2.o getting_started3.o \ + simple_vector.o \ + do_it_yourself_converters.o \ + pickle1.o pickle2.o pickle3.o \ + noncopyable_export.o noncopyable_import.o \ + ivect.o dvect.o + +.SUFFIXES: .o .cpp + +all: libboost_python.a \ + boost_python_test.so \ + abstract.so \ + getting_started1.so getting_started2.so getting_started3.so \ + simple_vector.so \ + do_it_yourself_converters.so \ + pickle1.so pickle2.so pickle3.so \ + noncopyable_export.so noncopyable_import.so \ + ivect.so dvect.so + +libboost_python.a: $(OBJ) + rm -f libboost_python.a + $(CPP) -ar -all -o libboost_python.a $(OBJ) + +boost_python_test.so: $(OBJ) comprehensive.o + $(LD) $(LDOPTS) $(OBJ) comprehensive.o -o boost_python_test.so -lm + +abstract.so: $(OBJ) abstract.o + $(LD) $(LDOPTS) $(OBJ) abstract.o -o abstract.so + +getting_started1.so: $(OBJ) getting_started1.o + $(LD) $(LDOPTS) $(OBJ) getting_started1.o -o getting_started1.so + +getting_started2.so: $(OBJ) getting_started2.o + $(LD) $(LDOPTS) $(OBJ) getting_started2.o -o getting_started2.so + +getting_started3.so: $(OBJ) getting_started3.o + $(LD) $(LDOPTS) $(OBJ) getting_started3.o -o getting_started3.so + +simple_vector.so: $(OBJ) simple_vector.o + $(LD) $(LDOPTS) $(OBJ) simple_vector.o -o simple_vector.so + +do_it_yourself_converters.so: $(OBJ) do_it_yourself_converters.o + $(LD) $(LDOPTS) $(OBJ) do_it_yourself_converters.o -o do_it_yourself_converters.so + +pickle1.so: $(OBJ) pickle1.o + $(LD) $(LDOPTS) $(OBJ) pickle1.o -o pickle1.so + +pickle2.so: $(OBJ) pickle2.o + $(LD) $(LDOPTS) $(OBJ) pickle2.o -o pickle2.so + +pickle3.so: $(OBJ) pickle3.o + $(LD) $(LDOPTS) $(OBJ) pickle3.o -o pickle3.so + +noncopyable_export.so: $(OBJ) noncopyable_export.o + $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \ + noncopyable_export.o -o noncopyable_export.so + +noncopyable_import.so: $(OBJ) noncopyable_import.o + $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \ + noncopyable_import.o -o noncopyable_import.so + +ivect.so: $(OBJ) ivect.o + $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) ivect.o -o ivect.so + +dvect.so: $(OBJ) dvect.o + $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.so + +.cpp.o: + $(CPP) $(CPPOPTS) -c $*.cpp + +test: + $(PYEXE) comprehensive.py + $(PYEXE) test_abstract.py + $(PYEXE) test_getting_started1.py + $(PYEXE) test_getting_started2.py + $(PYEXE) test_getting_started3.py + $(PYEXE) test_simple_vector.py + $(PYEXE) test_do_it_yourself_converters.py + $(PYEXE) test_pickle1.py + $(PYEXE) test_pickle2.py + $(PYEXE) test_pickle3.py + +tst: + $(PYEXE) tst_noncopyable.py + $(PYEXE) tst_ivect1.py + $(PYEXE) tst_dvect1.py + $(PYEXE) tst_ivect2.py + $(PYEXE) tst_dvect2.py + +clean: + rm -f $(OBJ) libboost_python.a libboost_python.a.input + rm -f comprehensive.o boost_python_test.so + rm -f abstract.o abstract.so + rm -f getting_started1.o getting_started1.so + rm -f getting_started2.o getting_started2.so + rm -f getting_started3.o getting_started3.so + rm -f simple_vector.o simple_vector.so + rm -f do_it_yourself_converters.o do_it_yourself_converters.so + rm -f pickle1.o pickle1.so + rm -f pickle2.o pickle2.so + rm -f pickle3.o pickle3.so + rm -f noncopyable_export.o noncopyable_export.so + rm -f noncopyable_import.o noncopyable_import.so + rm -f ivect.o ivect.so + rm -f dvect.o dvect.so + rm -f so_locations *.pyc + rm -rf ii_files + +softlinks: + $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) softlinks + +unlink: + $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) unlink + +cp: + $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) cp + +rm: + $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) rm + +depend: + @ cat Makefile.nodepend; \ + for obj in $(DEPOBJ); \ + do \ + bn=`echo "$$obj" | cut -d. -f1`; \ + $(CPP) $(CPPOPTS) $(MAKEDEP) "$$bn".cpp; \ + done + From 69e69a77d866b19cfe05298ffc580371d7d58983 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 1 Apr 2001 13:49:05 +0000 Subject: [PATCH 079/369] temp file removed after branching. [SVN r9691] --- build/irix_CC.mak | 167 ---------------------------------------------- 1 file changed, 167 deletions(-) delete mode 100644 build/irix_CC.mak diff --git a/build/irix_CC.mak b/build/irix_CC.mak deleted file mode 100644 index 91eb819e..00000000 --- a/build/irix_CC.mak +++ /dev/null @@ -1,167 +0,0 @@ -# Usage: -# -# Create a new empty directory anywhere (preferably not in the boost tree). -# Copy this Makefile to that new directory and rename it to "Makefile" -# Set the BOOST pathname below. -# -# make softlinks Create softlinks to source code and tests -# make Compile all sources -# make test Run doctest tests -# make clean Remove all object files -# make unlink Remove softlinks - -BOOST= /net/cci/rwgk/boost - -#PYEXE= /usr/bin/python -#PYINC= -I/usr/include/python1.5 -PYEXE= /usr/local/Python-1.5.2/bin/python -PYINC= -I/usr/local/Python-1.5.2/include/python1.5 -#PYEXE= /usr/local/Python-2.0/bin/python -#PYINC= -I/usr/local/Python-2.0/include/python2.0 -STLPORTINC= -I/net/cci/xp/C++_C_headers - -STDOPTS= -WARNOPTS= -woff 1001,1234,1682 - -CPP= CC -LANG:std -n32 -mips4 -CPPOPTS= $(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \ - $(STDOPTS) $(WARNOPTS) -g -MAKEDEP= -M - -LD= CC -LANG:std -n32 -mips4 -LDOPTS= -shared -all - -OBJ = classes.o conversions.o extension_class.o functions.o \ - init_function.o module_builder.o \ - objects.o types.o cross_module.o -DEPOBJ= $(OBJ) \ - comprehensive.o \ - abstract.o \ - getting_started1.o getting_started2.o getting_started3.o \ - simple_vector.o \ - do_it_yourself_converters.o \ - pickle1.o pickle2.o pickle3.o \ - noncopyable_export.o noncopyable_import.o \ - ivect.o dvect.o - -.SUFFIXES: .o .cpp - -all: libboost_python.a \ - boost_python_test.so \ - abstract.so \ - getting_started1.so getting_started2.so getting_started3.so \ - simple_vector.so \ - do_it_yourself_converters.so \ - pickle1.so pickle2.so pickle3.so \ - noncopyable_export.so noncopyable_import.so \ - ivect.so dvect.so - -libboost_python.a: $(OBJ) - rm -f libboost_python.a - $(CPP) -ar -all -o libboost_python.a $(OBJ) - -boost_python_test.so: $(OBJ) comprehensive.o - $(LD) $(LDOPTS) $(OBJ) comprehensive.o -o boost_python_test.so -lm - -abstract.so: $(OBJ) abstract.o - $(LD) $(LDOPTS) $(OBJ) abstract.o -o abstract.so - -getting_started1.so: $(OBJ) getting_started1.o - $(LD) $(LDOPTS) $(OBJ) getting_started1.o -o getting_started1.so - -getting_started2.so: $(OBJ) getting_started2.o - $(LD) $(LDOPTS) $(OBJ) getting_started2.o -o getting_started2.so - -getting_started3.so: $(OBJ) getting_started3.o - $(LD) $(LDOPTS) $(OBJ) getting_started3.o -o getting_started3.so - -simple_vector.so: $(OBJ) simple_vector.o - $(LD) $(LDOPTS) $(OBJ) simple_vector.o -o simple_vector.so - -do_it_yourself_converters.so: $(OBJ) do_it_yourself_converters.o - $(LD) $(LDOPTS) $(OBJ) do_it_yourself_converters.o -o do_it_yourself_converters.so - -pickle1.so: $(OBJ) pickle1.o - $(LD) $(LDOPTS) $(OBJ) pickle1.o -o pickle1.so - -pickle2.so: $(OBJ) pickle2.o - $(LD) $(LDOPTS) $(OBJ) pickle2.o -o pickle2.so - -pickle3.so: $(OBJ) pickle3.o - $(LD) $(LDOPTS) $(OBJ) pickle3.o -o pickle3.so - -noncopyable_export.so: $(OBJ) noncopyable_export.o - $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \ - noncopyable_export.o -o noncopyable_export.so - -noncopyable_import.so: $(OBJ) noncopyable_import.o - $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \ - noncopyable_import.o -o noncopyable_import.so - -ivect.so: $(OBJ) ivect.o - $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) ivect.o -o ivect.so - -dvect.so: $(OBJ) dvect.o - $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.so - -.cpp.o: - $(CPP) $(CPPOPTS) -c $*.cpp - -test: - $(PYEXE) comprehensive.py - $(PYEXE) test_abstract.py - $(PYEXE) test_getting_started1.py - $(PYEXE) test_getting_started2.py - $(PYEXE) test_getting_started3.py - $(PYEXE) test_simple_vector.py - $(PYEXE) test_do_it_yourself_converters.py - $(PYEXE) test_pickle1.py - $(PYEXE) test_pickle2.py - $(PYEXE) test_pickle3.py - -tst: - $(PYEXE) tst_noncopyable.py - $(PYEXE) tst_ivect1.py - $(PYEXE) tst_dvect1.py - $(PYEXE) tst_ivect2.py - $(PYEXE) tst_dvect2.py - -clean: - rm -f $(OBJ) libboost_python.a libboost_python.a.input - rm -f comprehensive.o boost_python_test.so - rm -f abstract.o abstract.so - rm -f getting_started1.o getting_started1.so - rm -f getting_started2.o getting_started2.so - rm -f getting_started3.o getting_started3.so - rm -f simple_vector.o simple_vector.so - rm -f do_it_yourself_converters.o do_it_yourself_converters.so - rm -f pickle1.o pickle1.so - rm -f pickle2.o pickle2.so - rm -f pickle3.o pickle3.so - rm -f noncopyable_export.o noncopyable_export.so - rm -f noncopyable_import.o noncopyable_import.so - rm -f ivect.o ivect.so - rm -f dvect.o dvect.so - rm -f so_locations *.pyc - rm -rf ii_files - -softlinks: - $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) softlinks - -unlink: - $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) unlink - -cp: - $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) cp - -rm: - $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) rm - -depend: - @ cat Makefile.nodepend; \ - for obj in $(DEPOBJ); \ - do \ - bn=`echo "$$obj" | cut -d. -f1`; \ - $(CPP) $(CPPOPTS) $(MAKEDEP) "$$bn".cpp; \ - done - From 748c118ea82c167f3b352023ac906d25ca5aa464 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 5 Apr 2001 17:46:24 +0000 Subject: [PATCH 080/369] added: from_python std::string type checking [SVN r9727] --- src/conversions.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/conversions.cpp b/src/conversions.cpp index 1bc923b1..4bfe2011 100644 --- a/src/conversions.cpp +++ b/src/conversions.cpp @@ -7,6 +7,7 @@ // producing this work. // // Revision History: +// 05 Apr 01 added: from_python std::string type checking (rwgk) // 12 Mar 01 Python 1.5.2 fixes (Ralf W. Grosse-Kunstleve) // 11 Mar 01 std::string *MAY* include nulls (Alex Martelli) // 04 Mar 01 std::complex<> fixes for MSVC (Dave Abrahams) @@ -250,6 +251,10 @@ PyObject* to_python(const std::string& s) std::string from_python(PyObject* p, boost::python::type) { + if (! PyString_Check(p)) { + PyErr_SetString(PyExc_TypeError, "expected a string"); + throw boost::python::argument_error(); + } return std::string(PyString_AsString(p), PyString_Size(p)); } From 9ee563b86415bc9f86cad7404cdf06296e2349fb Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 17 Apr 2001 18:51:17 +0000 Subject: [PATCH 081/369] Comment added with reference to cross_module.hpp [SVN r9812] --- include/boost/python/detail/extension_class.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/boost/python/detail/extension_class.hpp b/include/boost/python/detail/extension_class.hpp index 125f1eed..5c8e720a 100644 --- a/include/boost/python/detail/extension_class.hpp +++ b/include/boost/python/detail/extension_class.hpp @@ -10,6 +10,7 @@ // 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) @@ -166,6 +167,14 @@ BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // 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. +// +// 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 python_extension_class_converters { From 533a0057641283e3ff949c8a0383a77a394e0caa Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 17 Apr 2001 18:53:38 +0000 Subject: [PATCH 082/369] moved from branch ralf_grosse_kunstleve to trunk [SVN r9813] --- include/boost/python/cross_module.hpp | 322 ++++++++++++++++++++++++++ src/cross_module.cpp | 87 +++++++ 2 files changed, 409 insertions(+) create mode 100644 include/boost/python/cross_module.hpp create mode 100644 src/cross_module.cpp diff --git a/include/boost/python/cross_module.hpp b/include/boost/python/cross_module.hpp new file mode 100644 index 00000000..7c1fe507 --- /dev/null +++ b/include/boost/python/cross_module.hpp @@ -0,0 +1,322 @@ +/* (C) Copyright Ralf W. Grosse-Kunstleve 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. + + Revision History: + 17 Apr 01 merged into boost CVS trunk (Ralf W. Grosse-Kunstleve) +*/ + +/* Implementation of Boost.Python cross-module support. + See root/libs/python/doc/cross_module.html for details. +*/ + +#ifndef CROSS_MODULE_HPP +# define CROSS_MODULE_HPP + +# include + +namespace boost { namespace python { + struct import_error : error_already_set {}; + struct export_error : error_already_set {}; +}} + +namespace boost { namespace python { namespace detail { + +// Concept: throw exception if api_major is changed +// show warning on stderr if api_minor is changed +const int export_converters_api_major = 4; +const int export_converters_api_minor = 1; +extern const char* converters_attribute_name; +void* import_converter_object(const std::string& module_name, + const std::string& py_class_name, + const std::string& attribute_name); +void check_export_converters_api(const int importing_major, + const int importing_minor, + const int imported_major, + const int imported_minor); + +}}} + +// forward declaration +namespace boost { namespace python { namespace detail { +template class import_extension_class; +}}} + +BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE + +/* This class template is instantiated by import_converters. + This class is a look-alike of class python_extension_class_converters. + The converters in this class are wrappers that call converters + imported from another module. + To ensure that the dynamic loader resolves all symbols in the + intended way, the signature of all friend functions is changed with + respect to the original functions in class + python_extension_class_converters by adding an arbitrary additional + parameter with a default value, in this case "bool sig = false". + See also: comments for class export_converter_object_base below. + */ +template +class python_import_extension_class_converters +{ + public: + + friend python_import_extension_class_converters py_extension_class_converters(boost::python::type, bool sig = false) { + return python_import_extension_class_converters(); + } + + PyObject* to_python(const T& x) const { + return boost::python::detail::import_extension_class::get_converters()->to_python(x); + } + + friend T* from_python(PyObject* p, boost::python::type t, bool sig = false) { + return boost::python::detail::import_extension_class::get_converters()->from_python_Ts(p, t); + } + friend const T* from_python(PyObject* p, boost::python::type t, bool sig = false) { + return boost::python::detail::import_extension_class::get_converters()->from_python_cTs(p, t); + } + friend const T* from_python(PyObject* p, boost::python::type t, bool sig = false) { + return boost::python::detail::import_extension_class::get_converters()->from_python_cTscr(p, t); + } + friend T* from_python(PyObject* p, boost::python::type t, bool sig = false) { + return boost::python::detail::import_extension_class::get_converters()->from_python_Tscr(p, t); + } + friend T& from_python(PyObject* p, boost::python::type t, bool sig = false) { + return boost::python::detail::import_extension_class::get_converters()->from_python_Tr(p, t); + } + friend const T& from_python(PyObject* p, boost::python::type t, bool sig = false) { + return boost::python::detail::import_extension_class::get_converters()->from_python_cTr(p, t); + } + friend const T& from_python(PyObject* p, boost::python::type t, bool sig = false) { + return boost::python::detail::import_extension_class::get_converters()->from_python_T(p, t); + } + + friend std::auto_ptr& from_python(PyObject* p, boost::python::type&> t, bool sig = false) { + return boost::python::detail::import_extension_class::get_converters()->from_python_aTr(p, t); + } + friend std::auto_ptr from_python(PyObject* p, boost::python::type > t, bool sig = false) { + return boost::python::detail::import_extension_class::get_converters()->from_python_aT(p, t); + } + friend const std::auto_ptr& from_python(PyObject* p, boost::python::type&> t, bool sig = false) { + return boost::python::detail::import_extension_class::get_converters()->from_python_caTr(p, t); + } + friend PyObject* to_python(std::auto_ptr x, bool sig = false) { + return boost::python::detail::import_extension_class::get_converters()->to_python(x); + } + + friend boost::shared_ptr& from_python(PyObject* p, boost::python::type&> t, bool sig = false) { + return boost::python::detail::import_extension_class::get_converters()->from_python_sTr(p, t); + } + friend const boost::shared_ptr& from_python(PyObject* p, boost::python::type > t, bool sig = false) { + return boost::python::detail::import_extension_class::get_converters()->from_python_sT(p, t); + } + friend const boost::shared_ptr& from_python(PyObject* p, boost::python::type&> t, bool sig = false) { + return boost::python::detail::import_extension_class::get_converters()->from_python_csTr(p, t); + } + friend PyObject* to_python(boost::shared_ptr x, bool sig = false) { + return boost::python::detail::import_extension_class::get_converters()->to_python(x); + } +}; + +BOOST_PYTHON_END_CONVERSION_NAMESPACE + +namespace boost { namespace python { + +BOOST_PYTHON_IMPORT_CONVERSION(python_import_extension_class_converters); + +/* This class template is instantiated by export_converters(). + A pointer to this class is exported/imported via the Python API. + Using the Python API ensures maximum portability. + All member functions are virtual. This is, what we export/import + is essentially just a pointer to a vtbl. + To work around a deficiency of Visual C++ 6.0, the name of each + from_python() member functions is made unique by appending a few + characters (derived in a ad-hoc manner from the corresponding type). + */ +template +struct export_converter_object_base +{ + virtual int get_api_major() const { return detail::export_converters_api_major; } + virtual int get_api_minor() const { return detail::export_converters_api_minor; } + + virtual PyObject* to_python(const T& x) = 0; + + virtual T* from_python_Ts(PyObject* p, boost::python::type t) = 0; + virtual const T* from_python_cTs(PyObject* p, boost::python::type t) = 0; + virtual const T* from_python_cTscr(PyObject* p, boost::python::type t) = 0; + virtual T* from_python_Tscr(PyObject* p, boost::python::type t) = 0; + virtual T& from_python_Tr(PyObject* p, boost::python::type t) = 0; + virtual const T& from_python_cTr(PyObject* p, boost::python::type t) = 0; + virtual const T& from_python_T(PyObject* p, boost::python::type t) = 0; + + virtual std::auto_ptr& from_python_aTr(PyObject* p, boost::python::type&> t) = 0; + virtual std::auto_ptr from_python_aT(PyObject* p, boost::python::type > t) = 0; + virtual const std::auto_ptr& from_python_caTr(PyObject* p, boost::python::type&> t) = 0; + virtual PyObject* to_python(std::auto_ptr x) = 0; + + virtual boost::shared_ptr& from_python_sTr(PyObject* p, boost::python::type&> t) = 0; + virtual const boost::shared_ptr& from_python_sT(PyObject* p, boost::python::type > t) = 0; + virtual const boost::shared_ptr& from_python_csTr(PyObject* p, boost::python::type&> t) = 0; + virtual PyObject* to_python(boost::shared_ptr x) = 0; +}; + +// Converters to be used if T is not copyable. +template +struct export_converter_object_noncopyable : export_converter_object_base +{ + virtual PyObject* to_python(const T& x) { + PyErr_SetString(PyExc_RuntimeError, + "to_python(const T&) converter not exported"); + throw import_error(); + } + + virtual T* from_python_Ts(PyObject* p, boost::python::type t) { + return BOOST_PYTHON_CONVERSION::from_python(p, t); + } + virtual const T* from_python_cTs(PyObject* p, boost::python::type t) { + return BOOST_PYTHON_CONVERSION::from_python(p, t); + } + virtual const T* from_python_cTscr(PyObject* p, boost::python::type t) { + return BOOST_PYTHON_CONVERSION::from_python(p, t); + } + virtual T* from_python_Tscr(PyObject* p, boost::python::type t) { + return BOOST_PYTHON_CONVERSION::from_python(p, t); + } + virtual T& from_python_Tr(PyObject* p, boost::python::type t) { + return BOOST_PYTHON_CONVERSION::from_python(p, t); + } + virtual const T& from_python_cTr(PyObject* p, boost::python::type t) { + return BOOST_PYTHON_CONVERSION::from_python(p, t); + } + virtual const T& from_python_T(PyObject* p, boost::python::type t) { + return BOOST_PYTHON_CONVERSION::from_python(p, t); + } + + virtual std::auto_ptr& from_python_aTr(PyObject* p, boost::python::type&> t) { + return BOOST_PYTHON_CONVERSION::from_python(p, t); + } + virtual std::auto_ptr from_python_aT(PyObject* p, boost::python::type > t) { + return BOOST_PYTHON_CONVERSION::from_python(p, t); + } + virtual const std::auto_ptr& from_python_caTr(PyObject* p, boost::python::type&> t) { + return BOOST_PYTHON_CONVERSION::from_python(p, t); + } + virtual PyObject* to_python(std::auto_ptr x) { + return BOOST_PYTHON_CONVERSION::to_python(x); + } + + virtual boost::shared_ptr& from_python_sTr(PyObject* p, boost::python::type&> t) { + return BOOST_PYTHON_CONVERSION::from_python(p, t); + } + virtual const boost::shared_ptr& from_python_sT(PyObject* p, boost::python::type > t) { + return BOOST_PYTHON_CONVERSION::from_python(p, t); + } + virtual const boost::shared_ptr& from_python_csTr(PyObject* p, boost::python::type&> t) { + return BOOST_PYTHON_CONVERSION::from_python(p, t); + } + virtual PyObject* to_python(boost::shared_ptr x) { + return BOOST_PYTHON_CONVERSION::to_python(x); + } +}; + +// The addditional to_python() converter that can be used if T is copyable. +template +struct export_converter_object : export_converter_object_noncopyable +{ + virtual PyObject* to_python(const T& x) { + return BOOST_PYTHON_CONVERSION::py_extension_class_converters(boost::python::type()).to_python(x); + } +}; + +namespace detail { + +/* This class template is instantiated by import_converters. + Its purpose is to import the converter_object via the Python API. + The actual import is only done once. The pointer to the + imported converter object is kept in the static data member + imported_converters. + */ +template +class import_extension_class + : public python_import_extension_class_converters +{ + public: + inline import_extension_class(const char* module, const char* py_class) { + m_module = module; + m_py_class = py_class; + } + + static boost::python::export_converter_object_base* get_converters(); + + private: + static std::string m_module; + static std::string m_py_class; + static boost::python::export_converter_object_base* imported_converters; +}; + +template std::string import_extension_class::m_module; +template std::string import_extension_class::m_py_class; +template +boost::python::export_converter_object_base* +import_extension_class::imported_converters = 0; + +template +boost::python::export_converter_object_base* +import_extension_class::get_converters() { + if (imported_converters == 0) { + void* cobject + = import_converter_object(m_module, m_py_class, + converters_attribute_name); + imported_converters + = static_cast*>(cobject); + check_export_converters_api( + export_converters_api_major, + export_converters_api_minor, + imported_converters->get_api_major(), + imported_converters->get_api_minor()); + } + return imported_converters; +} + +}}} // namespace boost::python::detail + +namespace boost { namespace python { + +// Implementation of export_converters(). +template +void export_converters(class_builder& cb) +{ + static export_converter_object export_cvts; + cb.add( + ref(PyCObject_FromVoidPtr(reinterpret_cast(&export_cvts), NULL)), + detail::converters_attribute_name); +} + +// Implementation of export_converters_noncopyable(). +template +void export_converters_noncopyable(class_builder& cb) +{ + static export_converter_object_noncopyable export_cvts; + cb.add( + ref(PyCObject_FromVoidPtr(reinterpret_cast(&export_cvts), NULL)), + detail::converters_attribute_name); +} + +// Implementation of import_converters. +template +class import_converters + : python_import_extension_class_converters // Works around MSVC6.x/GCC2.95.2 bug described + // at the bottom of class_builder.hpp. +{ + public: + import_converters(const char* module, const char* py_class) + : m_class(new detail::import_extension_class(module, py_class)) + { } + private: + boost::shared_ptr > m_class; +}; + +}} // namespace boost::python + +#endif // CROSS_MODULE_HPP diff --git a/src/cross_module.cpp b/src/cross_module.cpp new file mode 100644 index 00000000..ea5a08de --- /dev/null +++ b/src/cross_module.cpp @@ -0,0 +1,87 @@ +/* (C) Copyright Ralf W. Grosse-Kunstleve 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. + + Revision History: + 17 Apr 01 merged into boost CVS trunk (Ralf W. Grosse-Kunstleve) +*/ + +# include +namespace python = boost::python; +# include // MSVC6.0SP4 does not know std::fprintf +# include // MSVC6.0SP4 does not know std::strcmp + +namespace { + + PyObject* get_module_dict(const char* module_name) + { + python::ref module_obj(PyImport_ImportModule((char*) module_name)); + PyObject* module_dict = PyModule_GetDict(module_obj.get()); + if (module_dict == 0) throw python::import_error(); + return module_dict; + } +} + +namespace boost { namespace python { namespace detail { + +const char* converters_attribute_name = "__converters__"; + +void* import_converter_object(const std::string& module_name, + const std::string& py_class_name, + const std::string& attribute_name) +{ + static std::string err; + PyObject* module_dict = get_module_dict(const_cast(module_name.c_str())); + PyObject* py_class = PyDict_GetItemString(module_dict, const_cast(py_class_name.c_str())); + if (py_class == 0) { + err = std::string("module ") + module_name + " has no attribute " + py_class_name; + PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); + throw python::import_error(); + } + python::ref c_obj(PyObject_GetAttrString(py_class, const_cast(attribute_name.c_str())), ref::null_ok); + if (c_obj.get() == 0) { + err = std::string("object ") + module_name + "." + py_class_name + + " has no attribute " + attribute_name; + PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); + throw python::import_error(); + } + if (! PyCObject_Check(c_obj.get())) { + err = std::string("object ") + module_name + "." + py_class_name + "." + + attribute_name + " is not a PyCObject"; + PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); + throw python::import_error(); + } + return PyCObject_AsVoidPtr(c_obj.get()); +} + +void check_export_converters_api(const int importing_major, + const int importing_minor, + const int imported_major, + const int imported_minor) +{ + if (importing_major != imported_major) { + // Python uses fprintf(stderr, ...) for API warnings. + fprintf(stderr, + "Fatal: export_converters_api mismatch:" + " Importing module = %d.%d" + " Imported module = %d.%d\n", + importing_major, importing_minor, + imported_major, imported_minor); + PyErr_SetString(PyExc_RuntimeError, + "Fatal: export_converters_api mismatch"); + throw import_error(); + } + if (importing_minor != imported_minor) { + // Python uses fprintf(stderr, ...) for API warnings. + fprintf(stderr, + "Warning: export_converters_api mismatch:" + " Importing module = %d.%d" + " Imported module = %d.%d\n", + importing_major, importing_minor, + imported_major, imported_minor); + } +} + +}}} // namespace boost::python::detail From 907033f725317d2c8cd7a1e00dc6d6b5ee2a321c Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 17 Apr 2001 19:00:43 +0000 Subject: [PATCH 083/369] Obsolete files removed. [SVN r9814] --- example/getting_started3.cpp | 120 ----------------------------- example/getting_started4.cpp | 101 ------------------------- example/getting_started5.cpp | 126 ------------------------------- example/test_getting_started3.py | 56 -------------- example/test_getting_started4.py | 35 --------- example/test_getting_started5.py | 22 ------ 6 files changed, 460 deletions(-) delete mode 100644 example/getting_started3.cpp delete mode 100644 example/getting_started4.cpp delete mode 100644 example/getting_started5.cpp delete mode 100644 example/test_getting_started3.py delete mode 100644 example/test_getting_started4.py delete mode 100644 example/test_getting_started5.py diff --git a/example/getting_started3.cpp b/example/getting_started3.cpp deleted file mode 100644 index 799f5cac..00000000 --- a/example/getting_started3.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - This example shows how to make an Extension Class "pickleable". - - Python's pickle module implements a basic but powerful algorithm - for "pickling" (a.k.a. serializing, marshalling or flattening) - nearly arbitrary Python objects. - - The user can influence how an Extension Class instance is pickled - by defining three special methods: __getinitargs__(), - __getstate__(), and __setstate(). This interface is similar to - that for regular Python classes as described in detail in the - Python Library Reference for pickle: - - http://www.python.org/doc/current/lib/module-pickle.html - - When an Extension Class instance is pickled, __getinitargs__() is - called, if implemented. This method should return a tuple - containing the arguments to be passed to the class constructor when - the object is restored. - - If there is no __getstate__() method, the instance's __dict__ is - pickled if it is not empty. If __getstate__() is defined, it should - return an object representing the state of the instance. - - If there is no __setstate__() method, __getstate__() must return a - dictionary. When the instance is restored, the items in this dictionary - are added to the instance's __dict__. - - If the Extension Class defines __setstate__(), the pickle loader - calls it with the result of __getstate__() as arguments. In this - case, the state object need not be a dictionary. The - __getstate__() and __setstate__() methods can do what they want. - - If both __getinitargs__() and __getstate__() are defined, the - instance is restored by first calling the constructor with - the result of __getinitargs__() as argument. After the instance - is reconstructed, the __dict__ is updated or __setstate__() is - called if implemented. - - The mechanism described here is an exact replication of that one - implemented by Jim Fulton's ExtensionClass (included in Zope 2.2.2). - */ - -#include -#include - -#include -namespace python = boost::python; - -namespace { // Avoid cluttering the global namespace. - - // A friendly class. - class world - { - private: - std::string country; - int secret_number; - public: - world(const std::string& country) : secret_number(0) { - this->country = country; - } - std::string greet() const { return "Hello from " + country + "!"; } - std::string get_country() const { return country; } - void set_secret_number(int number) { secret_number = number; } - int get_secret_number() const { return secret_number; } - }; - - // Support for pickle. - python::tuple world_getinitargs(const world& w) { - python::tuple result(1); - result.set_item(0, w.get_country()); - return result; - } - - python::tuple world_getstate(const world& w) { - python::tuple result(1); - result.set_item(0, w.get_secret_number()); - return result; - } - - void world_setstate(world& w, python::tuple state) { - if (state.size() != 1) { - PyErr_SetString(PyExc_ValueError, - "Unexpected argument in call to __setstate__."); - throw python::error_already_set(); - } - int number = BOOST_PYTHON_CONVERSION::from_python(state[0].get(), - python::type()); - if (number != 42) - w.set_secret_number(number); - } -} - -BOOST_PYTHON_MODULE_INIT(getting_started3) -{ - try - { - // Create an object representing this extension module. - python::module_builder this_module("getting_started3"); - - // Create the Python type object for our extension class. - python::class_builder world_class(this_module, "world"); - - // Add the __init__ function. - world_class.def(python::constructor()); - // Add a regular member function. - world_class.def(&world::greet, "greet"); - world_class.def(&world::get_secret_number, "get_secret_number"); - world_class.def(&world::set_secret_number, "set_secret_number"); - - // Support for pickle. - world_class.def(world_getinitargs, "__getinitargs__"); - world_class.def(world_getstate, "__getstate__"); - world_class.def(world_setstate, "__setstate__"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/getting_started4.cpp b/example/getting_started4.cpp deleted file mode 100644 index fe6a3421..00000000 --- a/example/getting_started4.cpp +++ /dev/null @@ -1,101 +0,0 @@ -#include -namespace python = boost::python; - -namespace { // Avoid cluttering the global namespace. - - // A wrapper is used to define additional constructors. - // - struct vector_double_wrapper: std::vector - { - // Tell the compiler how to convert a base class object to - // this wrapper object. - vector_double_wrapper(PyObject*, const std::vector& vd) - : std::vector(vd) {} - - vector_double_wrapper(PyObject* self) - : std::vector() {} - - vector_double_wrapper(PyObject* self, int n) - : std::vector(n) {} - - vector_double_wrapper(PyObject* self, python::tuple tuple) - : std::vector(tuple.size()) - { - std::vector::iterator vd = begin(); - for (int i = 0; i < tuple.size(); i++) - vd[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), - python::type()); - } - }; - - double getitem(const std::vector& vd, std::size_t key) { - return vd[key]; - } - - void setitem(std::vector& vd, std::size_t key, double d) { - std::vector::iterator vditer = vd.begin(); - vditer[key] = d; - } - - void delitem(std::vector& vd, std::size_t key) { - std::vector::iterator vditer = vd.begin(); - vd.erase(&vditer[key]); - } - - // Convert vector_double to a regular Python tuple. - // - python::tuple as_tuple(const std::vector& vd) - { - python::tuple t(vd.size()); - for (int i = 0; i < vd.size(); i++) t.set_item(i, - python::ref(BOOST_PYTHON_CONVERSION::to_python(vd[i]))); - return t; - } - - // Function returning a vector_double object to Python. - // - std::vector foo(int n) - { - std::vector vd(n); - std::vector::iterator vditer = vd.begin(); - for (int i = 0; i < n; i++) vditer[i] = double(i); - return vd; - } - - // Same as foo(), but avoid copying on return. - // - std::auto_ptr > bar(int n) - { - std::auto_ptr > vdptr(new std::vector(n)); - std::vector::iterator vditer = vdptr->begin(); - for (int i = 0; i < n; i++) vditer[i] = double(10 * i); - return vdptr; - } -} - -BOOST_PYTHON_MODULE_INIT(getting_started4) -{ - try - { - python::module_builder this_module("getting_started4"); - - python::class_builder, vector_double_wrapper> - vector_double(this_module, "vector_double"); - - vector_double.def(python::constructor<>()); - vector_double.def(python::constructor()); - vector_double.def(python::constructor()); - vector_double.def(&std::vector::size, "__len__"); - vector_double.def(getitem, "__getitem__"); - vector_double.def(setitem, "__setitem__"); - vector_double.def(delitem, "__delitem__"); - vector_double.def(as_tuple, "as_tuple"); - - this_module.def(foo, "foo"); - this_module.def(bar, "bar"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/getting_started5.cpp b/example/getting_started5.cpp deleted file mode 100644 index 9e9e7c75..00000000 --- a/example/getting_started5.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - This example shows how to convert a class from and to native - Python objects, such as tuples. - - We do not want to expose the helper class MillerIndex as an - Extension Class. However, in order to simplify the wrapper code, - we want to define from_python() and to_python() functions for - class MillerIndex. - - Consider the alternatives: - - - Expose MillerIndex as an Extension Class. - We need a constructor MillerIndex(python::tuple). - Python function calls become more complex: - foo(MillerIndex((1,2,3)) instead of foo((1,2,3)) - We need a method such as MillerIndex().as_tuple(). - - - Define a wrapper function for each function that we - want to expose, e.g.: - void add(const IndexingSet& ixset, const python::tuple PyMIx) - - The first alternative introduces a new type that the user has to - deal with. Other modules using Miller indices might organize them in - different ways, for example to increase runtime efficiency for - important procedures. This means, the user has to know how to - convert between the different kinds of Miller index representations. - This can quickly become a nuisance. Relying on native Python data - structures minimizes the number of special types the user has to - learn and convert. Of course, this argument is only valid for - small and relatively simply classes. - - If there are many member functions with MillerIndex arguments, the - second alternative is impractical, and concentrating the conversion - mechanism in one central place is essential for code - maintainability. An added benefit is that more convenient (smarter) - conversion functions can be provided without cluttering the rest of - the wrapper code. - - */ - -#include -#include -#include -namespace python = boost::python; - -namespace { // Avoid cluttering the global namespace. - - // The helper class. - // - class MillerIndex { - public: - int v[3]; - }; - - // The main class. Imagine that there are MANY member functions - // like add() and get(). - // - class IndexingSet { - private: - std::vector VMIx; - public: - void add(const MillerIndex& MIx) { VMIx.push_back(MIx); } - MillerIndex get(std::size_t i) const { return VMIx[i]; } - }; -} - -BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE - - // Convert a Python tuple to a MillerIndex object. - // - MillerIndex from_python(PyObject* p, python::type) - { - python::tuple tup - = python::tuple(python::ref(p, python::ref::increment_count)); - if (tup.size() != 3) { - PyErr_SetString(PyExc_ValueError, - "expecting exactly 3 values in tuple."); - throw python::error_already_set(); - } - MillerIndex result; - for (int i = 0; i < 3; i++) - result.v[i] = from_python(tup[i].get(), python::type()); - return result; - } - - // Similar conversion for MillerIndex objects passed by value. - // Not actually used, but included to show the principle. - // - MillerIndex from_python(PyObject* p, python::type) - { - return from_python(p, python::type()); - } - - // Convert a MillerIndex object to a Python tuple. - // - PyObject* to_python(const MillerIndex& hkl) - { - python::tuple result(3); - for (int i = 0; i < 3; i++) - result.set_item(i, python::ref(to_python(hkl.v[i]))); - return result.reference().release(); - } - -BOOST_PYTHON_END_CONVERSION_NAMESPACE - -BOOST_PYTHON_MODULE_INIT(getting_started5) -{ - try - { - // Create an object representing this extension module. - python::module_builder this_module("getting_started5"); - - // Create the Python type object for our extension class. - python::class_builder ixset_class(this_module, "IndexingSet"); - - // Add the __init__ function. - ixset_class.def(python::constructor<>()); - // Add the member functions. - ixset_class.def(&IndexingSet::add, "add"); - ixset_class.def(&IndexingSet::get, "get"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/test_getting_started3.py b/example/test_getting_started3.py deleted file mode 100644 index d62cf5a2..00000000 --- a/example/test_getting_started3.py +++ /dev/null @@ -1,56 +0,0 @@ -r'''>>> import getting_started3 - >>> import re - >>> import pickle - >>> getting_started3.world.__module__ - 'getting_started3' - >>> getting_started3.world.__safe_for_unpickling__ - 1 - >>> getting_started3.world.__reduce__() - 'world' - >>> assert re.match( - ... "\(, \('Hello',\), \(0,\)\)", - ... repr(getting_started3.world('Hello').__reduce__())) - >>> - >>> for number in (24, 42): - ... wd = getting_started3.world('California') - ... wd.set_secret_number(number) - ... pstr = pickle.dumps(wd) - ... print pstr - ... wl = pickle.loads(pstr) - ... print wd.greet(), wd.get_secret_number() - ... print wl.greet(), wl.get_secret_number() - cgetting_started3 - world - p0 - (S'California' - p1 - tp2 - R(I24 - tp3 - bp4 - . - Hello from California! 24 - Hello from California! 24 - cgetting_started3 - world - p0 - (S'California' - p1 - tp2 - R(I42 - tp3 - bp4 - . - Hello from California! 42 - Hello from California! 0 -''' - -def run(args = None): - if args is not None: - import sys - sys.argv = args - import doctest, test_getting_started3 - doctest.testmod(test_getting_started3) - -if __name__ == '__main__': - run() diff --git a/example/test_getting_started4.py b/example/test_getting_started4.py deleted file mode 100644 index 82b5c794..00000000 --- a/example/test_getting_started4.py +++ /dev/null @@ -1,35 +0,0 @@ -r'''>>> import getting_started4 - >>> v=getting_started4.vector_double() - >>> print v.as_tuple() - () - >>> v=getting_started4.vector_double(5) - >>> print v.as_tuple() - (0.0, 0.0, 0.0, 0.0, 0.0) - >>> print len(v) - 5 - >>> v=getting_started4.vector_double((3,4,5)) - >>> print v.as_tuple() - (3.0, 4.0, 5.0) - >>> print v[1] - 4.0 - >>> v[1] = 40 - >>> print v.as_tuple() - (3.0, 40.0, 5.0) - >>> del v[1] - >>> print v.as_tuple() - (3.0, 5.0) - >>> print getting_started4.foo(11).as_tuple() - (0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0) - >>> print getting_started4.bar(12).as_tuple() - (0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 110.0) -''' - -def run(args = None): - if args is not None: - import sys - sys.argv = args - import doctest, test_getting_started4 - doctest.testmod(test_getting_started4) - -if __name__ == '__main__': - run() diff --git a/example/test_getting_started5.py b/example/test_getting_started5.py deleted file mode 100644 index 8eeba1e2..00000000 --- a/example/test_getting_started5.py +++ /dev/null @@ -1,22 +0,0 @@ -r'''>>> import getting_started5 - >>> ixset = getting_started5.IndexingSet() - >>> ixset.add((1,2,3)) - >>> ixset.add((4,5,6)) - >>> ixset.add((7,8,9)) - >>> print ixset.get(0) - (1, 2, 3) - >>> print ixset.get(1) - (4, 5, 6) - >>> print ixset.get(2) - (7, 8, 9) -''' - -def run(args = None): - if args is not None: - import sys - sys.argv = args - import doctest, test_getting_started5 - doctest.testmod(test_getting_started5) - -if __name__ == '__main__': - run() From dc520c6c32a4b0485d583d3ecc11e24df77a3eb7 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 17 Apr 2001 19:04:16 +0000 Subject: [PATCH 084/369] Author included [SVN r9815] --- example/getting_started1.cpp | 2 ++ example/getting_started2.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/example/getting_started1.cpp b/example/getting_started1.cpp index 7a8e9087..c6a77723 100644 --- a/example/getting_started1.cpp +++ b/example/getting_started1.cpp @@ -1,3 +1,5 @@ +// Example by Ralf W. Grosse-Kunstleve + #include namespace { // Avoid cluttering the global namespace. diff --git a/example/getting_started2.cpp b/example/getting_started2.cpp index 72b04105..9121b1a0 100644 --- a/example/getting_started2.cpp +++ b/example/getting_started2.cpp @@ -1,3 +1,5 @@ +// Example by Ralf W. Grosse-Kunstleve + #include #include From 8158a509c92eeb0c8917ed7aca6276529ddad1e8 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 17 Apr 2001 19:20:31 +0000 Subject: [PATCH 085/369] moved from branch ralf_grosse_kunstleve to trunk [SVN r9816] --- example/do_it_yourself_converters.cpp | 128 ++++++++++++++++++ example/dvect.cpp | 45 +++++++ example/dvect.h | 32 +++++ example/dvect_conversions.cpp | 51 ++++++++ example/dvect_defs.cpp | 13 ++ example/ivect.cpp | 45 +++++++ example/noncopyable.h | 14 ++ example/noncopyable_export.cpp | 25 ++++ example/noncopyable_import.cpp | 42 ++++++ example/pickle1.cpp | 64 +++++++++ example/pickle2.cpp | 100 +++++++++++++++ example/pickle3.cpp | 150 ++++++++++++++++++++++ example/simple_vector.cpp | 103 +++++++++++++++ example/test_do_it_yourself_converters.py | 22 ++++ example/test_pickle1.py | 31 +++++ example/test_pickle2.py | 45 +++++++ example/test_pickle3.py | 38 ++++++ example/test_simple_vector.py | 35 +++++ 18 files changed, 983 insertions(+) create mode 100644 example/do_it_yourself_converters.cpp create mode 100644 example/dvect.cpp create mode 100644 example/dvect.h create mode 100644 example/dvect_conversions.cpp create mode 100644 example/dvect_defs.cpp create mode 100644 example/ivect.cpp create mode 100644 example/noncopyable.h create mode 100644 example/noncopyable_export.cpp create mode 100644 example/noncopyable_import.cpp create mode 100644 example/pickle1.cpp create mode 100644 example/pickle2.cpp create mode 100644 example/pickle3.cpp create mode 100644 example/simple_vector.cpp create mode 100644 example/test_do_it_yourself_converters.py create mode 100644 example/test_pickle1.py create mode 100644 example/test_pickle2.py create mode 100644 example/test_pickle3.py create mode 100644 example/test_simple_vector.py diff --git a/example/do_it_yourself_converters.cpp b/example/do_it_yourself_converters.cpp new file mode 100644 index 00000000..6d2d2d6a --- /dev/null +++ b/example/do_it_yourself_converters.cpp @@ -0,0 +1,128 @@ +// Example by Ralf W. Grosse-Kunstleve +/* + + This example shows how to convert a class from and to native + Python objects, such as tuples. + + We do not want to expose the helper class MillerIndex as an + Extension Class. However, in order to simplify the wrapper code, + we want to define from_python() and to_python() functions for + class MillerIndex. + + Consider the alternatives: + + - Expose MillerIndex as an Extension Class. + We need a constructor MillerIndex(python::tuple). + Python function calls become more complex: + foo(MillerIndex((1,2,3)) instead of foo((1,2,3)) + We need a method such as MillerIndex().as_tuple(). + + - Define a wrapper function for each function that we + want to expose, e.g.: + void add(const IndexingSet& ixset, const python::tuple PyMIx) + + The first alternative introduces a new type that the user has to + deal with. Other modules using Miller indices might organize them in + different ways, for example to increase runtime efficiency for + important procedures. This means, the user has to know how to + convert between the different kinds of Miller index representations. + This can quickly become a nuisance. Relying on native Python data + structures minimizes the number of special types the user has to + learn and convert. Of course, this argument is only valid for + small and relatively simply classes. + + If there are many member functions with MillerIndex arguments, the + second alternative is impractical, and concentrating the conversion + mechanism in one central place is essential for code + maintainability. An added benefit is that more convenient (smarter) + conversion functions can be provided without cluttering the rest of + the wrapper code. + + */ + +#include +#include +#include +namespace python = boost::python; + +namespace { // Avoid cluttering the global namespace. + + // The helper class. + // + class MillerIndex { + public: + int v[3]; + }; + + // The main class. Imagine that there are MANY member functions + // like add() and get(). + // + class IndexingSet { + private: + std::vector VMIx; + public: + void add(const MillerIndex& MIx) { VMIx.push_back(MIx); } + MillerIndex get(std::size_t i) const { return VMIx[i]; } + }; +} + +BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE + + // Convert a Python tuple to a MillerIndex object. + // + MillerIndex from_python(PyObject* p, python::type) + { + python::tuple tup + = python::tuple(python::ref(p, python::ref::increment_count)); + if (tup.size() != 3) { + PyErr_SetString(PyExc_ValueError, + "expecting exactly 3 values in tuple."); + throw python::error_already_set(); + } + MillerIndex result; + for (int i = 0; i < 3; i++) + result.v[i] = from_python(tup[i].get(), python::type()); + return result; + } + + // Similar conversion for MillerIndex objects passed by value. + // Not actually used, but included to show the principle. + // + MillerIndex from_python(PyObject* p, python::type) + { + return from_python(p, python::type()); + } + + // Convert a MillerIndex object to a Python tuple. + // + PyObject* to_python(const MillerIndex& hkl) + { + python::tuple result(3); + for (int i = 0; i < 3; i++) + result.set_item(i, python::ref(to_python(hkl.v[i]))); + return result.reference().release(); + } + +BOOST_PYTHON_END_CONVERSION_NAMESPACE + +BOOST_PYTHON_MODULE_INIT(do_it_yourself_converters) +{ + try + { + // Create an object representing this extension module. + python::module_builder this_module("do_it_yourself_converters"); + + // Create the Python type object for our extension class. + python::class_builder ixset_class(this_module, "IndexingSet"); + + // Add the __init__ function. + ixset_class.def(python::constructor<>()); + // Add the member functions. + ixset_class.def(&IndexingSet::add, "add"); + ixset_class.def(&IndexingSet::get, "get"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/dvect.cpp b/example/dvect.cpp new file mode 100644 index 00000000..da6b35a3 --- /dev/null +++ b/example/dvect.cpp @@ -0,0 +1,45 @@ +// Example by Ralf W. Grosse-Kunstleve +// See root/libs/python/doc/cross_module.html for an introduction. + +#include "dvect.h" +#include "ivect.h" +#include +namespace python = boost::python; + +namespace { + +# include "dvect_conversions.cpp" +# include "ivect_conversions.cpp" + + vects::ivect dvect_as_ivect(const vects::dvect& dv) + { + vects::ivect iv(dv.size()); + vects::ivect::iterator iviter = iv.begin(); + for (int i = 0; i < dv.size(); i++) iviter[i] = static_cast(dv[i]); + return iv; + } +} + +BOOST_PYTHON_MODULE_INIT(dvect) +{ + try + { + python::module_builder this_module("dvect"); + + python::class_builder dvect_class(this_module, "dvect"); + python::export_converters(dvect_class); + + python::import_converters ivect_converters("ivect", "ivect"); + + dvect_class.def(python::constructor()); + dvect_class.def(&vects::dvect::as_tuple, "as_tuple"); + dvect_class.def(dvect_as_ivect, "as_ivect"); + +# include "dvect_defs.cpp" +# include "ivect_defs.cpp" + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/dvect.h b/example/dvect.h new file mode 100644 index 00000000..8ffe7b50 --- /dev/null +++ b/example/dvect.h @@ -0,0 +1,32 @@ +#ifndef DVECT_H +#define DVECT_H + +#include +#include + +namespace vects { + + struct dvect : public std::vector + { + dvect() : std::vector() {} + dvect(size_t n) : std::vector(n) {} + dvect(boost::python::tuple tuple) : std::vector(tuple.size()) + { + std::vector::iterator v_it = begin(); + for (int i = 0; i < tuple.size(); i++) + v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), + boost::python::type()); + } + + boost::python::tuple as_tuple() const + { + boost::python::tuple t(size()); + for (int i = 0; i < size(); i++) + t.set_item(i, + boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i]))); + return t; + } + }; +} + +#endif // DVECT_H diff --git a/example/dvect_conversions.cpp b/example/dvect_conversions.cpp new file mode 100644 index 00000000..21527243 --- /dev/null +++ b/example/dvect_conversions.cpp @@ -0,0 +1,51 @@ + // basics first: const reference converters + boost::python::tuple const_dvect_reference_as_tuple(const vects::dvect& dv) + { + return dv.as_tuple(); + } + + // to_python smart pointer conversions + std::auto_ptr dvect_as_auto_ptr(const vects::dvect& dv) + { + return std::auto_ptr(new vects::dvect(dv)); + } + boost::shared_ptr dvect_as_shared_ptr(const vects::dvect& dv) + { + return boost::shared_ptr(new vects::dvect(dv)); + } + + // smart pointers passed by value + boost::python::ref auto_ptr_value_dvect_as_tuple(std::auto_ptr dv) + { + if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return dv->as_tuple().reference(); + } + boost::python::ref shared_ptr_value_dvect_as_tuple(boost::shared_ptr dv) + { + if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return dv->as_tuple().reference(); + } + + // smart pointers passed by reference + boost::python::ref auto_ptr_reference_dvect_as_tuple(std::auto_ptr& dv) + { + if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return dv->as_tuple().reference(); + } + boost::python::ref shared_ptr_reference_dvect_as_tuple(boost::shared_ptr& dv) + { + if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return dv->as_tuple().reference(); + } + + // smart pointers passed by const reference + boost::python::ref auto_ptr_const_reference_dvect_as_tuple(const std::auto_ptr& dv) + { + if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return dv->as_tuple().reference(); + } + boost::python::ref shared_ptr_const_reference_dvect_as_tuple(const boost::shared_ptr& dv) + { + if (dv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return dv->as_tuple().reference(); + } diff --git a/example/dvect_defs.cpp b/example/dvect_defs.cpp new file mode 100644 index 00000000..2739b219 --- /dev/null +++ b/example/dvect_defs.cpp @@ -0,0 +1,13 @@ + this_module.def(dvect_as_auto_ptr, "dvect_as_auto_ptr"); + this_module.def(dvect_as_shared_ptr, "dvect_as_shared_ptr"); + + this_module.def(const_dvect_reference_as_tuple, "const_dvect_reference_as_tuple"); + + this_module.def(auto_ptr_value_dvect_as_tuple, "auto_ptr_value_dvect_as_tuple"); + this_module.def(shared_ptr_value_dvect_as_tuple, "shared_ptr_value_dvect_as_tuple"); + + this_module.def(auto_ptr_reference_dvect_as_tuple, "auto_ptr_reference_dvect_as_tuple"); + this_module.def(shared_ptr_reference_dvect_as_tuple, "shared_ptr_reference_dvect_as_tuple"); + + this_module.def(auto_ptr_const_reference_dvect_as_tuple, "auto_ptr_const_reference_dvect_as_tuple"); + this_module.def(shared_ptr_const_reference_dvect_as_tuple, "shared_ptr_const_reference_dvect_as_tuple"); diff --git a/example/ivect.cpp b/example/ivect.cpp new file mode 100644 index 00000000..db1c0ec3 --- /dev/null +++ b/example/ivect.cpp @@ -0,0 +1,45 @@ +// Example by Ralf W. Grosse-Kunstleve +// See root/libs/python/doc/cross_module.html for an introduction. + +#include "dvect.h" +#include "ivect.h" +#include +namespace python = boost::python; + +namespace { + +# include "dvect_conversions.cpp" +# include "ivect_conversions.cpp" + + vects::dvect ivect_as_dvect(const vects::ivect& iv) + { + vects::dvect dv(iv.size()); + vects::dvect::iterator dviter = dv.begin(); + for (int i = 0; i < iv.size(); i++) dviter[i] = static_cast(iv[i]); + return dv; + } +} + +BOOST_PYTHON_MODULE_INIT(ivect) +{ + try + { + python::module_builder this_module("ivect"); + + python::class_builder ivect_class(this_module, "ivect"); + python::export_converters(ivect_class); + + python::import_converters dvect_converters("dvect", "dvect"); + + ivect_class.def(python::constructor()); + ivect_class.def(&vects::ivect::as_tuple, "as_tuple"); + ivect_class.def(ivect_as_dvect, "as_dvect"); + +# include "dvect_defs.cpp" +# include "ivect_defs.cpp" + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/noncopyable.h b/example/noncopyable.h new file mode 100644 index 00000000..de7b3672 --- /dev/null +++ b/example/noncopyable.h @@ -0,0 +1,14 @@ +#ifndef NONCOPYABLE_H +#define NONCOPYABLE_H + +class store +{ + private: + store(const store&) { } // Disable the copy constructor. + int number; + public: + store(const int i) : number(i) { } + int recall() const { return number; } +}; + +#endif // NONCOPYABLE_H diff --git a/example/noncopyable_export.cpp b/example/noncopyable_export.cpp new file mode 100644 index 00000000..794b1200 --- /dev/null +++ b/example/noncopyable_export.cpp @@ -0,0 +1,25 @@ +// Example by Ralf W. Grosse-Kunstleve +// See root/libs/python/doc/cross_module.html for an introduction. + +#include +namespace python = boost::python; + +#include "noncopyable.h" + +BOOST_PYTHON_MODULE_INIT(noncopyable_export) +{ + try + { + python::module_builder this_module("noncopyable_export"); + + python::class_builder store_class(this_module, "store"); + python::export_converters_noncopyable(store_class); + + store_class.def(python::constructor()); + store_class.def(&store::recall, "recall"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/noncopyable_import.cpp b/example/noncopyable_import.cpp new file mode 100644 index 00000000..ea2477be --- /dev/null +++ b/example/noncopyable_import.cpp @@ -0,0 +1,42 @@ +// Example by Ralf W. Grosse-Kunstleve +// See root/libs/python/doc/cross_module.html for an introduction. + +#include +namespace python = boost::python; + +#include "noncopyable.h" + +namespace { // Avoid cluttering the global namespace. + + // A function with store objects as both input and output parameters. + // Because the copy constructor is disabled, we cannot pass a store + // object by value. Instead, we pass a smart pointer. + std::auto_ptr add_stores(const store& s1, const store& s2) + { + int sum = s1.recall() + s2.recall(); + std::auto_ptr ss = std::auto_ptr(new store(sum)); + return ss; + } +} + +BOOST_PYTHON_MODULE_INIT(noncopyable_import) +{ + try + { + python::module_builder this_module("noncopyable_import"); + + python::import_converters + dvect_converters("noncopyable_export", "store"); + + // Imagine all the additional classes with member functions + // that have store objects as input and output parameters. + // Lots and lots of them. + // However, to keep this example simple, we only define a + // module-level function. + this_module.def(add_stores, "add_stores"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/pickle1.cpp b/example/pickle1.cpp new file mode 100644 index 00000000..cdd78989 --- /dev/null +++ b/example/pickle1.cpp @@ -0,0 +1,64 @@ +// Example by Ralf W. Grosse-Kunstleve + +/* + This example shows how to make an Extension Class "pickleable". + + The world class below can be fully restored by passing the + appropriate argument to the constructor. Therefore it is sufficient + to define the pickle interface method __getinitargs__. + + For more information refer to boost/libs/python/doc/pickle.html. + */ + +#include + +#include +namespace python = boost::python; + +namespace { // Avoid cluttering the global namespace. + + // A friendly class. + class world + { + private: + std::string country; + int secret_number; + public: + world(const std::string& country) : secret_number(0) { + this->country = country; + } + std::string greet() const { return "Hello from " + country + "!"; } + std::string get_country() const { return country; } + }; + + // Support for pickle. + python::ref world_getinitargs(const world& w) { + python::tuple result(1); + result.set_item(0, w.get_country()); + return result.reference(); + } +} + +BOOST_PYTHON_MODULE_INIT(pickle1) +{ + try + { + // Create an object representing this extension module. + python::module_builder this_module("pickle1"); + + // Create the Python type object for our extension class. + python::class_builder world_class(this_module, "world"); + + // Add the __init__ function. + world_class.def(python::constructor()); + // Add a regular member function. + world_class.def(&world::greet, "greet"); + + // Support for pickle. + world_class.def(world_getinitargs, "__getinitargs__"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/pickle2.cpp b/example/pickle2.cpp new file mode 100644 index 00000000..d6aa3201 --- /dev/null +++ b/example/pickle2.cpp @@ -0,0 +1,100 @@ +// Example by Ralf W. Grosse-Kunstleve + +/* + This example shows how to make an Extension Class "pickleable". + + The world class below contains member data (secret_number) that + cannot be restored by any of the constructors. Therefore it is + necessary to provide the __getstate__/__setstate__ pair of pickle + interface methods. + + For simplicity, the __dict__ is not included in the result of + __getstate__. This is not generally recommended, but a valid + approach if it is anticipated that the object's __dict__ will + always be empty. Note that safety guard are provided to catch the + cases where this assumption is not true. + + pickle3.cpp shows how to include the object's __dict__ in the + result of __getstate__. + + For more information refer to boost/libs/python/doc/pickle.html. + */ + +#include + +#include +namespace python = boost::python; + +namespace { // Avoid cluttering the global namespace. + + // A friendly class. + class world + { + public: + world(const std::string& country) : secret_number(0) { + this->country = country; + } + std::string greet() const { return "Hello from " + country + "!"; } + std::string get_country() const { return country; } + void set_secret_number(int number) { secret_number = number; } + int get_secret_number() const { return secret_number; } + private: + std::string country; + int secret_number; + }; + + // Support for pickle. + + using BOOST_PYTHON_CONVERSION::from_python; + + python::ref world_getinitargs(const world& w) { + python::tuple result(1); + result.set_item(0, w.get_country()); + return result.reference(); // returning the reference avoids the copying. + } + + python::ref world_getstate(const world& w) { + python::tuple result(1); + result.set_item(0, w.get_secret_number()); + return result.reference(); // returning the reference avoids the copying. + } + + void world_setstate(world& w, python::tuple state) { + if (state.size() != 1) { + PyErr_SetString(PyExc_ValueError, + "Unexpected argument in call to __setstate__."); + throw python::error_already_set(); + } + int number = from_python(state[0].get(), python::type()); + if (number != 42) + w.set_secret_number(number); + } +} + +BOOST_PYTHON_MODULE_INIT(pickle2) +{ + try + { + // Create an object representing this extension module. + python::module_builder this_module("pickle2"); + + // Create the Python type object for our extension class. + python::class_builder world_class(this_module, "world"); + + // Add the __init__ function. + world_class.def(python::constructor()); + // Add a regular member function. + world_class.def(&world::greet, "greet"); + world_class.def(&world::get_secret_number, "get_secret_number"); + world_class.def(&world::set_secret_number, "set_secret_number"); + + // Support for pickle. + world_class.def(world_getinitargs, "__getinitargs__"); + world_class.def(world_getstate, "__getstate__"); + world_class.def(world_setstate, "__setstate__"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/pickle3.cpp b/example/pickle3.cpp new file mode 100644 index 00000000..bfa7dc54 --- /dev/null +++ b/example/pickle3.cpp @@ -0,0 +1,150 @@ +// Example by Ralf W. Grosse-Kunstleve + +/* + This example shows how to make an Extension Class "pickleable". + + The world class below contains member data (secret_number) that + cannot be restored by any of the constructors. Therefore it is + necessary to provide the __getstate__/__setstate__ pair of pickle + interface methods. + + The object's __dict__ is included in the result of __getstate__. + This requires more code (compare with pickle2.cpp), but is + unavoidable if the object's __dict__ is not always empty. + + For more information refer to boost/libs/python/doc/pickle.html. + */ + +#include + +#include +namespace python = boost::python; + +namespace boost { namespace python { + + ref getattr(PyObject* o, const std::string& attr_name) { + return ref(PyObject_GetAttrString(o, const_cast(attr_name.c_str()))); + } + ref getattr(const ref& r, const std::string& attr_name) { + return getattr(r.get(), attr_name); + } + +}} + +namespace { // Avoid cluttering the global namespace. + + // A friendly class. + class world + { + public: + world(const std::string& country) : secret_number(0) { + this->country = country; + } + std::string greet() const { return "Hello from " + country + "!"; } + std::string get_country() const { return country; } + void set_secret_number(int number) { secret_number = number; } + int get_secret_number() const { return secret_number; } + private: + std::string country; + int secret_number; + }; + + // Support for pickle. + python::ref world_getinitargs(const world& w) { + python::tuple result(1); + result.set_item(0, w.get_country()); + return result.reference(); // returning the reference avoids the copying. + } + + python::ref world_getstate(python::tuple const & args, + python::dictionary const & keywords); + + PyObject* world_setstate(python::tuple const & args, + python::dictionary const & keywords); +} + +BOOST_PYTHON_MODULE_INIT(pickle3) +{ + try + { + // Create an object representing this extension module. + python::module_builder this_module("pickle3"); + + // Create the Python type object for our extension class. + python::class_builder world_class(this_module, "world"); + + // Add the __init__ function. + world_class.def(python::constructor()); + // Add a regular member function. + world_class.def(&world::greet, "greet"); + world_class.def(&world::get_secret_number, "get_secret_number"); + world_class.def(&world::set_secret_number, "set_secret_number"); + + // Support for pickle. + world_class.def(world_getinitargs, "__getinitargs__"); + world_class.def_raw(world_getstate, "__getstate__"); + world_class.def_raw(world_setstate, "__setstate__"); + world_class.getstate_manages_dict(); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} + +namespace { + + using BOOST_PYTHON_CONVERSION::from_python; + using boost::python::type; + using boost::python::ref; + using boost::python::tuple; + using boost::python::list; + using boost::python::dictionary; + using boost::python::getattr; + + ref world_getstate(tuple const & args, dictionary const & keywords) + { + if(args.size() != 1 || keywords.size() != 0) { + PyErr_SetString(PyExc_TypeError, "wrong number of arguments"); + throw boost::python::argument_error(); + } + const world& w = from_python(args[0].get(), type()); + ref mydict = getattr(args[0], "__dict__"); + tuple result(2); + // store the object's __dict__ + result.set_item(0, mydict); + // store the internal state of the C++ object + result.set_item(1, w.get_secret_number()); + return result.reference(); // returning the reference avoids the copying. + } + + PyObject* world_setstate(tuple const & args, dictionary const & keywords) + { + if(args.size() != 2 || keywords.size() != 0) { + PyErr_SetString(PyExc_TypeError, "wrong number of arguments"); + throw boost::python::argument_error(); + } + world& w = from_python(args[0].get(), type()); + ref mydict = getattr(args[0], "__dict__"); + tuple state = from_python(args[1].get(), type()); + if (state.size() != 2) { + PyErr_SetString(PyExc_ValueError, + "Unexpected argument in call to __setstate__."); + throw python::error_already_set(); + } + // restore the object's __dict__ + dictionary odict = from_python(mydict.get(), type()); + const dictionary& pdict = from_python(state[0].get(), type()); + list pkeys(pdict.keys()); + for (int i = 0; i < pkeys.size(); i++) { + ref k(pkeys[i]); + //odict[k] = pdict[k]; // XXX memory leak! + odict[k] = pdict.get_item(k); // this does not leak. + } + // restore the internal state of the C++ object + int number = from_python(state[1].get(), type()); + if (number != 42) + w.set_secret_number(number); + return python::detail::none(); + } +} diff --git a/example/simple_vector.cpp b/example/simple_vector.cpp new file mode 100644 index 00000000..5ac0767b --- /dev/null +++ b/example/simple_vector.cpp @@ -0,0 +1,103 @@ +// Example by Ralf W. Grosse-Kunstleve + +#include +namespace python = boost::python; + +namespace { // Avoid cluttering the global namespace. + + // A wrapper is used to define additional constructors. + // + struct vector_double_wrapper: std::vector + { + // Tell the compiler how to convert a base class object to + // this wrapper object. + vector_double_wrapper(PyObject*, const std::vector& vd) + : std::vector(vd) {} + + vector_double_wrapper(PyObject* self) + : std::vector() {} + + vector_double_wrapper(PyObject* self, int n) + : std::vector(n) {} + + vector_double_wrapper(PyObject* self, python::tuple tuple) + : std::vector(tuple.size()) + { + std::vector::iterator vd = begin(); + for (int i = 0; i < tuple.size(); i++) + vd[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), + python::type()); + } + }; + + double getitem(const std::vector& vd, std::size_t key) { + return vd[key]; + } + + void setitem(std::vector& vd, std::size_t key, double d) { + std::vector::iterator vditer = vd.begin(); + vditer[key] = d; + } + + void delitem(std::vector& vd, std::size_t key) { + std::vector::iterator vditer = vd.begin(); + vd.erase(&vditer[key]); + } + + // Convert vector_double to a regular Python tuple. + // + python::tuple as_tuple(const std::vector& vd) + { + python::tuple t(vd.size()); + for (int i = 0; i < vd.size(); i++) t.set_item(i, + python::ref(BOOST_PYTHON_CONVERSION::to_python(vd[i]))); + return t; + } + + // Function returning a vector_double object to Python. + // + std::vector foo(int n) + { + std::vector vd(n); + std::vector::iterator vditer = vd.begin(); + for (int i = 0; i < n; i++) vditer[i] = double(i); + return vd; + } + + // Same as foo(), but avoid copying on return. + // + std::auto_ptr > bar(int n) + { + std::auto_ptr > vdptr(new std::vector(n)); + std::vector::iterator vditer = vdptr->begin(); + for (int i = 0; i < n; i++) vditer[i] = double(10 * i); + return vdptr; + } +} + +BOOST_PYTHON_MODULE_INIT(simple_vector) +{ + try + { + python::module_builder this_module("simple_vector"); + + python::class_builder, vector_double_wrapper> + vector_double(this_module, "vector_double"); + + vector_double.def(python::constructor<>()); + vector_double.def(python::constructor()); + vector_double.def(python::constructor()); + vector_double.def(&std::vector::size, "__len__"); + vector_double.def(getitem, "__getitem__"); + vector_double.def(setitem, "__setitem__"); + vector_double.def(delitem, "__delitem__"); + vector_double.def(as_tuple, "as_tuple"); + + this_module.def(foo, "foo"); + this_module.def(bar, "bar"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/test_do_it_yourself_converters.py b/example/test_do_it_yourself_converters.py new file mode 100644 index 00000000..e256c614 --- /dev/null +++ b/example/test_do_it_yourself_converters.py @@ -0,0 +1,22 @@ +r'''>>> import do_it_yourself_converters + >>> ixset = do_it_yourself_converters.IndexingSet() + >>> ixset.add((1,2,3)) + >>> ixset.add((4,5,6)) + >>> ixset.add((7,8,9)) + >>> print ixset.get(0) + (1, 2, 3) + >>> print ixset.get(1) + (4, 5, 6) + >>> print ixset.get(2) + (7, 8, 9) +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_do_it_yourself_converters + doctest.testmod(test_do_it_yourself_converters) + +if __name__ == '__main__': + run() diff --git a/example/test_pickle1.py b/example/test_pickle1.py new file mode 100644 index 00000000..05696d4a --- /dev/null +++ b/example/test_pickle1.py @@ -0,0 +1,31 @@ +r'''>>> import pickle1 + >>> import re + >>> import pickle + >>> pickle1.world.__module__ + 'pickle1' + >>> pickle1.world.__safe_for_unpickling__ + 1 + >>> pickle1.world.__reduce__() + 'world' + >>> assert re.match( + ... "\(, \('Hello',\)\)", + ... repr(pickle1.world('Hello').__reduce__())) + >>> + >>> wd = pickle1.world('California') + >>> pstr = pickle.dumps(wd) + >>> wl = pickle.loads(pstr) + >>> print wd.greet() + Hello from California! + >>> print wl.greet() + Hello from California! +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_pickle1 + doctest.testmod(test_pickle1) + +if __name__ == '__main__': + run() diff --git a/example/test_pickle2.py b/example/test_pickle2.py new file mode 100644 index 00000000..463befa6 --- /dev/null +++ b/example/test_pickle2.py @@ -0,0 +1,45 @@ +r'''>>> import pickle2 + >>> import re + >>> import pickle + >>> pickle2.world.__module__ + 'pickle2' + >>> pickle2.world.__safe_for_unpickling__ + 1 + >>> pickle2.world.__reduce__() + 'world' + >>> assert re.match( + ... "\(, \('Hello',\), \(0,\)\)", + ... repr(pickle2.world('Hello').__reduce__())) + >>> + >>> for number in (24, 42): + ... wd = pickle2.world('California') + ... wd.set_secret_number(number) + ... pstr = pickle.dumps(wd) + ... wl = pickle.loads(pstr) + ... print wd.greet(), wd.get_secret_number() + ... print wl.greet(), wl.get_secret_number() + Hello from California! 24 + Hello from California! 24 + Hello from California! 42 + Hello from California! 0 + +# Now show that the __dict__ is not taken care of. + >>> wd = pickle2.world('California') + >>> wd.x = 1 + >>> wd.__dict__ + {'x': 1} + >>> try: pstr = pickle.dumps(wd) + ... except RuntimeError, err: print err[0] + ... + Incomplete pickle support (__getstate_manages_dict__ not set) +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_pickle2 + doctest.testmod(test_pickle2) + +if __name__ == '__main__': + run() diff --git a/example/test_pickle3.py b/example/test_pickle3.py new file mode 100644 index 00000000..b964f1a2 --- /dev/null +++ b/example/test_pickle3.py @@ -0,0 +1,38 @@ +r'''>>> import pickle3 + >>> import re + >>> import pickle + >>> pickle3.world.__module__ + 'pickle3' + >>> pickle3.world.__safe_for_unpickling__ + 1 + >>> pickle3.world.__reduce__() + 'world' + >>> assert re.match( + ... "\(, \('Hello',\), \(\{\}, 0\)\)", + ... repr(pickle3.world('Hello').__reduce__())) + >>> + >>> for number in (24, 42): + ... wd = pickle3.world('California') + ... wd.set_secret_number(number) + ... wd.x = 2 * number + ... wd.y = 'y' * number + ... wd.z = 3. * number + ... pstr = pickle.dumps(wd) + ... wl = pickle.loads(pstr) + ... print wd.greet(), wd.get_secret_number(), wd.__dict__ + ... print wl.greet(), wl.get_secret_number(), wl.__dict__ + Hello from California! 24 {'z': 72.0, 'x': 48, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyy'} + Hello from California! 24 {'z': 72.0, 'x': 48, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyy'} + Hello from California! 42 {'z': 126.0, 'x': 84, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'} + Hello from California! 0 {'z': 126.0, 'x': 84, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'} +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_pickle3 + doctest.testmod(test_pickle3) + +if __name__ == '__main__': + run() diff --git a/example/test_simple_vector.py b/example/test_simple_vector.py new file mode 100644 index 00000000..a19e205b --- /dev/null +++ b/example/test_simple_vector.py @@ -0,0 +1,35 @@ +r'''>>> import simple_vector + >>> v=simple_vector.vector_double() + >>> print v.as_tuple() + () + >>> v=simple_vector.vector_double(5) + >>> print v.as_tuple() + (0.0, 0.0, 0.0, 0.0, 0.0) + >>> print len(v) + 5 + >>> v=simple_vector.vector_double((3,4,5)) + >>> print v.as_tuple() + (3.0, 4.0, 5.0) + >>> print v[1] + 4.0 + >>> v[1] = 40 + >>> print v.as_tuple() + (3.0, 40.0, 5.0) + >>> del v[1] + >>> print v.as_tuple() + (3.0, 5.0) + >>> print simple_vector.foo(11).as_tuple() + (0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0) + >>> print simple_vector.bar(12).as_tuple() + (0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 110.0) +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_simple_vector + doctest.testmod(test_simple_vector) + +if __name__ == '__main__': + run() From ef7c4379572ef0f9758a4c1c5add34616a8c0757 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 17 Apr 2001 19:31:00 +0000 Subject: [PATCH 086/369] moved from branch ralf_grosse_kunstleve to trunk [SVN r9817] --- example/ivect.h | 32 ++++++++ example/ivect_conversions.cpp | 51 +++++++++++++ example/ivect_defs.cpp | 13 ++++ example/test_cross_module.py | 139 ++++++++++++++++++++++++++++++++++ example/tst_dvect1.py | 20 +++++ example/tst_dvect2.py | 98 ++++++++++++++++++++++++ example/tst_ivect1.py | 20 +++++ example/tst_ivect2.py | 98 ++++++++++++++++++++++++ example/tst_noncopyable.py | 16 ++++ 9 files changed, 487 insertions(+) create mode 100644 example/ivect.h create mode 100644 example/ivect_conversions.cpp create mode 100644 example/ivect_defs.cpp create mode 100644 example/test_cross_module.py create mode 100644 example/tst_dvect1.py create mode 100644 example/tst_dvect2.py create mode 100644 example/tst_ivect1.py create mode 100644 example/tst_ivect2.py create mode 100644 example/tst_noncopyable.py diff --git a/example/ivect.h b/example/ivect.h new file mode 100644 index 00000000..a0187307 --- /dev/null +++ b/example/ivect.h @@ -0,0 +1,32 @@ +#ifndef IVECT_H +#define IVECT_H + +#include +#include + +namespace vects { + + struct ivect : public std::vector + { + ivect() : std::vector() {} + ivect(size_t n) : std::vector(n) {} + ivect(boost::python::tuple tuple) : std::vector(tuple.size()) + { + std::vector::iterator v_it = begin(); + for (int i = 0; i < tuple.size(); i++) + v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), + boost::python::type()); + } + + boost::python::tuple as_tuple() const + { + boost::python::tuple t(size()); + for (int i = 0; i < size(); i++) + t.set_item(i, + boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i]))); + return t; + } + }; +} + +#endif // IVECT_H diff --git a/example/ivect_conversions.cpp b/example/ivect_conversions.cpp new file mode 100644 index 00000000..4f59573d --- /dev/null +++ b/example/ivect_conversions.cpp @@ -0,0 +1,51 @@ + // basics first: const reference converters + boost::python::tuple const_ivect_reference_as_tuple(const vects::ivect& iv) + { + return iv.as_tuple(); + } + + // to_python smart pointer conversions + std::auto_ptr ivect_as_auto_ptr(const vects::ivect& iv) + { + return std::auto_ptr(new vects::ivect(iv)); + } + boost::shared_ptr ivect_as_shared_ptr(const vects::ivect& iv) + { + return boost::shared_ptr(new vects::ivect(iv)); + } + + // smart pointers passed by value + boost::python::ref auto_ptr_value_ivect_as_tuple(std::auto_ptr iv) + { + if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return iv->as_tuple().reference(); + } + boost::python::ref shared_ptr_value_ivect_as_tuple(boost::shared_ptr iv) + { + if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return iv->as_tuple().reference(); + } + + // smart pointers passed by reference + boost::python::ref auto_ptr_reference_ivect_as_tuple(std::auto_ptr& iv) + { + if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return iv->as_tuple().reference(); + } + boost::python::ref shared_ptr_reference_ivect_as_tuple(boost::shared_ptr& iv) + { + if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return iv->as_tuple().reference(); + } + + // smart pointers passed by const reference + boost::python::ref auto_ptr_const_reference_ivect_as_tuple(const std::auto_ptr& iv) + { + if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return iv->as_tuple().reference(); + } + boost::python::ref shared_ptr_const_reference_ivect_as_tuple(const boost::shared_ptr& iv) + { + if (iv.get() == 0) return boost::python::ref(Py_None, boost::python::ref::increment_count); + return iv->as_tuple().reference(); + } diff --git a/example/ivect_defs.cpp b/example/ivect_defs.cpp new file mode 100644 index 00000000..811c243d --- /dev/null +++ b/example/ivect_defs.cpp @@ -0,0 +1,13 @@ + this_module.def(ivect_as_auto_ptr, "ivect_as_auto_ptr"); + this_module.def(ivect_as_shared_ptr, "ivect_as_shared_ptr"); + + this_module.def(const_ivect_reference_as_tuple, "const_ivect_reference_as_tuple"); + + this_module.def(auto_ptr_value_ivect_as_tuple, "auto_ptr_value_ivect_as_tuple"); + this_module.def(shared_ptr_value_ivect_as_tuple, "shared_ptr_value_ivect_as_tuple"); + + this_module.def(auto_ptr_reference_ivect_as_tuple, "auto_ptr_reference_ivect_as_tuple"); + this_module.def(shared_ptr_reference_ivect_as_tuple, "shared_ptr_reference_ivect_as_tuple"); + + this_module.def(auto_ptr_const_reference_ivect_as_tuple, "auto_ptr_const_reference_ivect_as_tuple"); + this_module.def(shared_ptr_const_reference_ivect_as_tuple, "shared_ptr_const_reference_ivect_as_tuple"); diff --git a/example/test_cross_module.py b/example/test_cross_module.py new file mode 100644 index 00000000..81057f23 --- /dev/null +++ b/example/test_cross_module.py @@ -0,0 +1,139 @@ +r'''>>> import tst_noncopyable + >>> tst_noncopyable.f() + 1 + 2 + 3 + >>> import tst_dvect1 + >>> tst_dvect1.f() + (1.0, 2.0, 3.0, 4.0, 5.0) + (1, 2, 3, 4, 5) + (1, 2, 3, 4, 5) + (1, 2, 3, 4, 5) + (1, 2, 3, 4, 5) + (1, 2, 3, 4, 5) + (1, 2, 3, 4, 5) + >>> import tst_ivect1 + >>> tst_ivect1.f() + (1, 2, 3, 4, 5) + (1.0, 2.0, 3.0, 4.0, 5.0) + (1.0, 2.0, 3.0, 4.0, 5.0) + (1.0, 2.0, 3.0, 4.0, 5.0) + (1.0, 2.0, 3.0, 4.0, 5.0) + (1.0, 2.0, 3.0, 4.0, 5.0) + (1.0, 2.0, 3.0, 4.0, 5.0) + >>> import sys + >>> if ("--broken-auto-ptr" in sys.argv): + ... broken_auto_ptr = 1 + ... else: + ... broken_auto_ptr = 0 + >>> import tst_dvect2 + >>> tst_dvect2.f(broken_auto_ptr) + 1. auto_ptr_value_ivect_as_tuple + (1, 2, 3, 4, 5) + 2. auto_ptr_value_ivect_as_tuple + None + 1. auto_ptr_value_dvect_as_tuple + (1.0, 2.0, 3.0, 4.0, 5.0) + 2. auto_ptr_value_dvect_as_tuple + None + 1. shared_ptr_value_ivect_as_tuple + (1, 2, 3, 4, 5) + 2. shared_ptr_value_ivect_as_tuple + (1, 2, 3, 4, 5) + 1. shared_ptr_value_dvect_as_tuple + (1.0, 2.0, 3.0, 4.0, 5.0) + 2. shared_ptr_value_dvect_as_tuple + (1.0, 2.0, 3.0, 4.0, 5.0) + 1. auto_ptr_reference_ivect_as_tuple + (1, 2, 3, 4, 5) + 2. auto_ptr_reference_ivect_as_tuple + (1, 2, 3, 4, 5) + 1. auto_ptr_reference_dvect_as_tuple + (1.0, 2.0, 3.0, 4.0, 5.0) + 2. auto_ptr_reference_dvect_as_tuple + (1.0, 2.0, 3.0, 4.0, 5.0) + 1. shared_ptr_reference_ivect_as_tuple + (1, 2, 3, 4, 5) + 2. shared_ptr_reference_ivect_as_tuple + (1, 2, 3, 4, 5) + 1. shared_ptr_reference_dvect_as_tuple + (1.0, 2.0, 3.0, 4.0, 5.0) + 2. shared_ptr_reference_dvect_as_tuple + (1.0, 2.0, 3.0, 4.0, 5.0) + 1. auto_ptr_const_reference_ivect_as_tuple + (1, 2, 3, 4, 5) + 2. auto_ptr_const_reference_ivect_as_tuple + (1, 2, 3, 4, 5) + 1. auto_ptr_const_reference_dvect_as_tuple + (1.0, 2.0, 3.0, 4.0, 5.0) + 2. auto_ptr_const_reference_dvect_as_tuple + (1.0, 2.0, 3.0, 4.0, 5.0) + 1. shared_ptr_const_reference_ivect_as_tuple + (1, 2, 3, 4, 5) + 2. shared_ptr_const_reference_ivect_as_tuple + (1, 2, 3, 4, 5) + 1. shared_ptr_const_reference_dvect_as_tuple + (1.0, 2.0, 3.0, 4.0, 5.0) + 2. shared_ptr_const_reference_dvect_as_tuple + (1.0, 2.0, 3.0, 4.0, 5.0) + >>> import tst_ivect2 + >>> tst_ivect2.f(broken_auto_ptr) + 1. auto_ptr_value_dvect_as_tuple + (1.0, 2.0, 3.0, 4.0, 5.0) + 2. auto_ptr_value_dvect_as_tuple + None + 1. auto_ptr_value_ivect_as_tuple + (1, 2, 3, 4, 5) + 2. auto_ptr_value_ivect_as_tuple + None + 1. shared_ptr_value_dvect_as_tuple + (1.0, 2.0, 3.0, 4.0, 5.0) + 2. shared_ptr_value_dvect_as_tuple + (1.0, 2.0, 3.0, 4.0, 5.0) + 1. shared_ptr_value_ivect_as_tuple + (1, 2, 3, 4, 5) + 2. shared_ptr_value_ivect_as_tuple + (1, 2, 3, 4, 5) + 1. auto_ptr_reference_dvect_as_tuple + (1.0, 2.0, 3.0, 4.0, 5.0) + 2. auto_ptr_reference_dvect_as_tuple + (1.0, 2.0, 3.0, 4.0, 5.0) + 1. auto_ptr_reference_ivect_as_tuple + (1, 2, 3, 4, 5) + 2. auto_ptr_reference_ivect_as_tuple + (1, 2, 3, 4, 5) + 1. shared_ptr_reference_dvect_as_tuple + (1.0, 2.0, 3.0, 4.0, 5.0) + 2. shared_ptr_reference_dvect_as_tuple + (1.0, 2.0, 3.0, 4.0, 5.0) + 1. shared_ptr_reference_ivect_as_tuple + (1, 2, 3, 4, 5) + 2. shared_ptr_reference_ivect_as_tuple + (1, 2, 3, 4, 5) + 1. auto_ptr_const_reference_dvect_as_tuple + (1.0, 2.0, 3.0, 4.0, 5.0) + 2. auto_ptr_const_reference_dvect_as_tuple + (1.0, 2.0, 3.0, 4.0, 5.0) + 1. auto_ptr_const_reference_ivect_as_tuple + (1, 2, 3, 4, 5) + 2. auto_ptr_const_reference_ivect_as_tuple + (1, 2, 3, 4, 5) + 1. shared_ptr_const_reference_dvect_as_tuple + (1.0, 2.0, 3.0, 4.0, 5.0) + 2. shared_ptr_const_reference_dvect_as_tuple + (1.0, 2.0, 3.0, 4.0, 5.0) + 1. shared_ptr_const_reference_ivect_as_tuple + (1, 2, 3, 4, 5) + 2. shared_ptr_const_reference_ivect_as_tuple + (1, 2, 3, 4, 5) +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_cross_module + doctest.testmod(test_cross_module) + +if __name__ == '__main__': + run() diff --git a/example/tst_dvect1.py b/example/tst_dvect1.py new file mode 100644 index 00000000..22315528 --- /dev/null +++ b/example/tst_dvect1.py @@ -0,0 +1,20 @@ +def f(): + import dvect + dv = dvect.dvect((1,2,3,4,5)) + print dv.as_tuple() + iv = dv.as_ivect() + print iv.as_tuple() + print dvect.const_ivect_reference_as_tuple(iv) + aiv = dvect.ivect_as_auto_ptr(iv) + print dvect.const_ivect_reference_as_tuple(aiv) + siv = dvect.ivect_as_shared_ptr(iv) + print dvect.const_ivect_reference_as_tuple(siv) + print aiv.as_tuple() + print siv.as_tuple() + +if (__name__ == "__main__"): + import sys, string + n = 1 + if (len(sys.argv) > 1): n = string.atoi(sys.argv[1]) + for i in xrange(n): + f() diff --git a/example/tst_dvect2.py b/example/tst_dvect2.py new file mode 100644 index 00000000..539e0b88 --- /dev/null +++ b/example/tst_dvect2.py @@ -0,0 +1,98 @@ +def f(broken_auto_ptr): + import dvect + import ivect + # + dv = dvect.dvect((1,2,3,4,5)) + iv = dv.as_ivect() + # + aiv = dvect.ivect_as_auto_ptr(iv) + print '1. auto_ptr_value_ivect_as_tuple' + print ivect.auto_ptr_value_ivect_as_tuple(aiv) + print '2. auto_ptr_value_ivect_as_tuple' + if (not broken_auto_ptr): + print ivect.auto_ptr_value_ivect_as_tuple(aiv) + else: + print None + # + adv = dvect.dvect_as_auto_ptr(dv) + print '1. auto_ptr_value_dvect_as_tuple' + print ivect.auto_ptr_value_dvect_as_tuple(adv) + print '2. auto_ptr_value_dvect_as_tuple' + if (not broken_auto_ptr): + print ivect.auto_ptr_value_dvect_as_tuple(adv) + else: + print None + # + siv = dvect.ivect_as_shared_ptr(iv) + print '1. shared_ptr_value_ivect_as_tuple' + print ivect.shared_ptr_value_ivect_as_tuple(siv) + print '2. shared_ptr_value_ivect_as_tuple' + print ivect.shared_ptr_value_ivect_as_tuple(siv) + # + sdv = dvect.dvect_as_shared_ptr(dv) + print '1. shared_ptr_value_dvect_as_tuple' + print ivect.shared_ptr_value_dvect_as_tuple(sdv) + print '2. shared_ptr_value_dvect_as_tuple' + print ivect.shared_ptr_value_dvect_as_tuple(sdv) + # + aiv = dvect.ivect_as_auto_ptr(iv) + print '1. auto_ptr_reference_ivect_as_tuple' + print ivect.auto_ptr_reference_ivect_as_tuple(aiv) + print '2. auto_ptr_reference_ivect_as_tuple' + print ivect.auto_ptr_reference_ivect_as_tuple(aiv) + # + adv = dvect.dvect_as_auto_ptr(dv) + print '1. auto_ptr_reference_dvect_as_tuple' + print ivect.auto_ptr_reference_dvect_as_tuple(adv) + print '2. auto_ptr_reference_dvect_as_tuple' + print ivect.auto_ptr_reference_dvect_as_tuple(adv) + # + siv = dvect.ivect_as_shared_ptr(iv) + print '1. shared_ptr_reference_ivect_as_tuple' + print ivect.shared_ptr_reference_ivect_as_tuple(siv) + print '2. shared_ptr_reference_ivect_as_tuple' + print ivect.shared_ptr_reference_ivect_as_tuple(siv) + # + sdv = dvect.dvect_as_shared_ptr(dv) + print '1. shared_ptr_reference_dvect_as_tuple' + print ivect.shared_ptr_reference_dvect_as_tuple(sdv) + print '2. shared_ptr_reference_dvect_as_tuple' + print ivect.shared_ptr_reference_dvect_as_tuple(sdv) + # + aiv = dvect.ivect_as_auto_ptr(iv) + print '1. auto_ptr_const_reference_ivect_as_tuple' + print ivect.auto_ptr_const_reference_ivect_as_tuple(aiv) + print '2. auto_ptr_const_reference_ivect_as_tuple' + print ivect.auto_ptr_const_reference_ivect_as_tuple(aiv) + # + adv = dvect.dvect_as_auto_ptr(dv) + print '1. auto_ptr_const_reference_dvect_as_tuple' + print ivect.auto_ptr_const_reference_dvect_as_tuple(adv) + print '2. auto_ptr_const_reference_dvect_as_tuple' + print ivect.auto_ptr_const_reference_dvect_as_tuple(adv) + # + siv = dvect.ivect_as_shared_ptr(iv) + print '1. shared_ptr_const_reference_ivect_as_tuple' + print ivect.shared_ptr_const_reference_ivect_as_tuple(siv) + print '2. shared_ptr_const_reference_ivect_as_tuple' + print ivect.shared_ptr_const_reference_ivect_as_tuple(siv) + # + sdv = dvect.dvect_as_shared_ptr(dv) + print '1. shared_ptr_const_reference_dvect_as_tuple' + print ivect.shared_ptr_const_reference_dvect_as_tuple(sdv) + print '2. shared_ptr_const_reference_dvect_as_tuple' + print ivect.shared_ptr_const_reference_dvect_as_tuple(sdv) + +if (__name__ == "__main__"): + import sys, string + broken_auto_ptr = 0 + n = 1 + if (len(sys.argv) > 1): + if (sys.argv[1] == "--broken-auto-ptr"): + broken_auto_ptr = 1 + if (len(sys.argv) > 2): + n = string.atoi(sys.argv[2]) + else: + n = string.atoi(sys.argv[1]) + for i in xrange(n): + f(broken_auto_ptr) diff --git a/example/tst_ivect1.py b/example/tst_ivect1.py new file mode 100644 index 00000000..7369fdbf --- /dev/null +++ b/example/tst_ivect1.py @@ -0,0 +1,20 @@ +def f(): + import ivect + iv = ivect.ivect((1,2,3,4,5)) + print iv.as_tuple() + dv = iv.as_dvect() + print dv.as_tuple() + print ivect.const_dvect_reference_as_tuple(dv) + adv = ivect.dvect_as_auto_ptr(dv) + print ivect.const_dvect_reference_as_tuple(adv) + sdv = ivect.dvect_as_shared_ptr(dv) + print ivect.const_dvect_reference_as_tuple(sdv) + print adv.as_tuple() + print sdv.as_tuple() + +if (__name__ == "__main__"): + import sys, string + n = 1 + if (len(sys.argv) > 1): n = string.atoi(sys.argv[1]) + for i in xrange(n): + f() diff --git a/example/tst_ivect2.py b/example/tst_ivect2.py new file mode 100644 index 00000000..6ffd2826 --- /dev/null +++ b/example/tst_ivect2.py @@ -0,0 +1,98 @@ +def f(broken_auto_ptr): + import ivect + import dvect + # + iv = ivect.ivect((1,2,3,4,5)) + dv = iv.as_dvect() + # + adv = ivect.dvect_as_auto_ptr(dv) + print '1. auto_ptr_value_dvect_as_tuple' + print dvect.auto_ptr_value_dvect_as_tuple(adv) + print '2. auto_ptr_value_dvect_as_tuple' + if (not broken_auto_ptr): + print dvect.auto_ptr_value_dvect_as_tuple(adv) + else: + print None + # + aiv = ivect.ivect_as_auto_ptr(iv) + print '1. auto_ptr_value_ivect_as_tuple' + print dvect.auto_ptr_value_ivect_as_tuple(aiv) + print '2. auto_ptr_value_ivect_as_tuple' + if (not broken_auto_ptr): + print dvect.auto_ptr_value_ivect_as_tuple(aiv) + else: + print None + # + sdv = ivect.dvect_as_shared_ptr(dv) + print '1. shared_ptr_value_dvect_as_tuple' + print dvect.shared_ptr_value_dvect_as_tuple(sdv) + print '2. shared_ptr_value_dvect_as_tuple' + print dvect.shared_ptr_value_dvect_as_tuple(sdv) + # + siv = ivect.ivect_as_shared_ptr(iv) + print '1. shared_ptr_value_ivect_as_tuple' + print dvect.shared_ptr_value_ivect_as_tuple(siv) + print '2. shared_ptr_value_ivect_as_tuple' + print dvect.shared_ptr_value_ivect_as_tuple(siv) + # + adv = ivect.dvect_as_auto_ptr(dv) + print '1. auto_ptr_reference_dvect_as_tuple' + print dvect.auto_ptr_reference_dvect_as_tuple(adv) + print '2. auto_ptr_reference_dvect_as_tuple' + print dvect.auto_ptr_reference_dvect_as_tuple(adv) + # + aiv = ivect.ivect_as_auto_ptr(iv) + print '1. auto_ptr_reference_ivect_as_tuple' + print dvect.auto_ptr_reference_ivect_as_tuple(aiv) + print '2. auto_ptr_reference_ivect_as_tuple' + print dvect.auto_ptr_reference_ivect_as_tuple(aiv) + # + sdv = ivect.dvect_as_shared_ptr(dv) + print '1. shared_ptr_reference_dvect_as_tuple' + print dvect.shared_ptr_reference_dvect_as_tuple(sdv) + print '2. shared_ptr_reference_dvect_as_tuple' + print dvect.shared_ptr_reference_dvect_as_tuple(sdv) + # + siv = ivect.ivect_as_shared_ptr(iv) + print '1. shared_ptr_reference_ivect_as_tuple' + print dvect.shared_ptr_reference_ivect_as_tuple(siv) + print '2. shared_ptr_reference_ivect_as_tuple' + print dvect.shared_ptr_reference_ivect_as_tuple(siv) + # + adv = ivect.dvect_as_auto_ptr(dv) + print '1. auto_ptr_const_reference_dvect_as_tuple' + print dvect.auto_ptr_const_reference_dvect_as_tuple(adv) + print '2. auto_ptr_const_reference_dvect_as_tuple' + print dvect.auto_ptr_const_reference_dvect_as_tuple(adv) + # + aiv = ivect.ivect_as_auto_ptr(iv) + print '1. auto_ptr_const_reference_ivect_as_tuple' + print dvect.auto_ptr_const_reference_ivect_as_tuple(aiv) + print '2. auto_ptr_const_reference_ivect_as_tuple' + print dvect.auto_ptr_const_reference_ivect_as_tuple(aiv) + # + sdv = ivect.dvect_as_shared_ptr(dv) + print '1. shared_ptr_const_reference_dvect_as_tuple' + print dvect.shared_ptr_const_reference_dvect_as_tuple(sdv) + print '2. shared_ptr_const_reference_dvect_as_tuple' + print dvect.shared_ptr_const_reference_dvect_as_tuple(sdv) + # + siv = ivect.ivect_as_shared_ptr(iv) + print '1. shared_ptr_const_reference_ivect_as_tuple' + print dvect.shared_ptr_const_reference_ivect_as_tuple(siv) + print '2. shared_ptr_const_reference_ivect_as_tuple' + print dvect.shared_ptr_const_reference_ivect_as_tuple(siv) + +if (__name__ == "__main__"): + import sys, string + broken_auto_ptr = 0 + n = 1 + if (len(sys.argv) > 1): + if (sys.argv[1] == "--broken-auto-ptr"): + broken_auto_ptr = 1 + if (len(sys.argv) > 2): + n = string.atoi(sys.argv[2]) + else: + n = string.atoi(sys.argv[1]) + for i in xrange(n): + f(broken_auto_ptr) diff --git a/example/tst_noncopyable.py b/example/tst_noncopyable.py new file mode 100644 index 00000000..155910a5 --- /dev/null +++ b/example/tst_noncopyable.py @@ -0,0 +1,16 @@ +def f(): + import noncopyable_export + import noncopyable_import + s1 = noncopyable_export.store(1) + print s1.recall() + s2 = noncopyable_export.store(2) + print s2.recall() + s3 = noncopyable_import.add_stores(s1, s2) + print s3.recall() + +if (__name__ == "__main__"): + import sys, string + n = 1 + if (len(sys.argv) > 1): n = string.atoi(sys.argv[1]) + for i in xrange(n): + f() From b5a86a904507dff5777e8aa49b471808a11a5988 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 17 Apr 2001 19:38:20 +0000 Subject: [PATCH 087/369] cross_module mods [SVN r9819] --- build/como.mak | 11 +++++++---- build/gcc.mak | 36 +++++++++++++++++++++++++----------- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/build/como.mak b/build/como.mak index 581eefea..8f05e309 100644 --- a/build/como.mak +++ b/build/como.mak @@ -1,10 +1,12 @@ # Revision History: +# 17 Apr 01 include cross-module support, compile getting_started1 (R.W. Grosse-Kunstleve) UNTESTED! # 06 Mar 01 Fixed typo in use of "PYTHON_LIB" (Dave Abrahams) # 04 Mar 01 Changed library name to libboost_python.a (David Abrahams) LIBSRC = \ classes.cpp \ conversions.cpp \ + cross_module.cpp \ extension_class.cpp \ functions.cpp \ init_function.cpp \ @@ -34,11 +36,12 @@ endif | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \ [ -s $@ ] || rm -f $@ -example1: example1.o libboost_python.a - como-dyn-link -o ../example/hellomodule.$(MODULE_EXTENSION) $(PYTHON_LIB) example1.o -L. -lboost_python - python ../example/test_example1.py +getting_started1: getting_started1.o libboost_python.a + como-dyn-link -o ../example/getting_started1.$(MODULE_EXTENSION) $(PYTHON_LIB) getting_started1.o -L. -lboost_python + ln -s ../test/doctest.py ../example + python ../example/test_getting_started1.py -example1.o: ../example/example1.cpp +getting_started1.o: ../example/getting_started1.cpp como --pic $(INC) -o $*.o -c $< clean: diff --git a/build/gcc.mak b/build/gcc.mak index f71185e0..ce718f2b 100644 --- a/build/gcc.mak +++ b/build/gcc.mak @@ -1,5 +1,7 @@ # Revision History +# 17 Apr 01 include cross-module support, compile getting_started1 (R.W. Grosse-Kunstleve) +# 17 Apr 01 build shared library (patch provided by Dan Nuffer) # 04 Mar 01 Changed library name to libboost_python.a, various cleanups, # attempted Cygwin compatibility. Still needs testing on Linux # (David Abrahams) @@ -8,6 +10,7 @@ LIBSRC = \ classes.cpp \ conversions.cpp \ + cross_module.cpp \ extension_class.cpp \ functions.cpp \ init_function.cpp \ @@ -18,7 +21,7 @@ LIBSRC = \ LIBOBJ = $(LIBSRC:.cpp=.o) OBJ = $(LIBOBJ) -PYTHON_INC=$(ROOT)/usr/local/include/python2.0 +LIBNAME = libboost_python # libpython2.0.dll ifeq "$(OS)" "Windows_NT" @@ -26,13 +29,18 @@ ROOT=c:/cygnus INC = -Ic:/cygnus/usr/include/g++-3 -Ic:/cygnus/usr/include -Ic:/boost -I$(PYTHON_INC) MODULE_EXTENSION=dll PYTHON_LIB=c:/cygnus/usr/local/lib/python2.0/config/libpython2.0.dll.a +SHARED_LIB = $(LIBNAME).dll else -INC = -I$(PYTHON_INC) +PYTHON_INC=$(ROOT)/usr/local/Python-2.0/include/python2.0 +BOOST_INC=../../.. +INC = -I$(BOOST_INC) -I$(PYTHON_INC) MODULE_EXTENSION=so +VERSION=1 +SHARED_LIB = $(LIBNAME).so.$(VERSION) endif %.o: ../src/%.cpp - g++ -fPIC -Wall -W $(INC) -o $*.o -c $< + g++ -fPIC -Wall -W $(INC) $(CXXFLAGS) -o $*.o -c $< %.d: ../src/%.cpp @echo creating $@ @@ -43,7 +51,9 @@ endif PYTHON = python -test: comprehensive.o libboost_python.a +all: test $(SHARED_LIB) getting_started1 + +test: comprehensive.o $(LIBNAME).a $(SHARED_LIB) g++ $(CXXFLAGS) -shared -o ../test/boost_python_test.$(MODULE_EXTENSION) comprehensive.o -L. -lboost_python $(PYTHON_LIB) $(PYTHON) ../test/comprehensive.py @@ -51,20 +61,24 @@ comprehensive.o: ../test/comprehensive.cpp g++ $(CXXFLAGS) --template-depth-32 -fPIC -Wall -W $(INC) -o $*.o -c $< -example1: example1.o libboost_python.a - g++ $(CXXFLAGS) -shared -o ../example/hellomodule.$(MODULE_EXTENSION) example1.o -L. -lboost_python $(PYTHON_LIB) - $(PYTHON) ../example/test_example1.py +getting_started1: getting_started1.o $(LIBNAME).a + g++ $(CXXFLAGS) -shared -o ../example/getting_started1.$(MODULE_EXTENSION) getting_started1.o -L. -lboost_python $(PYTHON_LIB) + ln -s ../test/doctest.py ../example + $(PYTHON) ../example/test_getting_started1.py -example1.o: ../example/example1.cpp +getting_started1.o: ../example/getting_started1.cpp g++ $(CXXFLAGS) --template-depth-32 -fPIC -Wall -W $(INC) -o $*.o -c $< clean: rm -rf *.o *.$(MODULE_EXTENSION) *.a *.d *.pyc *.bak a.out -libboost_python.a: $(LIBOBJ) - rm -f libboost_python.a - ar cq libboost_python.a $(LIBOBJ) +$(LIBNAME).a: $(LIBOBJ) + rm -f $@ + ar cqs $@ $(LIBOBJ) + +$(SHARED_LIB): $(LIBOBJ) + g++ $(CXXFLAGS) -shared -o $@ -Wl,--soname=$(LIBNAME).$(MODULE_EXTENSION) DEP = $(OBJ:.o=.d) From 0c954dde270cb59e7a6093aee5ce36eb8fd7de55 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 17 Apr 2001 19:42:35 +0000 Subject: [PATCH 088/369] moved from branch ralf_grosse_kunstleve to trunk [SVN r9820] --- build/filemgr.py | 135 ++++++++++++++++++++++++ build/irix_CC.mak | 165 ++++++++++++++++++++++++++++++ build/linux_gcc.mak | 191 +++++++++++++++++----------------- build/mingw32.mak | 242 +++++++++++++++++++++----------------------- build/tru64_cxx.mak | 186 ++++++++++++++++++---------------- build/vc60.mak | 133 ++++++++++++++++++++++++ 6 files changed, 740 insertions(+), 312 deletions(-) create mode 100644 build/filemgr.py create mode 100644 build/irix_CC.mak create mode 100644 build/vc60.mak diff --git a/build/filemgr.py b/build/filemgr.py new file mode 100644 index 00000000..fa674f18 --- /dev/null +++ b/build/filemgr.py @@ -0,0 +1,135 @@ +# Revision history: +# 12 Apr 01 use os.path, shutil +# Initial version: R.W. Grosse-Kunstleve + +bpl_src = "/libs/python/src" +bpl_tst = "/libs/python/test" +bpl_exa = "/libs/python/example" +files = ( +bpl_src + "/classes.cpp", +bpl_src + "/conversions.cpp", +bpl_src + "/extension_class.cpp", +bpl_src + "/functions.cpp", +bpl_src + "/init_function.cpp", +bpl_src + "/module_builder.cpp", +bpl_src + "/objects.cpp", +bpl_src + "/types.cpp", +bpl_src + "/cross_module.cpp", +bpl_tst + "/comprehensive.cpp", +bpl_tst + "/comprehensive.hpp", +bpl_tst + "/comprehensive.py", +bpl_tst + "/doctest.py", +bpl_exa + "/abstract.cpp", +bpl_exa + "/getting_started1.cpp", +bpl_exa + "/getting_started2.cpp", +bpl_exa + "/getting_started3.cpp", +bpl_exa + "/simple_vector.cpp", +bpl_exa + "/do_it_yourself_converters.cpp", +bpl_exa + "/pickle1.cpp", +bpl_exa + "/pickle2.cpp", +bpl_exa + "/pickle3.cpp", +bpl_exa + "/test_abstract.py", +bpl_exa + "/test_getting_started1.py", +bpl_exa + "/test_getting_started2.py", +bpl_exa + "/test_getting_started3.py", +bpl_exa + "/test_simple_vector.py", +bpl_exa + "/test_do_it_yourself_converters.py", +bpl_exa + "/test_pickle1.py", +bpl_exa + "/test_pickle2.py", +bpl_exa + "/test_pickle3.py", +bpl_exa + "/noncopyable.h", +bpl_exa + "/noncopyable_export.cpp", +bpl_exa + "/noncopyable_import.cpp", +bpl_exa + "/dvect.h", +bpl_exa + "/dvect.cpp", +bpl_exa + "/dvect_conversions.cpp", +bpl_exa + "/dvect_defs.cpp", +bpl_exa + "/ivect.h", +bpl_exa + "/ivect.cpp", +bpl_exa + "/ivect_conversions.cpp", +bpl_exa + "/ivect_defs.cpp", +bpl_exa + "/tst_noncopyable.py", +bpl_exa + "/tst_dvect1.py", +bpl_exa + "/tst_dvect2.py", +bpl_exa + "/tst_ivect1.py", +bpl_exa + "/tst_ivect2.py", +bpl_exa + "/test_cross_module.py", +) + +defs = ( +"boost_python_test", +"abstract", +"getting_started1", +"getting_started2", +"getting_started3", +"simple_vector", +"do_it_yourself_converters", +"pickle1", +"pickle2", +"pickle3", +"noncopyable_export", +"noncopyable_import", +"ivect", +"dvect", +) + +if (__name__ == "__main__"): + + import sys, os, shutil + + path = sys.argv[1] + mode = sys.argv[2] + if (not mode in ("softlinks", "unlink", "cp", "rm", "copy", "del")): + raise RuntimeError, \ + "usage: python filemgr.py path " + + if (mode in ("cp", "copy")): + for fn in files: + f = os.path.basename(fn) + print "Copying: " + f + shutil.copy(path + fn, ".") + + elif (mode == "softlinks"): + for fn in files: + f = os.path.basename(fn) + if (os.path.exists(f)): + print "File exists: " + f + else: + print "Linking: " + f + os.symlink(path + fn, f) + + elif (mode in ("rm", "del")): + for fn in files: + f = os.path.basename(fn) + if (os.path.exists(f)): + print "Removing: " + f + try: os.unlink(f) + except: pass + + elif (mode == "unlink"): + for fn in files: + f = os.path.basename(fn) + if (os.path.exists(f)): + if (os.path.islink(f)): + print "Unlinking: " + f + try: os.unlink(f) + except: pass + else: + print "Not a softlink: " + f + + if (mode in ("softlinks", "cp", "copy")): + for d in defs: + fn = d + ".def" + print "Creating: " + fn + f = open(fn, "w") + f.write("EXPORTS\n") + f.write("\tinit" + d + "\n") + f.close() + + if (mode in ("unlink", "rm", "del")): + for d in defs: + fn = d + ".def" + if (os.path.exists(fn)): + print "Removing: " + fn + try: os.unlink(fn) + except: pass diff --git a/build/irix_CC.mak b/build/irix_CC.mak new file mode 100644 index 00000000..88d374d8 --- /dev/null +++ b/build/irix_CC.mak @@ -0,0 +1,165 @@ +# Usage: +# +# Create a new empty directory anywhere (preferably not in the boost tree). +# Copy this Makefile to that new directory and rename it to "Makefile" +# Adjust the pathnames below. +# +# make softlinks Create softlinks to source code and tests +# make Compile all sources +# make test Run doctest tests +# make clean Remove all object files +# make unlink Remove softlinks +# +# Revision history: +# 12 Apr 01 new macro ROOT to simplify configuration (R.W. Grosse-Kunstleve) +# Initial version: R.W. Grosse-Kunstleve + +ROOT=$(HOME) +BOOST=$(ROOT)/boost + +PYEXE=/usr/local/Python-1.5.2/bin/python +PYINC=-I/usr/local/Python-1.5.2/include/python1.5 +#PYEXE=/usr/local/Python-2.0/bin/python +#PYINC=-I/usr/local/Python-2.0/include/python2.0 +STLPORTINC=-I$(BOOST)/boost/compatibility/cpp_c_headers + +STDOPTS= +WARNOPTS=-woff 1001,1234,1682 +OPTOPTS=-g + +CPP=CC -LANG:std -n32 -mips4 +CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \ + $(STDOPTS) $(WARNOPTS) $(OPTOPTS) +MAKEDEP=-M + +LD=CC -LANG:std -n32 -mips4 +LDOPTS=-shared + +OBJ=classes.o conversions.o extension_class.o functions.o \ + init_function.o module_builder.o \ + objects.o types.o cross_module.o +DEPOBJ=$(OBJ) \ + comprehensive.o \ + abstract.o \ + getting_started1.o getting_started2.o getting_started3.o \ + simple_vector.o \ + do_it_yourself_converters.o \ + pickle1.o pickle2.o pickle3.o \ + noncopyable_export.o noncopyable_import.o \ + ivect.o dvect.o + +.SUFFIXES: .o .cpp + +all: libboost_python.a \ + boost_python_test.so \ + abstract.so \ + getting_started1.so getting_started2.so getting_started3.so \ + simple_vector.so \ + do_it_yourself_converters.so \ + pickle1.so pickle2.so pickle3.so \ + noncopyable_export.so noncopyable_import.so \ + ivect.so dvect.so + +libboost_python.a: $(OBJ) + rm -f libboost_python.a + $(CPP) -ar -o libboost_python.a $(OBJ) + +boost_python_test.so: $(OBJ) comprehensive.o + $(LD) $(LDOPTS) $(OBJ) comprehensive.o -o boost_python_test.so -lm + +abstract.so: $(OBJ) abstract.o + $(LD) $(LDOPTS) $(OBJ) abstract.o -o abstract.so + +getting_started1.so: $(OBJ) getting_started1.o + $(LD) $(LDOPTS) $(OBJ) getting_started1.o -o getting_started1.so + +getting_started2.so: $(OBJ) getting_started2.o + $(LD) $(LDOPTS) $(OBJ) getting_started2.o -o getting_started2.so + +getting_started3.so: $(OBJ) getting_started3.o + $(LD) $(LDOPTS) $(OBJ) getting_started3.o -o getting_started3.so + +simple_vector.so: $(OBJ) simple_vector.o + $(LD) $(LDOPTS) $(OBJ) simple_vector.o -o simple_vector.so + +do_it_yourself_converters.so: $(OBJ) do_it_yourself_converters.o + $(LD) $(LDOPTS) $(OBJ) do_it_yourself_converters.o -o do_it_yourself_converters.so + +pickle1.so: $(OBJ) pickle1.o + $(LD) $(LDOPTS) $(OBJ) pickle1.o -o pickle1.so + +pickle2.so: $(OBJ) pickle2.o + $(LD) $(LDOPTS) $(OBJ) pickle2.o -o pickle2.so + +pickle3.so: $(OBJ) pickle3.o + $(LD) $(LDOPTS) $(OBJ) pickle3.o -o pickle3.so + +noncopyable_export.so: $(OBJ) noncopyable_export.o + $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \ + noncopyable_export.o -o noncopyable_export.so + +noncopyable_import.so: $(OBJ) noncopyable_import.o + $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \ + noncopyable_import.o -o noncopyable_import.so + +ivect.so: $(OBJ) ivect.o + $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) ivect.o -o ivect.so + +dvect.so: $(OBJ) dvect.o + $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.so + +.cpp.o: + $(CPP) $(CPPOPTS) -c $*.cpp + +test: + $(PYEXE) comprehensive.py + $(PYEXE) test_abstract.py + $(PYEXE) test_getting_started1.py + $(PYEXE) test_getting_started2.py + $(PYEXE) test_getting_started3.py + $(PYEXE) test_simple_vector.py + $(PYEXE) test_do_it_yourself_converters.py + $(PYEXE) test_pickle1.py + $(PYEXE) test_pickle2.py + $(PYEXE) test_pickle3.py + $(PYEXE) test_cross_module.py + +clean: + rm -f $(OBJ) libboost_python.a libboost_python.a.input + rm -f comprehensive.o boost_python_test.so + rm -f abstract.o abstract.so + rm -f getting_started1.o getting_started1.so + rm -f getting_started2.o getting_started2.so + rm -f getting_started3.o getting_started3.so + rm -f simple_vector.o simple_vector.so + rm -f do_it_yourself_converters.o do_it_yourself_converters.so + rm -f pickle1.o pickle1.so + rm -f pickle2.o pickle2.so + rm -f pickle3.o pickle3.so + rm -f noncopyable_export.o noncopyable_export.so + rm -f noncopyable_import.o noncopyable_import.so + rm -f ivect.o ivect.so + rm -f dvect.o dvect.so + rm -f so_locations *.pyc + rm -rf ii_files + +softlinks: + $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) softlinks + +unlink: + $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) unlink + +cp: + $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) cp + +rm: + $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) rm + +depend: + @ cat Makefile.nodepend; \ + for obj in $(DEPOBJ); \ + do \ + bn=`echo "$$obj" | cut -d. -f1`; \ + $(CPP) $(CPPOPTS) $(MAKEDEP) "$$bn".cpp; \ + done + diff --git a/build/linux_gcc.mak b/build/linux_gcc.mak index a07bb5da..9be8f1cb 100644 --- a/build/linux_gcc.mak +++ b/build/linux_gcc.mak @@ -2,110 +2,64 @@ # # Create a new empty directory anywhere (preferably not in the boost tree). # Copy this Makefile to that new directory and rename it to "Makefile" -# Set the BOOST pathname below. +# Adjust the pathnames below. # # make softlinks Create softlinks to source code and tests # make Compile all sources # make test Run doctest tests # make clean Remove all object files # make unlink Remove softlinks +# +# Revision history: +# 12 Apr 01 new macro ROOT to simplify configuration (R.W. Grosse-Kunstleve) +# Initial version: R.W. Grosse-Kunstleve -BOOST= /net/cci/rwgk/boost +ROOT=$(HOME) +BOOST=$(ROOT)/boost -PYEXE= /usr/local/Python-1.5.2/bin/python -PYINC= -I/usr/local/Python-1.5.2/include/python1.5 -#PYEXE= /usr/local/Python-2.0/bin/python -#PYINC= -I/usr/local/Python-2.0/include/python2.0 -#STLPORTINC= -I/usr/local/STLport-4.1b3/stlport -#STLPORTOPTS= \ -# -D__USE_STD_IOSTREAM \ -# -D__STL_NO_SGI_IOSTREAMS \ -# -D__STL_USE_NATIVE_STRING \ -# -D__STL_NO_NEW_C_HEADERS \ -# -D_RWSTD_COMPILE_INSTANTIATE=1 -#STLPORTINC= -I/usr/local/STLport-4.1b4/stlport -#STLPORTOPTS= -D__NO_USE_STD_IOSTREAM -D__STL_NO_SGI_IOSTREAMS -#STLPORTINC= -I/net/cci/xp/C++_C_headers +PYEXE=/usr/bin/python +PYINC=-I/usr/include/python1.5 +#PYEXE=/usr/local/Python-1.5.2/bin/python +#PYINC=-I/usr/local/Python-1.5.2/include/python1.5 +#PYEXE=/usr/local/Python-2.0/bin/python +#PYINC=-I/usr/local/Python-2.0/include/python2.0 -STDOPTS= -ftemplate-depth-21 +STDOPTS=-ftemplate-depth-21 WARNOPTS= -# use -msg_display_number to obtain integer tags for -msg_disable +OPTOPTS=-g -CPP= g++ -CPPOPTS= $(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \ - $(STDOPTS) $(WARNOPTS) -g -MAKEDEP= -M +CPP=g++ +CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \ + $(STDOPTS) $(WARNOPTS) $(OPTOPTS) +MAKEDEP=-M -LD= g++ -LDOPTS= -shared +LD=g++ +LDOPTS=-shared -#HIDDEN= -hidden - -BPL_SRC = $(BOOST)/libs/python/src -BPL_TST = $(BOOST)/libs/python/test -BPL_EXA = $(BOOST)/libs/python/example -SOFTLINKS = \ -$(BPL_SRC)/classes.cpp \ -$(BPL_SRC)/conversions.cpp \ -$(BPL_SRC)/extension_class.cpp \ -$(BPL_SRC)/functions.cpp \ -$(BPL_SRC)/init_function.cpp \ -$(BPL_SRC)/module_builder.cpp \ -$(BPL_SRC)/objects.cpp \ -$(BPL_SRC)/types.cpp \ -$(BPL_TST)/comprehensive.cpp \ -$(BPL_TST)/comprehensive.hpp \ -$(BPL_TST)/comprehensive.py \ -$(BPL_TST)/doctest.py \ -$(BPL_EXA)/abstract.cpp \ -$(BPL_EXA)/getting_started1.cpp \ -$(BPL_EXA)/getting_started2.cpp \ -$(BPL_EXA)/getting_started3.cpp \ -$(BPL_EXA)/getting_started4.cpp \ -$(BPL_EXA)/getting_started5.cpp \ -$(BPL_EXA)/test_abstract.py \ -$(BPL_EXA)/test_getting_started1.py \ -$(BPL_EXA)/test_getting_started2.py \ -$(BPL_EXA)/test_getting_started3.py \ -$(BPL_EXA)/test_getting_started4.py \ -$(BPL_EXA)/test_getting_started5.py - -OBJ = classes.o conversions.o extension_class.o functions.o \ - init_function.o module_builder.o \ - objects.o types.o -DEPOBJ= $(OBJ) comprehensive.o abstract.o \ - getting_started1.o getting_started2.o getting_started3.o \ - getting_started4.o getting_started5.o +OBJ=classes.o conversions.o extension_class.o functions.o \ + init_function.o module_builder.o \ + objects.o types.o cross_module.o +DEPOBJ=$(OBJ) \ + comprehensive.o \ + abstract.o \ + getting_started1.o getting_started2.o getting_started3.o \ + simple_vector.o \ + do_it_yourself_converters.o \ + pickle1.o pickle2.o pickle3.o \ + noncopyable_export.o noncopyable_import.o \ + ivect.o dvect.o .SUFFIXES: .o .cpp -all: libboost_python.a boost_python_test.so abstract.so \ +all: libboost_python.a \ + boost_python_test.so \ + abstract.so \ getting_started1.so getting_started2.so getting_started3.so \ - getting_started4.so getting_started5.so - -softlinks: - @ for pn in $(SOFTLINKS); \ - do \ - bn=`basename "$$pn"`; \ - if [ ! -e "$$bn" ]; then \ - echo "ln -s $$pn ."; \ - ln -s "$$pn" .; \ - else \ - echo "info: no softlink created (file exists): $$bn"; \ - fi; \ - done - -unlink: - @ for pn in $(SOFTLINKS); \ - do \ - bn=`basename "$$pn"`; \ - if [ -L "$$bn" ]; then \ - echo "rm $$bn"; \ - rm "$$bn"; \ - elif [ -e "$$bn" ]; then \ - echo "info: not a softlink: $$bn"; \ - fi; \ - done + simple_vector.so \ + do_it_yourself_converters.so \ + pickle1.so pickle2.so pickle3.so \ + noncopyable_export.so noncopyable_import.so \ + ivect.so dvect.so libboost_python.a: $(OBJ) rm -f libboost_python.a @@ -126,11 +80,34 @@ getting_started2.so: $(OBJ) getting_started2.o getting_started3.so: $(OBJ) getting_started3.o $(LD) $(LDOPTS) $(OBJ) getting_started3.o -o getting_started3.so -getting_started4.so: $(OBJ) getting_started4.o - $(LD) $(LDOPTS) $(OBJ) getting_started4.o -o getting_started4.so +simple_vector.so: $(OBJ) simple_vector.o + $(LD) $(LDOPTS) $(OBJ) simple_vector.o -o simple_vector.so -getting_started5.so: $(OBJ) getting_started5.o - $(LD) $(LDOPTS) $(OBJ) getting_started5.o -o getting_started5.so +do_it_yourself_converters.so: $(OBJ) do_it_yourself_converters.o + $(LD) $(LDOPTS) $(OBJ) do_it_yourself_converters.o -o do_it_yourself_converters.so + +pickle1.so: $(OBJ) pickle1.o + $(LD) $(LDOPTS) $(OBJ) pickle1.o -o pickle1.so + +pickle2.so: $(OBJ) pickle2.o + $(LD) $(LDOPTS) $(OBJ) pickle2.o -o pickle2.so + +pickle3.so: $(OBJ) pickle3.o + $(LD) $(LDOPTS) $(OBJ) pickle3.o -o pickle3.so + +noncopyable_export.so: $(OBJ) noncopyable_export.o + $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \ + noncopyable_export.o -o noncopyable_export.so + +noncopyable_import.so: $(OBJ) noncopyable_import.o + $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \ + noncopyable_import.o -o noncopyable_import.so + +ivect.so: $(OBJ) ivect.o + $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) ivect.o -o ivect.so + +dvect.so: $(OBJ) dvect.o + $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.so .cpp.o: $(CPP) $(CPPOPTS) -c $*.cpp @@ -141,8 +118,12 @@ test: $(PYEXE) test_getting_started1.py $(PYEXE) test_getting_started2.py $(PYEXE) test_getting_started3.py - $(PYEXE) test_getting_started4.py - $(PYEXE) test_getting_started5.py + $(PYEXE) test_simple_vector.py + $(PYEXE) test_do_it_yourself_converters.py + $(PYEXE) test_pickle1.py + $(PYEXE) test_pickle2.py + $(PYEXE) test_pickle3.py + $(PYEXE) test_cross_module.py clean: rm -f $(OBJ) libboost_python.a libboost_python.a.input @@ -151,10 +132,28 @@ clean: rm -f getting_started1.o getting_started1.so rm -f getting_started2.o getting_started2.so rm -f getting_started3.o getting_started3.so - rm -f getting_started4.o getting_started4.so - rm -f getting_started5.o getting_started5.so + rm -f simple_vector.o simple_vector.so + rm -f do_it_yourself_converters.o do_it_yourself_converters.so + rm -f pickle1.o pickle1.so + rm -f pickle2.o pickle2.so + rm -f pickle3.o pickle3.so + rm -f noncopyable_export.o noncopyable_export.so + rm -f noncopyable_import.o noncopyable_import.so + rm -f ivect.o ivect.so + rm -f dvect.o dvect.so rm -f so_locations *.pyc - rm -rf cxx_repository + +softlinks: + $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) softlinks + +unlink: + $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) unlink + +cp: + $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) cp + +rm: + $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) rm depend: @ cat Makefile.nodepend; \ diff --git a/build/mingw32.mak b/build/mingw32.mak index 014af132..98a26735 100644 --- a/build/mingw32.mak +++ b/build/mingw32.mak @@ -1,18 +1,14 @@ # Usage: # -# Create a new empty directory anywhere (preferably not in the boost tree). -# Copy this Makefile to that new directory and rename it to "Makefile" -# Set the BOOST_* pathnames below. +# make copy Copy the sources and tests +# make Compile all sources +# make test Run doctest tests +# make clean Remove all object files +# make del Remove the sources and tests # -# The idea is that the build directory is on a Unix filesystem that -# is mounted on a PC using SAMBA. Use this makefile under both Unix -# and Windows: -# -# Unix: make softlinks Create softlinks to source code and tests -# Win: make Compile all sources -# Win: make test Run doctest tests -# Unix: make clean Remove all object files -# Unix: make unlink Remove softlinks +# Revision history: +# 12 Apr 01 new macro ROOT to simplify configuration (R.W. Grosse-Kunstleve) +# Initial version: R.W. Grosse-Kunstleve # To install mingw32, follow instructions at: # http://starship.python.net/crew/kernr/mingw32/Notes.html @@ -31,117 +27,49 @@ # Could this be fixed with compiler options? # -fhuge-objects looks interesting, but requires recompiling the C++ library. # (what exactly does that mean?) -# -fvtable-thunks eliminates the compiler warning, -# but "import boost_python_test" still causes a crash. +# -fvtable-thunks eliminates the compiler warning, but +# "import boost_python_test" still causes a crash. -BOOST_UNIX= /net/cci/rwgk/boost -BOOST_WIN= "L:\boost" +ROOT=L: +BOOST_WIN="$(ROOT)\boost" +BOOST_UNIX=$(HOME)/boost -PYEXE= "C:\Program files\Python\python.exe" -PYINC= -I"C:\usr\include\python1.5" -PYLIB= "C:\usr\lib\libpython15.a" +PYEXE="C:\Program files\Python\python.exe" +PYINC=-I"C:\usr\include\python1.5" +PYLIB="C:\usr\lib\libpython15.a" -STDOPTS= -ftemplate-depth-21 +STDOPTS=-ftemplate-depth-21 WARNOPTS= +OPTOPTS=-g -CPP= g++ -CPPOPTS= $(STLPORTINC) $(STLPORTOPTS) -I$(BOOST_WIN) $(PYINC) \ - $(STDOPTS) $(WARNOPTS) -g +CPP=g++ +CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) -I$(BOOST_WIN) $(PYINC) \ + $(STDOPTS) $(WARNOPTS) $(OPTOPTS) -LD= g++ -LDOPTS= -shared +LD=g++ +LDOPTS=-shared -BPL_SRC = $(BOOST_UNIX)/libs/python/src -BPL_TST = $(BOOST_UNIX)/libs/python/test -BPL_EXA = $(BOOST_UNIX)/libs/python/example -SOFTLINKS = \ -$(BPL_SRC)/classes.cpp \ -$(BPL_SRC)/conversions.cpp \ -$(BPL_SRC)/extension_class.cpp \ -$(BPL_SRC)/functions.cpp \ -$(BPL_SRC)/init_function.cpp \ -$(BPL_SRC)/module_builder.cpp \ -$(BPL_SRC)/objects.cpp \ -$(BPL_SRC)/types.cpp \ -$(BPL_TST)/comprehensive.cpp \ -$(BPL_TST)/comprehensive.hpp \ -$(BPL_TST)/comprehensive.py \ -$(BPL_TST)/doctest.py \ -$(BPL_EXA)/abstract.cpp \ -$(BPL_EXA)/getting_started1.cpp \ -$(BPL_EXA)/getting_started2.cpp \ -$(BPL_EXA)/getting_started3.cpp \ -$(BPL_EXA)/getting_started4.cpp \ -$(BPL_EXA)/getting_started5.cpp \ -$(BPL_EXA)/passing_char.cpp \ -$(BPL_EXA)/test_abstract.py \ -$(BPL_EXA)/test_getting_started1.py \ -$(BPL_EXA)/test_getting_started2.py \ -$(BPL_EXA)/test_getting_started3.py \ -$(BPL_EXA)/test_getting_started4.py \ -$(BPL_EXA)/test_getting_started5.py - -DEFS= \ -boost_python_test \ -abstract \ -getting_started1 \ -getting_started2 \ -getting_started3 \ -getting_started4 \ -getting_started5 - -OBJ = classes.o conversions.o extension_class.o functions.o \ - init_function.o module_builder.o \ - objects.o types.o +OBJ=classes.o conversions.o extension_class.o functions.o \ + init_function.o module_builder.o \ + objects.o types.o cross_module.o .SUFFIXES: .o .cpp -all: libboost_python.a boost_python_test.pyd abstract.pyd \ +all: libboost_python.a \ + abstract.pyd \ getting_started1.pyd getting_started2.pyd getting_started3.pyd \ - getting_started4.pyd getting_started5.pyd - -softlinks: defs - @ for pn in $(SOFTLINKS); \ - do \ - bn=`basename "$$pn"`; \ - if [ ! -e "$$bn" ]; then \ - echo "ln -s $$pn ."; \ - ln -s "$$pn" .; \ - else \ - echo "info: no softlink created (file exists): $$bn"; \ - fi; \ - done - -unlink: rmdefs - @ for pn in $(SOFTLINKS); \ - do \ - bn=`basename "$$pn"`; \ - if [ -L "$$bn" ]; then \ - echo "rm $$bn"; \ - rm "$$bn"; \ - elif [ -e "$$bn" ]; then \ - echo "info: not a softlink: $$bn"; \ - fi; \ - done - -defs: - @ for def in $(DEFS); \ - do \ - echo "EXPORTS\n\tinit$$def" > $$def.def; \ - done - -rmdefs: - @ for def in $(DEFS); \ - do \ - rm $$def.def; \ - done + simple_vector.pyd \ + do_it_yourself_converters.pyd \ + pickle1.pyd pickle2.pyd pickle3.pyd \ + noncopyable_export.pyd noncopyable_import.pyd \ + ivect.pyd dvect.pyd libboost_python.a: $(OBJ) del libboost_python.a ar r libboost_python.a $(OBJ) -DLLWRAPOPTS= -s --driver-name g++ -s - --entry _DllMainCRTStartup@12 --target=i386-mingw32 +DLLWRAPOPTS=-s --driver-name g++ -s \ + --entry _DllMainCRTStartup@12 --target=i386-mingw32 boost_python_test.pyd: $(OBJ) comprehensive.o dllwrap $(DLLWRAPOPTS) \ @@ -173,38 +101,96 @@ getting_started3.pyd: $(OBJ) getting_started3.o --def getting_started3.def \ $(OBJ) getting_started3.o $(PYLIB) -getting_started4.pyd: $(OBJ) getting_started4.o +simple_vector.pyd: $(OBJ) simple_vector.o dllwrap $(DLLWRAPOPTS) \ - --dllname getting_started4.pyd \ - --def getting_started4.def \ - $(OBJ) getting_started4.o $(PYLIB) + --dllname simple_vector.pyd \ + --def simple_vector.def \ + $(OBJ) simple_vector.o $(PYLIB) -getting_started5.pyd: $(OBJ) getting_started5.o +do_it_yourself_converters.pyd: $(OBJ) do_it_yourself_converters.o dllwrap $(DLLWRAPOPTS) \ - --dllname getting_started5.pyd \ - --def getting_started5.def \ - $(OBJ) getting_started5.o $(PYLIB) + --dllname do_it_yourself_converters.pyd \ + --def do_it_yourself_converters.def \ + $(OBJ) do_it_yourself_converters.o $(PYLIB) + +pickle1.pyd: $(OBJ) pickle1.o + dllwrap $(DLLWRAPOPTS) \ + --dllname pickle1.pyd \ + --def pickle1.def \ + $(OBJ) pickle1.o $(PYLIB) + +pickle2.pyd: $(OBJ) pickle2.o + dllwrap $(DLLWRAPOPTS) \ + --dllname pickle2.pyd \ + --def pickle2.def \ + $(OBJ) pickle2.o $(PYLIB) + +pickle3.pyd: $(OBJ) pickle3.o + dllwrap $(DLLWRAPOPTS) \ + --dllname pickle3.pyd \ + --def pickle3.def \ + $(OBJ) pickle3.o $(PYLIB) + +noncopyable_export.pyd: $(OBJ) noncopyable_export.o + dllwrap $(DLLWRAPOPTS) \ + --dllname noncopyable_export.pyd \ + --def noncopyable_export.def \ + $(OBJ) noncopyable_export.o $(PYLIB) + +noncopyable_import.pyd: $(OBJ) noncopyable_import.o + dllwrap $(DLLWRAPOPTS) \ + --dllname noncopyable_import.pyd \ + --def noncopyable_import.def \ + $(OBJ) noncopyable_import.o $(PYLIB) + +ivect.pyd: $(OBJ) ivect.o + dllwrap $(DLLWRAPOPTS) \ + --dllname ivect.pyd \ + --def ivect.def \ + $(OBJ) ivect.o $(PYLIB) + +dvect.pyd: $(OBJ) dvect.o + dllwrap $(DLLWRAPOPTS) \ + --dllname dvect.pyd \ + --def dvect.def \ + $(OBJ) dvect.o $(PYLIB) .cpp.o: $(CPP) $(CPPOPTS) -c $*.cpp test: - $(PYEXE) comprehensive.py +# $(PYEXE) comprehensive.py $(PYEXE) test_abstract.py $(PYEXE) test_getting_started1.py $(PYEXE) test_getting_started2.py $(PYEXE) test_getting_started3.py - $(PYEXE) test_getting_started4.py - $(PYEXE) test_getting_started5.py + $(PYEXE) test_simple_vector.py + $(PYEXE) test_do_it_yourself_converters.py + $(PYEXE) test_pickle1.py + $(PYEXE) test_pickle2.py + $(PYEXE) test_pickle3.py + $(PYEXE) test_cross_module.py clean: - rm -f $(OBJ) libboost_python.a libboost_python.a.input - rm -f comprehensive.o boost_python_test.pyd - rm -f abstract.o abstract.pyd - rm -f getting_started1.o getting_started1.pyd - rm -f getting_started2.o getting_started2.pyd - rm -f getting_started3.o getting_started3.pyd - rm -f getting_started4.o getting_started4.pyd - rm -f getting_started5.o getting_started5.pyd - rm -f so_locations *.pyc - rm -rf cxx_repository + del *.o + del *.a + del *.pyd + del *.pyc + +softlinks: + python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) softlinks + +unlink: + python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) unlink + +cp: + python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) cp + +rm: + python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) rm + +copy: + $(PYEXE) $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) copy + +del: + $(PYEXE) $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) del diff --git a/build/tru64_cxx.mak b/build/tru64_cxx.mak index 3fd584b7..41f7a554 100644 --- a/build/tru64_cxx.mak +++ b/build/tru64_cxx.mak @@ -2,110 +2,74 @@ # # Create a new empty directory anywhere (preferably not in the boost tree). # Copy this Makefile to that new directory and rename it to "Makefile" -# Set the BOOST pathname below. +# Adjust the pathnames below. # # make softlinks Create softlinks to source code and tests # make Compile all sources # make test Run doctest tests # make clean Remove all object files # make unlink Remove softlinks +# +# Revision history: +# 12 Apr 01 new macro ROOT to simplify configuration (R.W. Grosse-Kunstleve) +# Initial version: R.W. Grosse-Kunstleve -BOOST= /net/cci/rwgk/boost +ROOT=$(HOME) +BOOST=$(ROOT)/boost -PYEXE= /usr/local/Python-1.5.2/bin/python -PYINC= -I/usr/local/Python-1.5.2/include/python1.5 -#PYEXE= /usr/local/Python-2.0/bin/python -#PYINC= -I/usr/local/Python-2.0/include/python2.0 -#STLPORTINC= -I/usr/local/STLport-4.1b3/stlport +PYEXE=/usr/local/Python-1.5.2/bin/python +PYINC=-I/usr/local/Python-1.5.2/include/python1.5 +#PYEXE=/usr/local/Python-2.0/bin/python +#PYINC=-I/usr/local/Python-2.0/include/python2.0 +#STLPORTINC=-I/usr/local/STLport-4.1b3/stlport +#STLPORTINC=-I/usr/local/STLport-4.1b4/stlport #STLPORTOPTS= \ # -D__USE_STD_IOSTREAM \ # -D__STL_NO_SGI_IOSTREAMS \ # -D__STL_USE_NATIVE_STRING \ # -D__STL_NO_NEW_C_HEADERS \ # -D_RWSTD_COMPILE_INSTANTIATE=1 -#STLPORTINC= -I/usr/local/STLport-4.1b4/stlport -#STLPORTOPTS= -D__NO_USE_STD_IOSTREAM -D__STL_NO_SGI_IOSTREAMS -STLPORTINC= -I/net/cci/xp/C++_C_headers +STLPORTINC=-I$(BOOST)/boost/compatibility/cpp_c_headers -STDOPTS= -std strict_ansi -WARNOPTS= -msg_disable 186,450,1115 +STDOPTS=-std strict_ansi # use -msg_display_number to obtain integer tags for -msg_disable +WARNOPTS=-msg_disable 186,450,1115 +OPTOPTS=-g -CPP= cxx -CPPOPTS= $(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \ - $(STDOPTS) $(WARNOPTS) -g -MAKEDEP= -Em +CPP=cxx +CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \ + $(STDOPTS) $(WARNOPTS) $(OPTOPTS) +MAKEDEP=-Em -LD= cxx -LDOPTS= -shared -expect_unresolved 'Py*' -expect_unresolved '_Py*' +LD=cxx +LDOPTS=-shared -expect_unresolved 'Py*' -expect_unresolved '_Py*' -#HIDDEN= -hidden +#HIDDEN=-hidden -BPL_SRC = $(BOOST)/libs/python/src -BPL_TST = $(BOOST)/libs/python/test -BPL_EXA = $(BOOST)/libs/python/example -SOFTLINKS = \ -$(BPL_SRC)/classes.cpp \ -$(BPL_SRC)/conversions.cpp \ -$(BPL_SRC)/extension_class.cpp \ -$(BPL_SRC)/functions.cpp \ -$(BPL_SRC)/init_function.cpp \ -$(BPL_SRC)/module_builder.cpp \ -$(BPL_SRC)/objects.cpp \ -$(BPL_SRC)/types.cpp \ -$(BPL_TST)/comprehensive.cpp \ -$(BPL_TST)/comprehensive.hpp \ -$(BPL_TST)/comprehensive.py \ -$(BPL_TST)/doctest.py \ -$(BPL_EXA)/abstract.cpp \ -$(BPL_EXA)/getting_started1.cpp \ -$(BPL_EXA)/getting_started2.cpp \ -$(BPL_EXA)/getting_started3.cpp \ -$(BPL_EXA)/getting_started4.cpp \ -$(BPL_EXA)/getting_started5.cpp \ -$(BPL_EXA)/test_abstract.py \ -$(BPL_EXA)/test_getting_started1.py \ -$(BPL_EXA)/test_getting_started2.py \ -$(BPL_EXA)/test_getting_started3.py \ -$(BPL_EXA)/test_getting_started4.py \ -$(BPL_EXA)/test_getting_started5.py - -OBJ = classes.o conversions.o extension_class.o functions.o \ - init_function.o module_builder.o \ - objects.o types.o -DEPOBJ= $(OBJ) comprehensive.o abstract.o \ - getting_started1.o getting_started2.o getting_started3.o \ - getting_started4.o getting_started5.o +OBJ=classes.o conversions.o extension_class.o functions.o \ + init_function.o module_builder.o \ + objects.o types.o cross_module.o +DEPOBJ=$(OBJ) \ + comprehensive.o \ + abstract.o \ + getting_started1.o getting_started2.o getting_started3.o \ + simple_vector.o \ + do_it_yourself_converters.o \ + pickle1.o pickle2.o pickle3.o \ + noncopyable_export.o noncopyable_import.o \ + ivect.o dvect.o .SUFFIXES: .o .cpp -all: libboost_python.a boost_python_test.so abstract.so \ +all: libboost_python.a \ + boost_python_test.so \ + abstract.so \ getting_started1.so getting_started2.so getting_started3.so \ - getting_started4.so getting_started5.so - -softlinks: - @ for pn in $(SOFTLINKS); \ - do \ - bn=`basename "$$pn"`; \ - if [ ! -e "$$bn" ]; then \ - echo "ln -s $$pn ."; \ - ln -s "$$pn" .; \ - else \ - echo "info: no softlink created (file exists): $$bn"; \ - fi; \ - done - -unlink: - @ for pn in $(SOFTLINKS); \ - do \ - bn=`basename "$$pn"`; \ - if [ -L "$$bn" ]; then \ - echo "rm $$bn"; \ - rm "$$bn"; \ - elif [ -e "$$bn" ]; then \ - echo "info: not a softlink: $$bn"; \ - fi; \ - done + simple_vector.so \ + do_it_yourself_converters.so \ + pickle1.so pickle2.so pickle3.so \ + noncopyable_export.so noncopyable_import.so \ + ivect.so dvect.so libboost_python.a: $(OBJ) rm -f libboost_python.a @@ -130,11 +94,34 @@ getting_started2.so: $(OBJ) getting_started2.o getting_started3.so: $(OBJ) getting_started3.o $(LD) $(LDOPTS) $(OBJ) getting_started3.o -o getting_started3.so -getting_started4.so: $(OBJ) getting_started4.o - $(LD) $(LDOPTS) $(OBJ) getting_started4.o -o getting_started4.so +simple_vector.so: $(OBJ) simple_vector.o + $(LD) $(LDOPTS) $(OBJ) simple_vector.o -o simple_vector.so -getting_started5.so: $(OBJ) getting_started5.o - $(LD) $(LDOPTS) $(OBJ) getting_started5.o -o getting_started5.so +do_it_yourself_converters.so: $(OBJ) do_it_yourself_converters.o + $(LD) $(LDOPTS) $(OBJ) do_it_yourself_converters.o -o do_it_yourself_converters.so + +pickle1.so: $(OBJ) pickle1.o + $(LD) $(LDOPTS) $(OBJ) pickle1.o -o pickle1.so + +pickle2.so: $(OBJ) pickle2.o + $(LD) $(LDOPTS) $(OBJ) pickle2.o -o pickle2.so + +pickle3.so: $(OBJ) pickle3.o + $(LD) $(LDOPTS) $(OBJ) pickle3.o -o pickle3.so + +noncopyable_export.so: $(OBJ) noncopyable_export.o + $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \ + noncopyable_export.o -o noncopyable_export.so + +noncopyable_import.so: $(OBJ) noncopyable_import.o + $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) \ + noncopyable_import.o -o noncopyable_import.so + +ivect.so: $(OBJ) ivect.o + $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) ivect.o -o ivect.so + +dvect.so: $(OBJ) dvect.o + $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.so .cpp.o: $(CPP) $(CPPOPTS) -c $*.cpp @@ -145,8 +132,12 @@ test: $(PYEXE) test_getting_started1.py $(PYEXE) test_getting_started2.py $(PYEXE) test_getting_started3.py - $(PYEXE) test_getting_started4.py - $(PYEXE) test_getting_started5.py + $(PYEXE) test_simple_vector.py + $(PYEXE) test_do_it_yourself_converters.py + $(PYEXE) test_pickle1.py + $(PYEXE) test_pickle2.py + $(PYEXE) test_pickle3.py + $(PYEXE) test_cross_module.py clean: rm -f $(OBJ) libboost_python.a libboost_python.a.input @@ -155,11 +146,30 @@ clean: rm -f getting_started1.o getting_started1.so rm -f getting_started2.o getting_started2.so rm -f getting_started3.o getting_started3.so - rm -f getting_started4.o getting_started4.so - rm -f getting_started5.o getting_started5.so + rm -f simple_vector.o simple_vector.so + rm -f do_it_yourself_converters.o do_it_yourself_converters.so + rm -f pickle1.o pickle1.so + rm -f pickle2.o pickle2.so + rm -f pickle3.o pickle3.so + rm -f noncopyable_export.o noncopyable_export.so + rm -f noncopyable_import.o noncopyable_import.so + rm -f ivect.o ivect.so + rm -f dvect.o dvect.so rm -f so_locations *.pyc rm -rf cxx_repository +softlinks: + $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) softlinks + +unlink: + $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) unlink + +cp: + $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) cp + +rm: + $(PYEXE) $(BOOST)/libs/python/build/filemgr.py $(BOOST) rm + depend: @ cat Makefile.nodepend; \ for obj in $(DEPOBJ); \ diff --git a/build/vc60.mak b/build/vc60.mak new file mode 100644 index 00000000..64e0b9df --- /dev/null +++ b/build/vc60.mak @@ -0,0 +1,133 @@ +# Usage: +# +# make copy Copy the sources and tests +# make Compile all sources +# make test Run doctest tests +# make clean Remove all object files +# make del Remove the sources and tests +# +# Revision history: +# 12 Apr 01 new macro ROOT to simplify configuration (R.W. Grosse-Kunstleve) +# Initial version: R.W. Grosse-Kunstleve + +ROOT=L: +BOOST_WIN="$(ROOT)\boost" +BOOST_UNIX=$(HOME)/boost + +PYEXE="C:\Program files\Python\python.exe" +PYINC=/I"C:\Program files\Python\include" +PYLIB="C:\Program files\Python\libs\python15.lib" + +STDOPTS=/nologo /MD /GR /GX /Zm200 +WARNOPTS= +OPTOPTS= + +CPP=cl.exe +CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) /I$(BOOST_WIN) $(PYINC) \ + $(STDOPTS) $(WARNOPTS) $(OPTOPTS) + +LD=link.exe +LDOPTS=/nologo /dll /incremental:no + +OBJ=classes.obj conversions.obj extension_class.obj functions.obj \ + init_function.obj module_builder.obj \ + objects.obj types.obj cross_module.obj + +.SUFFIXES: .obj .cpp + +all: boost_python.lib \ + boost_python_test.pyd \ + abstract.pyd \ + getting_started1.pyd getting_started2.pyd getting_started3.pyd \ + simple_vector.pyd \ + do_it_yourself_converters.pyd \ + pickle1.pyd pickle2.pyd pickle3.pyd \ + noncopyable_export.pyd noncopyable_import.pyd \ + ivect.pyd dvect.pyd + +boost_python.lib: $(OBJ) + $(LD) -lib /nologo /out:boost_python.lib $(OBJ) + +boost_python_test.pyd: $(OBJ) comprehensive.obj + $(LD) $(LDOPTS) $(OBJ) comprehensive.obj $(PYLIB) /export:initboost_python_test /out:"boost_python_test.pyd" + +abstract.pyd: $(OBJ) abstract.obj + $(LD) $(LDOPTS) $(OBJ) abstract.obj $(PYLIB) /export:initabstract /out:"abstract.pyd" + +getting_started1.pyd: $(OBJ) getting_started1.obj + $(LD) $(LDOPTS) $(OBJ) getting_started1.obj $(PYLIB) /export:initgetting_started1 /out:"getting_started1.pyd" + +getting_started2.pyd: $(OBJ) getting_started2.obj + $(LD) $(LDOPTS) $(OBJ) getting_started2.obj $(PYLIB) /export:initgetting_started2 /out:"getting_started2.pyd" + +getting_started3.pyd: $(OBJ) getting_started3.obj + $(LD) $(LDOPTS) $(OBJ) getting_started3.obj $(PYLIB) /export:initgetting_started3 /out:"getting_started3.pyd" + +simple_vector.pyd: $(OBJ) simple_vector.obj + $(LD) $(LDOPTS) $(OBJ) simple_vector.obj $(PYLIB) /export:initsimple_vector /out:"simple_vector.pyd" + +do_it_yourself_converters.pyd: $(OBJ) do_it_yourself_converters.obj + $(LD) $(LDOPTS) $(OBJ) do_it_yourself_converters.obj $(PYLIB) /export:initdo_it_yourself_converters /out:"do_it_yourself_converters.pyd" + +pickle1.pyd: $(OBJ) pickle1.obj + $(LD) $(LDOPTS) $(OBJ) pickle1.obj $(PYLIB) /export:initpickle1 /out:"pickle1.pyd" + +pickle2.pyd: $(OBJ) pickle2.obj + $(LD) $(LDOPTS) $(OBJ) pickle2.obj $(PYLIB) /export:initpickle2 /out:"pickle2.pyd" + +pickle3.pyd: $(OBJ) pickle3.obj + $(LD) $(LDOPTS) $(OBJ) pickle3.obj $(PYLIB) /export:initpickle3 /out:"pickle3.pyd" + +noncopyable_export.pyd: $(OBJ) noncopyable_export.obj + $(LD) $(LDOPTS) $(OBJ) noncopyable_export.obj $(PYLIB) /export:initnoncopyable_export /out:"noncopyable_export.pyd" + +noncopyable_import.pyd: $(OBJ) noncopyable_import.obj + $(LD) $(LDOPTS) $(OBJ) noncopyable_import.obj $(PYLIB) /export:initnoncopyable_import /out:"noncopyable_import.pyd" + +ivect.pyd: $(OBJ) ivect.obj + $(LD) $(LDOPTS) $(OBJ) ivect.obj $(PYLIB) /export:initivect /out:"ivect.pyd" + +dvect.pyd: $(OBJ) dvect.obj + $(LD) $(LDOPTS) $(OBJ) dvect.obj $(PYLIB) /export:initdvect /out:"dvect.pyd" + +.cpp.obj: + $(CPP) $(CPPOPTS) /c $*.cpp + +test: + $(PYEXE) comprehensive.py --broken-auto-ptr + $(PYEXE) test_abstract.py + $(PYEXE) test_getting_started1.py + $(PYEXE) test_getting_started2.py + $(PYEXE) test_getting_started3.py + $(PYEXE) test_simple_vector.py + $(PYEXE) test_do_it_yourself_converters.py + $(PYEXE) test_pickle1.py + $(PYEXE) test_pickle2.py + $(PYEXE) test_pickle3.py + $(PYEXE) test_cross_module.py --broken-auto-ptr + +clean: + del *.obj + del *.lib + del *.exp + del *.idb + del *.pyd + del *.pyc + +softlinks: + python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) softlinks + +unlink: + python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) unlink + +cp: + python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) cp + +rm: + python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) rm + +copy: + $(PYEXE) $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) copy + +del: + $(PYEXE) $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) del From fde432601aae5fc1ca29e1ba10b763622af6ab76 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 17 Apr 2001 19:46:15 +0000 Subject: [PATCH 089/369] workaround for irix_CC problem. [SVN r9821] --- test/comprehensive.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/comprehensive.cpp b/test/comprehensive.cpp index 7699b01f..aa2d9886 100644 --- a/test/comprehensive.cpp +++ b/test/comprehensive.cpp @@ -15,6 +15,10 @@ #include // for pow() #include +#if defined(sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 +inline double pow(int x, int y) { return pow(static_cast(x), y); } +#endif + namespace bpl_test { FooCallback::FooCallback(PyObject* self, int x) From fa7b6591cf72da6d1d14d90dcb4b702cf9d325af Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 17 Apr 2001 19:49:42 +0000 Subject: [PATCH 090/369] moved from branch ralf_grosse_kunstleve to trunk (was cross_module_dependencies.html) [SVN r9822] --- doc/cross_module.html | 336 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 336 insertions(+) create mode 100644 doc/cross_module.html diff --git a/doc/cross_module.html b/doc/cross_module.html new file mode 100644 index 00000000..08c39bfe --- /dev/null +++ b/doc/cross_module.html @@ -0,0 +1,336 @@ + + +Cross-extension-module dependencies + +
      + +c++boost.gif (8819 bytes) + +
      +

      Cross-extension-module dependencies

      + +It is good programming practice to organize large projects as modules +that interact with each other via well defined interfaces. With +Boost.Python it is possible to reflect this organization at the C++ +level at the Python level. This is, each logical C++ module can be +organized as a separate Python extension module. + +

      +At first sight this might seem natural and straightforward. However, it +is a fairly complex problem to establish cross-extension-module +dependencies while maintaining the same ease of use Boost.Python +provides for classes that are wrapped in the same extension module. To +a large extent this complexity can be hidden from the author of a +Boost.Python extension module, but not entirely. + +


      +

      The recipe

      + +Suppose there is an extension module that exposes certain instances of +the C++ std::vector template library such that it can be used +from Python in the following manner: + +
      +import std_vector
      +v = std_vector.double([1, 2, 3, 4])
      +v.push_back(5)
      +v.size()
      +
      + +Suppose the std_vector module is done well and reflects all +C++ functions that are useful at the Python level, for all C++ built-in +data types (std_vector.int, std_vector.long, etc.). + +

      +Suppose further that there is statistic module with a C++ class that +has constructors or member functions that use or return a +std::vector. For example: + +

      +class xy {
      +  public:
      +    xy(const std::vector<double>& x, const std::vector<double>& y) : m_x(x), m_y(y) {}
      +    const std::vector<double>& x() const { return m_x; }
      +    const std::vector<double>& y() const { return m_y; }
      +    double correlation();
      +  private:
      +    std::vector<double> m_x;
      +    std::vector<double> m_y;
      +}
      +
      + +What is more natural than reusing the std_vector extension +module to expose these constructors or functions to Python? + +

      +Unfortunately, what seems natural needs a little work in both the +std_vector and the statistics module. + +

      +In the std_vector extension module, +std::vector<double> is exposed to Python in the usual +way with the class_builder<> template. To also enable the +automatic conversion of std::vector<double> function +arguments or return values in other Boost.Python C++ modules, the +converters that convert a std::vector<double> C++ object +to a Python object and vice versa (i.e. the to_python() and +from_python() template functions) have to be exported. For +example: + +

      +  #include <boost/python/cross_module.hpp>
      +  //...
      +  class_builder<std::vector<double> > v_double(std_vector_module, "double");
      +  export_converters(v_double);
      +
      + +In the extension module that wraps class xy we can now import +these converters with the import_converters<> template. +For example: + +
      +  #include <boost/python/cross_module.hpp>
      +  //...
      +  import_converters<std::vector<double> > v_double_converters("std_vector", "double");
      +
      + +That is all. All the attributes that are defined for +std_vector.double in the std_vector Boost.Python +module will be available for the returned objects of xy.x() +and xy.y(). Similarly, the constructor for xy will +accept objects that were created by the std_vectormodule. + +
      +

      Placement of import_converters<> template instantiations

      + +import_converts<> can be viewed as a drop-in replacement +for class_wrapper<>, and the recommendations for the +placement of class_wrapper<> template instantiations +also apply to to import_converts<>. In particular, it is +important that an instantiation of class_wrapper<> is +visible to any code which wraps a C++ function with a T, +T*, const T&, etc. parameter or return value. +Therefore you may want to group all class_wrapper<> and +import_converts<> instantiations at the top of your +module's init function, then def() the member functions later +to avoid problems with inter-class dependencies. + +
      +

      Non-copyable types

      + +export_converters() instantiates C++ template functions that +invoke the copy constructor of the wrapped type. For a type that is +non-copyable this will result in compile-time error messages. In such a +case, export_converters_noncopyable() can be used to export +the converters that do not involve the copy constructor of the wrapped +type. For example: + +
      +class_builder<store> py_store(your_module, "store");
      +export_converters_noncopyable(py_store);
      +
      + +The corresponding import_converters<> statement does not +need any special attention: + +
      +import_converters<store> py_store("noncopyable_export", "store");
      +
      + +
      +

      Python module search path

      + +The std_vector and statistics modules can now be used +in the following way: + +
      +import std_vector
      +import statistics
      +x = std_vector.double([1, 2, 3, 4])
      +y = std_vector.double([2, 4, 6, 8])
      +xy = statistics.xy(x, y)
      +xy.correlation()
      +
      + +In this example it is clear that Python has to be able to find both the +std_vector and the statistics extension module. In +other words, both extension modules need to be in the Python module +search path (sys.path). + +

      +The situation is not always this obvious. Suppose the +statistics module has a random() function that +returns a vector of random numbers with a given length: + +

      +import statistics
      +x = statistics.random(5)
      +y = statistics.random(5)
      +xy = statistics.xy(x, y)
      +xy.correlation()
      +
      + +A naive user will not easily anticipate that the std_vector +module is used to pass the x and y vectors around. If +the std_vector module is in the Python module search path, +this form of ignorance is of no harm. On the contrary, we are glad +that we do not have to bother the user with details like this. + +

      +If the std_vector module is not in the Python module search +path, a Python exception will be raised: + +

      +Traceback (innermost last):
      +  File "foo.py", line 2, in ?
      +    x = statistics.random(5)
      +ImportError: No module named std_vector
      +
      + +As is the case with any system of a non-trivial complexity, it is +important that the setup is consistent and complete. + +
      +

      Two-way module dependencies

      + +Boost.Python supports two-way module dependencies. This is best +illustrated by a simple example. + +

      +Suppose there is a module ivect that implements vectors of +integers, and a similar module dvect that implements vectors +of doubles. We want to be able do convert an integer vector to a double +vector and vice versa. For example: + +

      +import ivect
      +iv = ivect.ivect((1,2,3,4,5))
      +dv = iv.as_dvect()
      +
      + +The last expression will implicitly import the dvect module in +order to enable the conversion of the C++ representation of +dvect to a Python object. The analogous is possible for a +dvect: + +
      +import dvect
      +dv = dvect.dvect((1,2,3,4,5))
      +iv = dv.as_ivect()
      +
      + +Now the ivect module is imported implicitly. + +

      +Note that the two-way dependencies are possible because the +dependencies are resolved only when needed. This is, the initialization +of the ivect module does not rely on the dvect +module, and vice versa. Only if as_dvect() or +as_ivect() is actually invoked will the corresponding module +be implicitly imported. This also means that, for example, the +dvect module does not have to be available at all if +as_dvect() is never used. + +


      +

      Clarification of compile-time and link-time dependencies

      + +Boost.Python's support for resolving cross-module dependencies at +runtime does not imply that compile-time dependencies are eliminated. +For example, the statistics extension module in the example above will +need to #include <vector>. This is immediately obvious +from the definition of class xy. + +

      +If a library is wrapped that consists of both header files and compiled +components (e.g. libdvect.a, dvect.lib, etc.), both +the Boost.Python extension module with the +export_converters() statement and the module with the +import_converters<> statement need to be linked against +the object library. Ideally one would build a shared library (e.g. +libdvect.so, dvect.dll, etc.). However, this +introduces the issue of having to configure the search path for the +dynamic loading correctly. For small libraries it is therefore often +more convenient to ignore the fact that the object files are loaded +into memory more than once. + +


      +

      Summary of motivation for cross-module support

      + +The main purpose of Boost.Python's cross-module support is to allow for +a modular system layout. With this support it is straightforward to +reflect C++ code organization at the Python level. Without the +cross-module support, a multi-purpose module like std_vector +would be impractical because the entire wrapper code would somehow have +to be duplicated in all extension modules that use it, making them +harder to maintain and harder to build. + +

      +Another motivation for the cross-module support is that two extension +modules that wrap the same class cannot both be imported into Python. +For example, if there are two modules A and B that +both wrap a given class X, this will work: + +

      +import A
      +x = A.X()
      +
      + +This will also work: + +
      +import B
      +x = B.X()
      +
      + +However, this will fail: + +
      +import A
      +import B
      +python: /net/cci/rwgk/boost/boost/python/detail/extension_class.hpp:866:
      +static void boost::python::detail::class_registry<X>::register_class(boost::python::detail::extension_class_base *):
      +Assertion `static_class_object == 0' failed.
      +Abort
      +
      + +A good solution is to wrap class X only once. Depending on the +situation, this could be done by module A or B, or an +additional small extension module that only wraps and exports +class X. + +

      +Finally, there can be important psychological or political reasons for +using the cross-module support. If a group of classes is lumped +together with many others in a huge module, the authors will have +difficulties in being identified with their work. The situation is +much more transparent if the work is represented by a module with a +recognizable name. This is not just a question of strong egos, but also +of getting credit and funding. + +


      +

      Why not use export_converters() universally?

      + +There is some overhead associated with the Boost.Python cross-module +support. Depending on the platform, the size of the code generated by +export_converters() is roughly 10%-20% of that generated +by class_builder<>. For a large extension module with +many wrapped classes, this could mean a significant difference. +Therefore the general recommendation is to use +export_converters() only for classes that are likely to +be used as function arguments or return values in other modules. + +
      +© Copyright Ralf W. Grosse-Kunstleve 2001. 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. + +

      +Updated: April 2001 + +

      From 38ac4fe84938e5a211d54b20fb912c1969f34aa3 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 17 Apr 2001 19:51:30 +0000 Subject: [PATCH 091/369] cross-module mods [SVN r9823] --- doc/index.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/index.html b/doc/index.html index c6e0722e..5ec32a6b 100644 --- a/doc/index.html +++ b/doc/index.html @@ -134,6 +134,8 @@ among others.
    • Pickle Support +
    • Cross-Extension-Module Dependencies +
    • Wrapping Enums
    • Pointers and Smart Pointers From 62b90206e842edce572c4ac10af9f9716a4f9173 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 17 Apr 2001 19:52:44 +0000 Subject: [PATCH 092/369] More organized presentation. [SVN r9824] --- doc/building.html | 279 +++++++++++++++++++++++++--------------------- 1 file changed, 151 insertions(+), 128 deletions(-) diff --git a/doc/building.html b/doc/building.html index 2a8c9cae..f9458c42 100644 --- a/doc/building.html +++ b/doc/building.html @@ -5,153 +5,176 @@ Building an Extension Module
      -

      c++boost.gif (8819 bytes)Building an Extension Module

      The build process for Boost is currently undergoing some evolution, and, it is to be hoped, improvement. The following facts may help: +


      + Makefiles for various platforms and a Visual Studio project + reside in the Boost subdirectory libs/python/build. + Build targets include: +
        -
      • - Makefiles for various platforms reside in the Boost subdirectory - libs/python/build: +
      • The boost_python library for static linking with your + extension module. On the various Unices, this library will be + called libboost_python.a. When using Visual C++, the + library will be called boost_python.lib. -
          -
        • como.mak (Comeau C++ on Linux) +

          +

        • A comprehensive test of Boost.Python features. This test builds + a Boost.Python extension module, then runs Python to import the + module, and runs a series of tests on it using doctest. Source code for the module + and tests is available in the Boost subdirectory + libs/python/test. -
        • linux_gcc.mak (GCC on - Linux/Unix) +

          +

        • Various examples from the Boost subdirectory + libs/python/example. + All these examples include a doctest modeled + on the comprehensive test above. -
        • gcc.mak (older makefile for GCC - on Linux/Unix. Deprecated.) - -
        • mingw32.mak - (highly-specialized makefile for mingw32 (Win32-targeted) GCC. Read - the header comment). - -
        • tru64_cxx.mak (Compaq - Alpha). -
        -
        - -
      • - A project workspace for Microsoft Visual Studio is provided at libs/python/build/build.dsw. The - include paths for this project may need to be changed for your - installation. They currently assume that python has been installed at - c:\tools\python. Three configurations of all targets are - supported: - -
          -
        • Release (optimization, -DNDEBUG) - -
        • Debug (no optimization -D_DEBUG) - -
        • DebugPython (no optimization, -D_DEBUG - -DBOOST_DEBUG_PYTHON) -
        - -

        When extension modules are built with Visual C++ using - -D_DEBUG, Python defaults to force linking with a - special debugging version of the Python DLL. Since this debug DLL - isn't supplied with the default Python installation for Windows, - Boost.Python uses boost/python/detail/wrap_python.hpp - to temporarily undefine _DEBUG when Python.h is - #included. - -

        If you want the extra runtime checks available with the debugging - version of the library, #define BOOST_DEBUG_PYTHON to - re-enable library forcing, and link with the DebugPython version of - boost_python.lib. You'll need to get the debugging version - of the Python executable (python_d.exe) and DLL - (python20_d.dll or python15_d.dll). The Python - sources include project files for building these. If you download them, change the name of the - top-level directory to src, and install it under - c:\tools\python, the workspace supplied by Boost.Python will - be able to use it without modification. Just open - c:\tools\python\src\pcbuild\pcbuild.dsw and invoke "build - all" to generate all the debugging targets. - -

        If you do not #define BOOST_DEBUG_PYTHON, be sure that - any source files #include <boost/python/detail/wrap_python.hpp> - instead of the usual Python.h, or you will have link - incompatibilities.
        -
        - - -

      • - The makefiles and Visual Studio project can all build at least the - following: - -
          -
        • The boost_python library for static linking with your - extension module. On the various Unices, this library will be - called libboost_python.a. On Win32 platforms, the library - will be called boost_python.lib. - -
        • A comprehensive test of Boost.Python features. This test builds - a Boost.Python extension module, then runs Python to import the - module, and runs a series of tests on it using doctest. Source code for the module - and tests is available in the Boost subdirectory - libs/python/test.
          - - -
        • Various examples from the Boost subdirectory - libs/python/example. Which examples are built currently - depends on the platform. The most up-to-date examples are - getting_startedn.cpp from Ralf W. - Grosse-Kunstleve. All these examples include a doctest modeled - on the comprehensive test above.
          -
          - -
        - -
      • - If your platform isn't directly supported, you can build a static - library from the following source files (in the Boost subdirectory - libs/python/src), or compile them directly and link the - resulting objects into your extension module: - -
      -

      Next: Wrapping Enums Previous: + There is a group of makefiles with support for simultaneous + compilation on multiple platforms and a consistent set of + features that build the boost_python library for static + linking, the comprehensive test, and all examples in + libs/python/example: + +

      + Usage of these makefiles is described here. + +
      + There is another group of makefiles for GNU make. + These makefiles are less redundant than the makefiles + in the group above, + but the list of compilation targets is not as complete + and there is no support for simultaneous compilation + on multiple platforms. + + + +
      + A project workspace for Microsoft Visual Studio is provided at libs/python/build/build.dsw. The + include paths for this project may need to be changed for your + installation. They currently assume that python has been installed at + c:\tools\python. Three configurations of all targets are + supported: + +
        +
      • Release (optimization, -DNDEBUG) + +
      • Debug (no optimization -D_DEBUG) + +
      • DebugPython (no optimization, -D_DEBUG + -DBOOST_DEBUG_PYTHON) +
      + +

      When extension modules are built with Visual C++ using + -D_DEBUG, Python defaults to force linking with a + special debugging version of the Python DLL. Since this debug DLL + isn't supplied with the default Python installation for Windows, + Boost.Python uses boost/python/detail/wrap_python.hpp + to temporarily undefine _DEBUG when Python.h is + #included. + +

      If you want the extra runtime checks available with the debugging + version of the library, #define BOOST_DEBUG_PYTHON to + re-enable library forcing, and link with the DebugPython version of + boost_python.lib. You'll need to get the debugging version + of the Python executable (python_d.exe) and DLL + (python20_d.dll or python15_d.dll). The Python + sources include project files for building these. If you download them, change the name of the + top-level directory to src, and install it under + c:\tools\python, the workspace supplied by Boost.Python will + be able to use it without modification. Just open + c:\tools\python\src\pcbuild\pcbuild.dsw and invoke "build + all" to generate all the debugging targets. + +

      If you do not #define BOOST_DEBUG_PYTHON, be sure that + any source files #include <boost/python/detail/wrap_python.hpp> + instead of the usual Python.h, or you will have link + incompatibilities.
      + +


      + If your platform isn't directly supported, you can build a static + library from the following source files (in the Boost subdirectory + libs/python/src), or compile them directly and link the + resulting objects into your extension module: + + + +
      + Next: Wrapping Enums Previous: A Peek Under the Hood Up: Top +

      © Copyright David Abrahams 2000. 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. -

      Updated: Mar 6, 2001 +

      Updated: Apr 17, 2001 (R.W. Grosse-Kunstleve)

      - From ad4b0fff565fb36c827f20357de54255dc365d3d Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 17 Apr 2001 19:55:11 +0000 Subject: [PATCH 093/369] moved from branch ralf_grosse_kunstleve to trunk [SVN r9825] --- doc/pickle.html | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/doc/pickle.html b/doc/pickle.html index 842112d3..994a78ab 100644 --- a/doc/pickle.html +++ b/doc/pickle.html @@ -227,11 +227,38 @@ Both __getinitargs__ and __getstate__ are not defined.

    -

    Example

    +

    Examples

    -An example that shows how to configure pickle support is available in the -boost/lib/python/example directory -(getting_started3.cpp). +There are three files in boost/libs/python/example that +show how so provide pickle support. + +

    pickle1.cpp

    + + The C++ class in this example can be fully restored by passing the + appropriate argument to the constructor. Therefore it is sufficient + to define the pickle interface method __getinitargs__. + +

    pickle2.cpp

    + + The C++ class in this example contains member data that cannot be + restored by any of the constructors. Therefore it is necessary to + provide the __getstate__/__setstate__ pair of + pickle interface methods. + +

    + For simplicity, the __dict__ is not included in the result + of __getstate__. This is not generally recommended, but a + valid approach if it is anticipated that the object's + __dict__ will always be empty. Note that the safety guards + will catch the cases where this assumption is violated. + +

    pickle3.cpp

    + + This example is similar to pickle2.cpp. However, the + object's __dict__ is included in the result of + __getstate__. This requires more code but is unavoidable + if the object's __dict__ is not always empty.
    © Copyright Ralf W. Grosse-Kunstleve 2001. Permission to copy, @@ -241,5 +268,5 @@ is" without express or implied warranty, and with no claim as to its suitability for any purpose.

    -Updated: March 10, 2001 +Updated: March 21, 2001 From da83f20a283d943ed9fa42317109d3d0c3af14ec Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 17 Apr 2001 20:02:20 +0000 Subject: [PATCH 094/369] stray getting_started3 references removed. [SVN r9826] --- build/filemgr.py | 3 --- build/irix_CC.mak | 9 ++------- build/linux_gcc.mak | 9 ++------- build/mingw32.mak | 9 +-------- build/tru64_cxx.mak | 9 ++------- build/vc60.mak | 6 +----- 6 files changed, 8 insertions(+), 37 deletions(-) diff --git a/build/filemgr.py b/build/filemgr.py index fa674f18..d8310f6d 100644 --- a/build/filemgr.py +++ b/build/filemgr.py @@ -22,7 +22,6 @@ bpl_tst + "/doctest.py", bpl_exa + "/abstract.cpp", bpl_exa + "/getting_started1.cpp", bpl_exa + "/getting_started2.cpp", -bpl_exa + "/getting_started3.cpp", bpl_exa + "/simple_vector.cpp", bpl_exa + "/do_it_yourself_converters.cpp", bpl_exa + "/pickle1.cpp", @@ -31,7 +30,6 @@ bpl_exa + "/pickle3.cpp", bpl_exa + "/test_abstract.py", bpl_exa + "/test_getting_started1.py", bpl_exa + "/test_getting_started2.py", -bpl_exa + "/test_getting_started3.py", bpl_exa + "/test_simple_vector.py", bpl_exa + "/test_do_it_yourself_converters.py", bpl_exa + "/test_pickle1.py", @@ -61,7 +59,6 @@ defs = ( "abstract", "getting_started1", "getting_started2", -"getting_started3", "simple_vector", "do_it_yourself_converters", "pickle1", diff --git a/build/irix_CC.mak b/build/irix_CC.mak index 88d374d8..5894ff51 100644 --- a/build/irix_CC.mak +++ b/build/irix_CC.mak @@ -41,7 +41,7 @@ OBJ=classes.o conversions.o extension_class.o functions.o \ DEPOBJ=$(OBJ) \ comprehensive.o \ abstract.o \ - getting_started1.o getting_started2.o getting_started3.o \ + getting_started1.o getting_started2.o \ simple_vector.o \ do_it_yourself_converters.o \ pickle1.o pickle2.o pickle3.o \ @@ -53,7 +53,7 @@ DEPOBJ=$(OBJ) \ all: libboost_python.a \ boost_python_test.so \ abstract.so \ - getting_started1.so getting_started2.so getting_started3.so \ + getting_started1.so getting_started2.so \ simple_vector.so \ do_it_yourself_converters.so \ pickle1.so pickle2.so pickle3.so \ @@ -76,9 +76,6 @@ getting_started1.so: $(OBJ) getting_started1.o getting_started2.so: $(OBJ) getting_started2.o $(LD) $(LDOPTS) $(OBJ) getting_started2.o -o getting_started2.so -getting_started3.so: $(OBJ) getting_started3.o - $(LD) $(LDOPTS) $(OBJ) getting_started3.o -o getting_started3.so - simple_vector.so: $(OBJ) simple_vector.o $(LD) $(LDOPTS) $(OBJ) simple_vector.o -o simple_vector.so @@ -116,7 +113,6 @@ test: $(PYEXE) test_abstract.py $(PYEXE) test_getting_started1.py $(PYEXE) test_getting_started2.py - $(PYEXE) test_getting_started3.py $(PYEXE) test_simple_vector.py $(PYEXE) test_do_it_yourself_converters.py $(PYEXE) test_pickle1.py @@ -130,7 +126,6 @@ clean: rm -f abstract.o abstract.so rm -f getting_started1.o getting_started1.so rm -f getting_started2.o getting_started2.so - rm -f getting_started3.o getting_started3.so rm -f simple_vector.o simple_vector.so rm -f do_it_yourself_converters.o do_it_yourself_converters.so rm -f pickle1.o pickle1.so diff --git a/build/linux_gcc.mak b/build/linux_gcc.mak index 9be8f1cb..9cd2b5de 100644 --- a/build/linux_gcc.mak +++ b/build/linux_gcc.mak @@ -42,7 +42,7 @@ OBJ=classes.o conversions.o extension_class.o functions.o \ DEPOBJ=$(OBJ) \ comprehensive.o \ abstract.o \ - getting_started1.o getting_started2.o getting_started3.o \ + getting_started1.o getting_started2.o \ simple_vector.o \ do_it_yourself_converters.o \ pickle1.o pickle2.o pickle3.o \ @@ -54,7 +54,7 @@ DEPOBJ=$(OBJ) \ all: libboost_python.a \ boost_python_test.so \ abstract.so \ - getting_started1.so getting_started2.so getting_started3.so \ + getting_started1.so getting_started2.so \ simple_vector.so \ do_it_yourself_converters.so \ pickle1.so pickle2.so pickle3.so \ @@ -77,9 +77,6 @@ getting_started1.so: $(OBJ) getting_started1.o getting_started2.so: $(OBJ) getting_started2.o $(LD) $(LDOPTS) $(OBJ) getting_started2.o -o getting_started2.so -getting_started3.so: $(OBJ) getting_started3.o - $(LD) $(LDOPTS) $(OBJ) getting_started3.o -o getting_started3.so - simple_vector.so: $(OBJ) simple_vector.o $(LD) $(LDOPTS) $(OBJ) simple_vector.o -o simple_vector.so @@ -117,7 +114,6 @@ test: $(PYEXE) test_abstract.py $(PYEXE) test_getting_started1.py $(PYEXE) test_getting_started2.py - $(PYEXE) test_getting_started3.py $(PYEXE) test_simple_vector.py $(PYEXE) test_do_it_yourself_converters.py $(PYEXE) test_pickle1.py @@ -131,7 +127,6 @@ clean: rm -f abstract.o abstract.so rm -f getting_started1.o getting_started1.so rm -f getting_started2.o getting_started2.so - rm -f getting_started3.o getting_started3.so rm -f simple_vector.o simple_vector.so rm -f do_it_yourself_converters.o do_it_yourself_converters.so rm -f pickle1.o pickle1.so diff --git a/build/mingw32.mak b/build/mingw32.mak index 98a26735..0a16f332 100644 --- a/build/mingw32.mak +++ b/build/mingw32.mak @@ -57,7 +57,7 @@ OBJ=classes.o conversions.o extension_class.o functions.o \ all: libboost_python.a \ abstract.pyd \ - getting_started1.pyd getting_started2.pyd getting_started3.pyd \ + getting_started1.pyd getting_started2.pyd \ simple_vector.pyd \ do_it_yourself_converters.pyd \ pickle1.pyd pickle2.pyd pickle3.pyd \ @@ -95,12 +95,6 @@ getting_started2.pyd: $(OBJ) getting_started2.o --def getting_started2.def \ $(OBJ) getting_started2.o $(PYLIB) -getting_started3.pyd: $(OBJ) getting_started3.o - dllwrap $(DLLWRAPOPTS) \ - --dllname getting_started3.pyd \ - --def getting_started3.def \ - $(OBJ) getting_started3.o $(PYLIB) - simple_vector.pyd: $(OBJ) simple_vector.o dllwrap $(DLLWRAPOPTS) \ --dllname simple_vector.pyd \ @@ -163,7 +157,6 @@ test: $(PYEXE) test_abstract.py $(PYEXE) test_getting_started1.py $(PYEXE) test_getting_started2.py - $(PYEXE) test_getting_started3.py $(PYEXE) test_simple_vector.py $(PYEXE) test_do_it_yourself_converters.py $(PYEXE) test_pickle1.py diff --git a/build/tru64_cxx.mak b/build/tru64_cxx.mak index 41f7a554..21a8126e 100644 --- a/build/tru64_cxx.mak +++ b/build/tru64_cxx.mak @@ -52,7 +52,7 @@ OBJ=classes.o conversions.o extension_class.o functions.o \ DEPOBJ=$(OBJ) \ comprehensive.o \ abstract.o \ - getting_started1.o getting_started2.o getting_started3.o \ + getting_started1.o getting_started2.o \ simple_vector.o \ do_it_yourself_converters.o \ pickle1.o pickle2.o pickle3.o \ @@ -64,7 +64,7 @@ DEPOBJ=$(OBJ) \ all: libboost_python.a \ boost_python_test.so \ abstract.so \ - getting_started1.so getting_started2.so getting_started3.so \ + getting_started1.so getting_started2.so \ simple_vector.so \ do_it_yourself_converters.so \ pickle1.so pickle2.so pickle3.so \ @@ -91,9 +91,6 @@ getting_started1.so: $(OBJ) getting_started1.o getting_started2.so: $(OBJ) getting_started2.o $(LD) $(LDOPTS) $(OBJ) getting_started2.o -o getting_started2.so -getting_started3.so: $(OBJ) getting_started3.o - $(LD) $(LDOPTS) $(OBJ) getting_started3.o -o getting_started3.so - simple_vector.so: $(OBJ) simple_vector.o $(LD) $(LDOPTS) $(OBJ) simple_vector.o -o simple_vector.so @@ -131,7 +128,6 @@ test: $(PYEXE) test_abstract.py $(PYEXE) test_getting_started1.py $(PYEXE) test_getting_started2.py - $(PYEXE) test_getting_started3.py $(PYEXE) test_simple_vector.py $(PYEXE) test_do_it_yourself_converters.py $(PYEXE) test_pickle1.py @@ -145,7 +141,6 @@ clean: rm -f abstract.o abstract.so rm -f getting_started1.o getting_started1.so rm -f getting_started2.o getting_started2.so - rm -f getting_started3.o getting_started3.so rm -f simple_vector.o simple_vector.so rm -f do_it_yourself_converters.o do_it_yourself_converters.so rm -f pickle1.o pickle1.so diff --git a/build/vc60.mak b/build/vc60.mak index 64e0b9df..f0016075 100644 --- a/build/vc60.mak +++ b/build/vc60.mak @@ -38,7 +38,7 @@ OBJ=classes.obj conversions.obj extension_class.obj functions.obj \ all: boost_python.lib \ boost_python_test.pyd \ abstract.pyd \ - getting_started1.pyd getting_started2.pyd getting_started3.pyd \ + getting_started1.pyd getting_started2.pyd \ simple_vector.pyd \ do_it_yourself_converters.pyd \ pickle1.pyd pickle2.pyd pickle3.pyd \ @@ -60,9 +60,6 @@ getting_started1.pyd: $(OBJ) getting_started1.obj getting_started2.pyd: $(OBJ) getting_started2.obj $(LD) $(LDOPTS) $(OBJ) getting_started2.obj $(PYLIB) /export:initgetting_started2 /out:"getting_started2.pyd" -getting_started3.pyd: $(OBJ) getting_started3.obj - $(LD) $(LDOPTS) $(OBJ) getting_started3.obj $(PYLIB) /export:initgetting_started3 /out:"getting_started3.pyd" - simple_vector.pyd: $(OBJ) simple_vector.obj $(LD) $(LDOPTS) $(OBJ) simple_vector.obj $(PYLIB) /export:initsimple_vector /out:"simple_vector.pyd" @@ -98,7 +95,6 @@ test: $(PYEXE) test_abstract.py $(PYEXE) test_getting_started1.py $(PYEXE) test_getting_started2.py - $(PYEXE) test_getting_started3.py $(PYEXE) test_simple_vector.py $(PYEXE) test_do_it_yourself_converters.py $(PYEXE) test_pickle1.py From c3215d0ba5b3b75e2e6f42e37b5e8ad592fb57c3 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 17 Apr 2001 21:30:05 +0000 Subject: [PATCH 095/369] enhancement [SVN r9827] --- example/README | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/example/README b/example/README index 34b50d61..35d822d5 100644 --- a/example/README +++ b/example/README @@ -1,6 +1,24 @@ To get started with the Boost Python Library, use the examples -getting_started?.cpp and abstract.cpp. +getting_started1.cpp and getting_started2.cpp. + +Examples for providing pickle support can be found in: + pickle1.cpp + pickle2.cpp + pickle3.cpp +See also: libs/python/doc/pickle.html + +Other advanced concepts are introduced by: + abstract.cpp + simple_vector.cpp + do_it_yourself_converters.cpp + +Examples for the cross-module support are provided by: + noncopyable_export.cpp + noncopyable_import.cpp + dvect.cpp + ivect.cpp +See also: libs/python/doc/cross_module.html The files example1.cpp and rwgk1.cpp are obsolete. They are only -included because the makefiles in the build directory still refer to -them. This will be fixed later. +included because the Visual Studio project in the build directory still +refers to them. From ebb0145256b4247bf270d6442b669773153d487c Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 18 Apr 2001 01:23:50 +0000 Subject: [PATCH 096/369] trying to clean cvs attic mess... [SVN r9828] --- example/simple_vector.cpp | 103 -------------------------------------- 1 file changed, 103 deletions(-) delete mode 100644 example/simple_vector.cpp diff --git a/example/simple_vector.cpp b/example/simple_vector.cpp deleted file mode 100644 index 5ac0767b..00000000 --- a/example/simple_vector.cpp +++ /dev/null @@ -1,103 +0,0 @@ -// Example by Ralf W. Grosse-Kunstleve - -#include -namespace python = boost::python; - -namespace { // Avoid cluttering the global namespace. - - // A wrapper is used to define additional constructors. - // - struct vector_double_wrapper: std::vector - { - // Tell the compiler how to convert a base class object to - // this wrapper object. - vector_double_wrapper(PyObject*, const std::vector& vd) - : std::vector(vd) {} - - vector_double_wrapper(PyObject* self) - : std::vector() {} - - vector_double_wrapper(PyObject* self, int n) - : std::vector(n) {} - - vector_double_wrapper(PyObject* self, python::tuple tuple) - : std::vector(tuple.size()) - { - std::vector::iterator vd = begin(); - for (int i = 0; i < tuple.size(); i++) - vd[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), - python::type()); - } - }; - - double getitem(const std::vector& vd, std::size_t key) { - return vd[key]; - } - - void setitem(std::vector& vd, std::size_t key, double d) { - std::vector::iterator vditer = vd.begin(); - vditer[key] = d; - } - - void delitem(std::vector& vd, std::size_t key) { - std::vector::iterator vditer = vd.begin(); - vd.erase(&vditer[key]); - } - - // Convert vector_double to a regular Python tuple. - // - python::tuple as_tuple(const std::vector& vd) - { - python::tuple t(vd.size()); - for (int i = 0; i < vd.size(); i++) t.set_item(i, - python::ref(BOOST_PYTHON_CONVERSION::to_python(vd[i]))); - return t; - } - - // Function returning a vector_double object to Python. - // - std::vector foo(int n) - { - std::vector vd(n); - std::vector::iterator vditer = vd.begin(); - for (int i = 0; i < n; i++) vditer[i] = double(i); - return vd; - } - - // Same as foo(), but avoid copying on return. - // - std::auto_ptr > bar(int n) - { - std::auto_ptr > vdptr(new std::vector(n)); - std::vector::iterator vditer = vdptr->begin(); - for (int i = 0; i < n; i++) vditer[i] = double(10 * i); - return vdptr; - } -} - -BOOST_PYTHON_MODULE_INIT(simple_vector) -{ - try - { - python::module_builder this_module("simple_vector"); - - python::class_builder, vector_double_wrapper> - vector_double(this_module, "vector_double"); - - vector_double.def(python::constructor<>()); - vector_double.def(python::constructor()); - vector_double.def(python::constructor()); - vector_double.def(&std::vector::size, "__len__"); - vector_double.def(getitem, "__getitem__"); - vector_double.def(setitem, "__setitem__"); - vector_double.def(delitem, "__delitem__"); - vector_double.def(as_tuple, "as_tuple"); - - this_module.def(foo, "foo"); - this_module.def(bar, "bar"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} From 22024e7c1f8b7f8d2b92ad9ea0f2ce9307451e94 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 18 Apr 2001 01:24:34 +0000 Subject: [PATCH 097/369] trying to clean cvs attic mess... [SVN r9829] --- example/simple_vector.cpp | 103 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 example/simple_vector.cpp diff --git a/example/simple_vector.cpp b/example/simple_vector.cpp new file mode 100644 index 00000000..5ac0767b --- /dev/null +++ b/example/simple_vector.cpp @@ -0,0 +1,103 @@ +// Example by Ralf W. Grosse-Kunstleve + +#include +namespace python = boost::python; + +namespace { // Avoid cluttering the global namespace. + + // A wrapper is used to define additional constructors. + // + struct vector_double_wrapper: std::vector + { + // Tell the compiler how to convert a base class object to + // this wrapper object. + vector_double_wrapper(PyObject*, const std::vector& vd) + : std::vector(vd) {} + + vector_double_wrapper(PyObject* self) + : std::vector() {} + + vector_double_wrapper(PyObject* self, int n) + : std::vector(n) {} + + vector_double_wrapper(PyObject* self, python::tuple tuple) + : std::vector(tuple.size()) + { + std::vector::iterator vd = begin(); + for (int i = 0; i < tuple.size(); i++) + vd[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), + python::type()); + } + }; + + double getitem(const std::vector& vd, std::size_t key) { + return vd[key]; + } + + void setitem(std::vector& vd, std::size_t key, double d) { + std::vector::iterator vditer = vd.begin(); + vditer[key] = d; + } + + void delitem(std::vector& vd, std::size_t key) { + std::vector::iterator vditer = vd.begin(); + vd.erase(&vditer[key]); + } + + // Convert vector_double to a regular Python tuple. + // + python::tuple as_tuple(const std::vector& vd) + { + python::tuple t(vd.size()); + for (int i = 0; i < vd.size(); i++) t.set_item(i, + python::ref(BOOST_PYTHON_CONVERSION::to_python(vd[i]))); + return t; + } + + // Function returning a vector_double object to Python. + // + std::vector foo(int n) + { + std::vector vd(n); + std::vector::iterator vditer = vd.begin(); + for (int i = 0; i < n; i++) vditer[i] = double(i); + return vd; + } + + // Same as foo(), but avoid copying on return. + // + std::auto_ptr > bar(int n) + { + std::auto_ptr > vdptr(new std::vector(n)); + std::vector::iterator vditer = vdptr->begin(); + for (int i = 0; i < n; i++) vditer[i] = double(10 * i); + return vdptr; + } +} + +BOOST_PYTHON_MODULE_INIT(simple_vector) +{ + try + { + python::module_builder this_module("simple_vector"); + + python::class_builder, vector_double_wrapper> + vector_double(this_module, "vector_double"); + + vector_double.def(python::constructor<>()); + vector_double.def(python::constructor()); + vector_double.def(python::constructor()); + vector_double.def(&std::vector::size, "__len__"); + vector_double.def(getitem, "__getitem__"); + vector_double.def(setitem, "__setitem__"); + vector_double.def(delitem, "__delitem__"); + vector_double.def(as_tuple, "as_tuple"); + + this_module.def(foo, "foo"); + this_module.def(bar, "bar"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} From dc462cdc1f1fd22a97a69eda4b2a3cc97bb8bd7a Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 18 Apr 2001 01:27:51 +0000 Subject: [PATCH 098/369] cleaning up cvs attic mess [SVN r9830] --- example/do_it_yourself_converters.cpp | 128 ---------------------- example/dvect.cpp | 45 -------- example/ivect.cpp | 45 -------- example/noncopyable_export.cpp | 25 ----- example/noncopyable_import.cpp | 42 -------- example/pickle1.cpp | 64 ----------- example/pickle2.cpp | 100 ----------------- example/pickle3.cpp | 150 -------------------------- example/tst_dvect1.py | 20 ---- example/tst_ivect1.py | 20 ---- example/tst_noncopyable.py | 16 --- 11 files changed, 655 deletions(-) delete mode 100644 example/do_it_yourself_converters.cpp delete mode 100644 example/dvect.cpp delete mode 100644 example/ivect.cpp delete mode 100644 example/noncopyable_export.cpp delete mode 100644 example/noncopyable_import.cpp delete mode 100644 example/pickle1.cpp delete mode 100644 example/pickle2.cpp delete mode 100644 example/pickle3.cpp delete mode 100644 example/tst_dvect1.py delete mode 100644 example/tst_ivect1.py delete mode 100644 example/tst_noncopyable.py diff --git a/example/do_it_yourself_converters.cpp b/example/do_it_yourself_converters.cpp deleted file mode 100644 index 6d2d2d6a..00000000 --- a/example/do_it_yourself_converters.cpp +++ /dev/null @@ -1,128 +0,0 @@ -// Example by Ralf W. Grosse-Kunstleve -/* - - This example shows how to convert a class from and to native - Python objects, such as tuples. - - We do not want to expose the helper class MillerIndex as an - Extension Class. However, in order to simplify the wrapper code, - we want to define from_python() and to_python() functions for - class MillerIndex. - - Consider the alternatives: - - - Expose MillerIndex as an Extension Class. - We need a constructor MillerIndex(python::tuple). - Python function calls become more complex: - foo(MillerIndex((1,2,3)) instead of foo((1,2,3)) - We need a method such as MillerIndex().as_tuple(). - - - Define a wrapper function for each function that we - want to expose, e.g.: - void add(const IndexingSet& ixset, const python::tuple PyMIx) - - The first alternative introduces a new type that the user has to - deal with. Other modules using Miller indices might organize them in - different ways, for example to increase runtime efficiency for - important procedures. This means, the user has to know how to - convert between the different kinds of Miller index representations. - This can quickly become a nuisance. Relying on native Python data - structures minimizes the number of special types the user has to - learn and convert. Of course, this argument is only valid for - small and relatively simply classes. - - If there are many member functions with MillerIndex arguments, the - second alternative is impractical, and concentrating the conversion - mechanism in one central place is essential for code - maintainability. An added benefit is that more convenient (smarter) - conversion functions can be provided without cluttering the rest of - the wrapper code. - - */ - -#include -#include -#include -namespace python = boost::python; - -namespace { // Avoid cluttering the global namespace. - - // The helper class. - // - class MillerIndex { - public: - int v[3]; - }; - - // The main class. Imagine that there are MANY member functions - // like add() and get(). - // - class IndexingSet { - private: - std::vector VMIx; - public: - void add(const MillerIndex& MIx) { VMIx.push_back(MIx); } - MillerIndex get(std::size_t i) const { return VMIx[i]; } - }; -} - -BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE - - // Convert a Python tuple to a MillerIndex object. - // - MillerIndex from_python(PyObject* p, python::type) - { - python::tuple tup - = python::tuple(python::ref(p, python::ref::increment_count)); - if (tup.size() != 3) { - PyErr_SetString(PyExc_ValueError, - "expecting exactly 3 values in tuple."); - throw python::error_already_set(); - } - MillerIndex result; - for (int i = 0; i < 3; i++) - result.v[i] = from_python(tup[i].get(), python::type()); - return result; - } - - // Similar conversion for MillerIndex objects passed by value. - // Not actually used, but included to show the principle. - // - MillerIndex from_python(PyObject* p, python::type) - { - return from_python(p, python::type()); - } - - // Convert a MillerIndex object to a Python tuple. - // - PyObject* to_python(const MillerIndex& hkl) - { - python::tuple result(3); - for (int i = 0; i < 3; i++) - result.set_item(i, python::ref(to_python(hkl.v[i]))); - return result.reference().release(); - } - -BOOST_PYTHON_END_CONVERSION_NAMESPACE - -BOOST_PYTHON_MODULE_INIT(do_it_yourself_converters) -{ - try - { - // Create an object representing this extension module. - python::module_builder this_module("do_it_yourself_converters"); - - // Create the Python type object for our extension class. - python::class_builder ixset_class(this_module, "IndexingSet"); - - // Add the __init__ function. - ixset_class.def(python::constructor<>()); - // Add the member functions. - ixset_class.def(&IndexingSet::add, "add"); - ixset_class.def(&IndexingSet::get, "get"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/dvect.cpp b/example/dvect.cpp deleted file mode 100644 index da6b35a3..00000000 --- a/example/dvect.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// Example by Ralf W. Grosse-Kunstleve -// See root/libs/python/doc/cross_module.html for an introduction. - -#include "dvect.h" -#include "ivect.h" -#include -namespace python = boost::python; - -namespace { - -# include "dvect_conversions.cpp" -# include "ivect_conversions.cpp" - - vects::ivect dvect_as_ivect(const vects::dvect& dv) - { - vects::ivect iv(dv.size()); - vects::ivect::iterator iviter = iv.begin(); - for (int i = 0; i < dv.size(); i++) iviter[i] = static_cast(dv[i]); - return iv; - } -} - -BOOST_PYTHON_MODULE_INIT(dvect) -{ - try - { - python::module_builder this_module("dvect"); - - python::class_builder dvect_class(this_module, "dvect"); - python::export_converters(dvect_class); - - python::import_converters ivect_converters("ivect", "ivect"); - - dvect_class.def(python::constructor()); - dvect_class.def(&vects::dvect::as_tuple, "as_tuple"); - dvect_class.def(dvect_as_ivect, "as_ivect"); - -# include "dvect_defs.cpp" -# include "ivect_defs.cpp" - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/ivect.cpp b/example/ivect.cpp deleted file mode 100644 index db1c0ec3..00000000 --- a/example/ivect.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// Example by Ralf W. Grosse-Kunstleve -// See root/libs/python/doc/cross_module.html for an introduction. - -#include "dvect.h" -#include "ivect.h" -#include -namespace python = boost::python; - -namespace { - -# include "dvect_conversions.cpp" -# include "ivect_conversions.cpp" - - vects::dvect ivect_as_dvect(const vects::ivect& iv) - { - vects::dvect dv(iv.size()); - vects::dvect::iterator dviter = dv.begin(); - for (int i = 0; i < iv.size(); i++) dviter[i] = static_cast(iv[i]); - return dv; - } -} - -BOOST_PYTHON_MODULE_INIT(ivect) -{ - try - { - python::module_builder this_module("ivect"); - - python::class_builder ivect_class(this_module, "ivect"); - python::export_converters(ivect_class); - - python::import_converters dvect_converters("dvect", "dvect"); - - ivect_class.def(python::constructor()); - ivect_class.def(&vects::ivect::as_tuple, "as_tuple"); - ivect_class.def(ivect_as_dvect, "as_dvect"); - -# include "dvect_defs.cpp" -# include "ivect_defs.cpp" - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/noncopyable_export.cpp b/example/noncopyable_export.cpp deleted file mode 100644 index 794b1200..00000000 --- a/example/noncopyable_export.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// Example by Ralf W. Grosse-Kunstleve -// See root/libs/python/doc/cross_module.html for an introduction. - -#include -namespace python = boost::python; - -#include "noncopyable.h" - -BOOST_PYTHON_MODULE_INIT(noncopyable_export) -{ - try - { - python::module_builder this_module("noncopyable_export"); - - python::class_builder store_class(this_module, "store"); - python::export_converters_noncopyable(store_class); - - store_class.def(python::constructor()); - store_class.def(&store::recall, "recall"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/noncopyable_import.cpp b/example/noncopyable_import.cpp deleted file mode 100644 index ea2477be..00000000 --- a/example/noncopyable_import.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// Example by Ralf W. Grosse-Kunstleve -// See root/libs/python/doc/cross_module.html for an introduction. - -#include -namespace python = boost::python; - -#include "noncopyable.h" - -namespace { // Avoid cluttering the global namespace. - - // A function with store objects as both input and output parameters. - // Because the copy constructor is disabled, we cannot pass a store - // object by value. Instead, we pass a smart pointer. - std::auto_ptr add_stores(const store& s1, const store& s2) - { - int sum = s1.recall() + s2.recall(); - std::auto_ptr ss = std::auto_ptr(new store(sum)); - return ss; - } -} - -BOOST_PYTHON_MODULE_INIT(noncopyable_import) -{ - try - { - python::module_builder this_module("noncopyable_import"); - - python::import_converters - dvect_converters("noncopyable_export", "store"); - - // Imagine all the additional classes with member functions - // that have store objects as input and output parameters. - // Lots and lots of them. - // However, to keep this example simple, we only define a - // module-level function. - this_module.def(add_stores, "add_stores"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/pickle1.cpp b/example/pickle1.cpp deleted file mode 100644 index cdd78989..00000000 --- a/example/pickle1.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// Example by Ralf W. Grosse-Kunstleve - -/* - This example shows how to make an Extension Class "pickleable". - - The world class below can be fully restored by passing the - appropriate argument to the constructor. Therefore it is sufficient - to define the pickle interface method __getinitargs__. - - For more information refer to boost/libs/python/doc/pickle.html. - */ - -#include - -#include -namespace python = boost::python; - -namespace { // Avoid cluttering the global namespace. - - // A friendly class. - class world - { - private: - std::string country; - int secret_number; - public: - world(const std::string& country) : secret_number(0) { - this->country = country; - } - std::string greet() const { return "Hello from " + country + "!"; } - std::string get_country() const { return country; } - }; - - // Support for pickle. - python::ref world_getinitargs(const world& w) { - python::tuple result(1); - result.set_item(0, w.get_country()); - return result.reference(); - } -} - -BOOST_PYTHON_MODULE_INIT(pickle1) -{ - try - { - // Create an object representing this extension module. - python::module_builder this_module("pickle1"); - - // Create the Python type object for our extension class. - python::class_builder world_class(this_module, "world"); - - // Add the __init__ function. - world_class.def(python::constructor()); - // Add a regular member function. - world_class.def(&world::greet, "greet"); - - // Support for pickle. - world_class.def(world_getinitargs, "__getinitargs__"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/pickle2.cpp b/example/pickle2.cpp deleted file mode 100644 index d6aa3201..00000000 --- a/example/pickle2.cpp +++ /dev/null @@ -1,100 +0,0 @@ -// Example by Ralf W. Grosse-Kunstleve - -/* - This example shows how to make an Extension Class "pickleable". - - The world class below contains member data (secret_number) that - cannot be restored by any of the constructors. Therefore it is - necessary to provide the __getstate__/__setstate__ pair of pickle - interface methods. - - For simplicity, the __dict__ is not included in the result of - __getstate__. This is not generally recommended, but a valid - approach if it is anticipated that the object's __dict__ will - always be empty. Note that safety guard are provided to catch the - cases where this assumption is not true. - - pickle3.cpp shows how to include the object's __dict__ in the - result of __getstate__. - - For more information refer to boost/libs/python/doc/pickle.html. - */ - -#include - -#include -namespace python = boost::python; - -namespace { // Avoid cluttering the global namespace. - - // A friendly class. - class world - { - public: - world(const std::string& country) : secret_number(0) { - this->country = country; - } - std::string greet() const { return "Hello from " + country + "!"; } - std::string get_country() const { return country; } - void set_secret_number(int number) { secret_number = number; } - int get_secret_number() const { return secret_number; } - private: - std::string country; - int secret_number; - }; - - // Support for pickle. - - using BOOST_PYTHON_CONVERSION::from_python; - - python::ref world_getinitargs(const world& w) { - python::tuple result(1); - result.set_item(0, w.get_country()); - return result.reference(); // returning the reference avoids the copying. - } - - python::ref world_getstate(const world& w) { - python::tuple result(1); - result.set_item(0, w.get_secret_number()); - return result.reference(); // returning the reference avoids the copying. - } - - void world_setstate(world& w, python::tuple state) { - if (state.size() != 1) { - PyErr_SetString(PyExc_ValueError, - "Unexpected argument in call to __setstate__."); - throw python::error_already_set(); - } - int number = from_python(state[0].get(), python::type()); - if (number != 42) - w.set_secret_number(number); - } -} - -BOOST_PYTHON_MODULE_INIT(pickle2) -{ - try - { - // Create an object representing this extension module. - python::module_builder this_module("pickle2"); - - // Create the Python type object for our extension class. - python::class_builder world_class(this_module, "world"); - - // Add the __init__ function. - world_class.def(python::constructor()); - // Add a regular member function. - world_class.def(&world::greet, "greet"); - world_class.def(&world::get_secret_number, "get_secret_number"); - world_class.def(&world::set_secret_number, "set_secret_number"); - - // Support for pickle. - world_class.def(world_getinitargs, "__getinitargs__"); - world_class.def(world_getstate, "__getstate__"); - world_class.def(world_setstate, "__setstate__"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/pickle3.cpp b/example/pickle3.cpp deleted file mode 100644 index bfa7dc54..00000000 --- a/example/pickle3.cpp +++ /dev/null @@ -1,150 +0,0 @@ -// Example by Ralf W. Grosse-Kunstleve - -/* - This example shows how to make an Extension Class "pickleable". - - The world class below contains member data (secret_number) that - cannot be restored by any of the constructors. Therefore it is - necessary to provide the __getstate__/__setstate__ pair of pickle - interface methods. - - The object's __dict__ is included in the result of __getstate__. - This requires more code (compare with pickle2.cpp), but is - unavoidable if the object's __dict__ is not always empty. - - For more information refer to boost/libs/python/doc/pickle.html. - */ - -#include - -#include -namespace python = boost::python; - -namespace boost { namespace python { - - ref getattr(PyObject* o, const std::string& attr_name) { - return ref(PyObject_GetAttrString(o, const_cast(attr_name.c_str()))); - } - ref getattr(const ref& r, const std::string& attr_name) { - return getattr(r.get(), attr_name); - } - -}} - -namespace { // Avoid cluttering the global namespace. - - // A friendly class. - class world - { - public: - world(const std::string& country) : secret_number(0) { - this->country = country; - } - std::string greet() const { return "Hello from " + country + "!"; } - std::string get_country() const { return country; } - void set_secret_number(int number) { secret_number = number; } - int get_secret_number() const { return secret_number; } - private: - std::string country; - int secret_number; - }; - - // Support for pickle. - python::ref world_getinitargs(const world& w) { - python::tuple result(1); - result.set_item(0, w.get_country()); - return result.reference(); // returning the reference avoids the copying. - } - - python::ref world_getstate(python::tuple const & args, - python::dictionary const & keywords); - - PyObject* world_setstate(python::tuple const & args, - python::dictionary const & keywords); -} - -BOOST_PYTHON_MODULE_INIT(pickle3) -{ - try - { - // Create an object representing this extension module. - python::module_builder this_module("pickle3"); - - // Create the Python type object for our extension class. - python::class_builder world_class(this_module, "world"); - - // Add the __init__ function. - world_class.def(python::constructor()); - // Add a regular member function. - world_class.def(&world::greet, "greet"); - world_class.def(&world::get_secret_number, "get_secret_number"); - world_class.def(&world::set_secret_number, "set_secret_number"); - - // Support for pickle. - world_class.def(world_getinitargs, "__getinitargs__"); - world_class.def_raw(world_getstate, "__getstate__"); - world_class.def_raw(world_setstate, "__setstate__"); - world_class.getstate_manages_dict(); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} - -namespace { - - using BOOST_PYTHON_CONVERSION::from_python; - using boost::python::type; - using boost::python::ref; - using boost::python::tuple; - using boost::python::list; - using boost::python::dictionary; - using boost::python::getattr; - - ref world_getstate(tuple const & args, dictionary const & keywords) - { - if(args.size() != 1 || keywords.size() != 0) { - PyErr_SetString(PyExc_TypeError, "wrong number of arguments"); - throw boost::python::argument_error(); - } - const world& w = from_python(args[0].get(), type()); - ref mydict = getattr(args[0], "__dict__"); - tuple result(2); - // store the object's __dict__ - result.set_item(0, mydict); - // store the internal state of the C++ object - result.set_item(1, w.get_secret_number()); - return result.reference(); // returning the reference avoids the copying. - } - - PyObject* world_setstate(tuple const & args, dictionary const & keywords) - { - if(args.size() != 2 || keywords.size() != 0) { - PyErr_SetString(PyExc_TypeError, "wrong number of arguments"); - throw boost::python::argument_error(); - } - world& w = from_python(args[0].get(), type()); - ref mydict = getattr(args[0], "__dict__"); - tuple state = from_python(args[1].get(), type()); - if (state.size() != 2) { - PyErr_SetString(PyExc_ValueError, - "Unexpected argument in call to __setstate__."); - throw python::error_already_set(); - } - // restore the object's __dict__ - dictionary odict = from_python(mydict.get(), type()); - const dictionary& pdict = from_python(state[0].get(), type()); - list pkeys(pdict.keys()); - for (int i = 0; i < pkeys.size(); i++) { - ref k(pkeys[i]); - //odict[k] = pdict[k]; // XXX memory leak! - odict[k] = pdict.get_item(k); // this does not leak. - } - // restore the internal state of the C++ object - int number = from_python(state[1].get(), type()); - if (number != 42) - w.set_secret_number(number); - return python::detail::none(); - } -} diff --git a/example/tst_dvect1.py b/example/tst_dvect1.py deleted file mode 100644 index 22315528..00000000 --- a/example/tst_dvect1.py +++ /dev/null @@ -1,20 +0,0 @@ -def f(): - import dvect - dv = dvect.dvect((1,2,3,4,5)) - print dv.as_tuple() - iv = dv.as_ivect() - print iv.as_tuple() - print dvect.const_ivect_reference_as_tuple(iv) - aiv = dvect.ivect_as_auto_ptr(iv) - print dvect.const_ivect_reference_as_tuple(aiv) - siv = dvect.ivect_as_shared_ptr(iv) - print dvect.const_ivect_reference_as_tuple(siv) - print aiv.as_tuple() - print siv.as_tuple() - -if (__name__ == "__main__"): - import sys, string - n = 1 - if (len(sys.argv) > 1): n = string.atoi(sys.argv[1]) - for i in xrange(n): - f() diff --git a/example/tst_ivect1.py b/example/tst_ivect1.py deleted file mode 100644 index 7369fdbf..00000000 --- a/example/tst_ivect1.py +++ /dev/null @@ -1,20 +0,0 @@ -def f(): - import ivect - iv = ivect.ivect((1,2,3,4,5)) - print iv.as_tuple() - dv = iv.as_dvect() - print dv.as_tuple() - print ivect.const_dvect_reference_as_tuple(dv) - adv = ivect.dvect_as_auto_ptr(dv) - print ivect.const_dvect_reference_as_tuple(adv) - sdv = ivect.dvect_as_shared_ptr(dv) - print ivect.const_dvect_reference_as_tuple(sdv) - print adv.as_tuple() - print sdv.as_tuple() - -if (__name__ == "__main__"): - import sys, string - n = 1 - if (len(sys.argv) > 1): n = string.atoi(sys.argv[1]) - for i in xrange(n): - f() diff --git a/example/tst_noncopyable.py b/example/tst_noncopyable.py deleted file mode 100644 index 155910a5..00000000 --- a/example/tst_noncopyable.py +++ /dev/null @@ -1,16 +0,0 @@ -def f(): - import noncopyable_export - import noncopyable_import - s1 = noncopyable_export.store(1) - print s1.recall() - s2 = noncopyable_export.store(2) - print s2.recall() - s3 = noncopyable_import.add_stores(s1, s2) - print s3.recall() - -if (__name__ == "__main__"): - import sys, string - n = 1 - if (len(sys.argv) > 1): n = string.atoi(sys.argv[1]) - for i in xrange(n): - f() From cbff11296bcbf7c486019db142cc9ba46560b20a Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 18 Apr 2001 01:29:23 +0000 Subject: [PATCH 099/369] cleaning up cvs attic mess [SVN r9831] --- example/do_it_yourself_converters.cpp | 128 ++++++++++++++++++++++ example/dvect.cpp | 45 ++++++++ example/ivect.cpp | 45 ++++++++ example/noncopyable_export.cpp | 25 +++++ example/noncopyable_import.cpp | 42 ++++++++ example/pickle1.cpp | 64 +++++++++++ example/pickle2.cpp | 100 +++++++++++++++++ example/pickle3.cpp | 150 ++++++++++++++++++++++++++ example/tst_dvect1.py | 20 ++++ example/tst_ivect1.py | 20 ++++ example/tst_noncopyable.py | 16 +++ 11 files changed, 655 insertions(+) create mode 100644 example/do_it_yourself_converters.cpp create mode 100644 example/dvect.cpp create mode 100644 example/ivect.cpp create mode 100644 example/noncopyable_export.cpp create mode 100644 example/noncopyable_import.cpp create mode 100644 example/pickle1.cpp create mode 100644 example/pickle2.cpp create mode 100644 example/pickle3.cpp create mode 100644 example/tst_dvect1.py create mode 100644 example/tst_ivect1.py create mode 100644 example/tst_noncopyable.py diff --git a/example/do_it_yourself_converters.cpp b/example/do_it_yourself_converters.cpp new file mode 100644 index 00000000..6d2d2d6a --- /dev/null +++ b/example/do_it_yourself_converters.cpp @@ -0,0 +1,128 @@ +// Example by Ralf W. Grosse-Kunstleve +/* + + This example shows how to convert a class from and to native + Python objects, such as tuples. + + We do not want to expose the helper class MillerIndex as an + Extension Class. However, in order to simplify the wrapper code, + we want to define from_python() and to_python() functions for + class MillerIndex. + + Consider the alternatives: + + - Expose MillerIndex as an Extension Class. + We need a constructor MillerIndex(python::tuple). + Python function calls become more complex: + foo(MillerIndex((1,2,3)) instead of foo((1,2,3)) + We need a method such as MillerIndex().as_tuple(). + + - Define a wrapper function for each function that we + want to expose, e.g.: + void add(const IndexingSet& ixset, const python::tuple PyMIx) + + The first alternative introduces a new type that the user has to + deal with. Other modules using Miller indices might organize them in + different ways, for example to increase runtime efficiency for + important procedures. This means, the user has to know how to + convert between the different kinds of Miller index representations. + This can quickly become a nuisance. Relying on native Python data + structures minimizes the number of special types the user has to + learn and convert. Of course, this argument is only valid for + small and relatively simply classes. + + If there are many member functions with MillerIndex arguments, the + second alternative is impractical, and concentrating the conversion + mechanism in one central place is essential for code + maintainability. An added benefit is that more convenient (smarter) + conversion functions can be provided without cluttering the rest of + the wrapper code. + + */ + +#include +#include +#include +namespace python = boost::python; + +namespace { // Avoid cluttering the global namespace. + + // The helper class. + // + class MillerIndex { + public: + int v[3]; + }; + + // The main class. Imagine that there are MANY member functions + // like add() and get(). + // + class IndexingSet { + private: + std::vector VMIx; + public: + void add(const MillerIndex& MIx) { VMIx.push_back(MIx); } + MillerIndex get(std::size_t i) const { return VMIx[i]; } + }; +} + +BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE + + // Convert a Python tuple to a MillerIndex object. + // + MillerIndex from_python(PyObject* p, python::type) + { + python::tuple tup + = python::tuple(python::ref(p, python::ref::increment_count)); + if (tup.size() != 3) { + PyErr_SetString(PyExc_ValueError, + "expecting exactly 3 values in tuple."); + throw python::error_already_set(); + } + MillerIndex result; + for (int i = 0; i < 3; i++) + result.v[i] = from_python(tup[i].get(), python::type()); + return result; + } + + // Similar conversion for MillerIndex objects passed by value. + // Not actually used, but included to show the principle. + // + MillerIndex from_python(PyObject* p, python::type) + { + return from_python(p, python::type()); + } + + // Convert a MillerIndex object to a Python tuple. + // + PyObject* to_python(const MillerIndex& hkl) + { + python::tuple result(3); + for (int i = 0; i < 3; i++) + result.set_item(i, python::ref(to_python(hkl.v[i]))); + return result.reference().release(); + } + +BOOST_PYTHON_END_CONVERSION_NAMESPACE + +BOOST_PYTHON_MODULE_INIT(do_it_yourself_converters) +{ + try + { + // Create an object representing this extension module. + python::module_builder this_module("do_it_yourself_converters"); + + // Create the Python type object for our extension class. + python::class_builder ixset_class(this_module, "IndexingSet"); + + // Add the __init__ function. + ixset_class.def(python::constructor<>()); + // Add the member functions. + ixset_class.def(&IndexingSet::add, "add"); + ixset_class.def(&IndexingSet::get, "get"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/dvect.cpp b/example/dvect.cpp new file mode 100644 index 00000000..da6b35a3 --- /dev/null +++ b/example/dvect.cpp @@ -0,0 +1,45 @@ +// Example by Ralf W. Grosse-Kunstleve +// See root/libs/python/doc/cross_module.html for an introduction. + +#include "dvect.h" +#include "ivect.h" +#include +namespace python = boost::python; + +namespace { + +# include "dvect_conversions.cpp" +# include "ivect_conversions.cpp" + + vects::ivect dvect_as_ivect(const vects::dvect& dv) + { + vects::ivect iv(dv.size()); + vects::ivect::iterator iviter = iv.begin(); + for (int i = 0; i < dv.size(); i++) iviter[i] = static_cast(dv[i]); + return iv; + } +} + +BOOST_PYTHON_MODULE_INIT(dvect) +{ + try + { + python::module_builder this_module("dvect"); + + python::class_builder dvect_class(this_module, "dvect"); + python::export_converters(dvect_class); + + python::import_converters ivect_converters("ivect", "ivect"); + + dvect_class.def(python::constructor()); + dvect_class.def(&vects::dvect::as_tuple, "as_tuple"); + dvect_class.def(dvect_as_ivect, "as_ivect"); + +# include "dvect_defs.cpp" +# include "ivect_defs.cpp" + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/ivect.cpp b/example/ivect.cpp new file mode 100644 index 00000000..db1c0ec3 --- /dev/null +++ b/example/ivect.cpp @@ -0,0 +1,45 @@ +// Example by Ralf W. Grosse-Kunstleve +// See root/libs/python/doc/cross_module.html for an introduction. + +#include "dvect.h" +#include "ivect.h" +#include +namespace python = boost::python; + +namespace { + +# include "dvect_conversions.cpp" +# include "ivect_conversions.cpp" + + vects::dvect ivect_as_dvect(const vects::ivect& iv) + { + vects::dvect dv(iv.size()); + vects::dvect::iterator dviter = dv.begin(); + for (int i = 0; i < iv.size(); i++) dviter[i] = static_cast(iv[i]); + return dv; + } +} + +BOOST_PYTHON_MODULE_INIT(ivect) +{ + try + { + python::module_builder this_module("ivect"); + + python::class_builder ivect_class(this_module, "ivect"); + python::export_converters(ivect_class); + + python::import_converters dvect_converters("dvect", "dvect"); + + ivect_class.def(python::constructor()); + ivect_class.def(&vects::ivect::as_tuple, "as_tuple"); + ivect_class.def(ivect_as_dvect, "as_dvect"); + +# include "dvect_defs.cpp" +# include "ivect_defs.cpp" + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/noncopyable_export.cpp b/example/noncopyable_export.cpp new file mode 100644 index 00000000..794b1200 --- /dev/null +++ b/example/noncopyable_export.cpp @@ -0,0 +1,25 @@ +// Example by Ralf W. Grosse-Kunstleve +// See root/libs/python/doc/cross_module.html for an introduction. + +#include +namespace python = boost::python; + +#include "noncopyable.h" + +BOOST_PYTHON_MODULE_INIT(noncopyable_export) +{ + try + { + python::module_builder this_module("noncopyable_export"); + + python::class_builder store_class(this_module, "store"); + python::export_converters_noncopyable(store_class); + + store_class.def(python::constructor()); + store_class.def(&store::recall, "recall"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/noncopyable_import.cpp b/example/noncopyable_import.cpp new file mode 100644 index 00000000..ea2477be --- /dev/null +++ b/example/noncopyable_import.cpp @@ -0,0 +1,42 @@ +// Example by Ralf W. Grosse-Kunstleve +// See root/libs/python/doc/cross_module.html for an introduction. + +#include +namespace python = boost::python; + +#include "noncopyable.h" + +namespace { // Avoid cluttering the global namespace. + + // A function with store objects as both input and output parameters. + // Because the copy constructor is disabled, we cannot pass a store + // object by value. Instead, we pass a smart pointer. + std::auto_ptr add_stores(const store& s1, const store& s2) + { + int sum = s1.recall() + s2.recall(); + std::auto_ptr ss = std::auto_ptr(new store(sum)); + return ss; + } +} + +BOOST_PYTHON_MODULE_INIT(noncopyable_import) +{ + try + { + python::module_builder this_module("noncopyable_import"); + + python::import_converters + dvect_converters("noncopyable_export", "store"); + + // Imagine all the additional classes with member functions + // that have store objects as input and output parameters. + // Lots and lots of them. + // However, to keep this example simple, we only define a + // module-level function. + this_module.def(add_stores, "add_stores"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/pickle1.cpp b/example/pickle1.cpp new file mode 100644 index 00000000..cdd78989 --- /dev/null +++ b/example/pickle1.cpp @@ -0,0 +1,64 @@ +// Example by Ralf W. Grosse-Kunstleve + +/* + This example shows how to make an Extension Class "pickleable". + + The world class below can be fully restored by passing the + appropriate argument to the constructor. Therefore it is sufficient + to define the pickle interface method __getinitargs__. + + For more information refer to boost/libs/python/doc/pickle.html. + */ + +#include + +#include +namespace python = boost::python; + +namespace { // Avoid cluttering the global namespace. + + // A friendly class. + class world + { + private: + std::string country; + int secret_number; + public: + world(const std::string& country) : secret_number(0) { + this->country = country; + } + std::string greet() const { return "Hello from " + country + "!"; } + std::string get_country() const { return country; } + }; + + // Support for pickle. + python::ref world_getinitargs(const world& w) { + python::tuple result(1); + result.set_item(0, w.get_country()); + return result.reference(); + } +} + +BOOST_PYTHON_MODULE_INIT(pickle1) +{ + try + { + // Create an object representing this extension module. + python::module_builder this_module("pickle1"); + + // Create the Python type object for our extension class. + python::class_builder world_class(this_module, "world"); + + // Add the __init__ function. + world_class.def(python::constructor()); + // Add a regular member function. + world_class.def(&world::greet, "greet"); + + // Support for pickle. + world_class.def(world_getinitargs, "__getinitargs__"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/pickle2.cpp b/example/pickle2.cpp new file mode 100644 index 00000000..d6aa3201 --- /dev/null +++ b/example/pickle2.cpp @@ -0,0 +1,100 @@ +// Example by Ralf W. Grosse-Kunstleve + +/* + This example shows how to make an Extension Class "pickleable". + + The world class below contains member data (secret_number) that + cannot be restored by any of the constructors. Therefore it is + necessary to provide the __getstate__/__setstate__ pair of pickle + interface methods. + + For simplicity, the __dict__ is not included in the result of + __getstate__. This is not generally recommended, but a valid + approach if it is anticipated that the object's __dict__ will + always be empty. Note that safety guard are provided to catch the + cases where this assumption is not true. + + pickle3.cpp shows how to include the object's __dict__ in the + result of __getstate__. + + For more information refer to boost/libs/python/doc/pickle.html. + */ + +#include + +#include +namespace python = boost::python; + +namespace { // Avoid cluttering the global namespace. + + // A friendly class. + class world + { + public: + world(const std::string& country) : secret_number(0) { + this->country = country; + } + std::string greet() const { return "Hello from " + country + "!"; } + std::string get_country() const { return country; } + void set_secret_number(int number) { secret_number = number; } + int get_secret_number() const { return secret_number; } + private: + std::string country; + int secret_number; + }; + + // Support for pickle. + + using BOOST_PYTHON_CONVERSION::from_python; + + python::ref world_getinitargs(const world& w) { + python::tuple result(1); + result.set_item(0, w.get_country()); + return result.reference(); // returning the reference avoids the copying. + } + + python::ref world_getstate(const world& w) { + python::tuple result(1); + result.set_item(0, w.get_secret_number()); + return result.reference(); // returning the reference avoids the copying. + } + + void world_setstate(world& w, python::tuple state) { + if (state.size() != 1) { + PyErr_SetString(PyExc_ValueError, + "Unexpected argument in call to __setstate__."); + throw python::error_already_set(); + } + int number = from_python(state[0].get(), python::type()); + if (number != 42) + w.set_secret_number(number); + } +} + +BOOST_PYTHON_MODULE_INIT(pickle2) +{ + try + { + // Create an object representing this extension module. + python::module_builder this_module("pickle2"); + + // Create the Python type object for our extension class. + python::class_builder world_class(this_module, "world"); + + // Add the __init__ function. + world_class.def(python::constructor()); + // Add a regular member function. + world_class.def(&world::greet, "greet"); + world_class.def(&world::get_secret_number, "get_secret_number"); + world_class.def(&world::set_secret_number, "set_secret_number"); + + // Support for pickle. + world_class.def(world_getinitargs, "__getinitargs__"); + world_class.def(world_getstate, "__getstate__"); + world_class.def(world_setstate, "__setstate__"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/pickle3.cpp b/example/pickle3.cpp new file mode 100644 index 00000000..bfa7dc54 --- /dev/null +++ b/example/pickle3.cpp @@ -0,0 +1,150 @@ +// Example by Ralf W. Grosse-Kunstleve + +/* + This example shows how to make an Extension Class "pickleable". + + The world class below contains member data (secret_number) that + cannot be restored by any of the constructors. Therefore it is + necessary to provide the __getstate__/__setstate__ pair of pickle + interface methods. + + The object's __dict__ is included in the result of __getstate__. + This requires more code (compare with pickle2.cpp), but is + unavoidable if the object's __dict__ is not always empty. + + For more information refer to boost/libs/python/doc/pickle.html. + */ + +#include + +#include +namespace python = boost::python; + +namespace boost { namespace python { + + ref getattr(PyObject* o, const std::string& attr_name) { + return ref(PyObject_GetAttrString(o, const_cast(attr_name.c_str()))); + } + ref getattr(const ref& r, const std::string& attr_name) { + return getattr(r.get(), attr_name); + } + +}} + +namespace { // Avoid cluttering the global namespace. + + // A friendly class. + class world + { + public: + world(const std::string& country) : secret_number(0) { + this->country = country; + } + std::string greet() const { return "Hello from " + country + "!"; } + std::string get_country() const { return country; } + void set_secret_number(int number) { secret_number = number; } + int get_secret_number() const { return secret_number; } + private: + std::string country; + int secret_number; + }; + + // Support for pickle. + python::ref world_getinitargs(const world& w) { + python::tuple result(1); + result.set_item(0, w.get_country()); + return result.reference(); // returning the reference avoids the copying. + } + + python::ref world_getstate(python::tuple const & args, + python::dictionary const & keywords); + + PyObject* world_setstate(python::tuple const & args, + python::dictionary const & keywords); +} + +BOOST_PYTHON_MODULE_INIT(pickle3) +{ + try + { + // Create an object representing this extension module. + python::module_builder this_module("pickle3"); + + // Create the Python type object for our extension class. + python::class_builder world_class(this_module, "world"); + + // Add the __init__ function. + world_class.def(python::constructor()); + // Add a regular member function. + world_class.def(&world::greet, "greet"); + world_class.def(&world::get_secret_number, "get_secret_number"); + world_class.def(&world::set_secret_number, "set_secret_number"); + + // Support for pickle. + world_class.def(world_getinitargs, "__getinitargs__"); + world_class.def_raw(world_getstate, "__getstate__"); + world_class.def_raw(world_setstate, "__setstate__"); + world_class.getstate_manages_dict(); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} + +namespace { + + using BOOST_PYTHON_CONVERSION::from_python; + using boost::python::type; + using boost::python::ref; + using boost::python::tuple; + using boost::python::list; + using boost::python::dictionary; + using boost::python::getattr; + + ref world_getstate(tuple const & args, dictionary const & keywords) + { + if(args.size() != 1 || keywords.size() != 0) { + PyErr_SetString(PyExc_TypeError, "wrong number of arguments"); + throw boost::python::argument_error(); + } + const world& w = from_python(args[0].get(), type()); + ref mydict = getattr(args[0], "__dict__"); + tuple result(2); + // store the object's __dict__ + result.set_item(0, mydict); + // store the internal state of the C++ object + result.set_item(1, w.get_secret_number()); + return result.reference(); // returning the reference avoids the copying. + } + + PyObject* world_setstate(tuple const & args, dictionary const & keywords) + { + if(args.size() != 2 || keywords.size() != 0) { + PyErr_SetString(PyExc_TypeError, "wrong number of arguments"); + throw boost::python::argument_error(); + } + world& w = from_python(args[0].get(), type()); + ref mydict = getattr(args[0], "__dict__"); + tuple state = from_python(args[1].get(), type()); + if (state.size() != 2) { + PyErr_SetString(PyExc_ValueError, + "Unexpected argument in call to __setstate__."); + throw python::error_already_set(); + } + // restore the object's __dict__ + dictionary odict = from_python(mydict.get(), type()); + const dictionary& pdict = from_python(state[0].get(), type()); + list pkeys(pdict.keys()); + for (int i = 0; i < pkeys.size(); i++) { + ref k(pkeys[i]); + //odict[k] = pdict[k]; // XXX memory leak! + odict[k] = pdict.get_item(k); // this does not leak. + } + // restore the internal state of the C++ object + int number = from_python(state[1].get(), type()); + if (number != 42) + w.set_secret_number(number); + return python::detail::none(); + } +} diff --git a/example/tst_dvect1.py b/example/tst_dvect1.py new file mode 100644 index 00000000..22315528 --- /dev/null +++ b/example/tst_dvect1.py @@ -0,0 +1,20 @@ +def f(): + import dvect + dv = dvect.dvect((1,2,3,4,5)) + print dv.as_tuple() + iv = dv.as_ivect() + print iv.as_tuple() + print dvect.const_ivect_reference_as_tuple(iv) + aiv = dvect.ivect_as_auto_ptr(iv) + print dvect.const_ivect_reference_as_tuple(aiv) + siv = dvect.ivect_as_shared_ptr(iv) + print dvect.const_ivect_reference_as_tuple(siv) + print aiv.as_tuple() + print siv.as_tuple() + +if (__name__ == "__main__"): + import sys, string + n = 1 + if (len(sys.argv) > 1): n = string.atoi(sys.argv[1]) + for i in xrange(n): + f() diff --git a/example/tst_ivect1.py b/example/tst_ivect1.py new file mode 100644 index 00000000..7369fdbf --- /dev/null +++ b/example/tst_ivect1.py @@ -0,0 +1,20 @@ +def f(): + import ivect + iv = ivect.ivect((1,2,3,4,5)) + print iv.as_tuple() + dv = iv.as_dvect() + print dv.as_tuple() + print ivect.const_dvect_reference_as_tuple(dv) + adv = ivect.dvect_as_auto_ptr(dv) + print ivect.const_dvect_reference_as_tuple(adv) + sdv = ivect.dvect_as_shared_ptr(dv) + print ivect.const_dvect_reference_as_tuple(sdv) + print adv.as_tuple() + print sdv.as_tuple() + +if (__name__ == "__main__"): + import sys, string + n = 1 + if (len(sys.argv) > 1): n = string.atoi(sys.argv[1]) + for i in xrange(n): + f() diff --git a/example/tst_noncopyable.py b/example/tst_noncopyable.py new file mode 100644 index 00000000..155910a5 --- /dev/null +++ b/example/tst_noncopyable.py @@ -0,0 +1,16 @@ +def f(): + import noncopyable_export + import noncopyable_import + s1 = noncopyable_export.store(1) + print s1.recall() + s2 = noncopyable_export.store(2) + print s2.recall() + s3 = noncopyable_import.add_stores(s1, s2) + print s3.recall() + +if (__name__ == "__main__"): + import sys, string + n = 1 + if (len(sys.argv) > 1): n = string.atoi(sys.argv[1]) + for i in xrange(n): + f() From 349b9bb2bf2f5dbc9b2365752b4d516d4ed62147 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 18 Apr 2001 19:13:11 +0000 Subject: [PATCH 100/369] use reserved symbol for detecting sgi [SVN r9835] --- test/comprehensive.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/comprehensive.cpp b/test/comprehensive.cpp index aa2d9886..410bd243 100644 --- a/test/comprehensive.cpp +++ b/test/comprehensive.cpp @@ -15,7 +15,7 @@ #include // for pow() #include -#if defined(sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 +#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 inline double pow(int x, int y) { return pow(static_cast(x), y); } #endif From fb8d9edfdfda1999bffd73c3e3dcb9cd626a039b Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Wed, 25 Apr 2001 00:24:50 +0000 Subject: [PATCH 101/369] Change all eGroups references to YahooGroups [SVN r9979] --- doc/index.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/index.html b/doc/index.html index 5ec32a6b..f636e7a8 100644 --- a/doc/index.html +++ b/doc/index.html @@ -1,6 +1,5 @@ - The Boost Python Library (Boost.Python) @@ -154,7 +153,7 @@ among others.

    Questions should be directed to the boost mailing list. + "http://www.yahoogroups.com/list/boost">the boost mailing list.

    © Copyright David Abrahams 2001. Permission to copy, use, modify, From 00b4f09e8abc953f106663bf316bad837af4ec82 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 5 May 2001 01:06:33 +0000 Subject: [PATCH 102/369] Check indices passed to __getitem__, __setitem__, __delitem__ [SVN r10009] --- build/irix_CC.mak | 2 +- example/simple_vector.cpp | 8 ++++++++ example/test_simple_vector.py | 5 +++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/build/irix_CC.mak b/build/irix_CC.mak index 5894ff51..0436ef8a 100644 --- a/build/irix_CC.mak +++ b/build/irix_CC.mak @@ -24,7 +24,7 @@ PYINC=-I/usr/local/Python-1.5.2/include/python1.5 STLPORTINC=-I$(BOOST)/boost/compatibility/cpp_c_headers STDOPTS= -WARNOPTS=-woff 1001,1234,1682 +WARNOPTS=-woff 1001,1183,1234,1682 OPTOPTS=-g CPP=CC -LANG:std -n32 -mips4 diff --git a/example/simple_vector.cpp b/example/simple_vector.cpp index 5ac0767b..8f30121b 100644 --- a/example/simple_vector.cpp +++ b/example/simple_vector.cpp @@ -30,16 +30,24 @@ namespace { // Avoid cluttering the global namespace. } }; + void raise_vector_IndexError() { + PyErr_SetString(PyExc_IndexError, "IndexError: vector index out of range"); + throw python::error_already_set(); + } + double getitem(const std::vector& vd, std::size_t key) { + if (key < 0 || key >= vd.size()) raise_vector_IndexError(); return vd[key]; } void setitem(std::vector& vd, std::size_t key, double d) { + if (key < 0 || key >= vd.size()) raise_vector_IndexError(); std::vector::iterator vditer = vd.begin(); vditer[key] = d; } void delitem(std::vector& vd, std::size_t key) { + if (key < 0 || key >= vd.size()) raise_vector_IndexError(); std::vector::iterator vditer = vd.begin(); vd.erase(&vditer[key]); } diff --git a/example/test_simple_vector.py b/example/test_simple_vector.py index a19e205b..ca38d715 100644 --- a/example/test_simple_vector.py +++ b/example/test_simple_vector.py @@ -15,6 +15,11 @@ r'''>>> import simple_vector >>> v[1] = 40 >>> print v.as_tuple() (3.0, 40.0, 5.0) + >>> for e in v: + ... print e + 3.0 + 40.0 + 5.0 >>> del v[1] >>> print v.as_tuple() (3.0, 5.0) From 25320cd0e02bb14b058fa51fc2e2bc6e29000435 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 14 May 2001 21:43:34 +0000 Subject: [PATCH 103/369] Removed: unnecessary key < 0 test. [SVN r10113] --- build/irix_CC.mak | 2 +- example/simple_vector.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/irix_CC.mak b/build/irix_CC.mak index 0436ef8a..5894ff51 100644 --- a/build/irix_CC.mak +++ b/build/irix_CC.mak @@ -24,7 +24,7 @@ PYINC=-I/usr/local/Python-1.5.2/include/python1.5 STLPORTINC=-I$(BOOST)/boost/compatibility/cpp_c_headers STDOPTS= -WARNOPTS=-woff 1001,1183,1234,1682 +WARNOPTS=-woff 1001,1234,1682 OPTOPTS=-g CPP=CC -LANG:std -n32 -mips4 diff --git a/example/simple_vector.cpp b/example/simple_vector.cpp index 8f30121b..2b3aa290 100644 --- a/example/simple_vector.cpp +++ b/example/simple_vector.cpp @@ -31,23 +31,23 @@ namespace { // Avoid cluttering the global namespace. }; void raise_vector_IndexError() { - PyErr_SetString(PyExc_IndexError, "IndexError: vector index out of range"); + PyErr_SetString(PyExc_IndexError, "vector index out of range"); throw python::error_already_set(); } double getitem(const std::vector& vd, std::size_t key) { - if (key < 0 || key >= vd.size()) raise_vector_IndexError(); + if (key >= vd.size()) raise_vector_IndexError(); return vd[key]; } void setitem(std::vector& vd, std::size_t key, double d) { - if (key < 0 || key >= vd.size()) raise_vector_IndexError(); + if (key >= vd.size()) raise_vector_IndexError(); std::vector::iterator vditer = vd.begin(); vditer[key] = d; } void delitem(std::vector& vd, std::size_t key) { - if (key < 0 || key >= vd.size()) raise_vector_IndexError(); + if (key >= vd.size()) raise_vector_IndexError(); std::vector::iterator vditer = vd.begin(); vd.erase(&vditer[key]); } From d04f613c419c0b726d6f5d28b5e48d9ee3dff4e4 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 18 May 2001 15:12:30 +0000 Subject: [PATCH 104/369] Fix up internal links [SVN r10122] --- doc/overriding.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/overriding.html b/doc/overriding.html index af458d79..02665be5 100644 --- a/doc/overriding.html +++ b/doc/overriding.html @@ -47,17 +47,17 @@ class hello PyObject* argument. The initial argument should be stored in the self data member described above. -

  • If the class being wrapped is ever returned by +
  • If the class being wrapped is ever returned by value from a wrapped function, be sure you do the same for the T's copy constructor: you'll need a constructor taking arguments (PyObject*, const T&). -
  • An implementation of each virtual function you may +
  • An implementation of each virtual function you may wish to override in Python which uses callback<return-type>::call_method(self, "name", args...) to call the Python override. -
  • For each non-pure virtual function meant to be +
  • For each non-pure virtual function meant to be overridable from Python, a static member function (or a free function) taking a reference or pointer to the T as the first parameter and which forwards any additional parameters neccessary to the default @@ -211,5 +211,5 @@ href="http://cs.calvin.edu/c++/C++Standard-Nov97/basic.html#basic.def.odr">ODR - Updated: Mar 6, 2001 + Updated: Mar 21, 2001 From 188597ecaf2968d6811d0272dc4cbc09e8d77023 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 24 May 2001 08:28:46 +0000 Subject: [PATCH 105/369] fixes tested with vc60, tru64cxx, irixCC, gcc2952 [SVN r10208] --- include/boost/python/callback.hpp | 440 ++++++++++++------------- include/boost/python/caller.hpp | 68 ++-- include/boost/python/detail/config.hpp | 23 +- 3 files changed, 264 insertions(+), 267 deletions(-) diff --git a/include/boost/python/callback.hpp b/include/boost/python/callback.hpp index 7240b5b7..b9e850c6 100644 --- a/include/boost/python/callback.hpp +++ b/include/boost/python/callback.hpp @@ -46,7 +46,7 @@ struct callback template static R call_method(PyObject* self, const char* name, const A1& a1) { - ref p1(to_python(a1)); + ref p1(to_python(search_namespace, a1)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(O)"), p1.get())); @@ -57,7 +57,7 @@ struct callback template static R call(PyObject* self, const A1& a1) { - ref p1(to_python(a1)); + ref p1(to_python(search_namespace, a1)); ref result(PyEval_CallFunction(self, const_cast("(O)"), p1.get())); detail::callback_adjust_refcount(result.get(), type()); @@ -67,8 +67,8 @@ struct callback template static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OO)"), p1.get(), @@ -80,8 +80,8 @@ struct callback template static R call(PyObject* self, const A1& a1, const A2& a2) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); ref result(PyEval_CallFunction(self, const_cast("(OO)"), p1.get(), p2.get())); @@ -92,9 +92,9 @@ struct callback template static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOO)"), p1.get(), @@ -107,9 +107,9 @@ struct callback template static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); ref result(PyEval_CallFunction(self, const_cast("(OOO)"), p1.get(), p2.get(), @@ -121,10 +121,10 @@ struct callback template static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOO)"), p1.get(), @@ -138,10 +138,10 @@ struct callback template static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); ref result(PyEval_CallFunction(self, const_cast("(OOOO)"), p1.get(), p2.get(), @@ -154,11 +154,11 @@ struct callback template static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOO)"), p1.get(), @@ -173,11 +173,11 @@ struct callback template static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); ref result(PyEval_CallFunction(self, const_cast("(OOOOO)"), p1.get(), p2.get(), @@ -191,12 +191,12 @@ struct callback template static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); + ref p6(to_python(search_namespace, a6)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOOO)"), p1.get(), @@ -212,12 +212,12 @@ struct callback template static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); + ref p6(to_python(search_namespace, a6)); ref result(PyEval_CallFunction(self, const_cast("(OOOOOO)"), p1.get(), p2.get(), @@ -232,13 +232,13 @@ struct callback template static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); + ref p6(to_python(search_namespace, a6)); + ref p7(to_python(search_namespace, a7)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOOOO)"), p1.get(), @@ -255,13 +255,13 @@ struct callback template static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); + ref p6(to_python(search_namespace, a6)); + ref p7(to_python(search_namespace, a7)); ref result(PyEval_CallFunction(self, const_cast("(OOOOOOO)"), p1.get(), p2.get(), @@ -277,14 +277,14 @@ struct callback template static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); + ref p6(to_python(search_namespace, a6)); + ref p7(to_python(search_namespace, a7)); + ref p8(to_python(search_namespace, a8)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOOOOO)"), p1.get(), @@ -302,14 +302,14 @@ struct callback template static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); + ref p6(to_python(search_namespace, a6)); + ref p7(to_python(search_namespace, a7)); + ref p8(to_python(search_namespace, a8)); ref result(PyEval_CallFunction(self, const_cast("(OOOOOOOO)"), p1.get(), p2.get(), @@ -326,15 +326,15 @@ struct callback template static R call_method(PyObject* self, const char* name, 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) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); - ref p9(to_python(a9)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); + ref p6(to_python(search_namespace, a6)); + ref p7(to_python(search_namespace, a7)); + ref p8(to_python(search_namespace, a8)); + ref p9(to_python(search_namespace, a9)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOOOOOO)"), p1.get(), @@ -353,15 +353,15 @@ struct callback template static R call(PyObject* self, 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) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); - ref p9(to_python(a9)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); + ref p6(to_python(search_namespace, a6)); + ref p7(to_python(search_namespace, a7)); + ref p8(to_python(search_namespace, a8)); + ref p9(to_python(search_namespace, a9)); ref result(PyEval_CallFunction(self, const_cast("(OOOOOOOOO)"), p1.get(), p2.get(), @@ -379,16 +379,16 @@ struct callback template static R call_method(PyObject* self, const char* name, 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) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); - ref p9(to_python(a9)); - ref p10(to_python(a10)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); + ref p6(to_python(search_namespace, a6)); + ref p7(to_python(search_namespace, a7)); + ref p8(to_python(search_namespace, a8)); + ref p9(to_python(search_namespace, a9)); + ref p10(to_python(search_namespace, a10)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOOOOOOO)"), p1.get(), @@ -408,16 +408,16 @@ struct callback template static R call(PyObject* self, 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) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); - ref p9(to_python(a9)); - ref p10(to_python(a10)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); + ref p6(to_python(search_namespace, a6)); + ref p7(to_python(search_namespace, a7)); + ref p8(to_python(search_namespace, a8)); + ref p9(to_python(search_namespace, a9)); + ref p10(to_python(search_namespace, a10)); ref result(PyEval_CallFunction(self, const_cast("(OOOOOOOOOO)"), p1.get(), p2.get(), @@ -455,7 +455,7 @@ struct callback template static void call_method(PyObject* self, const char* name, const A1& a1) { - ref p1(to_python(a1)); + ref p1(to_python(search_namespace, a1)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(O)"), p1.get())); @@ -464,7 +464,7 @@ struct callback template static void call(PyObject* self, const A1& a1) { - ref p1(to_python(a1)); + ref p1(to_python(search_namespace, a1)); ref result(PyEval_CallFunction(self, const_cast("(O)"), p1.get())); } @@ -472,8 +472,8 @@ struct callback template static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OO)"), p1.get(), @@ -483,8 +483,8 @@ struct callback template static void call(PyObject* self, const A1& a1, const A2& a2) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); ref result(PyEval_CallFunction(self, const_cast("(OO)"), p1.get(), p2.get())); @@ -493,9 +493,9 @@ struct callback template static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOO)"), p1.get(), @@ -506,9 +506,9 @@ struct callback template static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); ref result(PyEval_CallFunction(self, const_cast("(OOO)"), p1.get(), p2.get(), @@ -518,10 +518,10 @@ struct callback template static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOO)"), p1.get(), @@ -533,10 +533,10 @@ struct callback template static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); ref result(PyEval_CallFunction(self, const_cast("(OOOO)"), p1.get(), p2.get(), @@ -547,11 +547,11 @@ struct callback template static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOO)"), p1.get(), @@ -564,11 +564,11 @@ struct callback template static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); ref result(PyEval_CallFunction(self, const_cast("(OOOOO)"), p1.get(), p2.get(), @@ -580,12 +580,12 @@ struct callback template static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); + ref p6(to_python(search_namespace, a6)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOOO)"), p1.get(), @@ -599,12 +599,12 @@ struct callback template static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); + ref p6(to_python(search_namespace, a6)); ref result(PyEval_CallFunction(self, const_cast("(OOOOOO)"), p1.get(), p2.get(), @@ -617,13 +617,13 @@ struct callback template static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); + ref p6(to_python(search_namespace, a6)); + ref p7(to_python(search_namespace, a7)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOOOO)"), p1.get(), @@ -638,13 +638,13 @@ struct callback template static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); + ref p6(to_python(search_namespace, a6)); + ref p7(to_python(search_namespace, a7)); ref result(PyEval_CallFunction(self, const_cast("(OOOOOOO)"), p1.get(), p2.get(), @@ -658,14 +658,14 @@ struct callback template static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); + ref p6(to_python(search_namespace, a6)); + ref p7(to_python(search_namespace, a7)); + ref p8(to_python(search_namespace, a8)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOOOOO)"), p1.get(), @@ -681,14 +681,14 @@ struct callback template static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); + ref p6(to_python(search_namespace, a6)); + ref p7(to_python(search_namespace, a7)); + ref p8(to_python(search_namespace, a8)); ref result(PyEval_CallFunction(self, const_cast("(OOOOOOOO)"), p1.get(), p2.get(), @@ -703,15 +703,15 @@ struct callback template static void call_method(PyObject* self, const char* name, 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) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); - ref p9(to_python(a9)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); + ref p6(to_python(search_namespace, a6)); + ref p7(to_python(search_namespace, a7)); + ref p8(to_python(search_namespace, a8)); + ref p9(to_python(search_namespace, a9)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOOOOOO)"), p1.get(), @@ -728,15 +728,15 @@ struct callback template static void call(PyObject* self, 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) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); - ref p9(to_python(a9)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); + ref p6(to_python(search_namespace, a6)); + ref p7(to_python(search_namespace, a7)); + ref p8(to_python(search_namespace, a8)); + ref p9(to_python(search_namespace, a9)); ref result(PyEval_CallFunction(self, const_cast("(OOOOOOOOO)"), p1.get(), p2.get(), @@ -752,16 +752,16 @@ struct callback template static void call_method(PyObject* self, const char* name, 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) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); - ref p9(to_python(a9)); - ref p10(to_python(a10)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); + ref p6(to_python(search_namespace, a6)); + ref p7(to_python(search_namespace, a7)); + ref p8(to_python(search_namespace, a8)); + ref p9(to_python(search_namespace, a9)); + ref p10(to_python(search_namespace, a10)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOOOOOOO)"), p1.get(), @@ -779,16 +779,16 @@ struct callback template static void call(PyObject* self, 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) { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); - ref p9(to_python(a9)); - ref p10(to_python(a10)); + ref p1(to_python(search_namespace, a1)); + ref p2(to_python(search_namespace, a2)); + ref p3(to_python(search_namespace, a3)); + ref p4(to_python(search_namespace, a4)); + ref p5(to_python(search_namespace, a5)); + ref p6(to_python(search_namespace, a6)); + ref p7(to_python(search_namespace, a7)); + ref p8(to_python(search_namespace, a8)); + ref p9(to_python(search_namespace, a9)); + ref p10(to_python(search_namespace, a10)); ref result(PyEval_CallFunction(self, const_cast("(OOOOOOOOOO)"), p1.get(), p2.get(), diff --git a/include/boost/python/caller.hpp b/include/boost/python/caller.hpp index 35b2d618..86820233 100644 --- a/include/boost/python/caller.hpp +++ b/include/boost/python/caller.hpp @@ -30,7 +30,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("O"), &self)) return 0; T& target = from_python(self, type()); - return to_python((target.*pmf)()); + return to_python(search_namespace, (target.*pmf)()); } template @@ -40,7 +40,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OO"), &self, &a1)) return 0; T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()))); + return to_python(search_namespace, (target.*pmf)(from_python(a1, type()))); } template @@ -51,7 +51,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOO"), &self, &a1, &a2)) return 0; T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), + return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), from_python(a2, type()))); } @@ -64,7 +64,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOO"), &self, &a1, &a2, &a3)) return 0; T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), + return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()))); } @@ -79,7 +79,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOO"), &self, &a1, &a2, &a3, &a4)) return 0; T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), + return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()))); @@ -96,7 +96,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOO"), &self, &a1, &a2, &a3, &a4, &a5)) return 0; T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), + return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -115,7 +115,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6)) return 0; T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), + return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -136,7 +136,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7)) return 0; T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), + return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -159,7 +159,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8)) return 0; T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), + return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -184,7 +184,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9)) return 0; T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), + return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -211,7 +211,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10)) return 0; T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), + return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -230,7 +230,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("O"), &self)) return 0; T& target = from_python(self, type()); - return to_python((target.*pmf)()); + return to_python(search_namespace, (target.*pmf)()); } template @@ -240,7 +240,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OO"), &self, &a1)) return 0; T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()))); + return to_python(search_namespace, (target.*pmf)(from_python(a1, type()))); } template @@ -251,7 +251,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOO"), &self, &a1, &a2)) return 0; T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), + return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), from_python(a2, type()))); } @@ -264,7 +264,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOO"), &self, &a1, &a2, &a3)) return 0; T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), + return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()))); } @@ -279,7 +279,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOO"), &self, &a1, &a2, &a3, &a4)) return 0; T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), + return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()))); @@ -296,7 +296,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOO"), &self, &a1, &a2, &a3, &a4, &a5)) return 0; T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), + return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -315,7 +315,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6)) return 0; T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), + return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -336,7 +336,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7)) return 0; T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), + return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -359,7 +359,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8)) return 0; T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), + return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -384,7 +384,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9)) return 0; T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), + return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -411,7 +411,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10)) return 0; T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), + return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -427,7 +427,7 @@ struct caller static PyObject* call(R (*f)(), PyObject* args, PyObject* /* keywords */ ) { if (!PyArg_ParseTuple(args, const_cast(""))) return 0; - return to_python(f()); + return to_python(search_namespace, f()); } template @@ -435,7 +435,7 @@ struct caller PyObject* a1; if (!PyArg_ParseTuple(args, const_cast("O"), &a1)) return 0; - return to_python(f(from_python(a1, type()))); + return to_python(search_namespace, f(from_python(a1, type()))); } template @@ -444,7 +444,7 @@ struct caller PyObject* a2; if (!PyArg_ParseTuple(args, const_cast("OO"), &a1, &a2)) return 0; - return to_python(f(from_python(a1, type()), + return to_python(search_namespace, f(from_python(a1, type()), from_python(a2, type()))); } @@ -455,7 +455,7 @@ struct caller PyObject* a3; if (!PyArg_ParseTuple(args, const_cast("OOO"), &a1, &a2, &a3)) return 0; - return to_python(f(from_python(a1, type()), + return to_python(search_namespace, f(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()))); } @@ -468,7 +468,7 @@ struct caller PyObject* a4; if (!PyArg_ParseTuple(args, const_cast("OOOO"), &a1, &a2, &a3, &a4)) return 0; - return to_python(f(from_python(a1, type()), + return to_python(search_namespace, f(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()))); @@ -483,7 +483,7 @@ struct caller PyObject* a5; if (!PyArg_ParseTuple(args, const_cast("OOOOO"), &a1, &a2, &a3, &a4, &a5)) return 0; - return to_python(f(from_python(a1, type()), + return to_python(search_namespace, f(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -500,7 +500,7 @@ struct caller PyObject* a6; if (!PyArg_ParseTuple(args, const_cast("OOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6)) return 0; - return to_python(f(from_python(a1, type()), + return to_python(search_namespace, f(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -519,7 +519,7 @@ struct caller PyObject* a7; if (!PyArg_ParseTuple(args, const_cast("OOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7)) return 0; - return to_python(f(from_python(a1, type()), + return to_python(search_namespace, f(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -540,7 +540,7 @@ struct caller PyObject* a8; if (!PyArg_ParseTuple(args, const_cast("OOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8)) return 0; - return to_python(f(from_python(a1, type()), + return to_python(search_namespace, f(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -563,7 +563,7 @@ struct caller PyObject* a9; if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9)) return 0; - return to_python(f(from_python(a1, type()), + return to_python(search_namespace, f(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -588,7 +588,7 @@ struct caller PyObject* a10; if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10)) return 0; - return to_python(f(from_python(a1, type()), + return to_python(search_namespace, f(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -615,7 +615,7 @@ struct caller PyObject* a11; if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10, &a11)) return 0; - return to_python(f(from_python(a1, type()), + return to_python(search_namespace, f(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), diff --git a/include/boost/python/detail/config.hpp b/include/boost/python/detail/config.hpp index 9792695e..348bcc39 100644 --- a/include/boost/python/detail/config.hpp +++ b/include/boost/python/detail/config.hpp @@ -15,19 +15,6 @@ # include # include -# 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 @@ -37,6 +24,16 @@ # endif +# if defined(BOOST_PYTHON_USE_FRIEND_KOENIG_LOOKUP) +// for compilers that support Koenig lookup +# define BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE namespace boost { namespace python { +# define BOOST_PYTHON_END_CONVERSION_NAMESPACE }} // namespace boost::python +# else +// for compilers that do not support Koenig lookup for friend functions +# define BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE +# define BOOST_PYTHON_END_CONVERSION_NAMESPACE +# 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. From 294254efbb4539e93fb86249e7c92a5377191b88 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 24 May 2001 08:43:56 +0000 Subject: [PATCH 106/369] Fix accident: restore main version. [SVN r10209] --- include/boost/python/callback.hpp | 440 +++++++++++++++--------------- include/boost/python/caller.hpp | 68 ++--- 2 files changed, 254 insertions(+), 254 deletions(-) diff --git a/include/boost/python/callback.hpp b/include/boost/python/callback.hpp index b9e850c6..7240b5b7 100644 --- a/include/boost/python/callback.hpp +++ b/include/boost/python/callback.hpp @@ -46,7 +46,7 @@ struct callback template static R call_method(PyObject* self, const char* name, const A1& a1) { - ref p1(to_python(search_namespace, a1)); + ref p1(to_python(a1)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(O)"), p1.get())); @@ -57,7 +57,7 @@ struct callback template static R call(PyObject* self, const A1& a1) { - ref p1(to_python(search_namespace, a1)); + ref p1(to_python(a1)); ref result(PyEval_CallFunction(self, const_cast("(O)"), p1.get())); detail::callback_adjust_refcount(result.get(), type()); @@ -67,8 +67,8 @@ struct callback template static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OO)"), p1.get(), @@ -80,8 +80,8 @@ struct callback template static R call(PyObject* self, const A1& a1, const A2& a2) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); ref result(PyEval_CallFunction(self, const_cast("(OO)"), p1.get(), p2.get())); @@ -92,9 +92,9 @@ struct callback template static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOO)"), p1.get(), @@ -107,9 +107,9 @@ struct callback template static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); ref result(PyEval_CallFunction(self, const_cast("(OOO)"), p1.get(), p2.get(), @@ -121,10 +121,10 @@ struct callback template static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOO)"), p1.get(), @@ -138,10 +138,10 @@ struct callback template static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); ref result(PyEval_CallFunction(self, const_cast("(OOOO)"), p1.get(), p2.get(), @@ -154,11 +154,11 @@ struct callback template static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOO)"), p1.get(), @@ -173,11 +173,11 @@ struct callback template static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); ref result(PyEval_CallFunction(self, const_cast("(OOOOO)"), p1.get(), p2.get(), @@ -191,12 +191,12 @@ struct callback template static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); - ref p6(to_python(search_namespace, a6)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); + ref p6(to_python(a6)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOOO)"), p1.get(), @@ -212,12 +212,12 @@ struct callback template static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); - ref p6(to_python(search_namespace, a6)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); + ref p6(to_python(a6)); ref result(PyEval_CallFunction(self, const_cast("(OOOOOO)"), p1.get(), p2.get(), @@ -232,13 +232,13 @@ struct callback template static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); - ref p6(to_python(search_namespace, a6)); - ref p7(to_python(search_namespace, a7)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); + ref p6(to_python(a6)); + ref p7(to_python(a7)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOOOO)"), p1.get(), @@ -255,13 +255,13 @@ struct callback template static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); - ref p6(to_python(search_namespace, a6)); - ref p7(to_python(search_namespace, a7)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); + ref p6(to_python(a6)); + ref p7(to_python(a7)); ref result(PyEval_CallFunction(self, const_cast("(OOOOOOO)"), p1.get(), p2.get(), @@ -277,14 +277,14 @@ struct callback template static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); - ref p6(to_python(search_namespace, a6)); - ref p7(to_python(search_namespace, a7)); - ref p8(to_python(search_namespace, a8)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); + ref p6(to_python(a6)); + ref p7(to_python(a7)); + ref p8(to_python(a8)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOOOOO)"), p1.get(), @@ -302,14 +302,14 @@ struct callback template static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); - ref p6(to_python(search_namespace, a6)); - ref p7(to_python(search_namespace, a7)); - ref p8(to_python(search_namespace, a8)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); + ref p6(to_python(a6)); + ref p7(to_python(a7)); + ref p8(to_python(a8)); ref result(PyEval_CallFunction(self, const_cast("(OOOOOOOO)"), p1.get(), p2.get(), @@ -326,15 +326,15 @@ struct callback template static R call_method(PyObject* self, const char* name, 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) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); - ref p6(to_python(search_namespace, a6)); - ref p7(to_python(search_namespace, a7)); - ref p8(to_python(search_namespace, a8)); - ref p9(to_python(search_namespace, a9)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); + ref p6(to_python(a6)); + ref p7(to_python(a7)); + ref p8(to_python(a8)); + ref p9(to_python(a9)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOOOOOO)"), p1.get(), @@ -353,15 +353,15 @@ struct callback template static R call(PyObject* self, 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) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); - ref p6(to_python(search_namespace, a6)); - ref p7(to_python(search_namespace, a7)); - ref p8(to_python(search_namespace, a8)); - ref p9(to_python(search_namespace, a9)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); + ref p6(to_python(a6)); + ref p7(to_python(a7)); + ref p8(to_python(a8)); + ref p9(to_python(a9)); ref result(PyEval_CallFunction(self, const_cast("(OOOOOOOOO)"), p1.get(), p2.get(), @@ -379,16 +379,16 @@ struct callback template static R call_method(PyObject* self, const char* name, 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) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); - ref p6(to_python(search_namespace, a6)); - ref p7(to_python(search_namespace, a7)); - ref p8(to_python(search_namespace, a8)); - ref p9(to_python(search_namespace, a9)); - ref p10(to_python(search_namespace, a10)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); + ref p6(to_python(a6)); + ref p7(to_python(a7)); + ref p8(to_python(a8)); + ref p9(to_python(a9)); + ref p10(to_python(a10)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOOOOOOO)"), p1.get(), @@ -408,16 +408,16 @@ struct callback template static R call(PyObject* self, 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) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); - ref p6(to_python(search_namespace, a6)); - ref p7(to_python(search_namespace, a7)); - ref p8(to_python(search_namespace, a8)); - ref p9(to_python(search_namespace, a9)); - ref p10(to_python(search_namespace, a10)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); + ref p6(to_python(a6)); + ref p7(to_python(a7)); + ref p8(to_python(a8)); + ref p9(to_python(a9)); + ref p10(to_python(a10)); ref result(PyEval_CallFunction(self, const_cast("(OOOOOOOOOO)"), p1.get(), p2.get(), @@ -455,7 +455,7 @@ struct callback template static void call_method(PyObject* self, const char* name, const A1& a1) { - ref p1(to_python(search_namespace, a1)); + ref p1(to_python(a1)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(O)"), p1.get())); @@ -464,7 +464,7 @@ struct callback template static void call(PyObject* self, const A1& a1) { - ref p1(to_python(search_namespace, a1)); + ref p1(to_python(a1)); ref result(PyEval_CallFunction(self, const_cast("(O)"), p1.get())); } @@ -472,8 +472,8 @@ struct callback template static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OO)"), p1.get(), @@ -483,8 +483,8 @@ struct callback template static void call(PyObject* self, const A1& a1, const A2& a2) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); ref result(PyEval_CallFunction(self, const_cast("(OO)"), p1.get(), p2.get())); @@ -493,9 +493,9 @@ struct callback template static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOO)"), p1.get(), @@ -506,9 +506,9 @@ struct callback template static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); ref result(PyEval_CallFunction(self, const_cast("(OOO)"), p1.get(), p2.get(), @@ -518,10 +518,10 @@ struct callback template static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOO)"), p1.get(), @@ -533,10 +533,10 @@ struct callback template static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); ref result(PyEval_CallFunction(self, const_cast("(OOOO)"), p1.get(), p2.get(), @@ -547,11 +547,11 @@ struct callback template static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOO)"), p1.get(), @@ -564,11 +564,11 @@ struct callback template static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); ref result(PyEval_CallFunction(self, const_cast("(OOOOO)"), p1.get(), p2.get(), @@ -580,12 +580,12 @@ struct callback template static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); - ref p6(to_python(search_namespace, a6)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); + ref p6(to_python(a6)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOOO)"), p1.get(), @@ -599,12 +599,12 @@ struct callback template static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); - ref p6(to_python(search_namespace, a6)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); + ref p6(to_python(a6)); ref result(PyEval_CallFunction(self, const_cast("(OOOOOO)"), p1.get(), p2.get(), @@ -617,13 +617,13 @@ struct callback template static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); - ref p6(to_python(search_namespace, a6)); - ref p7(to_python(search_namespace, a7)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); + ref p6(to_python(a6)); + ref p7(to_python(a7)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOOOO)"), p1.get(), @@ -638,13 +638,13 @@ struct callback template static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); - ref p6(to_python(search_namespace, a6)); - ref p7(to_python(search_namespace, a7)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); + ref p6(to_python(a6)); + ref p7(to_python(a7)); ref result(PyEval_CallFunction(self, const_cast("(OOOOOOO)"), p1.get(), p2.get(), @@ -658,14 +658,14 @@ struct callback template static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); - ref p6(to_python(search_namespace, a6)); - ref p7(to_python(search_namespace, a7)); - ref p8(to_python(search_namespace, a8)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); + ref p6(to_python(a6)); + ref p7(to_python(a7)); + ref p8(to_python(a8)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOOOOO)"), p1.get(), @@ -681,14 +681,14 @@ struct callback template static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); - ref p6(to_python(search_namespace, a6)); - ref p7(to_python(search_namespace, a7)); - ref p8(to_python(search_namespace, a8)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); + ref p6(to_python(a6)); + ref p7(to_python(a7)); + ref p8(to_python(a8)); ref result(PyEval_CallFunction(self, const_cast("(OOOOOOOO)"), p1.get(), p2.get(), @@ -703,15 +703,15 @@ struct callback template static void call_method(PyObject* self, const char* name, 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) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); - ref p6(to_python(search_namespace, a6)); - ref p7(to_python(search_namespace, a7)); - ref p8(to_python(search_namespace, a8)); - ref p9(to_python(search_namespace, a9)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); + ref p6(to_python(a6)); + ref p7(to_python(a7)); + ref p8(to_python(a8)); + ref p9(to_python(a9)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOOOOOO)"), p1.get(), @@ -728,15 +728,15 @@ struct callback template static void call(PyObject* self, 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) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); - ref p6(to_python(search_namespace, a6)); - ref p7(to_python(search_namespace, a7)); - ref p8(to_python(search_namespace, a8)); - ref p9(to_python(search_namespace, a9)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); + ref p6(to_python(a6)); + ref p7(to_python(a7)); + ref p8(to_python(a8)); + ref p9(to_python(a9)); ref result(PyEval_CallFunction(self, const_cast("(OOOOOOOOO)"), p1.get(), p2.get(), @@ -752,16 +752,16 @@ struct callback template static void call_method(PyObject* self, const char* name, 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) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); - ref p6(to_python(search_namespace, a6)); - ref p7(to_python(search_namespace, a7)); - ref p8(to_python(search_namespace, a8)); - ref p9(to_python(search_namespace, a9)); - ref p10(to_python(search_namespace, a10)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); + ref p6(to_python(a6)); + ref p7(to_python(a7)); + ref p8(to_python(a8)); + ref p9(to_python(a9)); + ref p10(to_python(a10)); ref result(PyEval_CallMethod(self, const_cast(name), const_cast("(OOOOOOOOOO)"), p1.get(), @@ -779,16 +779,16 @@ struct callback template static void call(PyObject* self, 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) { - ref p1(to_python(search_namespace, a1)); - ref p2(to_python(search_namespace, a2)); - ref p3(to_python(search_namespace, a3)); - ref p4(to_python(search_namespace, a4)); - ref p5(to_python(search_namespace, a5)); - ref p6(to_python(search_namespace, a6)); - ref p7(to_python(search_namespace, a7)); - ref p8(to_python(search_namespace, a8)); - ref p9(to_python(search_namespace, a9)); - ref p10(to_python(search_namespace, a10)); + ref p1(to_python(a1)); + ref p2(to_python(a2)); + ref p3(to_python(a3)); + ref p4(to_python(a4)); + ref p5(to_python(a5)); + ref p6(to_python(a6)); + ref p7(to_python(a7)); + ref p8(to_python(a8)); + ref p9(to_python(a9)); + ref p10(to_python(a10)); ref result(PyEval_CallFunction(self, const_cast("(OOOOOOOOOO)"), p1.get(), p2.get(), diff --git a/include/boost/python/caller.hpp b/include/boost/python/caller.hpp index 86820233..35b2d618 100644 --- a/include/boost/python/caller.hpp +++ b/include/boost/python/caller.hpp @@ -30,7 +30,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("O"), &self)) return 0; T& target = from_python(self, type()); - return to_python(search_namespace, (target.*pmf)()); + return to_python((target.*pmf)()); } template @@ -40,7 +40,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OO"), &self, &a1)) return 0; T& target = from_python(self, type()); - return to_python(search_namespace, (target.*pmf)(from_python(a1, type()))); + return to_python((target.*pmf)(from_python(a1, type()))); } template @@ -51,7 +51,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOO"), &self, &a1, &a2)) return 0; T& target = from_python(self, type()); - return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), + return to_python((target.*pmf)(from_python(a1, type()), from_python(a2, type()))); } @@ -64,7 +64,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOO"), &self, &a1, &a2, &a3)) return 0; T& target = from_python(self, type()); - return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), + return to_python((target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()))); } @@ -79,7 +79,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOO"), &self, &a1, &a2, &a3, &a4)) return 0; T& target = from_python(self, type()); - return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), + return to_python((target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()))); @@ -96,7 +96,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOO"), &self, &a1, &a2, &a3, &a4, &a5)) return 0; T& target = from_python(self, type()); - return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), + return to_python((target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -115,7 +115,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6)) return 0; T& target = from_python(self, type()); - return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), + return to_python((target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -136,7 +136,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7)) return 0; T& target = from_python(self, type()); - return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), + return to_python((target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -159,7 +159,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8)) return 0; T& target = from_python(self, type()); - return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), + return to_python((target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -184,7 +184,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9)) return 0; T& target = from_python(self, type()); - return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), + return to_python((target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -211,7 +211,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10)) return 0; T& target = from_python(self, type()); - return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), + return to_python((target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -230,7 +230,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("O"), &self)) return 0; T& target = from_python(self, type()); - return to_python(search_namespace, (target.*pmf)()); + return to_python((target.*pmf)()); } template @@ -240,7 +240,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OO"), &self, &a1)) return 0; T& target = from_python(self, type()); - return to_python(search_namespace, (target.*pmf)(from_python(a1, type()))); + return to_python((target.*pmf)(from_python(a1, type()))); } template @@ -251,7 +251,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOO"), &self, &a1, &a2)) return 0; T& target = from_python(self, type()); - return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), + return to_python((target.*pmf)(from_python(a1, type()), from_python(a2, type()))); } @@ -264,7 +264,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOO"), &self, &a1, &a2, &a3)) return 0; T& target = from_python(self, type()); - return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), + return to_python((target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()))); } @@ -279,7 +279,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOO"), &self, &a1, &a2, &a3, &a4)) return 0; T& target = from_python(self, type()); - return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), + return to_python((target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()))); @@ -296,7 +296,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOO"), &self, &a1, &a2, &a3, &a4, &a5)) return 0; T& target = from_python(self, type()); - return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), + return to_python((target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -315,7 +315,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6)) return 0; T& target = from_python(self, type()); - return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), + return to_python((target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -336,7 +336,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7)) return 0; T& target = from_python(self, type()); - return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), + return to_python((target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -359,7 +359,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8)) return 0; T& target = from_python(self, type()); - return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), + return to_python((target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -384,7 +384,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9)) return 0; T& target = from_python(self, type()); - return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), + return to_python((target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -411,7 +411,7 @@ struct caller if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10)) return 0; T& target = from_python(self, type()); - return to_python(search_namespace, (target.*pmf)(from_python(a1, type()), + return to_python((target.*pmf)(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -427,7 +427,7 @@ struct caller static PyObject* call(R (*f)(), PyObject* args, PyObject* /* keywords */ ) { if (!PyArg_ParseTuple(args, const_cast(""))) return 0; - return to_python(search_namespace, f()); + return to_python(f()); } template @@ -435,7 +435,7 @@ struct caller PyObject* a1; if (!PyArg_ParseTuple(args, const_cast("O"), &a1)) return 0; - return to_python(search_namespace, f(from_python(a1, type()))); + return to_python(f(from_python(a1, type()))); } template @@ -444,7 +444,7 @@ struct caller PyObject* a2; if (!PyArg_ParseTuple(args, const_cast("OO"), &a1, &a2)) return 0; - return to_python(search_namespace, f(from_python(a1, type()), + return to_python(f(from_python(a1, type()), from_python(a2, type()))); } @@ -455,7 +455,7 @@ struct caller PyObject* a3; if (!PyArg_ParseTuple(args, const_cast("OOO"), &a1, &a2, &a3)) return 0; - return to_python(search_namespace, f(from_python(a1, type()), + return to_python(f(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()))); } @@ -468,7 +468,7 @@ struct caller PyObject* a4; if (!PyArg_ParseTuple(args, const_cast("OOOO"), &a1, &a2, &a3, &a4)) return 0; - return to_python(search_namespace, f(from_python(a1, type()), + return to_python(f(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()))); @@ -483,7 +483,7 @@ struct caller PyObject* a5; if (!PyArg_ParseTuple(args, const_cast("OOOOO"), &a1, &a2, &a3, &a4, &a5)) return 0; - return to_python(search_namespace, f(from_python(a1, type()), + return to_python(f(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -500,7 +500,7 @@ struct caller PyObject* a6; if (!PyArg_ParseTuple(args, const_cast("OOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6)) return 0; - return to_python(search_namespace, f(from_python(a1, type()), + return to_python(f(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -519,7 +519,7 @@ struct caller PyObject* a7; if (!PyArg_ParseTuple(args, const_cast("OOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7)) return 0; - return to_python(search_namespace, f(from_python(a1, type()), + return to_python(f(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -540,7 +540,7 @@ struct caller PyObject* a8; if (!PyArg_ParseTuple(args, const_cast("OOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8)) return 0; - return to_python(search_namespace, f(from_python(a1, type()), + return to_python(f(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -563,7 +563,7 @@ struct caller PyObject* a9; if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9)) return 0; - return to_python(search_namespace, f(from_python(a1, type()), + return to_python(f(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -588,7 +588,7 @@ struct caller PyObject* a10; if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10)) return 0; - return to_python(search_namespace, f(from_python(a1, type()), + return to_python(f(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), @@ -615,7 +615,7 @@ struct caller PyObject* a11; if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10, &a11)) return 0; - return to_python(search_namespace, f(from_python(a1, type()), + return to_python(f(from_python(a1, type()), from_python(a2, type()), from_python(a3, type()), from_python(a4, type()), From 66da2339d4abfa1820d6a0320fc6f98e1bc92a5e Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 24 May 2001 08:51:05 +0000 Subject: [PATCH 107/369] Fix accident: restore main version. [SVN r10210] --- include/boost/python/detail/config.hpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/include/boost/python/detail/config.hpp b/include/boost/python/detail/config.hpp index 348bcc39..9792695e 100644 --- a/include/boost/python/detail/config.hpp +++ b/include/boost/python/detail/config.hpp @@ -15,6 +15,19 @@ # include # include +# 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 @@ -24,16 +37,6 @@ # endif -# if defined(BOOST_PYTHON_USE_FRIEND_KOENIG_LOOKUP) -// for compilers that support Koenig lookup -# define BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE namespace boost { namespace python { -# define BOOST_PYTHON_END_CONVERSION_NAMESPACE }} // namespace boost::python -# else -// for compilers that do not support Koenig lookup for friend functions -# define BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE -# define BOOST_PYTHON_END_CONVERSION_NAMESPACE -# 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. From 29a855813d307864ee96d5f45f63582d24d846ca Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 28 May 2001 20:14:25 +0000 Subject: [PATCH 108/369] fixed typo [SVN r10240] --- doc/pointers.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/pointers.html b/doc/pointers.html index fdbee797..00f7bb41 100644 --- a/doc/pointers.html +++ b/doc/pointers.html @@ -85,7 +85,7 @@ code before the last Python reference to it disappears: BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround PyObject* to_python(Foo* p) { - return boost::python::python_extension_class_converters<Foo>::ptr_to_python(p); + return boost::python::python_extension_class_converters<Foo>::ptr_to_python(p); } PyObject* to_python(const Foo* p) From 7a71cea92a4ecbc59a4072b8d083f2fb9680942e Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 18 Jun 2001 12:11:46 +0000 Subject: [PATCH 109/369] updated ILU links thanks to Scott Langley [SVN r10355] --- doc/comparisons.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/comparisons.html b/doc/comparisons.html index 6f082d51..57cec744 100644 --- a/doc/comparisons.html +++ b/doc/comparisons.html @@ -112,10 +112,10 @@ that.''
    -Paul Dubois

    ILU

    ILU + href="ftp://ftp.parc.xerox.com/pub/ilu/ilu.html">ILU is a very ambitious project which tries to describe a module's interface (types and functions) in terms of an Interface + href="ftp://ftp.parc.xerox.com/pub/ilu/2.0b1/manual-html/manual_2.html">Interface Specification Language (ISL) so that it can be uniformly interfaced to a wide range of computer languages, including Common Lisp, C++, C, Modula-3, and Python. ILU can parse the ISL to generate a C++ language From 91f0728b5598b144df3a87f236f6512c5dae459d Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 21 Jun 2001 20:46:26 +0000 Subject: [PATCH 110/369] Minor fix, thanks to Jens Maurer. [SVN r10377] --- example/simple_vector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/simple_vector.cpp b/example/simple_vector.cpp index 2b3aa290..3499c8f7 100644 --- a/example/simple_vector.cpp +++ b/example/simple_vector.cpp @@ -49,7 +49,7 @@ namespace { // Avoid cluttering the global namespace. void delitem(std::vector& vd, std::size_t key) { if (key >= vd.size()) raise_vector_IndexError(); std::vector::iterator vditer = vd.begin(); - vd.erase(&vditer[key]); + vd.erase(vditer + key); } // Convert vector_double to a regular Python tuple. From 8b88e9f7272e8d0041deaca23b017193615cb849 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 21 Jun 2001 20:49:41 +0000 Subject: [PATCH 111/369] define changed to enable Silicon Graphics gcc compilation. [SVN r10378] --- test/comprehensive.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/comprehensive.cpp b/test/comprehensive.cpp index 410bd243..427ed2d8 100644 --- a/test/comprehensive.cpp +++ b/test/comprehensive.cpp @@ -15,7 +15,9 @@ #include // for pow() #include -#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 +#if defined(__sgi) \ + && ( (defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730) \ + && !defined(__GNUC__)) inline double pow(int x, int y) { return pow(static_cast(x), y); } #endif From 7c33a46a76dc7174317644e90e0aabfd52718b59 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 21 Jun 2001 23:38:42 +0000 Subject: [PATCH 112/369] A small fix for Borland [SVN r10389] --- src/classes.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/classes.cpp b/src/classes.cpp index c609eeef..8755bb34 100644 --- a/src/classes.cpp +++ b/src/classes.cpp @@ -203,7 +203,8 @@ namespace detail { } if (!BOOST_CSTD_::strcmp(name, "__reduce__")) { - ref target(as_object(this), ref::increment_count); + PyObject* self = as_object(this); + ref target(self, ref::increment_count); return bound_function::create(target, global_class_reduce()); } @@ -808,7 +809,7 @@ namespace detail { // Enable the special handler for methods of the given name, if any. void enable_named_method(boost::python::detail::class_base* type_obj, const char* name) { - const std::size_t num_enablers = sizeof(enablers) / sizeof(enablers[0]); + const std::size_t num_enablers = PY_ARRAY_LENGTH(enablers); // Make sure this ends with "__" since we'll only compare the head of the // string. This is done to make the __getattr____/__setattr____ From 1364b97b881185c8ea231c146679fbce172532b1 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 21 Jun 2001 23:39:30 +0000 Subject: [PATCH 113/369] A small Borland fix [SVN r10390] --- include/boost/python/detail/init_function.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/boost/python/detail/init_function.hpp b/include/boost/python/detail/init_function.hpp index f4b24fa6..c0c50272 100644 --- a/include/boost/python/detail/init_function.hpp +++ b/include/boost/python/detail/init_function.hpp @@ -73,7 +73,8 @@ namespace detail { struct parameter_traits { private: - typedef const_ref_selector::value> selector; + enum { is_ref = boost::is_reference::value }; + typedef const_ref_selector selector; public: typedef typename selector::template const_ref::type const_reference; }; From 081150b477dfbd5dce9d3a7faaa0d12fce9380e9 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 21 Jun 2001 23:40:04 +0000 Subject: [PATCH 114/369] Quick Borland fix [SVN r10391] --- include/boost/python/detail/types.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/python/detail/types.hpp b/include/boost/python/detail/types.hpp index ee33ce04..5f0c8f97 100644 --- a/include/boost/python/detail/types.hpp +++ b/include/boost/python/detail/types.hpp @@ -375,8 +375,12 @@ PyObject* reprable::instance_repr(PyObject* obj) const // 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 inline void countof_validate(T* const, T* const*); From 88372000b5b4348610e4e5440de4e9a8d4b5f29d Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 22 Jun 2001 00:49:58 +0000 Subject: [PATCH 115/369] fixes due to Jens Maurer (merged from branch boost_python_friend_fixes) [SVN r10395] --- build/linux_gcc.mak | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build/linux_gcc.mak b/build/linux_gcc.mak index 9cd2b5de..5971ca61 100644 --- a/build/linux_gcc.mak +++ b/build/linux_gcc.mak @@ -17,14 +17,14 @@ ROOT=$(HOME) BOOST=$(ROOT)/boost -PYEXE=/usr/bin/python +PYEXE=PYTHONPATH=. /usr/bin/python PYINC=-I/usr/include/python1.5 #PYEXE=/usr/local/Python-1.5.2/bin/python #PYINC=-I/usr/local/Python-1.5.2/include/python1.5 #PYEXE=/usr/local/Python-2.0/bin/python #PYINC=-I/usr/local/Python-2.0/include/python2.0 -STDOPTS=-ftemplate-depth-21 +STDOPTS=-fPIC -ftemplate-depth-21 WARNOPTS= OPTOPTS=-g @@ -33,7 +33,7 @@ CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \ $(STDOPTS) $(WARNOPTS) $(OPTOPTS) MAKEDEP=-M -LD=g++ +LD=$(CPP) LDOPTS=-shared OBJ=classes.o conversions.o extension_class.o functions.o \ From 4328ae1d8d86607807d5e649d4e0d9135a4d07bf Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 22 Jun 2001 22:36:00 +0000 Subject: [PATCH 116/369] Updates for Boost.Build [SVN r10403] --- example/test_abstract.py | 5 +++-- example/test_cross_module.py | 5 +++-- example/test_do_it_yourself_converters.py | 5 +++-- example/test_example1.py | 5 +++-- example/test_getting_started1.py | 5 +++-- example/test_getting_started2.py | 6 ++++-- example/test_pickle1.py | 6 ++++-- example/test_pickle2.py | 6 ++++-- example/test_pickle3.py | 5 +++-- example/test_rwgk1.py | 6 ++++-- example/test_simple_vector.py | 6 ++++-- test/comprehensive.py | 4 ++-- 12 files changed, 40 insertions(+), 24 deletions(-) diff --git a/example/test_abstract.py b/example/test_abstract.py index dda8aaa7..a48aff1b 100644 --- a/example/test_abstract.py +++ b/example/test_abstract.py @@ -17,7 +17,8 @@ def run(args = None): import sys sys.argv = args import doctest, test_abstract - doctest.testmod(test_abstract) + return doctest.testmod(test_abstract) if __name__ == '__main__': - run() + import sys + sys.exit(run()[0]) diff --git a/example/test_cross_module.py b/example/test_cross_module.py index 81057f23..86c1be0e 100644 --- a/example/test_cross_module.py +++ b/example/test_cross_module.py @@ -133,7 +133,8 @@ def run(args = None): import sys sys.argv = args import doctest, test_cross_module - doctest.testmod(test_cross_module) + return doctest.testmod(test_cross_module) if __name__ == '__main__': - run() + import sys + sys.exit(run()) diff --git a/example/test_do_it_yourself_converters.py b/example/test_do_it_yourself_converters.py index e256c614..17240750 100644 --- a/example/test_do_it_yourself_converters.py +++ b/example/test_do_it_yourself_converters.py @@ -16,7 +16,8 @@ def run(args = None): import sys sys.argv = args import doctest, test_do_it_yourself_converters - doctest.testmod(test_do_it_yourself_converters) + return doctest.testmod(test_do_it_yourself_converters) if __name__ == '__main__': - run() + import sys + sys.exit(run()[0]) diff --git a/example/test_example1.py b/example/test_example1.py index 0e3a9a18..3a30cb5b 100644 --- a/example/test_example1.py +++ b/example/test_example1.py @@ -44,7 +44,8 @@ def run(args = None): import sys sys.argv = args import doctest, test_example1 - doctest.testmod(test_example1) + return doctest.testmod(test_example1) if __name__ == '__main__': - run() + import sys + sys.exit(run()[0]) diff --git a/example/test_getting_started1.py b/example/test_getting_started1.py index 7daf65af..cd8fb59e 100644 --- a/example/test_getting_started1.py +++ b/example/test_getting_started1.py @@ -11,7 +11,8 @@ def run(args = None): import sys sys.argv = args import doctest, test_getting_started1 - doctest.testmod(test_getting_started1) + return doctest.testmod(test_getting_started1) if __name__ == '__main__': - run() + import sys + sys.exit(run()[0]) diff --git a/example/test_getting_started2.py b/example/test_getting_started2.py index 49cf765d..ccfaa4f1 100644 --- a/example/test_getting_started2.py +++ b/example/test_getting_started2.py @@ -23,7 +23,9 @@ def run(args = None): import sys sys.argv = args import doctest, test_getting_started2 - doctest.testmod(test_getting_started2) + return doctest.testmod(test_getting_started2) if __name__ == '__main__': - run() + import sys + sys.exit(run()[0]) + diff --git a/example/test_pickle1.py b/example/test_pickle1.py index 05696d4a..48c76a5f 100644 --- a/example/test_pickle1.py +++ b/example/test_pickle1.py @@ -25,7 +25,9 @@ def run(args = None): import sys sys.argv = args import doctest, test_pickle1 - doctest.testmod(test_pickle1) + return doctest.testmod(test_pickle1) if __name__ == '__main__': - run() + import sys + sys.exit(run()[0]) + diff --git a/example/test_pickle2.py b/example/test_pickle2.py index 463befa6..bafa9875 100644 --- a/example/test_pickle2.py +++ b/example/test_pickle2.py @@ -39,7 +39,9 @@ def run(args = None): import sys sys.argv = args import doctest, test_pickle2 - doctest.testmod(test_pickle2) + return doctest.testmod(test_pickle2) if __name__ == '__main__': - run() + import sys + sys.exit(run()[0]) + diff --git a/example/test_pickle3.py b/example/test_pickle3.py index b964f1a2..36da735d 100644 --- a/example/test_pickle3.py +++ b/example/test_pickle3.py @@ -32,7 +32,8 @@ def run(args = None): import sys sys.argv = args import doctest, test_pickle3 - doctest.testmod(test_pickle3) + return doctest.testmod(test_pickle3) if __name__ == '__main__': - run() + import sys + sys.exit(run()[0]) diff --git a/example/test_rwgk1.py b/example/test_rwgk1.py index 87298875..631eea3e 100644 --- a/example/test_rwgk1.py +++ b/example/test_rwgk1.py @@ -11,7 +11,9 @@ def run(args = None): import sys sys.argv = args import doctest, test_rwgk1 - doctest.testmod(test_rwgk1) + return doctest.testmod(test_rwgk1) if __name__ == '__main__': - run() + import sys + sys.exit(run()[0]) + diff --git a/example/test_simple_vector.py b/example/test_simple_vector.py index ca38d715..c6a2cd59 100644 --- a/example/test_simple_vector.py +++ b/example/test_simple_vector.py @@ -34,7 +34,9 @@ def run(args = None): import sys sys.argv = args import doctest, test_simple_vector - doctest.testmod(test_simple_vector) + return doctest.testmod(test_simple_vector) if __name__ == '__main__': - run() + import sys + sys.exit(run()[0]) + diff --git a/test/comprehensive.py b/test/comprehensive.py index c1424d25..06a191af 100644 --- a/test/comprehensive.py +++ b/test/comprehensive.py @@ -1188,7 +1188,7 @@ def run(args = None): if args is not None: sys.argv = args import doctest, comprehensive - doctest.testmod(comprehensive) + return doctest.testmod(comprehensive) if __name__ == '__main__': - run() + sys.exit(run()[0]) From ff2b37f6e374d6c9b594747ffa1eaa267b9ca952 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 29 Jun 2001 03:57:34 +0000 Subject: [PATCH 117/369] Fix so it compiles with Cygwin [SVN r10480] --- include/boost/python/detail/config.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/python/detail/config.hpp b/include/boost/python/detail/config.hpp index 9792695e..b6075368 100644 --- a/include/boost/python/detail/config.hpp +++ b/include/boost/python/detail/config.hpp @@ -57,7 +57,7 @@ # define BOOST_CSTD_ std # endif -#ifdef _WIN32 +#if defined(_WIN32) || defined(__CYGWIN__) # define BOOST_PYTHON_MODULE_INIT(name) extern "C" __declspec(dllexport) void init##name() #else # define BOOST_PYTHON_MODULE_INIT(name) extern "C" void init##name() From a32dedd16c8998faad1aa7cd31f57de4d4e5ecee Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 29 Jun 2001 20:30:58 +0000 Subject: [PATCH 118/369] updates for Python2.1 [SVN r10485] --- test/comprehensive.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/test/comprehensive.py b/test/comprehensive.py index 06a191af..013fae96 100644 --- a/test/comprehensive.py +++ b/test/comprehensive.py @@ -19,10 +19,13 @@ Load up the extension module Automatic checking of the number and type of arguments. Foo's constructor takes a single long parameter. - >>> ext = Foo() - Traceback (innermost last): - File "", line 1, in ? - TypeError: function requires exactly 1 argument; 0 given + >>> try: + ... ext = Foo() + ... except TypeError, err: + ... assert re.match(r'function .* exactly 1 argument;? \(?0 given\)?', + ... str(err)) + ... else: + ... print 'no exception' >>> try: ext = Foo('foo') ... except TypeError, err: @@ -1014,9 +1017,12 @@ test inheritB2 -2 >>> str(i) '2' - >>> j = i/i - Traceback (innermost last): - TypeError: bad operand type(s) for / + >>> try: j = i/i + ... except TypeError, err: + ... assert re.match(r'(bad|unsupported) operand type\(s\) for /', + ... str(err)) + ... else: print 'no exception' + >>> j = abs(i) Traceback (innermost last): TypeError: bad operand type for abs() From 884b59a0b308f448b63f856ea6b56af7a99106c5 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 2 Jul 2001 00:16:28 +0000 Subject: [PATCH 119/369] Added JIT debugging hooks [SVN r10507] --- example/dvect.cpp | 11 +++++++++++ example/ivect.cpp | 11 +++++++++++ example/noncopyable_export.cpp | 10 ++++++++++ example/noncopyable_import.cpp | 10 ++++++++++ 4 files changed, 42 insertions(+) diff --git a/example/dvect.cpp b/example/dvect.cpp index da6b35a3..4d109c96 100644 --- a/example/dvect.cpp +++ b/example/dvect.cpp @@ -20,6 +20,16 @@ namespace { } } +# ifdef BOOST_MSVC // fixes for JIT debugging +# include +extern "C" void structured_exception_translator(unsigned int, EXCEPTION_POINTERS*) +{ + throw; +} +extern "C" void (*old_translator)(unsigned int, EXCEPTION_POINTERS*) + = _set_se_translator(structured_exception_translator); +# endif + BOOST_PYTHON_MODULE_INIT(dvect) { try @@ -43,3 +53,4 @@ BOOST_PYTHON_MODULE_INIT(dvect) python::handle_exception(); // Deal with the exception for Python } } + diff --git a/example/ivect.cpp b/example/ivect.cpp index db1c0ec3..848d693e 100644 --- a/example/ivect.cpp +++ b/example/ivect.cpp @@ -20,6 +20,16 @@ namespace { } } +# ifdef BOOST_MSVC // fixes for JIT debugging +# include +extern "C" void structured_exception_translator(unsigned int, EXCEPTION_POINTERS*) +{ + throw; +} +extern "C" void (*old_translator)(unsigned int, EXCEPTION_POINTERS*) + = _set_se_translator(structured_exception_translator); +# endif + BOOST_PYTHON_MODULE_INIT(ivect) { try @@ -43,3 +53,4 @@ BOOST_PYTHON_MODULE_INIT(ivect) python::handle_exception(); // Deal with the exception for Python } } + diff --git a/example/noncopyable_export.cpp b/example/noncopyable_export.cpp index 794b1200..b118abb8 100644 --- a/example/noncopyable_export.cpp +++ b/example/noncopyable_export.cpp @@ -6,6 +6,16 @@ namespace python = boost::python; #include "noncopyable.h" +# ifdef BOOST_MSVC // fixes for JIT debugging +# include +extern "C" void structured_exception_translator(unsigned int, EXCEPTION_POINTERS*) +{ + throw; +} +extern "C" void (*old_translator)(unsigned int, EXCEPTION_POINTERS*) + = _set_se_translator(structured_exception_translator); +# endif + BOOST_PYTHON_MODULE_INIT(noncopyable_export) { try diff --git a/example/noncopyable_import.cpp b/example/noncopyable_import.cpp index ea2477be..66c6457d 100644 --- a/example/noncopyable_import.cpp +++ b/example/noncopyable_import.cpp @@ -19,6 +19,16 @@ namespace { // Avoid cluttering the global namespace. } } +# ifdef BOOST_MSVC // fixes for JIT debugging +# include +extern "C" void structured_exception_translator(unsigned int, EXCEPTION_POINTERS*) +{ + throw; +} +extern "C" void (*old_translator)(unsigned int, EXCEPTION_POINTERS*) + = _set_se_translator(structured_exception_translator); +# endif + BOOST_PYTHON_MODULE_INIT(noncopyable_import) { try From e504c3cd466326b11d40c363a67c89e356049db5 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 2 Jul 2001 00:16:53 +0000 Subject: [PATCH 120/369] Made it a little more immune to command-line argument ordering [SVN r10508] --- example/tst_dvect2.py | 20 +++++++++++++------- example/tst_ivect2.py | 20 +++++++++++++------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/example/tst_dvect2.py b/example/tst_dvect2.py index 539e0b88..2e72bf8b 100644 --- a/example/tst_dvect2.py +++ b/example/tst_dvect2.py @@ -87,12 +87,18 @@ if (__name__ == "__main__"): import sys, string broken_auto_ptr = 0 n = 1 - if (len(sys.argv) > 1): - if (sys.argv[1] == "--broken-auto-ptr"): - broken_auto_ptr = 1 - if (len(sys.argv) > 2): - n = string.atoi(sys.argv[2]) - else: - n = string.atoi(sys.argv[1]) + + if len(sys.argv) > 1: + argv = [] + + for x in sys.argv: + if x != '--broken_auto_ptr': + argv.append(x) + broken_auto_ptr = argv != sys.argv + sys.argv = argv + + if len(sys.argv) > 1: + n = string.atoi(sys.argv[1]) + for i in xrange(n): f(broken_auto_ptr) diff --git a/example/tst_ivect2.py b/example/tst_ivect2.py index 6ffd2826..e7607151 100644 --- a/example/tst_ivect2.py +++ b/example/tst_ivect2.py @@ -87,12 +87,18 @@ if (__name__ == "__main__"): import sys, string broken_auto_ptr = 0 n = 1 - if (len(sys.argv) > 1): - if (sys.argv[1] == "--broken-auto-ptr"): - broken_auto_ptr = 1 - if (len(sys.argv) > 2): - n = string.atoi(sys.argv[2]) - else: - n = string.atoi(sys.argv[1]) + + if len(sys.argv) > 1: + argv = [] + + for x in sys.argv: + if x != '--broken_auto_ptr': + argv.append(x) + broken_auto_ptr = argv != sys.argv + sys.argv = argv + + if len(sys.argv) > 1: + n = string.atoi(sys.argv[1]) + for i in xrange(n): f(broken_auto_ptr) From 76c6adf1cfe57835c6fa264296820739cd1ef7b6 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 3 Jul 2001 12:43:12 +0000 Subject: [PATCH 121/369] --broken_auto_ptr -> --broken-auto-ptr [SVN r10511] --- example/tst_dvect2.py | 2 +- example/tst_ivect2.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/example/tst_dvect2.py b/example/tst_dvect2.py index 2e72bf8b..90d381a7 100644 --- a/example/tst_dvect2.py +++ b/example/tst_dvect2.py @@ -92,7 +92,7 @@ if (__name__ == "__main__"): argv = [] for x in sys.argv: - if x != '--broken_auto_ptr': + if x != '--broken-auto-ptr': argv.append(x) broken_auto_ptr = argv != sys.argv sys.argv = argv diff --git a/example/tst_ivect2.py b/example/tst_ivect2.py index e7607151..a9e6aeef 100644 --- a/example/tst_ivect2.py +++ b/example/tst_ivect2.py @@ -92,7 +92,7 @@ if (__name__ == "__main__"): argv = [] for x in sys.argv: - if x != '--broken_auto_ptr': + if x != '--broken-auto-ptr': argv.append(x) broken_auto_ptr = argv != sys.argv sys.argv = argv From 606898f5691a641a695d806941ad7c08d0a204f6 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 6 Jul 2001 07:31:39 +0000 Subject: [PATCH 122/369] tiny trivial fix. [SVN r10547] --- example/test_cross_module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/test_cross_module.py b/example/test_cross_module.py index 86c1be0e..c5e2bef6 100644 --- a/example/test_cross_module.py +++ b/example/test_cross_module.py @@ -137,4 +137,4 @@ def run(args = None): if __name__ == '__main__': import sys - sys.exit(run()) + sys.exit(run()[0]) From 8ad7d06ec6fd2bce16011e5d3a0b7ade321f98ee Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 8 Jul 2001 22:30:12 +0000 Subject: [PATCH 123/369] fixed > -> > [SVN r10571] --- doc/pointers.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/pointers.html b/doc/pointers.html index 00f7bb41..9085e152 100644 --- a/doc/pointers.html +++ b/doc/pointers.html @@ -85,7 +85,7 @@ code before the last Python reference to it disappears: BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround PyObject* to_python(Foo* p) { - return boost::python::python_extension_class_converters<Foo>::ptr_to_python(p); + return boost::python::python_extension_class_converters<Foo>::ptr_to_python(p); } PyObject* to_python(const Foo* p) From 819db1524fe330793593ea4efea395f20068381a Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 9 Jul 2001 23:45:09 +0000 Subject: [PATCH 124/369] Integrate fix from Peter.Bienstman@rug.ac.be [SVN r10574] --- doc/enums.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/enums.html b/doc/enums.html index 32d61447..c58ca34d 100644 --- a/doc/enums.html +++ b/doc/enums.html @@ -91,8 +91,8 @@ initialization. These bind the corresponding enum values to the appropriate names so they can be used from Python:

    -mymodule.add(boost::python::to_python(enum_value_1), "enum_value_1");
    -mymodule.add(boost::python::to_python(enum_value_2), "enum_value_2");
    +mymodule.add(boost::python::make_ref(enum_value_1), "enum_value_1");
    +mymodule.add(boost::python::make_ref(enum_value_2), "enum_value_2");
     ...
     
    From 26aa8b69f96b7537652ba8b41e5ba10214e7a6dd Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 10 Jul 2001 17:57:06 +0000 Subject: [PATCH 125/369] Integrate fix from Peter.Bienstman@rug.ac.be [SVN r10584] --- doc/pointers.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/pointers.html b/doc/pointers.html index 9085e152..11cfd8d9 100644 --- a/doc/pointers.html +++ b/doc/pointers.html @@ -85,7 +85,7 @@ code before the last Python reference to it disappears: BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround PyObject* to_python(Foo* p) { - return boost::python::python_extension_class_converters<Foo>::ptr_to_python(p); + return boost::python::python_extension_class_converters<Foo>::smart_ptr_to_python(p); } PyObject* to_python(const Foo* p) From 4f41a10fef7761fc571212659afa4639bf5816d4 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 11 Jul 2001 11:53:46 +0000 Subject: [PATCH 126/369] fixed a comment [SVN r10588] --- include/boost/python/detail/base_object.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/python/detail/base_object.hpp b/include/boost/python/detail/base_object.hpp index bf0faa7b..95a2805c 100644 --- a/include/boost/python/detail/base_object.hpp +++ b/include/boost/python/detail/base_object.hpp @@ -39,7 +39,7 @@ typedef base_object python_type; // -// class_t template member function implementations +// base_object member function implementations // template base_object::base_object(PyTypeObject* type_obj) From 24509a21d4fca7d6ae0a8f1250508af5f45a1b38 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Thu, 12 Jul 2001 15:31:15 +0000 Subject: [PATCH 127/369] Change absolute URL's to relative [SVN r10594] --- doc/under-the-hood.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/under-the-hood.html b/doc/under-the-hood.html index 733f0f54..e2a0ce2b 100644 --- a/doc/under-the-hood.html +++ b/doc/under-the-hood.html @@ -36,7 +36,7 @@ template defines a whole raft of these conversions (for T, T*, T&, std::auto_ptr<T>, etc.), using the same inline friend function technique employed by the boost operators + "file:///c:/boost/site/libs/utility/operators.htm">the boost operators library.

    Because the to_python and from_python functions From 08eb28f7b825de12a84f8e0eeb86309ba4d5c26d Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 22 Jul 2001 17:03:15 +0000 Subject: [PATCH 128/369] move to main trunk [SVN r10690] --- build/Jamfile | 248 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 248 insertions(+) create mode 100644 build/Jamfile diff --git a/build/Jamfile b/build/Jamfile new file mode 100644 index 00000000..fa31efc4 --- /dev/null +++ b/build/Jamfile @@ -0,0 +1,248 @@ +# (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 +# +# 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 .test and .run +# .test runs the test when it is out-of-date, and the "all" target +# depends on it so that it it is built by default. .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_converters - +# pickle1 - +# pickle2 - +# pickle3 - +# +# dvect1 - +# dvect2 - +# ivect1 - +# ivect2 - +# noncopyable - +# +# subproject-specific environment/command-line variables: +# +# 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 ; + +# Do some OS-specific setup +if $(NT) +{ + PYTHON_ROOT ?= c:/tools/python ; + PYTHON_INCLUDES ?= $(PYTHON_ROOT)/include <*>/usr/include/python2.1 ; + PYTHON_LIBS ?= c:/cygnus/lib/python2.1/config/libpython2.1.dll.a ; + PYTHON_LIB_PATH = $(PYTHON_ROOT)/libs ; + + # common properties required for compiling any Python module. + PYTHON_PROPERTIES ?= + <*>SIZEOF_LONG=4 + <*>USE_DL_IMPORT + + # if you don't request multithreading, you can't get the DLL runtime, + # which is needed for the python modules to work right + <*>multi + ; + + SHELL_SET ?= "set " ; + SHELL_EXPORT ?= ; # shell variables are exported by default +} +else if $(UNIX) +{ + PYTHON_INCLUDES ?= /usr/include/python1.5 ; + PYTHON_LIBS ?= /usr/lib/python1.5/config/libpython1.5.a ; + SHELL_SET ?= "" ; + SHELL_EXPORT ?= "export " ; +} + +####################### + +# +# Declare the boost python static link library +# + +# standard include requirements for anything using Boost.Python +BOOST_PYTHON_INCLUDES = $(BOOST_ROOT) $(PYTHON_INCLUDES) ; + +# Base names of the source files for libboost_python +CPP_SOURCES = + classes conversions extension_class functions + init_function module_builder objects types cross_module ; + +lib libboost_python : ../src/$(CPP_SOURCES).cpp + # requirements + : $(BOOST_PYTHON_INCLUDES) + true + $(PYTHON_PROPERTIES) ; + +####################### + +# boost-python name : sources : requirements : default-BUILD +# +# Declare a boost python module. Return a list of the DLL files generated. +rule boost-python +{ + # declare a DLL; add the boost python library to sources + dll $(<) : libboost_python $(>) + + # Requirements + : $(3) # caller-specified requirements + + # standard requirements + $(BOOST_PYTHON_INCLUDES) + <*>$(PYTHON_LIB_PATH) + <*>$(PYTHON_LIBS) + $(PYTHON_PROPERTIES) + + : $(4) ; # pass on the default-BUILD, if any +} + +####################### + +# boost-python-test target : python-script sources : requirements : local-build : args +# +# declare two python module tests: $(<).test which builds when out-of-date, and +# $(<).run which builds unconditionally. +rule boost-python-test +{ + # tell Jam that the python script is relative to this directory + SEARCH on $(>[1]) = $(SEARCH_SOURCE) ; + + # required command-line args can be specified in argument 5 + # The user can add additional arguments in PYTHON_TEST_ARGS. + local gPYTHON_TEST_ARGS = $(5) $(PYTHON_TEST_ARGS) ; + + # declare the two subsidiary tests. + declare-local-target $(<:S=.test) : $(>) : $(PYTHON_PROPERTIES) : $(4) : PYTHON_TEST ; + declare-local-target $(<:S=.run) : $(>) : $(PYTHON_PROPERTIES) : $(4) : PYTHON_RUNTEST ; +} + +# how do we invoke python? +PYTHON ?= python ; + +# special rules for two new target types: PYTHON_TEST and PYTHON_RUNTEST. +# These are identical except that PYTHON_TEST runs the test when out-of-date, and +# PYTHON_RUNTEST runs the test unconditionally. These are used by boost-python-test. +SUFPYTHON_TEST = .test ; +gGENERATOR_FUNCTION(PYTHON_TEST) = python-test-target ; +rule python-test-target # test-target : sources : +{ + python-test-aux $(<) : $(>) ; + Clean clean : $(<) ; # remove the test-target as part of any clean operation + type-DEPENDS test : $(<) ; + MakeLocate $(<) : $(LOCATE_TARGET) ; +} +actions python-test-target +{ + $(SHELL_SET)PYTHONPATH=$(PYTHONPATH) + $(SHELL_EXPORT)PYTHONPATH + $(PYTHON) "$(>)" $(ARGS) > "$(<)" +} + +SUFPYTHON_RUNTEST = .run ; +gGENERATOR_FUNCTION(PYTHON_RUNTEST) = python-runtest-target ; +rule python-runtest-target # test-target : sources : +{ + python-test-aux $(<) : $(>) ; + NOTFILE $(<) ; + ALWAYS $(<) ; +} +actions python-runtest-target +{ + $(SHELL_SET)PYTHONPATH=$(PYTHONPATH) + $(SHELL_EXPORT)PYTHONPATH + $(PYTHON) "$(>)" $(ARGS) +} + +rule python-test-aux # target : sources +{ + DEPENDS $(<) : $(>) ; + + ARGS on $(<) += $(gPYTHON_TEST_ARGS) ; + + # Some tests need an extra command-line arg if built with + # msvc. Checking the target grist is a cheap way to + # find out. + switch $(<) + { + case <*\\\\msvc\\\\*>* : ARGS on $(<) += --broken-auto-ptr ; + } + + # compute the PYTHONPATH environment variable that will allow the test to + # find all of the modules on which it depends. + PYTHONPATH on $(<) = [ join + $(gLOCATE($(>[1]))) # location of python test file + $(gRUN_PATH($(<))) # location of module dependencies + [ join-path $(TOP) libs python test ] # location of doctest + $(PYTHONPATH) # base PYTHONPATH from environment + : $(SPLITPATH) ] ; # platform path separator +} + +############# comprehensive module and test ########### +boost-python boost_python_test : ../test/comprehensive.cpp ; +boost-python-test comprehensive : [ join-path $(DOTDOT) test comprehensive.py ] boost_python_test ; + +############# simple tests from ../example ############ + +rule boost-python-example-test +{ + boost-python $(<) : ../example/$(<).cpp ; + boost-python-test $(<) : [ join-path $(DOTDOT) example test_$(<).py ] $(<) ; +} + + +boost-python-example-test abstract ; +boost-python-example-test getting_started1 ; +boost-python-example-test getting_started2 ; +boost-python-example-test simple_vector ; +boost-python-example-test do_it_yourself_converters ; +boost-python-example-test pickle1 ; +boost-python-example-test pickle2 ; +boost-python-example-test pickle3 ; + + +boost-python ivect : ../example/ivect.cpp ; +boost-python dvect : ../example/dvect.cpp ; +boost-python noncopyable_export : ../example/noncopyable_export.cpp ; +boost-python 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 +rule boost-python-multi-example-test # test-name : python-file libs +{ + boost-python-test $(<) : ../example/tst_$(<).py $(>) : : : $(PYTHON_VECT_ITERATIONS) ; +} +PYTHON_VECT_ITERATIONS ?= 10 ; + +boost-python-multi-example-test dvect1 : ivect dvect ; +boost-python-multi-example-test dvect2 : ivect dvect ; + +boost-python-multi-example-test ivect1 : ivect dvect ; +boost-python-multi-example-test ivect2 : ivect dvect ; + +boost-python-multi-example-test noncopyable : noncopyable_import noncopyable_export ; + From 3c6a8d718fc5a7d198e1b089016b733eaaee4469 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 23 Jul 2001 03:34:37 +0000 Subject: [PATCH 129/369] build system update [SVN r10695] --- build/Jamfile | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/build/Jamfile b/build/Jamfile index fa31efc4..314b1440 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -61,10 +61,7 @@ if $(NT) PYTHON_PROPERTIES ?= <*>SIZEOF_LONG=4 <*>USE_DL_IMPORT - - # if you don't request multithreading, you can't get the DLL runtime, - # which is needed for the python modules to work right - <*>multi + dynamic ; SHELL_SET ?= "set " ; From f2e34d4836eab58dfd123b1aba294f5ed1d799fe Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 30 Jul 2001 13:31:23 +0000 Subject: [PATCH 130/369] MSVC doesn't like boost::dereferencable unless T has a default constructor, so operator-> must be defined by hand [SVN r10720] --- include/boost/python/detail/cast.hpp | 7 ++++++- include/boost/python/reference.hpp | 9 ++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/include/boost/python/detail/cast.hpp b/include/boost/python/detail/cast.hpp index a6f2f046..e047c0b3 100644 --- a/include/boost/python/detail/cast.hpp +++ b/include/boost/python/detail/cast.hpp @@ -51,7 +51,7 @@ inline PyObject* as_object(PyTypeObject* p) { return reinterpret_cast // If I didn't have to support stupid MSVC6 we could just use a simple template function: // template T* downcast(PyObject*). template -struct downcast : boost::dereferenceable, T*> +struct downcast { downcast(PyObject* p) : m_p(detail::downcast_traits::cast(detail::as_base_object((T*)0, p))) @@ -70,6 +70,11 @@ struct downcast : boost::dereferenceable, T*> {} 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: diff --git a/include/boost/python/reference.hpp b/include/boost/python/reference.hpp index c633b9d7..a1585099 100644 --- a/include/boost/python/reference.hpp +++ b/include/boost/python/reference.hpp @@ -20,7 +20,7 @@ BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE -template +template struct py_ptr_conversions : Base { inline friend T from_python(PyObject* x, boost::python::type) @@ -42,8 +42,7 @@ BOOST_PYTHON_IMPORT_CONVERSION(py_ptr_conversions); template class reference - : public py_ptr_conversions, T, - boost::dereferenceable, T*> > // supplies op-> + : public py_ptr_conversions, T> { public: typedef T value_type; @@ -117,6 +116,10 @@ public: T& operator*() 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* release() From f1ae502b1f9b3c7a55782557774b4fb77171b32c Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 31 Jul 2001 07:12:14 +0000 Subject: [PATCH 131/369] Merged from branch boost_python_richcmp. [SVN r10728] --- build/filemgr.py | 10 + build/irix_CC.mak | 25 ++- build/linux_gcc.mak | 25 ++- build/mingw32.mak | 34 +++- build/tru64_cxx.mak | 25 ++- build/vc60.mak | 30 ++- doc/richcmp.html | 106 +++++++++++ doc/special.html | 59 +++++- example/pickle3.cpp | 4 +- example/richcmp1.cpp | 87 +++++++++ example/richcmp2.cpp | 65 +++++++ example/richcmp3.cpp | 178 ++++++++++++++++++ example/test_pickle3.py | 12 +- example/test_richcmp1.py | 40 ++++ example/test_richcmp2.py | 41 ++++ example/test_richcmp3.py | 77 ++++++++ example/vector_wrapper.h | 117 ++++++++++++ include/boost/python/classes.hpp | 52 +++++ .../boost/python/detail/extension_class.hpp | 12 ++ include/boost/python/detail/types.hpp | 10 +- include/boost/python/operators.hpp | 14 +- src/classes.cpp | 36 ++++ src/gen_extclass.py | 21 +++ src/gen_init_function.py | 3 +- src/types.cpp | 70 ++++++- test/comprehensive.py | 8 +- 26 files changed, 1110 insertions(+), 51 deletions(-) create mode 100644 doc/richcmp.html create mode 100644 example/richcmp1.cpp create mode 100644 example/richcmp2.cpp create mode 100644 example/richcmp3.cpp create mode 100644 example/test_richcmp1.py create mode 100644 example/test_richcmp2.py create mode 100644 example/test_richcmp3.py create mode 100644 example/vector_wrapper.h diff --git a/build/filemgr.py b/build/filemgr.py index d8310f6d..5e32460e 100644 --- a/build/filemgr.py +++ b/build/filemgr.py @@ -52,6 +52,13 @@ bpl_exa + "/tst_dvect2.py", bpl_exa + "/tst_ivect1.py", bpl_exa + "/tst_ivect2.py", bpl_exa + "/test_cross_module.py", +bpl_exa + "/vector_wrapper.h", +bpl_exa + "/richcmp1.cpp", +bpl_exa + "/richcmp2.cpp", +bpl_exa + "/richcmp3.cpp", +bpl_exa + "/test_richcmp1.py", +bpl_exa + "/test_richcmp2.py", +bpl_exa + "/test_richcmp3.py", ) defs = ( @@ -68,6 +75,9 @@ defs = ( "noncopyable_import", "ivect", "dvect", +"richcmp1", +"richcmp2", +"richcmp3", ) if (__name__ == "__main__"): diff --git a/build/irix_CC.mak b/build/irix_CC.mak index 5894ff51..1fbe3388 100644 --- a/build/irix_CC.mak +++ b/build/irix_CC.mak @@ -19,8 +19,8 @@ BOOST=$(ROOT)/boost PYEXE=/usr/local/Python-1.5.2/bin/python PYINC=-I/usr/local/Python-1.5.2/include/python1.5 -#PYEXE=/usr/local/Python-2.0/bin/python -#PYINC=-I/usr/local/Python-2.0/include/python2.0 +#PYEXE=/usr/local/Python-2.1/bin/python +#PYINC=-I/usr/local/Python-2.1/include/python2.1 STLPORTINC=-I$(BOOST)/boost/compatibility/cpp_c_headers STDOPTS= @@ -46,7 +46,8 @@ DEPOBJ=$(OBJ) \ do_it_yourself_converters.o \ pickle1.o pickle2.o pickle3.o \ noncopyable_export.o noncopyable_import.o \ - ivect.o dvect.o + ivect.o dvect.o \ + richcmp1.o richcmp2.o richcmp3.o .SUFFIXES: .o .cpp @@ -58,7 +59,8 @@ all: libboost_python.a \ do_it_yourself_converters.so \ pickle1.so pickle2.so pickle3.so \ noncopyable_export.so noncopyable_import.so \ - ivect.so dvect.so + ivect.so dvect.so \ + richcmp1.so richcmp2.so richcmp3.so libboost_python.a: $(OBJ) rm -f libboost_python.a @@ -105,6 +107,15 @@ ivect.so: $(OBJ) ivect.o dvect.so: $(OBJ) dvect.o $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.so +richcmp1.so: $(OBJ) richcmp1.o + $(LD) $(LDOPTS) $(OBJ) richcmp1.o -o richcmp1.so + +richcmp2.so: $(OBJ) richcmp2.o + $(LD) $(LDOPTS) $(OBJ) richcmp2.o -o richcmp2.so + +richcmp3.so: $(OBJ) richcmp3.o + $(LD) $(LDOPTS) $(OBJ) richcmp3.o -o richcmp3.so + .cpp.o: $(CPP) $(CPPOPTS) -c $*.cpp @@ -119,6 +130,9 @@ test: $(PYEXE) test_pickle2.py $(PYEXE) test_pickle3.py $(PYEXE) test_cross_module.py + $(PYEXE) test_richcmp1.py + $(PYEXE) test_richcmp2.py + $(PYEXE) test_richcmp3.py clean: rm -f $(OBJ) libboost_python.a libboost_python.a.input @@ -135,6 +149,9 @@ clean: rm -f noncopyable_import.o noncopyable_import.so rm -f ivect.o ivect.so rm -f dvect.o dvect.so + rm -f richcmp1.o richcmp1.so + rm -f richcmp2.o richcmp2.so + rm -f richcmp3.o richcmp3.so rm -f so_locations *.pyc rm -rf ii_files diff --git a/build/linux_gcc.mak b/build/linux_gcc.mak index 5971ca61..3fe407a0 100644 --- a/build/linux_gcc.mak +++ b/build/linux_gcc.mak @@ -21,8 +21,8 @@ PYEXE=PYTHONPATH=. /usr/bin/python PYINC=-I/usr/include/python1.5 #PYEXE=/usr/local/Python-1.5.2/bin/python #PYINC=-I/usr/local/Python-1.5.2/include/python1.5 -#PYEXE=/usr/local/Python-2.0/bin/python -#PYINC=-I/usr/local/Python-2.0/include/python2.0 +#PYEXE=/usr/local/Python-2.1/bin/python +#PYINC=-I/usr/local/Python-2.1/include/python2.1 STDOPTS=-fPIC -ftemplate-depth-21 WARNOPTS= @@ -47,7 +47,8 @@ DEPOBJ=$(OBJ) \ do_it_yourself_converters.o \ pickle1.o pickle2.o pickle3.o \ noncopyable_export.o noncopyable_import.o \ - ivect.o dvect.o + ivect.o dvect.o \ + richcmp1.o richcmp2.o richcmp3.o .SUFFIXES: .o .cpp @@ -59,7 +60,8 @@ all: libboost_python.a \ do_it_yourself_converters.so \ pickle1.so pickle2.so pickle3.so \ noncopyable_export.so noncopyable_import.so \ - ivect.so dvect.so + ivect.so dvect.so \ + richcmp1.so richcmp2.so richcmp3.so libboost_python.a: $(OBJ) rm -f libboost_python.a @@ -106,6 +108,15 @@ ivect.so: $(OBJ) ivect.o dvect.so: $(OBJ) dvect.o $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.so +richcmp1.so: $(OBJ) richcmp1.o + $(LD) $(LDOPTS) $(OBJ) richcmp1.o -o richcmp1.so + +richcmp2.so: $(OBJ) richcmp2.o + $(LD) $(LDOPTS) $(OBJ) richcmp2.o -o richcmp2.so + +richcmp3.so: $(OBJ) richcmp3.o + $(LD) $(LDOPTS) $(OBJ) richcmp3.o -o richcmp3.so + .cpp.o: $(CPP) $(CPPOPTS) -c $*.cpp @@ -120,6 +131,9 @@ test: $(PYEXE) test_pickle2.py $(PYEXE) test_pickle3.py $(PYEXE) test_cross_module.py + $(PYEXE) test_richcmp1.py + $(PYEXE) test_richcmp2.py + $(PYEXE) test_richcmp3.py clean: rm -f $(OBJ) libboost_python.a libboost_python.a.input @@ -136,6 +150,9 @@ clean: rm -f noncopyable_import.o noncopyable_import.so rm -f ivect.o ivect.so rm -f dvect.o dvect.so + rm -f richcmp1.o richcmp1.so + rm -f richcmp2.o richcmp2.so + rm -f richcmp3.o richcmp3.so rm -f so_locations *.pyc softlinks: diff --git a/build/mingw32.mak b/build/mingw32.mak index 0a16f332..6f192ce2 100644 --- a/build/mingw32.mak +++ b/build/mingw32.mak @@ -62,10 +62,11 @@ all: libboost_python.a \ do_it_yourself_converters.pyd \ pickle1.pyd pickle2.pyd pickle3.pyd \ noncopyable_export.pyd noncopyable_import.pyd \ - ivect.pyd dvect.pyd + ivect.pyd dvect.pyd \ + richcmp1.pyd richcmp2.pyd richcmp3.pyd libboost_python.a: $(OBJ) - del libboost_python.a + -del libboost_python.a ar r libboost_python.a $(OBJ) DLLWRAPOPTS=-s --driver-name g++ -s \ @@ -149,6 +150,24 @@ dvect.pyd: $(OBJ) dvect.o --def dvect.def \ $(OBJ) dvect.o $(PYLIB) +richcmp1.pyd: $(OBJ) richcmp1.o + dllwrap $(DLLWRAPOPTS) \ + --dllname richcmp1.pyd \ + --def richcmp1.def \ + $(OBJ) richcmp1.o $(PYLIB) + +richcmp2.pyd: $(OBJ) richcmp2.o + dllwrap $(DLLWRAPOPTS) \ + --dllname richcmp2.pyd \ + --def richcmp2.def \ + $(OBJ) richcmp2.o $(PYLIB) + +richcmp3.pyd: $(OBJ) richcmp3.o + dllwrap $(DLLWRAPOPTS) \ + --dllname richcmp3.pyd \ + --def richcmp3.def \ + $(OBJ) richcmp3.o $(PYLIB) + .cpp.o: $(CPP) $(CPPOPTS) -c $*.cpp @@ -163,12 +182,15 @@ test: $(PYEXE) test_pickle2.py $(PYEXE) test_pickle3.py $(PYEXE) test_cross_module.py + $(PYEXE) test_richcmp1.py + $(PYEXE) test_richcmp2.py + $(PYEXE) test_richcmp3.py clean: - del *.o - del *.a - del *.pyd - del *.pyc + -del *.o + -del *.a + -del *.pyd + -del *.pyc softlinks: python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) softlinks diff --git a/build/tru64_cxx.mak b/build/tru64_cxx.mak index 21a8126e..8f3d3abf 100644 --- a/build/tru64_cxx.mak +++ b/build/tru64_cxx.mak @@ -19,8 +19,8 @@ BOOST=$(ROOT)/boost PYEXE=/usr/local/Python-1.5.2/bin/python PYINC=-I/usr/local/Python-1.5.2/include/python1.5 -#PYEXE=/usr/local/Python-2.0/bin/python -#PYINC=-I/usr/local/Python-2.0/include/python2.0 +#PYEXE=/usr/local/Python-2.1/bin/python +#PYINC=-I/usr/local/Python-2.1/include/python2.1 #STLPORTINC=-I/usr/local/STLport-4.1b3/stlport #STLPORTINC=-I/usr/local/STLport-4.1b4/stlport #STLPORTOPTS= \ @@ -57,7 +57,8 @@ DEPOBJ=$(OBJ) \ do_it_yourself_converters.o \ pickle1.o pickle2.o pickle3.o \ noncopyable_export.o noncopyable_import.o \ - ivect.o dvect.o + ivect.o dvect.o \ + richcmp1.o richcmp2.o richcmp3.o .SUFFIXES: .o .cpp @@ -69,7 +70,8 @@ all: libboost_python.a \ do_it_yourself_converters.so \ pickle1.so pickle2.so pickle3.so \ noncopyable_export.so noncopyable_import.so \ - ivect.so dvect.so + ivect.so dvect.so \ + richcmp1.so richcmp2.so richcmp3.so libboost_python.a: $(OBJ) rm -f libboost_python.a @@ -120,6 +122,15 @@ ivect.so: $(OBJ) ivect.o dvect.so: $(OBJ) dvect.o $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.so +richcmp1.so: $(OBJ) richcmp1.o + $(LD) $(LDOPTS) $(OBJ) richcmp1.o -o richcmp1.so + +richcmp2.so: $(OBJ) richcmp2.o + $(LD) $(LDOPTS) $(OBJ) richcmp2.o -o richcmp2.so + +richcmp3.so: $(OBJ) richcmp3.o + $(LD) $(LDOPTS) $(OBJ) richcmp3.o -o richcmp3.so + .cpp.o: $(CPP) $(CPPOPTS) -c $*.cpp @@ -134,6 +145,9 @@ test: $(PYEXE) test_pickle2.py $(PYEXE) test_pickle3.py $(PYEXE) test_cross_module.py + $(PYEXE) test_richcmp1.py + $(PYEXE) test_richcmp2.py + $(PYEXE) test_richcmp3.py clean: rm -f $(OBJ) libboost_python.a libboost_python.a.input @@ -150,6 +164,9 @@ clean: rm -f noncopyable_import.o noncopyable_import.so rm -f ivect.o ivect.so rm -f dvect.o dvect.so + rm -f richcmp1.o richcmp1.so + rm -f richcmp2.o richcmp2.so + rm -f richcmp3.o richcmp3.so rm -f so_locations *.pyc rm -rf cxx_repository diff --git a/build/vc60.mak b/build/vc60.mak index f0016075..f545015b 100644 --- a/build/vc60.mak +++ b/build/vc60.mak @@ -17,6 +17,9 @@ BOOST_UNIX=$(HOME)/boost PYEXE="C:\Program files\Python\python.exe" PYINC=/I"C:\Program files\Python\include" PYLIB="C:\Program files\Python\libs\python15.lib" +#PYEXE="C:\Python21\python.exe" +#PYINC=/I"C:\Python21\include" +#PYLIB="C:\Python21\libs\python21.lib" STDOPTS=/nologo /MD /GR /GX /Zm200 WARNOPTS= @@ -43,7 +46,8 @@ all: boost_python.lib \ do_it_yourself_converters.pyd \ pickle1.pyd pickle2.pyd pickle3.pyd \ noncopyable_export.pyd noncopyable_import.pyd \ - ivect.pyd dvect.pyd + ivect.pyd dvect.pyd \ + richcmp1.pyd richcmp2.pyd richcmp3.pyd boost_python.lib: $(OBJ) $(LD) -lib /nologo /out:boost_python.lib $(OBJ) @@ -87,6 +91,15 @@ ivect.pyd: $(OBJ) ivect.obj dvect.pyd: $(OBJ) dvect.obj $(LD) $(LDOPTS) $(OBJ) dvect.obj $(PYLIB) /export:initdvect /out:"dvect.pyd" +richcmp1.pyd: $(OBJ) richcmp1.obj + $(LD) $(LDOPTS) $(OBJ) richcmp1.obj $(PYLIB) /export:initrichcmp1 /out:"richcmp1.pyd" + +richcmp2.pyd: $(OBJ) richcmp2.obj + $(LD) $(LDOPTS) $(OBJ) richcmp2.obj $(PYLIB) /export:initrichcmp2 /out:"richcmp2.pyd" + +richcmp3.pyd: $(OBJ) richcmp3.obj + $(LD) $(LDOPTS) $(OBJ) richcmp3.obj $(PYLIB) /export:initrichcmp3 /out:"richcmp3.pyd" + .cpp.obj: $(CPP) $(CPPOPTS) /c $*.cpp @@ -101,14 +114,17 @@ test: $(PYEXE) test_pickle2.py $(PYEXE) test_pickle3.py $(PYEXE) test_cross_module.py --broken-auto-ptr + $(PYEXE) test_richcmp1.py + $(PYEXE) test_richcmp2.py + $(PYEXE) test_richcmp3.py clean: - del *.obj - del *.lib - del *.exp - del *.idb - del *.pyd - del *.pyc + -del *.obj + -del *.lib + -del *.exp + -del *.idb + -del *.pyd + -del *.pyc softlinks: python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) softlinks diff --git a/doc/richcmp.html b/doc/richcmp.html new file mode 100644 index 00000000..d9ab7044 --- /dev/null +++ b/doc/richcmp.html @@ -0,0 +1,106 @@ + + +Rich Comparisons + +

    + +c++boost.gif (8819 bytes) + +
    +

    Rich Comparisons

    + +
    +In Python versions up to and including Python 2.0, support for +implementing comparisons on user-defined classes and extension types +was quite simple. Classes could implement a __cmp__ method +that was given two instances of a class as arguments, and could only +return 0 if they were equal or +1 or -1 if +they were not. The method could not raise an exception or return +anything other than an integer value. +In Python 2.1, Rich Comparisons were added (see +PEP 207). +Python classes can now individually overload each of the <, <=, +>, >=, ==, and != operations. + +

    +For more detailed information, search for "rich comparison" +here. + +

    +Boost.Python supports both automatic overloading and manual overloading +of the Rich Comparison operators. The compile-time support is +independent of the Python version that is used when compiling +Boost.Python extension modules. That is, op_lt for example can +always be used, and the C++ operator< will always be bound +to the Python method __lt__. However, the run-time +behavior will depend on the Python version. + +

    +With Python versions before 2.1, the Rich Comparison operators will not +be called by Python when any of the six comparison operators +(<, <=, ==, !=, +>, >=) is used in an expression. The only way +to access the corresponding methods is to call them explicitly, e.g. +a.__lt__(b). Only with Python versions 2.1 or higher will +expressions like a < b work as expected. + +

    +To support Rich Comparisions, the Python C API was modified between +Python versions 2.0 and 2.1. A new slot was introduced in the +PyTypeObject structure: tp_richcompare. For backwards +compatibility, a flag (Py_TPFLAGS_HAVE_RICHCOMPARE) has to be +set to signal to the Python interpreter that Rich Comparisions are +supported by a particular type. +There is only one flag for all the six comparison operators. +When any of the six operators is wrapped automatically or +manually, Boost.Python will set this flag. Attempts to use comparison +operators at the Python level that are not defined at the C++ level +will then lead to an AttributeError when the Python 2.1 +(or higher) interpreter tries, e.g., a.__lt__(b). That +is, in general all six operators should be supplied. Automatically +wrapped operators and manually wrapped operators can be mixed. For +example:

    +    boost::python::class_builder<code> py_code(this_module, "code");
    +
    +    py_code.def(boost::python::constructor<>());
    +    py_code.def(boost::python::constructor<int>());
    +    py_code.def(boost::python::operators<(  boost::python::op_eq
    +                                          | boost::python::op_ne)>());
    +    py_code.def(NotImplemented, "__lt__");
    +    py_code.def(NotImplemented, "__le__");
    +    py_code.def(NotImplemented, "__gt__");
    +    py_code.def(NotImplemented, "__ge__");
    +
    + +NotImplemented is a simple free function that (currently) has +to be provided by the user. For example:
    +  boost::python::ref
    +  NotImplemented(const code&, const code&) {
    +    return
    +    boost::python::ref(Py_NotImplemented, boost::python::ref::increment_count);
    +  }
    +
    + +See also: + + +
    +© Copyright Nicholas K. Sauter & Ralf W. Grosse-Kunstleve 2001. +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. + +

    +Updated: July 2001 + +

    diff --git a/doc/special.html b/doc/special.html index 0caa1924..46ca0791 100644 --- a/doc/special.html +++ b/doc/special.html @@ -60,13 +60,27 @@ __str__(self)
    Create a string representation which is suitable for printing. +
    + __lt__(self, other) +
    + __le__(self, other) +
    + __eq__(self, other) +
    + __ne__(self, other) +
    + __gt__(self, other) +
    + __ge__(self, other) +
    + Rich Comparison methods. + New in Python 2.1. + See Rich Comparisons.
    __cmp__(self, other)
    - Three-way compare function, used to implement comparison operators - (< etc.) Should return a negative integer if self < other - , zero if self == other , a positive integer if - self > other . + Three-way compare function. + See Rich Comparisons.
    __hash__(self)
    @@ -544,17 +558,42 @@ Note that "__rrpow__" is an extension not present in plain Python. __cmp__, __rcmp__ cmp(left, right)
    - left < right
    - left <= right
    - left > right
    - left >= right
    - left == right
    - left != right +
    See Rich Comparisons. op_cmp cpp_left < cpp_right 
    cpp_right < cpp_left + + + __lt__ +
    __le__ +
    __eq__ +
    __ne__ +
    __gt__ +
    __ge__ + + left < right +
    left <= right +
    left == right +
    left != right +
    left > right +
    left >= right +
    See Rich Comparisons + + op_lt +
    op_le +
    op_eq +
    op_ne +
    op_gt +
    op_ge + + cpp_left < cpp_right  +
    cpp_left <= cpp_right  +
    cpp_left == cpp_right  +
    cpp_left != cpp_right  +
    cpp_left > cpp_right  +
    cpp_left >= cpp_right  diff --git a/example/pickle3.cpp b/example/pickle3.cpp index bfa7dc54..cb598ae6 100644 --- a/example/pickle3.cpp +++ b/example/pickle3.cpp @@ -106,7 +106,7 @@ namespace { { if(args.size() != 1 || keywords.size() != 0) { PyErr_SetString(PyExc_TypeError, "wrong number of arguments"); - throw boost::python::argument_error(); + throw boost::python::error_already_set(); } const world& w = from_python(args[0].get(), type()); ref mydict = getattr(args[0], "__dict__"); @@ -122,7 +122,7 @@ namespace { { if(args.size() != 2 || keywords.size() != 0) { PyErr_SetString(PyExc_TypeError, "wrong number of arguments"); - throw boost::python::argument_error(); + throw boost::python::error_already_set(); } world& w = from_python(args[0].get(), type()); ref mydict = getattr(args[0], "__dict__"); diff --git a/example/richcmp1.cpp b/example/richcmp1.cpp new file mode 100644 index 00000000..4dd74e1b --- /dev/null +++ b/example/richcmp1.cpp @@ -0,0 +1,87 @@ +// Example by Ralf W. Grosse-Kunstleve & Nicholas K. Sauter +// This example shows how to use rich comparisons for a vector type. +// It also shows how to template the entire wrapping of a std::vector. +// See vector_wrapper.h. + +#include +#include "vector_wrapper.h" + +namespace vects { + + struct dvect : public std::vector + { + dvect() : std::vector() {} + dvect(size_t n) : std::vector(n) {} + dvect(boost::python::tuple tuple) : std::vector(tuple.size()) + { + std::vector::iterator v_it = begin(); + for (std::size_t i = 0; i < tuple.size(); i++) + v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), + boost::python::type()); + } + + boost::python::tuple as_tuple() const + { + boost::python::tuple t(size()); + for (std::size_t i = 0; i < size(); i++) + t.set_item(i, + boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i]))); + return t; + } + +# define DVECT_BINARY_OPERATORS(oper) \ + friend std::vector \ + operator##oper(const dvect& lhs, const dvect& rhs) \ + { \ + if (lhs.size() != rhs.size()) { \ + PyErr_SetString(PyExc_ValueError, "vectors have different sizes"); \ + throw boost::python::error_already_set(); \ + } \ + std::vector result(lhs.size()); \ + for (std::size_t i=0; i) + DVECT_BINARY_OPERATORS(>=) +# undef VECTOR_BINARY_OPERATORS + }; + +} // namespace + + +namespace { + + void init_module(boost::python::module_builder& this_module) + { + (void) example::wrap_vector(this_module, "vector_of_bool", bool()); + + boost::python::class_builder py_dvect(this_module, "dvect"); + + py_dvect.def(boost::python::constructor()); + py_dvect.def(&vects::dvect::as_tuple, "as_tuple"); + + const long + comp_operators = ( boost::python::op_lt | boost::python::op_le + | boost::python::op_eq | boost::python::op_ne + | boost::python::op_gt | boost::python::op_ge); + py_dvect.def(boost::python::operators()); + } + +} // namespace + +BOOST_PYTHON_MODULE_INIT(richcmp1) +{ + try { + boost::python::module_builder this_module("richcmp1"); + // The actual work is done in a separate function in order + // to suppress a bogus VC60 warning. + init_module(this_module); + } + catch (...) { boost::python::handle_exception(); } +} diff --git a/example/richcmp2.cpp b/example/richcmp2.cpp new file mode 100644 index 00000000..213852b3 --- /dev/null +++ b/example/richcmp2.cpp @@ -0,0 +1,65 @@ +// Example by Ralf W. Grosse-Kunstleve +// This example shows how to use rich comparisons for a type that +// does not support all six operators (<, <=, ==, !=, >, >=). +// To keep the example simple, we are using a "code" type does +// not really require rich comparisons. __cmp__ would be sufficient. +// However, with a more complicated type the main point of this +// example would be in danger of getting lost. + +#include + +namespace { + + // suppose operator< and operator> are not meaningful for code + class code { + public: + code(int c = 0) : m_code(c) {} + inline friend bool operator==(const code& lhs, const code& rhs) { + return lhs.m_code == rhs.m_code; + } + inline friend bool operator!=(const code& lhs, const code& rhs) { + return lhs.m_code != rhs.m_code; + } + private: + int m_code; + }; + +#if PYTHON_API_VERSION >= 1010 + boost::python::ref + NotImplemented(const code&, const code&) { + return + boost::python::ref(Py_NotImplemented, boost::python::ref::increment_count); + } +#endif +} + +namespace { + + void init_module(boost::python::module_builder& this_module) + { + boost::python::class_builder py_code(this_module, "code"); + + py_code.def(boost::python::constructor<>()); + py_code.def(boost::python::constructor()); + py_code.def(boost::python::operators<( boost::python::op_eq + | boost::python::op_ne)>()); +#if PYTHON_API_VERSION >= 1010 + py_code.def(NotImplemented, "__lt__"); + py_code.def(NotImplemented, "__le__"); + py_code.def(NotImplemented, "__gt__"); + py_code.def(NotImplemented, "__ge__"); +#endif + } + +} // namespace + +BOOST_PYTHON_MODULE_INIT(richcmp2) +{ + try { + boost::python::module_builder this_module("richcmp2"); + // The actual work is done in a separate function in order + // to suppress a bogus VC60 warning. + init_module(this_module); + } + catch (...) { boost::python::handle_exception(); } +} diff --git a/example/richcmp3.cpp b/example/richcmp3.cpp new file mode 100644 index 00000000..169e7f00 --- /dev/null +++ b/example/richcmp3.cpp @@ -0,0 +1,178 @@ +// Example by Ralf W. Grosse-Kunstleve & Nicholas K. Sauter. +// Comprehensive operator overloading for two vector types and scalars. + +#include +#include "vector_wrapper.h" +#include "dvect.h" +#include "ivect.h" + +#define VECT_VECT_OPERATORS(result_type, vect_type1, oper, vect_type2) \ +namespace vects { \ + result_type \ + operator##oper (const vect_type1& lhs, const vect_type2& rhs) { \ + if (lhs.size() != rhs.size()) { \ + PyErr_SetString(PyExc_ValueError, "vectors have different sizes"); \ + throw boost::python::error_already_set(); \ + } \ + result_type result(lhs.size()); \ + for (std::size_t i=0; i, vect_type1, <, vect_type2) \ + VECT_VECT_OPERATORS(std::vector, vect_type1, <=, vect_type2) \ + VECT_VECT_OPERATORS(std::vector, vect_type1, ==, vect_type2) \ + VECT_VECT_OPERATORS(std::vector, vect_type1, !=, vect_type2) \ + VECT_VECT_OPERATORS(std::vector, vect_type1, >, vect_type2) \ + VECT_VECT_OPERATORS(std::vector, vect_type1, >=, vect_type2) + +#define MATH_VECT_SCALAR_OPERATORS(result_type, vect_type, scalar_type) \ + VECT_SCALAR_OPERATORS(result_type, vect_type, +, scalar_type) \ + VECT_SCALAR_OPERATORS(result_type, vect_type, -, scalar_type) \ + VECT_SCALAR_OPERATORS(result_type, vect_type, *, scalar_type) \ + VECT_SCALAR_OPERATORS(result_type, vect_type, /, scalar_type) + +#define COMP_VECT_SCALAR_OPERATORS(vect_type, scalar_type) \ + VECT_SCALAR_OPERATORS(std::vector, vect_type, <, scalar_type) \ + VECT_SCALAR_OPERATORS(std::vector, vect_type, <=, scalar_type) \ + VECT_SCALAR_OPERATORS(std::vector, vect_type, ==, scalar_type) \ + VECT_SCALAR_OPERATORS(std::vector, vect_type, !=, scalar_type) \ + VECT_SCALAR_OPERATORS(std::vector, vect_type, >, scalar_type) \ + VECT_SCALAR_OPERATORS(std::vector, vect_type, >=, scalar_type) + +#define MATH_SCALAR_VECT_OPERATORS(result_type, scalar_type, vect_type) \ + SCALAR_VECT_OPERATORS(result_type, scalar_type, +, vect_type) \ + SCALAR_VECT_OPERATORS(result_type, scalar_type, -, vect_type) \ + SCALAR_VECT_OPERATORS(result_type, scalar_type, *, vect_type) \ + SCALAR_VECT_OPERATORS(result_type, scalar_type, /, vect_type) + +MATH_VECT_VECT_OPERATORS(dvect, dvect, dvect) +COMP_VECT_VECT_OPERATORS( dvect, dvect) +MATH_VECT_SCALAR_OPERATORS(dvect, dvect, double) +COMP_VECT_SCALAR_OPERATORS( dvect, double) +MATH_SCALAR_VECT_OPERATORS(dvect, double, dvect) +// comparison operators not needed since Python uses reflection + +MATH_VECT_VECT_OPERATORS(ivect, ivect, ivect) +COMP_VECT_VECT_OPERATORS( ivect, ivect) +MATH_VECT_SCALAR_OPERATORS(ivect, ivect, int) +COMP_VECT_SCALAR_OPERATORS( ivect, int) +MATH_SCALAR_VECT_OPERATORS(ivect, int, ivect) +// comparison operators not needed since Python uses reflection + +MATH_VECT_VECT_OPERATORS(dvect, dvect, ivect) +COMP_VECT_VECT_OPERATORS( dvect, ivect) +MATH_VECT_VECT_OPERATORS(dvect, ivect, dvect) +COMP_VECT_VECT_OPERATORS( ivect, dvect) + +#undef VECT_VECT_OPERATORS +#undef SCALAR_VECT_OPERATORS +#undef VECT_SCALAR_OPERATORS +#undef MATH_VECT_VECT_OPERATORS +#undef COMP_VECT_VECT_OPERATORS +#undef MATH_VECT_SCALAR_OPERATORS +#undef COMP_VECT_SCALAR_OPERATORS +#undef MATH_SCALAR_VECT_OPERATORS + +namespace { + + void init_module(boost::python::module_builder& this_module) + { + (void) example::wrap_vector(this_module, "vector_of_bool", bool()); + + const long + math_operators ( boost::python::op_mul | boost::python::op_add + | boost::python::op_div | boost::python::op_sub); + const long + comp_operators = ( boost::python::op_lt | boost::python::op_le + | boost::python::op_eq | boost::python::op_ne + | boost::python::op_gt | boost::python::op_ge); + + boost::python::class_builder + dvect_class(this_module, "dvect"); + boost::python::class_builder + ivect_class(this_module, "ivect"); + + dvect_class.def(boost::python::constructor()); + dvect_class.def(&vects::dvect::as_tuple,"as_tuple"); + + dvect_class.def(boost::python::operators()); + dvect_class.def(boost::python::operators(), + boost::python::right_operand() ); + dvect_class.def(boost::python::operators(), + boost::python::left_operand() ); + dvect_class.def(boost::python::operators(), + boost::python::right_operand() ); + + dvect_class.def(boost::python::operators()); + dvect_class.def(boost::python::operators(), + boost::python::right_operand() ); + // left_operand not needed since Python uses reflection + dvect_class.def(boost::python::operators(), + boost::python::right_operand() ); + + ivect_class.def(boost::python::constructor()); + ivect_class.def(&vects::ivect::as_tuple,"as_tuple"); + + ivect_class.def(boost::python::operators()); + ivect_class.def(boost::python::operators(), + boost::python::right_operand() ); + ivect_class.def(boost::python::operators(), + boost::python::left_operand() ); + ivect_class.def(boost::python::operators(), + boost::python::right_operand() ); + + ivect_class.def(boost::python::operators()); + ivect_class.def(boost::python::operators(), + boost::python::right_operand() ); + // left_operand not needed since Python uses reflection + ivect_class.def(boost::python::operators(), + boost::python::right_operand() ); + } + +} // namespace + +BOOST_PYTHON_MODULE_INIT(richcmp3) +{ + try { + boost::python::module_builder this_module("richcmp3"); + // The actual work is done in a separate function in order + // to suppress a bogus VC60 warning. + init_module(this_module); + } + catch (...) { boost::python::handle_exception(); } +} diff --git a/example/test_pickle3.py b/example/test_pickle3.py index 36da735d..6ac83b18 100644 --- a/example/test_pickle3.py +++ b/example/test_pickle3.py @@ -19,12 +19,12 @@ r'''>>> import pickle3 ... wd.z = 3. * number ... pstr = pickle.dumps(wd) ... wl = pickle.loads(pstr) - ... print wd.greet(), wd.get_secret_number(), wd.__dict__ - ... print wl.greet(), wl.get_secret_number(), wl.__dict__ - Hello from California! 24 {'z': 72.0, 'x': 48, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyy'} - Hello from California! 24 {'z': 72.0, 'x': 48, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyy'} - Hello from California! 42 {'z': 126.0, 'x': 84, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'} - Hello from California! 0 {'z': 126.0, 'x': 84, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'} + ... print wd.greet(), wd.get_secret_number(), wd.x, wd.y, wd.z + ... print wl.greet(), wl.get_secret_number(), wl.x, wl.y, wl.z + Hello from California! 24 48 yyyyyyyyyyyyyyyyyyyyyyyy 72.0 + Hello from California! 24 48 yyyyyyyyyyyyyyyyyyyyyyyy 72.0 + Hello from California! 42 84 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 126.0 + Hello from California! 0 84 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 126.0 ''' def run(args = None): diff --git a/example/test_richcmp1.py b/example/test_richcmp1.py new file mode 100644 index 00000000..d25fcc9c --- /dev/null +++ b/example/test_richcmp1.py @@ -0,0 +1,40 @@ +r'''>>> import richcmp1 + >>> d1 = richcmp1.dvect((0, 1, 3, 3, 6, 7)) + >>> d2 = richcmp1.dvect((1, 2, 3, 4, 5, 6)) + >>> print d1.as_tuple() + (0.0, 1.0, 3.0, 3.0, 6.0, 7.0) + >>> print d2.as_tuple() + (1.0, 2.0, 3.0, 4.0, 5.0, 6.0) + >>> print (d1 < d2).as_tuple() + (1, 1, 0, 1, 0, 0) + >>> print (d1 <= d2).as_tuple() + (1, 1, 1, 1, 0, 0) + >>> print (d1 == d2).as_tuple() + (0, 0, 1, 0, 0, 0) + >>> print (d1 != d2).as_tuple() + (1, 1, 0, 1, 1, 1) + >>> print (d1 > d2).as_tuple() + (0, 0, 0, 0, 1, 1) + >>> print (d1 >= d2).as_tuple() + (0, 0, 1, 0, 1, 1) + >>> try: d1 == richcmp1.dvect((1, 2, 3, 4, 5)) + ... except ValueError, e: print str(e) + ... + vectors have different sizes +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_richcmp1 + return doctest.testmod(test_richcmp1) + +if __name__ == '__main__': + import sys + if ( hasattr(sys, 'version_info') + and ( (sys.version_info[0] == 2 and sys.version_info[1] >= 1) + or sys.version_info[0] > 2)): + sys.exit(run()[0]) + else: + print "Python version 2.1 or higher required. Test skipped." diff --git a/example/test_richcmp2.py b/example/test_richcmp2.py new file mode 100644 index 00000000..859928c3 --- /dev/null +++ b/example/test_richcmp2.py @@ -0,0 +1,41 @@ +r'''>>> import richcmp2 + >>> c1 = richcmp2.code(1) + >>> c2 = richcmp2.code(2) + >>> c3 = richcmp2.code(2) + >>> print c1 == c2 + 0 + >>> print c1 != c2 + 1 + >>> print c2 == c3 + 1 + >>> print c2 != c3 + 0 + >>> print c1 < c2 + 1 + >>> print c1 <= c2 + 1 + >>> print c1 == c2 + 0 + >>> print c1 != c2 + 1 + >>> print c1 > c2 + 0 + >>> print c1 >= c2 + 0 +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_richcmp1 + return doctest.testmod(test_richcmp1) + +if __name__ == '__main__': + import sys + if ( hasattr(sys, 'version_info') + and ( (sys.version_info[0] == 2 and sys.version_info[1] >= 1) + or sys.version_info[0] > 2)): + sys.exit(run()[0]) + else: + print "Python version 2.1 or higher required. Test skipped." diff --git a/example/test_richcmp3.py b/example/test_richcmp3.py new file mode 100644 index 00000000..a769af17 --- /dev/null +++ b/example/test_richcmp3.py @@ -0,0 +1,77 @@ +r'''>>> import richcmp3 + >>> + >>> iv = richcmp3.ivect((1,2,3,4,5)) + >>> print iv.as_tuple() + (1, 2, 3, 4, 5) + >>> dv = richcmp3.dvect((2,-2,3,8,-5)) + >>> print dv.as_tuple() + (2.0, -2.0, 3.0, 8.0, -5.0) + >>> + >>> print (iv+dv).as_tuple() + (3.0, 0.0, 6.0, 12.0, 0.0) + >>> print (iv+3).as_tuple() + (4, 5, 6, 7, 8) + >>> print (3+iv).as_tuple() + (4, 5, 6, 7, 8) + >>> + >>> print "vect vs. vect Comparisons:" + vect vs. vect Comparisons: + >>> print (iv < dv).as_tuple() + (1, 0, 0, 1, 0) + >>> print (iv <= dv).as_tuple() + (1, 0, 1, 1, 0) + >>> print (iv == dv).as_tuple() + (0, 0, 1, 0, 0) + >>> print (iv != dv).as_tuple() + (1, 1, 0, 1, 1) + >>> print (iv > dv).as_tuple() + (0, 1, 0, 0, 1) + >>> print (iv >= dv).as_tuple() + (0, 1, 1, 0, 1) + >>> + >>> print "vect vs. scalar Comparisons:" + vect vs. scalar Comparisons: + >>> print (iv < 3).as_tuple() + (1, 1, 0, 0, 0) + >>> print (iv <= 3).as_tuple() + (1, 1, 1, 0, 0) + >>> print (iv == 3).as_tuple() + (0, 0, 1, 0, 0) + >>> print (iv != 3).as_tuple() + (1, 1, 0, 1, 1) + >>> print (iv > 3).as_tuple() + (0, 0, 0, 1, 1) + >>> print (iv >= 3).as_tuple() + (0, 0, 1, 1, 1) + >>> + >>> print "scalar vs. vect Comparisons:" + scalar vs. vect Comparisons: + >>> print (3 < iv).as_tuple() + (0, 0, 0, 1, 1) + >>> print (3 <= iv).as_tuple() + (0, 0, 1, 1, 1) + >>> print (3 == iv).as_tuple() + (0, 0, 1, 0, 0) + >>> print (3 != iv).as_tuple() + (1, 1, 0, 1, 1) + >>> print (3 > iv).as_tuple() + (1, 1, 0, 0, 0) + >>> print (3 >= iv).as_tuple() + (1, 1, 1, 0, 0) +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_richcmp3 + return doctest.testmod(test_richcmp3) + +if __name__ == '__main__': + import sys + if ( hasattr(sys, 'version_info') + and ( (sys.version_info[0] == 2 and sys.version_info[1] >= 1) + or sys.version_info[0] > 2)): + sys.exit(run()[0]) + else: + print "Python version 2.1 or higher required. Test skipped." diff --git a/example/vector_wrapper.h b/example/vector_wrapper.h new file mode 100644 index 00000000..d5bd7215 --- /dev/null +++ b/example/vector_wrapper.h @@ -0,0 +1,117 @@ +// Based on wrapVector.hh by Mike Owen and Jeff Johnson. +// http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/spheral/src/src/BPLWraps/CXXWraps/ + +#ifndef BOOST_PYTHON_EXAMPLE_VECTOR_WRAPPER_H +#define BOOST_PYTHON_EXAMPLE_VECTOR_WRAPPER_H + +#include + +namespace example { + + // A wrapper is used to define additional constructors. This wrapper + // is templated on the template parameter for its corresponding vector. + template + struct vector_wrapper: std::vector + { + // Tell the compiler how to convert a base class object to + // this wrapper object. + vector_wrapper(PyObject*, + const std::vector& vec): + std::vector(vec) {} + + vector_wrapper(PyObject* self): + std::vector() {} + + vector_wrapper(PyObject* self, + std::size_t n): + std::vector(n) {} + + vector_wrapper(PyObject* self, + boost::python::tuple tuple): + std::vector(tuple.size()) + { + std::vector::iterator vec = begin(); + for (std::size_t i = 0; i < tuple.size(); i++) + vec[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), + boost::python::type()); + } + }; + + void raise_vector_IndexError() { + PyErr_SetString(PyExc_IndexError, "vector index out of range"); + throw boost::python::error_already_set(); + } + + template + struct vector_access + { + static + T + getitem(const std::vector& vec, + std::size_t key) + { + if (key >= vec.size()) raise_vector_IndexError(); + return vec[key]; + } + + static + void + setitem(std::vector& vec, + std::size_t key, + const T &value) + { + if (key >= vec.size()) raise_vector_IndexError(); + vec[key] = value; + } + + static + void + delitem(std::vector& vec, + std::size_t key) + { + if (key >= vec.size()) raise_vector_IndexError(); + vec.erase(vec.begin() + key); + } + + // Convert vector to a regular Python tuple. + static + boost::python::tuple + as_tuple(const std::vector& vec) + { + // Create a python type of size vec.size(). + boost::python::tuple t(vec.size()); + for (std::size_t i = 0; i < vec.size(); i++) { + t.set_item(i, + boost::python::ref(BOOST_PYTHON_CONVERSION::to_python(vec[i]))); + } + return t; + } + }; + + // This function will build a vector and add it to the given + // module with the given name. + template + boost::python::class_builder, vector_wrapper > + wrap_vector(boost::python::module_builder& module, + const std::string& vector_name, + const T&) + { + // Add the vector to the module. + boost::python::class_builder, vector_wrapper > + py_vector(module, vector_name.c_str()); + + // Define constructors and methods for the vector. + py_vector.def(boost::python::constructor<>()); + py_vector.def(boost::python::constructor()); + py_vector.def(boost::python::constructor()); + py_vector.def(&std::vector::size, "__len__"); + py_vector.def(&vector_access::getitem, "__getitem__"); + py_vector.def(&vector_access::setitem, "__setitem__"); + py_vector.def(&vector_access::delitem, "__delitem__"); + py_vector.def(&vector_access::as_tuple, "as_tuple"); + + return py_vector; + } +} + +#endif // BOOST_PYTHON_EXAMPLE_VECTOR_WRAPPER_H diff --git a/include/boost/python/classes.hpp b/include/boost/python/classes.hpp index d38fbba5..2d69e81e 100644 --- a/include/boost/python/classes.hpp +++ b/include/boost/python/classes.hpp @@ -70,6 +70,14 @@ class instance PyObject* oct(); PyObject* hex(); + // Rich comparisons + PyObject* lt(PyObject* other); + PyObject* le(PyObject* other); + PyObject* eq(PyObject* other); + PyObject* ne(PyObject* other); + PyObject* gt(PyObject* other); + PyObject* ge(PyObject* other); + private: // noncopyable, without the size bloat instance(const instance&); void operator=(const instance&); @@ -169,6 +177,14 @@ class class_t PyObject* instance_number_float(PyObject*) const; PyObject* instance_number_oct(PyObject*) const; PyObject* instance_number_hex(PyObject*) const; + + private: // Implement rich comparisons + PyObject* instance_lt(PyObject*, PyObject*) const; + PyObject* instance_le(PyObject*, PyObject*) const; + PyObject* instance_eq(PyObject*, PyObject*) const; + PyObject* instance_ne(PyObject*, PyObject*) const; + PyObject* instance_gt(PyObject*, PyObject*) const; + PyObject* instance_ge(PyObject*, PyObject*) const; private: // Miscellaneous "special" methods PyObject* instance_call(PyObject* obj, PyObject* args, PyObject* keywords) const; @@ -477,6 +493,42 @@ PyObject* class_t::instance_number_hex(PyObject* obj) const return downcast(obj)->hex(); } +template +PyObject* class_t::instance_lt(PyObject* obj, PyObject* other) const +{ + return downcast(obj)->lt(other); +} + +template +PyObject* class_t::instance_le(PyObject* obj, PyObject* other) const +{ + return downcast(obj)->le(other); +} + +template +PyObject* class_t::instance_eq(PyObject* obj, PyObject* other) const +{ + return downcast(obj)->eq(other); +} + +template +PyObject* class_t::instance_ne(PyObject* obj, PyObject* other) const +{ + return downcast(obj)->ne(other); +} + +template +PyObject* class_t::instance_gt(PyObject* obj, PyObject* other) const +{ + return downcast(obj)->gt(other); +} + +template +PyObject* class_t::instance_ge(PyObject* obj, PyObject* other) const +{ + return downcast(obj)->ge(other); +} + namespace detail { inline dictionary& class_base::dict() { diff --git a/include/boost/python/detail/extension_class.hpp b/include/boost/python/detail/extension_class.hpp index 5c8e720a..d871ad6e 100644 --- a/include/boost/python/detail/extension_class.hpp +++ b/include/boost/python/detail/extension_class.hpp @@ -616,6 +616,12 @@ class extension_class choose_op<(which & op_and)>::template args::add(this); choose_op<(which & op_xor)>::template args::add(this); choose_op<(which & op_or)>::template args::add(this); + choose_op<(which & op_gt)>::template args::add(this); + choose_op<(which & op_ge)>::template args::add(this); + choose_op<(which & op_lt)>::template args::add(this); + choose_op<(which & op_le)>::template args::add(this); + choose_op<(which & op_eq)>::template args::add(this); + choose_op<(which & op_ne)>::template args::add(this); choose_unary_op<(which & op_neg)>::template args::add(this); choose_unary_op<(which & op_pos)>::template args::add(this); choose_unary_op<(which & op_abs)>::template args::add(this); @@ -645,6 +651,12 @@ class extension_class choose_op<(which & op_xor)>::template args::add(this); choose_op<(which & op_or)>::template args::add(this); choose_op<(which & op_cmp)>::template args::add(this); + choose_op<(which & op_gt)>::template args::add(this); + choose_op<(which & op_ge)>::template args::add(this); + choose_op<(which & op_lt)>::template args::add(this); + choose_op<(which & op_le)>::template args::add(this); + choose_op<(which & op_eq)>::template args::add(this); + choose_op<(which & op_ne)>::template args::add(this); } template diff --git a/include/boost/python/detail/types.hpp b/include/boost/python/detail/types.hpp index 5f0c8f97..2d0d0f6b 100644 --- a/include/boost/python/detail/types.hpp +++ b/include/boost/python/detail/types.hpp @@ -45,7 +45,7 @@ class type_object_base : public python_type public: enum capability { - hash, call, str, getattr, setattr, compare, repr, + hash, call, str, getattr, setattr, compare, repr, richcompare, mapping_length, mapping_subscript, mapping_ass_subscript, @@ -115,6 +115,14 @@ class type_object_base : public python_type virtual PyObject* instance_number_float(PyObject*) const; virtual PyObject* instance_number_oct(PyObject*) const; virtual PyObject* instance_number_hex(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 diff --git a/include/boost/python/operators.hpp b/include/boost/python/operators.hpp index da88ec6c..52e52eee 100644 --- a/include/boost/python/operators.hpp +++ b/include/boost/python/operators.hpp @@ -65,7 +65,13 @@ enum operator_id op_long = 0x20000, op_float = 0x40000, op_str = 0x80000, - op_cmp = 0x100000 + op_cmp = 0x100000, + op_gt = 0x200000, + op_ge = 0x400000, + op_lt = 0x800000, + op_le = 0x1000000, + op_eq = 0x2000000, + op_ne = 0x4000000 }; // Wrap the operators given by "which". Usage: @@ -301,6 +307,12 @@ namespace detail PY_DEFINE_BINARY_OPERATORS(and, &); PY_DEFINE_BINARY_OPERATORS(xor, ^); PY_DEFINE_BINARY_OPERATORS(or, |); + PY_DEFINE_BINARY_OPERATORS(gt, >); + PY_DEFINE_BINARY_OPERATORS(ge, >=); + PY_DEFINE_BINARY_OPERATORS(lt, <); + PY_DEFINE_BINARY_OPERATORS(le, <=); + PY_DEFINE_BINARY_OPERATORS(eq, ==); + PY_DEFINE_BINARY_OPERATORS(ne, !=); PY_DEFINE_UNARY_OPERATORS(neg, -); PY_DEFINE_UNARY_OPERATORS(pos, +); diff --git a/src/classes.cpp b/src/classes.cpp index 8755bb34..a44c3c0a 100644 --- a/src/classes.cpp +++ b/src/classes.cpp @@ -736,6 +736,36 @@ PyObject* instance::hex() return callback::call_method(this, "__hex__"); } +PyObject* instance::lt(PyObject* other) +{ + return callback::call_method(this, "__lt__", other); +} + +PyObject* instance::le(PyObject* other) +{ + return callback::call_method(this, "__le__", other); +} + +PyObject* instance::eq(PyObject* other) +{ + return callback::call_method(this, "__eq__", other); +} + +PyObject* instance::ne(PyObject* other) +{ + return callback::call_method(this, "__ne__", other); +} + +PyObject* instance::gt(PyObject* other) +{ + return callback::call_method(this, "__gt__", other); +} + +PyObject* instance::ge(PyObject* other) +{ + return callback::call_method(this, "__ge__", other); +} + namespace { struct named_capability { @@ -747,6 +777,12 @@ namespace { { { "__hash__", detail::type_object_base::hash }, { "__cmp__", detail::type_object_base::compare }, + { "__gt__", detail::type_object_base::richcompare }, + { "__ge__", detail::type_object_base::richcompare }, + { "__lt__", detail::type_object_base::richcompare }, + { "__le__", detail::type_object_base::richcompare }, + { "__eq__", detail::type_object_base::richcompare }, + { "__ne__", detail::type_object_base::richcompare }, { "__repr__", detail::type_object_base::repr }, { "__str__", detail::type_object_base::str }, { "__call__", detail::type_object_base::call }, diff --git a/src/gen_extclass.py b/src/gen_extclass.py index 8de8a1ae..57189a7d 100644 --- a/src/gen_extclass.py +++ b/src/gen_extclass.py @@ -15,6 +15,7 @@ def gen_extclass(args): // 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) @@ -171,6 +172,14 @@ BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // 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. +// +// 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 python_extension_class_converters { @@ -607,6 +616,12 @@ class extension_class choose_op<(which & op_and)>::template args::add(this); choose_op<(which & op_xor)>::template args::add(this); choose_op<(which & op_or)>::template args::add(this); + choose_op<(which & op_gt)>::template args::add(this); + choose_op<(which & op_ge)>::template args::add(this); + choose_op<(which & op_lt)>::template args::add(this); + choose_op<(which & op_le)>::template args::add(this); + choose_op<(which & op_eq)>::template args::add(this); + choose_op<(which & op_ne)>::template args::add(this); choose_unary_op<(which & op_neg)>::template args::add(this); choose_unary_op<(which & op_pos)>::template args::add(this); choose_unary_op<(which & op_abs)>::template args::add(this); @@ -636,6 +651,12 @@ class extension_class choose_op<(which & op_xor)>::template args::add(this); choose_op<(which & op_or)>::template args::add(this); choose_op<(which & op_cmp)>::template args::add(this); + choose_op<(which & op_gt)>::template args::add(this); + choose_op<(which & op_ge)>::template args::add(this); + choose_op<(which & op_lt)>::template args::add(this); + choose_op<(which & op_le)>::template args::add(this); + choose_op<(which & op_eq)>::template args::add(this); + choose_op<(which & op_ne)>::template args::add(this); } template diff --git a/src/gen_init_function.py b/src/gen_init_function.py index 69935230..80a9c199 100644 --- a/src/gen_init_function.py +++ b/src/gen_init_function.py @@ -79,7 +79,8 @@ namespace detail { struct parameter_traits { private: - typedef const_ref_selector::value> selector; + enum { is_ref = boost::is_reference::value }; + typedef const_ref_selector selector; public: typedef typename selector::template const_ref::type const_reference; }; diff --git a/src/types.cpp b/src/types.cpp index 7ba5840b..f8cf1ea6 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -159,6 +159,28 @@ static PyObject* do_instance_repr(PyObject* obj) return call(obj, &type_object_base::instance_repr); } +static PyObject* do_instance_richcompare(PyObject* obj, PyObject* other, int d) +{ +#if PYTHON_API_VERSION >= 1010 + switch(d) + { + case Py_LT: + return call(obj, &type_object_base::instance_lt, other); + case Py_LE: + return call(obj, &type_object_base::instance_le, other); + case Py_EQ: + return call(obj, &type_object_base::instance_eq, other); + case Py_NE: + return call(obj, &type_object_base::instance_ne, other); + case Py_GT: + return call(obj, &type_object_base::instance_gt, other); + case Py_GE: + return call(obj, &type_object_base::instance_ge, other); + } +#endif + return 0; +} + static int do_instance_compare(PyObject* obj, PyObject* other) { return call(obj, &type_object_base::instance_compare, other); @@ -406,7 +428,7 @@ namespace bool add_capability_general(type_object_base::capability capability, PyTypeObject* dest) { assert(dest != 0); - + switch(capability) { ENABLE_GENERAL_CAPABILITY(hash); @@ -435,6 +457,20 @@ void create_method_table_if_null(T*& table) } } +bool add_capability_richcompare(type_object_base::capability capability, PyTypeObject* dest) +{ + assert(dest != 0); + if (capability == type_object_base::richcompare) { +#if PYTHON_API_VERSION >= 1010 + dest->tp_richcompare = &do_instance_richcompare; + dest->tp_flags |= Py_TPFLAGS_HAVE_RICHCOMPARE; +#endif + return true; + } + + return false; +} + #define ENABLE_MAPPING_CAPABILITY(field) \ case type_object_base::mapping_##field: \ create_method_table_if_null(dest); \ @@ -548,6 +584,8 @@ namespace detail { { if(add_capability_general(capability, dest_)) return; + if(add_capability_richcompare(capability, dest_)) + return; if(add_capability_mapping(capability, dest_->tp_as_mapping)) return; if(add_capability_sequence(capability, dest_->tp_as_sequence)) @@ -975,6 +1013,36 @@ PyObject* type_object_base::instance_number_hex(PyObject*) const return unimplemented("instance_number_hex"); } +PyObject* type_object_base::instance_lt(PyObject*, PyObject*) const +{ + return unimplemented("instance_lt"); +} + +PyObject* type_object_base::instance_le(PyObject*, PyObject*) const +{ + return unimplemented("instance_le"); +} + +PyObject* type_object_base::instance_eq(PyObject*, PyObject*) const +{ + return unimplemented("instance_eq"); +} + +PyObject* type_object_base::instance_ne(PyObject*, PyObject*) const +{ + return unimplemented("instance_ne"); +} + +PyObject* type_object_base::instance_gt(PyObject*, PyObject*) const +{ + return unimplemented("instance_gt"); +} + +PyObject* type_object_base::instance_ge(PyObject*, PyObject*) const +{ + return unimplemented("instance_ge"); +} + }} // namespace boost::python #ifdef TYPE_OBJECT_BASE_STANDALONE_TEST diff --git a/test/comprehensive.py b/test/comprehensive.py index 013fae96..db4f8b73 100644 --- a/test/comprehensive.py +++ b/test/comprehensive.py @@ -422,7 +422,7 @@ Some simple overloading tests: >>> try: r = Range('yikes') ... except TypeError, e: ... assert re.match( - ... 'No overloaded functions match [(]Range, string[)]\. Candidates are:\n.*\n.*', + ... 'No overloaded functions match [(]Range, str[a-z]*[)]\. Candidates are:\n.*\n.*', ... str(e)) ... else: print 'no exception' @@ -632,7 +632,7 @@ Testing overloaded free functions 15 >>> try: overloaded(1, 'foo') ... except TypeError, err: - ... assert re.match("No overloaded functions match \(int, string\)\. Candidates are:", + ... assert re.match("No overloaded functions match \(int, str[a-z]*\)\. Candidates are:", ... str(err)) ... else: ... print 'no exception' @@ -662,7 +662,7 @@ Testing overloaded constructors 5 >>> try: over = OverloadTest(1, 'foo') ... except TypeError, err: - ... assert re.match("No overloaded functions match \(OverloadTest, int, string\)\. Candidates are:", + ... assert re.match("No overloaded functions match \(OverloadTest, int, str[a-z]*\)\. Candidates are:", ... str(err)) ... else: ... print 'no exception' @@ -684,7 +684,7 @@ Testing overloaded methods 5 >>> try: over.overloaded(1,'foo') ... except TypeError, err: - ... assert re.match("No overloaded functions match \(OverloadTest, int, string\)\. Candidates are:", + ... assert re.match("No overloaded functions match \(OverloadTest, int, str[a-z]*\)\. Candidates are:", ... str(err)) ... else: ... print 'no exception' From 801cae13ac53968a3f65556d855ea84f08835999 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 31 Jul 2001 07:39:05 +0000 Subject: [PATCH 132/369] Macintosh mods: do_it_yourself_converters -> do_it_yourself_convts [SVN r10729] --- build/Jamfile | 4 ++-- build/filemgr.py | 6 +++--- build/irix_CC.mak | 12 ++++++------ build/linux_gcc.mak | 12 ++++++------ build/mingw32.mak | 12 ++++++------ build/tru64_cxx.mak | 12 ++++++------ build/vc60.mak | 8 ++++---- example/README | 2 +- ...self_converters.cpp => do_it_yourself_convts.cpp} | 4 ++-- ...f_converters.py => test_do_it_yourself_convts.py} | 8 ++++---- 10 files changed, 40 insertions(+), 40 deletions(-) rename example/{do_it_yourself_converters.cpp => do_it_yourself_convts.cpp} (97%) rename example/{test_do_it_yourself_converters.py => test_do_it_yourself_convts.py} (63%) diff --git a/build/Jamfile b/build/Jamfile index 314b1440..562aca1e 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -25,7 +25,7 @@ # getting_started1 - # getting_started2 - # simple_vector - -# do_it_yourself_converters - +# do_it_yourself_convts - # pickle1 - # pickle2 - # pickle3 - @@ -215,7 +215,7 @@ boost-python-example-test abstract ; boost-python-example-test getting_started1 ; boost-python-example-test getting_started2 ; boost-python-example-test simple_vector ; -boost-python-example-test do_it_yourself_converters ; +boost-python-example-test do_it_yourself_convts ; boost-python-example-test pickle1 ; boost-python-example-test pickle2 ; boost-python-example-test pickle3 ; diff --git a/build/filemgr.py b/build/filemgr.py index 5e32460e..2ff163f0 100644 --- a/build/filemgr.py +++ b/build/filemgr.py @@ -23,7 +23,7 @@ bpl_exa + "/abstract.cpp", bpl_exa + "/getting_started1.cpp", bpl_exa + "/getting_started2.cpp", bpl_exa + "/simple_vector.cpp", -bpl_exa + "/do_it_yourself_converters.cpp", +bpl_exa + "/do_it_yourself_convts.cpp", bpl_exa + "/pickle1.cpp", bpl_exa + "/pickle2.cpp", bpl_exa + "/pickle3.cpp", @@ -31,7 +31,7 @@ bpl_exa + "/test_abstract.py", bpl_exa + "/test_getting_started1.py", bpl_exa + "/test_getting_started2.py", bpl_exa + "/test_simple_vector.py", -bpl_exa + "/test_do_it_yourself_converters.py", +bpl_exa + "/test_do_it_yourself_convts.py", bpl_exa + "/test_pickle1.py", bpl_exa + "/test_pickle2.py", bpl_exa + "/test_pickle3.py", @@ -67,7 +67,7 @@ defs = ( "getting_started1", "getting_started2", "simple_vector", -"do_it_yourself_converters", +"do_it_yourself_convts", "pickle1", "pickle2", "pickle3", diff --git a/build/irix_CC.mak b/build/irix_CC.mak index 1fbe3388..6e465b98 100644 --- a/build/irix_CC.mak +++ b/build/irix_CC.mak @@ -43,7 +43,7 @@ DEPOBJ=$(OBJ) \ abstract.o \ getting_started1.o getting_started2.o \ simple_vector.o \ - do_it_yourself_converters.o \ + do_it_yourself_convts.o \ pickle1.o pickle2.o pickle3.o \ noncopyable_export.o noncopyable_import.o \ ivect.o dvect.o \ @@ -56,7 +56,7 @@ all: libboost_python.a \ abstract.so \ getting_started1.so getting_started2.so \ simple_vector.so \ - do_it_yourself_converters.so \ + do_it_yourself_convts.so \ pickle1.so pickle2.so pickle3.so \ noncopyable_export.so noncopyable_import.so \ ivect.so dvect.so \ @@ -81,8 +81,8 @@ getting_started2.so: $(OBJ) getting_started2.o simple_vector.so: $(OBJ) simple_vector.o $(LD) $(LDOPTS) $(OBJ) simple_vector.o -o simple_vector.so -do_it_yourself_converters.so: $(OBJ) do_it_yourself_converters.o - $(LD) $(LDOPTS) $(OBJ) do_it_yourself_converters.o -o do_it_yourself_converters.so +do_it_yourself_convts.so: $(OBJ) do_it_yourself_convts.o + $(LD) $(LDOPTS) $(OBJ) do_it_yourself_convts.o -o do_it_yourself_convts.so pickle1.so: $(OBJ) pickle1.o $(LD) $(LDOPTS) $(OBJ) pickle1.o -o pickle1.so @@ -125,7 +125,7 @@ test: $(PYEXE) test_getting_started1.py $(PYEXE) test_getting_started2.py $(PYEXE) test_simple_vector.py - $(PYEXE) test_do_it_yourself_converters.py + $(PYEXE) test_do_it_yourself_convts.py $(PYEXE) test_pickle1.py $(PYEXE) test_pickle2.py $(PYEXE) test_pickle3.py @@ -141,7 +141,7 @@ clean: rm -f getting_started1.o getting_started1.so rm -f getting_started2.o getting_started2.so rm -f simple_vector.o simple_vector.so - rm -f do_it_yourself_converters.o do_it_yourself_converters.so + rm -f do_it_yourself_convts.o do_it_yourself_convts.so rm -f pickle1.o pickle1.so rm -f pickle2.o pickle2.so rm -f pickle3.o pickle3.so diff --git a/build/linux_gcc.mak b/build/linux_gcc.mak index 3fe407a0..2c977473 100644 --- a/build/linux_gcc.mak +++ b/build/linux_gcc.mak @@ -44,7 +44,7 @@ DEPOBJ=$(OBJ) \ abstract.o \ getting_started1.o getting_started2.o \ simple_vector.o \ - do_it_yourself_converters.o \ + do_it_yourself_convts.o \ pickle1.o pickle2.o pickle3.o \ noncopyable_export.o noncopyable_import.o \ ivect.o dvect.o \ @@ -57,7 +57,7 @@ all: libboost_python.a \ abstract.so \ getting_started1.so getting_started2.so \ simple_vector.so \ - do_it_yourself_converters.so \ + do_it_yourself_convts.so \ pickle1.so pickle2.so pickle3.so \ noncopyable_export.so noncopyable_import.so \ ivect.so dvect.so \ @@ -82,8 +82,8 @@ getting_started2.so: $(OBJ) getting_started2.o simple_vector.so: $(OBJ) simple_vector.o $(LD) $(LDOPTS) $(OBJ) simple_vector.o -o simple_vector.so -do_it_yourself_converters.so: $(OBJ) do_it_yourself_converters.o - $(LD) $(LDOPTS) $(OBJ) do_it_yourself_converters.o -o do_it_yourself_converters.so +do_it_yourself_convts.so: $(OBJ) do_it_yourself_convts.o + $(LD) $(LDOPTS) $(OBJ) do_it_yourself_convts.o -o do_it_yourself_convts.so pickle1.so: $(OBJ) pickle1.o $(LD) $(LDOPTS) $(OBJ) pickle1.o -o pickle1.so @@ -126,7 +126,7 @@ test: $(PYEXE) test_getting_started1.py $(PYEXE) test_getting_started2.py $(PYEXE) test_simple_vector.py - $(PYEXE) test_do_it_yourself_converters.py + $(PYEXE) test_do_it_yourself_convts.py $(PYEXE) test_pickle1.py $(PYEXE) test_pickle2.py $(PYEXE) test_pickle3.py @@ -142,7 +142,7 @@ clean: rm -f getting_started1.o getting_started1.so rm -f getting_started2.o getting_started2.so rm -f simple_vector.o simple_vector.so - rm -f do_it_yourself_converters.o do_it_yourself_converters.so + rm -f do_it_yourself_convts.o do_it_yourself_convts.so rm -f pickle1.o pickle1.so rm -f pickle2.o pickle2.so rm -f pickle3.o pickle3.so diff --git a/build/mingw32.mak b/build/mingw32.mak index 6f192ce2..e966f48a 100644 --- a/build/mingw32.mak +++ b/build/mingw32.mak @@ -59,7 +59,7 @@ all: libboost_python.a \ abstract.pyd \ getting_started1.pyd getting_started2.pyd \ simple_vector.pyd \ - do_it_yourself_converters.pyd \ + do_it_yourself_convts.pyd \ pickle1.pyd pickle2.pyd pickle3.pyd \ noncopyable_export.pyd noncopyable_import.pyd \ ivect.pyd dvect.pyd \ @@ -102,11 +102,11 @@ simple_vector.pyd: $(OBJ) simple_vector.o --def simple_vector.def \ $(OBJ) simple_vector.o $(PYLIB) -do_it_yourself_converters.pyd: $(OBJ) do_it_yourself_converters.o +do_it_yourself_convts.pyd: $(OBJ) do_it_yourself_convts.o dllwrap $(DLLWRAPOPTS) \ - --dllname do_it_yourself_converters.pyd \ - --def do_it_yourself_converters.def \ - $(OBJ) do_it_yourself_converters.o $(PYLIB) + --dllname do_it_yourself_convts.pyd \ + --def do_it_yourself_convts.def \ + $(OBJ) do_it_yourself_convts.o $(PYLIB) pickle1.pyd: $(OBJ) pickle1.o dllwrap $(DLLWRAPOPTS) \ @@ -177,7 +177,7 @@ test: $(PYEXE) test_getting_started1.py $(PYEXE) test_getting_started2.py $(PYEXE) test_simple_vector.py - $(PYEXE) test_do_it_yourself_converters.py + $(PYEXE) test_do_it_yourself_convts.py $(PYEXE) test_pickle1.py $(PYEXE) test_pickle2.py $(PYEXE) test_pickle3.py diff --git a/build/tru64_cxx.mak b/build/tru64_cxx.mak index 8f3d3abf..fba2bfe1 100644 --- a/build/tru64_cxx.mak +++ b/build/tru64_cxx.mak @@ -54,7 +54,7 @@ DEPOBJ=$(OBJ) \ abstract.o \ getting_started1.o getting_started2.o \ simple_vector.o \ - do_it_yourself_converters.o \ + do_it_yourself_convts.o \ pickle1.o pickle2.o pickle3.o \ noncopyable_export.o noncopyable_import.o \ ivect.o dvect.o \ @@ -67,7 +67,7 @@ all: libboost_python.a \ abstract.so \ getting_started1.so getting_started2.so \ simple_vector.so \ - do_it_yourself_converters.so \ + do_it_yourself_convts.so \ pickle1.so pickle2.so pickle3.so \ noncopyable_export.so noncopyable_import.so \ ivect.so dvect.so \ @@ -96,8 +96,8 @@ getting_started2.so: $(OBJ) getting_started2.o simple_vector.so: $(OBJ) simple_vector.o $(LD) $(LDOPTS) $(OBJ) simple_vector.o -o simple_vector.so -do_it_yourself_converters.so: $(OBJ) do_it_yourself_converters.o - $(LD) $(LDOPTS) $(OBJ) do_it_yourself_converters.o -o do_it_yourself_converters.so +do_it_yourself_convts.so: $(OBJ) do_it_yourself_convts.o + $(LD) $(LDOPTS) $(OBJ) do_it_yourself_convts.o -o do_it_yourself_convts.so pickle1.so: $(OBJ) pickle1.o $(LD) $(LDOPTS) $(OBJ) pickle1.o -o pickle1.so @@ -140,7 +140,7 @@ test: $(PYEXE) test_getting_started1.py $(PYEXE) test_getting_started2.py $(PYEXE) test_simple_vector.py - $(PYEXE) test_do_it_yourself_converters.py + $(PYEXE) test_do_it_yourself_convts.py $(PYEXE) test_pickle1.py $(PYEXE) test_pickle2.py $(PYEXE) test_pickle3.py @@ -156,7 +156,7 @@ clean: rm -f getting_started1.o getting_started1.so rm -f getting_started2.o getting_started2.so rm -f simple_vector.o simple_vector.so - rm -f do_it_yourself_converters.o do_it_yourself_converters.so + rm -f do_it_yourself_convts.o do_it_yourself_convts.so rm -f pickle1.o pickle1.so rm -f pickle2.o pickle2.so rm -f pickle3.o pickle3.so diff --git a/build/vc60.mak b/build/vc60.mak index f545015b..ae655c14 100644 --- a/build/vc60.mak +++ b/build/vc60.mak @@ -43,7 +43,7 @@ all: boost_python.lib \ abstract.pyd \ getting_started1.pyd getting_started2.pyd \ simple_vector.pyd \ - do_it_yourself_converters.pyd \ + do_it_yourself_convts.pyd \ pickle1.pyd pickle2.pyd pickle3.pyd \ noncopyable_export.pyd noncopyable_import.pyd \ ivect.pyd dvect.pyd \ @@ -67,8 +67,8 @@ getting_started2.pyd: $(OBJ) getting_started2.obj simple_vector.pyd: $(OBJ) simple_vector.obj $(LD) $(LDOPTS) $(OBJ) simple_vector.obj $(PYLIB) /export:initsimple_vector /out:"simple_vector.pyd" -do_it_yourself_converters.pyd: $(OBJ) do_it_yourself_converters.obj - $(LD) $(LDOPTS) $(OBJ) do_it_yourself_converters.obj $(PYLIB) /export:initdo_it_yourself_converters /out:"do_it_yourself_converters.pyd" +do_it_yourself_convts.pyd: $(OBJ) do_it_yourself_convts.obj + $(LD) $(LDOPTS) $(OBJ) do_it_yourself_convts.obj $(PYLIB) /export:initdo_it_yourself_convts /out:"do_it_yourself_convts.pyd" pickle1.pyd: $(OBJ) pickle1.obj $(LD) $(LDOPTS) $(OBJ) pickle1.obj $(PYLIB) /export:initpickle1 /out:"pickle1.pyd" @@ -109,7 +109,7 @@ test: $(PYEXE) test_getting_started1.py $(PYEXE) test_getting_started2.py $(PYEXE) test_simple_vector.py - $(PYEXE) test_do_it_yourself_converters.py + $(PYEXE) test_do_it_yourself_convts.py $(PYEXE) test_pickle1.py $(PYEXE) test_pickle2.py $(PYEXE) test_pickle3.py diff --git a/example/README b/example/README index 35d822d5..817facd0 100644 --- a/example/README +++ b/example/README @@ -10,7 +10,7 @@ See also: libs/python/doc/pickle.html Other advanced concepts are introduced by: abstract.cpp simple_vector.cpp - do_it_yourself_converters.cpp + do_it_yourself_convts.cpp Examples for the cross-module support are provided by: noncopyable_export.cpp diff --git a/example/do_it_yourself_converters.cpp b/example/do_it_yourself_convts.cpp similarity index 97% rename from example/do_it_yourself_converters.cpp rename to example/do_it_yourself_convts.cpp index 6d2d2d6a..4d9c1c89 100644 --- a/example/do_it_yourself_converters.cpp +++ b/example/do_it_yourself_convts.cpp @@ -105,12 +105,12 @@ BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE BOOST_PYTHON_END_CONVERSION_NAMESPACE -BOOST_PYTHON_MODULE_INIT(do_it_yourself_converters) +BOOST_PYTHON_MODULE_INIT(do_it_yourself_convts) { try { // Create an object representing this extension module. - python::module_builder this_module("do_it_yourself_converters"); + python::module_builder this_module("do_it_yourself_convts"); // Create the Python type object for our extension class. python::class_builder ixset_class(this_module, "IndexingSet"); diff --git a/example/test_do_it_yourself_converters.py b/example/test_do_it_yourself_convts.py similarity index 63% rename from example/test_do_it_yourself_converters.py rename to example/test_do_it_yourself_convts.py index 17240750..6f5fa5a0 100644 --- a/example/test_do_it_yourself_converters.py +++ b/example/test_do_it_yourself_convts.py @@ -1,5 +1,5 @@ -r'''>>> import do_it_yourself_converters - >>> ixset = do_it_yourself_converters.IndexingSet() +r'''>>> import do_it_yourself_convts + >>> ixset = do_it_yourself_convts.IndexingSet() >>> ixset.add((1,2,3)) >>> ixset.add((4,5,6)) >>> ixset.add((7,8,9)) @@ -15,8 +15,8 @@ def run(args = None): if args is not None: import sys sys.argv = args - import doctest, test_do_it_yourself_converters - return doctest.testmod(test_do_it_yourself_converters) + import doctest, test_do_it_yourself_convts + return doctest.testmod(test_do_it_yourself_convts) if __name__ == '__main__': import sys From f646975c3668bdb05376b3a14b62f59cd96c1b0e Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 31 Jul 2001 08:10:05 +0000 Subject: [PATCH 133/369] convert int/double to complex [SVN r10730] --- include/boost/python/conversions.hpp | 5 +++++ test/comprehensive.py | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/include/boost/python/conversions.hpp b/include/boost/python/conversions.hpp index 47f80989..cf753e2d 100644 --- a/include/boost/python/conversions.hpp +++ b/include/boost/python/conversions.hpp @@ -7,6 +7,7 @@ // producing this work. // // Revision History: +// 31 Jul 01 convert int/double to complex (Peter Bienstman) // 04 Mar 01 Fixed std::complex<> stuff to work with MSVC (David Abrahams) // 03 Mar 01 added: converters for [plain] char and std::complex // (Ralf W. Grosse-Kunstleve) @@ -93,6 +94,10 @@ namespace detail { template std::complex complex_from_python(PyObject* p, boost::python::type) { + if (PyInt_Check(p)) return std::complex(PyInt_AS_LONG(p)); + if (PyLong_Check(p)) return std::complex(PyLong_AsDouble(p)); + if (PyFloat_Check(p)) return std::complex(PyFloat_AS_DOUBLE(p)); + expect_complex(p); return std::complex( diff --git a/test/comprehensive.py b/test/comprehensive.py index db4f8b73..4ff34b48 100644 --- a/test/comprehensive.py +++ b/test/comprehensive.py @@ -1175,6 +1175,18 @@ test methodologies for wrapping functions that return a pointer '2.94' >>> '%.3g' % (dreal(c)) '6.35' + >>> '%.3g' % (dreal(3)) + '3' + >>> '%.3g' % (dreal(3L)) + '3' + >>> '%.3g' % (dreal(3.)) + '3' + >>> '%.3g' % (freal(3)) + '3' + >>> '%.3g' % (freal(3L)) + '3' + >>> '%.3g' % (freal(3.)) + '3' ''' #' From 9f3cda0ac35cc752ab6928d8f7c8f7f1101eeef5 Mon Sep 17 00:00:00 2001 From: Darin Adler Date: Tue, 7 Aug 2001 17:22:02 +0000 Subject: [PATCH 134/369] Spell things consistently. Add some bits of Mac stuff to the tests. Use std::size_t where needed. [SVN r10800] --- example/dvect.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/dvect.h b/example/dvect.h index 8ffe7b50..d059f04d 100644 --- a/example/dvect.h +++ b/example/dvect.h @@ -9,7 +9,7 @@ namespace vects { struct dvect : public std::vector { dvect() : std::vector() {} - dvect(size_t n) : std::vector(n) {} + dvect(std::size_t n) : std::vector(n) {} dvect(boost::python::tuple tuple) : std::vector(tuple.size()) { std::vector::iterator v_it = begin(); From 6e6ae18aabefe93b2a8561effaa54877f5da983e Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 15 Aug 2001 19:15:57 +0000 Subject: [PATCH 135/369] Missing "std::" added (std::size_t) [SVN r10872] --- example/ivect.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/ivect.h b/example/ivect.h index a0187307..b8d52246 100644 --- a/example/ivect.h +++ b/example/ivect.h @@ -9,7 +9,7 @@ namespace vects { struct ivect : public std::vector { ivect() : std::vector() {} - ivect(size_t n) : std::vector(n) {} + ivect(std::size_t n) : std::vector(n) {} ivect(boost::python::tuple tuple) : std::vector(tuple.size()) { std::vector::iterator v_it = begin(); From 37b6e2232147e655aadf79d0fbaa99d628abae5f Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Mon, 20 Aug 2001 13:04:43 +0000 Subject: [PATCH 136/369] Misc; mostly fix links to hard disk locations [SVN r10902] --- doc/under-the-hood.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/under-the-hood.html b/doc/under-the-hood.html index e2a0ce2b..ee0ecdfb 100644 --- a/doc/under-the-hood.html +++ b/doc/under-the-hood.html @@ -35,8 +35,7 @@ "example1.html#world_class">extension_class<T> template defines a whole raft of these conversions (for T, T*, T&, std::auto_ptr<T>, etc.), using the same inline - friend function technique employed by the boost operators + friend function technique employed by the boost operators library.

    Because the to_python and from_python functions From c7f1c5e29cb6437cff63601ac0f7f6751cdf41af Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 28 Aug 2001 02:02:27 +0000 Subject: [PATCH 137/369] New example: nested.cpp [SVN r10946] --- build/filemgr.py | 3 +++ build/irix_CC.mak | 7 +++++++ build/linux_gcc.mak | 7 +++++++ build/mingw32.mak | 13 ++++++++++++- build/tru64_cxx.mak | 7 +++++++ build/vc60.mak | 7 ++++++- example/nested.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++ example/test_nested.py | 23 ++++++++++++++++++++++ 8 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 example/nested.cpp create mode 100644 example/test_nested.py diff --git a/build/filemgr.py b/build/filemgr.py index 2ff163f0..99f4ca30 100644 --- a/build/filemgr.py +++ b/build/filemgr.py @@ -24,6 +24,7 @@ bpl_exa + "/getting_started1.cpp", bpl_exa + "/getting_started2.cpp", bpl_exa + "/simple_vector.cpp", bpl_exa + "/do_it_yourself_convts.cpp", +bpl_exa + "/nested.cpp", bpl_exa + "/pickle1.cpp", bpl_exa + "/pickle2.cpp", bpl_exa + "/pickle3.cpp", @@ -32,6 +33,7 @@ bpl_exa + "/test_getting_started1.py", bpl_exa + "/test_getting_started2.py", bpl_exa + "/test_simple_vector.py", bpl_exa + "/test_do_it_yourself_convts.py", +bpl_exa + "/test_nested.py", bpl_exa + "/test_pickle1.py", bpl_exa + "/test_pickle2.py", bpl_exa + "/test_pickle3.py", @@ -68,6 +70,7 @@ defs = ( "getting_started2", "simple_vector", "do_it_yourself_convts", +"nested", "pickle1", "pickle2", "pickle3", diff --git a/build/irix_CC.mak b/build/irix_CC.mak index 6e465b98..e3a97781 100644 --- a/build/irix_CC.mak +++ b/build/irix_CC.mak @@ -44,6 +44,7 @@ DEPOBJ=$(OBJ) \ getting_started1.o getting_started2.o \ simple_vector.o \ do_it_yourself_convts.o \ + nested.o \ pickle1.o pickle2.o pickle3.o \ noncopyable_export.o noncopyable_import.o \ ivect.o dvect.o \ @@ -57,6 +58,7 @@ all: libboost_python.a \ getting_started1.so getting_started2.so \ simple_vector.so \ do_it_yourself_convts.so \ + nested.so \ pickle1.so pickle2.so pickle3.so \ noncopyable_export.so noncopyable_import.so \ ivect.so dvect.so \ @@ -84,6 +86,9 @@ simple_vector.so: $(OBJ) simple_vector.o do_it_yourself_convts.so: $(OBJ) do_it_yourself_convts.o $(LD) $(LDOPTS) $(OBJ) do_it_yourself_convts.o -o do_it_yourself_convts.so +nested.so: $(OBJ) nested.o + $(LD) $(LDOPTS) $(OBJ) nested.o -o nested.so + pickle1.so: $(OBJ) pickle1.o $(LD) $(LDOPTS) $(OBJ) pickle1.o -o pickle1.so @@ -126,6 +131,7 @@ test: $(PYEXE) test_getting_started2.py $(PYEXE) test_simple_vector.py $(PYEXE) test_do_it_yourself_convts.py + $(PYEXE) test_nested.py $(PYEXE) test_pickle1.py $(PYEXE) test_pickle2.py $(PYEXE) test_pickle3.py @@ -142,6 +148,7 @@ clean: rm -f getting_started2.o getting_started2.so rm -f simple_vector.o simple_vector.so rm -f do_it_yourself_convts.o do_it_yourself_convts.so + rm -f nested.o nested.so rm -f pickle1.o pickle1.so rm -f pickle2.o pickle2.so rm -f pickle3.o pickle3.so diff --git a/build/linux_gcc.mak b/build/linux_gcc.mak index 2c977473..64d61bab 100644 --- a/build/linux_gcc.mak +++ b/build/linux_gcc.mak @@ -45,6 +45,7 @@ DEPOBJ=$(OBJ) \ getting_started1.o getting_started2.o \ simple_vector.o \ do_it_yourself_convts.o \ + nested.o \ pickle1.o pickle2.o pickle3.o \ noncopyable_export.o noncopyable_import.o \ ivect.o dvect.o \ @@ -58,6 +59,7 @@ all: libboost_python.a \ getting_started1.so getting_started2.so \ simple_vector.so \ do_it_yourself_convts.so \ + nested.so \ pickle1.so pickle2.so pickle3.so \ noncopyable_export.so noncopyable_import.so \ ivect.so dvect.so \ @@ -85,6 +87,9 @@ simple_vector.so: $(OBJ) simple_vector.o do_it_yourself_convts.so: $(OBJ) do_it_yourself_convts.o $(LD) $(LDOPTS) $(OBJ) do_it_yourself_convts.o -o do_it_yourself_convts.so +nested.so: $(OBJ) nested.o + $(LD) $(LDOPTS) $(OBJ) nested.o -o nested.so + pickle1.so: $(OBJ) pickle1.o $(LD) $(LDOPTS) $(OBJ) pickle1.o -o pickle1.so @@ -127,6 +132,7 @@ test: $(PYEXE) test_getting_started2.py $(PYEXE) test_simple_vector.py $(PYEXE) test_do_it_yourself_convts.py + $(PYEXE) test_nested.py $(PYEXE) test_pickle1.py $(PYEXE) test_pickle2.py $(PYEXE) test_pickle3.py @@ -143,6 +149,7 @@ clean: rm -f getting_started2.o getting_started2.so rm -f simple_vector.o simple_vector.so rm -f do_it_yourself_convts.o do_it_yourself_convts.so + rm -f nested.o nested.so rm -f pickle1.o pickle1.so rm -f pickle2.o pickle2.so rm -f pickle3.o pickle3.so diff --git a/build/mingw32.mak b/build/mingw32.mak index e966f48a..bf590409 100644 --- a/build/mingw32.mak +++ b/build/mingw32.mak @@ -30,13 +30,16 @@ # -fvtable-thunks eliminates the compiler warning, but # "import boost_python_test" still causes a crash. -ROOT=L: +ROOT=R: BOOST_WIN="$(ROOT)\boost" BOOST_UNIX=$(HOME)/boost PYEXE="C:\Program files\Python\python.exe" PYINC=-I"C:\usr\include\python1.5" PYLIB="C:\usr\lib\libpython15.a" +#PYEXE="C:\Python21\python.exe" +#PYINC=-I"C:\usr\include\python2.1" +#PYLIB="C:\usr\lib\libpython21.a" STDOPTS=-ftemplate-depth-21 WARNOPTS= @@ -60,6 +63,7 @@ all: libboost_python.a \ getting_started1.pyd getting_started2.pyd \ simple_vector.pyd \ do_it_yourself_convts.pyd \ + nested.pyd \ pickle1.pyd pickle2.pyd pickle3.pyd \ noncopyable_export.pyd noncopyable_import.pyd \ ivect.pyd dvect.pyd \ @@ -108,6 +112,12 @@ do_it_yourself_convts.pyd: $(OBJ) do_it_yourself_convts.o --def do_it_yourself_convts.def \ $(OBJ) do_it_yourself_convts.o $(PYLIB) +nested.pyd: $(OBJ) nested.o + dllwrap $(DLLWRAPOPTS) \ + --dllname nested.pyd \ + --def nested.def \ + $(OBJ) nested.o $(PYLIB) + pickle1.pyd: $(OBJ) pickle1.o dllwrap $(DLLWRAPOPTS) \ --dllname pickle1.pyd \ @@ -178,6 +188,7 @@ test: $(PYEXE) test_getting_started2.py $(PYEXE) test_simple_vector.py $(PYEXE) test_do_it_yourself_convts.py + $(PYEXE) test_nested.py $(PYEXE) test_pickle1.py $(PYEXE) test_pickle2.py $(PYEXE) test_pickle3.py diff --git a/build/tru64_cxx.mak b/build/tru64_cxx.mak index fba2bfe1..d06f3372 100644 --- a/build/tru64_cxx.mak +++ b/build/tru64_cxx.mak @@ -55,6 +55,7 @@ DEPOBJ=$(OBJ) \ getting_started1.o getting_started2.o \ simple_vector.o \ do_it_yourself_convts.o \ + nested.o \ pickle1.o pickle2.o pickle3.o \ noncopyable_export.o noncopyable_import.o \ ivect.o dvect.o \ @@ -68,6 +69,7 @@ all: libboost_python.a \ getting_started1.so getting_started2.so \ simple_vector.so \ do_it_yourself_convts.so \ + nested.so \ pickle1.so pickle2.so pickle3.so \ noncopyable_export.so noncopyable_import.so \ ivect.so dvect.so \ @@ -99,6 +101,9 @@ simple_vector.so: $(OBJ) simple_vector.o do_it_yourself_convts.so: $(OBJ) do_it_yourself_convts.o $(LD) $(LDOPTS) $(OBJ) do_it_yourself_convts.o -o do_it_yourself_convts.so +nested.so: $(OBJ) nested.o + $(LD) $(LDOPTS) $(OBJ) nested.o -o nested.so + pickle1.so: $(OBJ) pickle1.o $(LD) $(LDOPTS) $(OBJ) pickle1.o -o pickle1.so @@ -141,6 +146,7 @@ test: $(PYEXE) test_getting_started2.py $(PYEXE) test_simple_vector.py $(PYEXE) test_do_it_yourself_convts.py + $(PYEXE) test_nested.py $(PYEXE) test_pickle1.py $(PYEXE) test_pickle2.py $(PYEXE) test_pickle3.py @@ -157,6 +163,7 @@ clean: rm -f getting_started2.o getting_started2.so rm -f simple_vector.o simple_vector.so rm -f do_it_yourself_convts.o do_it_yourself_convts.so + rm -f nested.o nested.so rm -f pickle1.o pickle1.so rm -f pickle2.o pickle2.so rm -f pickle3.o pickle3.so diff --git a/build/vc60.mak b/build/vc60.mak index ae655c14..a348de54 100644 --- a/build/vc60.mak +++ b/build/vc60.mak @@ -10,7 +10,7 @@ # 12 Apr 01 new macro ROOT to simplify configuration (R.W. Grosse-Kunstleve) # Initial version: R.W. Grosse-Kunstleve -ROOT=L: +ROOT=R: BOOST_WIN="$(ROOT)\boost" BOOST_UNIX=$(HOME)/boost @@ -44,6 +44,7 @@ all: boost_python.lib \ getting_started1.pyd getting_started2.pyd \ simple_vector.pyd \ do_it_yourself_convts.pyd \ + nested.pyd \ pickle1.pyd pickle2.pyd pickle3.pyd \ noncopyable_export.pyd noncopyable_import.pyd \ ivect.pyd dvect.pyd \ @@ -70,6 +71,9 @@ simple_vector.pyd: $(OBJ) simple_vector.obj do_it_yourself_convts.pyd: $(OBJ) do_it_yourself_convts.obj $(LD) $(LDOPTS) $(OBJ) do_it_yourself_convts.obj $(PYLIB) /export:initdo_it_yourself_convts /out:"do_it_yourself_convts.pyd" +nested.pyd: $(OBJ) nested.obj + $(LD) $(LDOPTS) $(OBJ) nested.obj $(PYLIB) /export:initnested /out:"nested.pyd" + pickle1.pyd: $(OBJ) pickle1.obj $(LD) $(LDOPTS) $(OBJ) pickle1.obj $(PYLIB) /export:initpickle1 /out:"pickle1.pyd" @@ -110,6 +114,7 @@ test: $(PYEXE) test_getting_started2.py $(PYEXE) test_simple_vector.py $(PYEXE) test_do_it_yourself_convts.py + $(PYEXE) test_nested.py $(PYEXE) test_pickle1.py $(PYEXE) test_pickle2.py $(PYEXE) test_pickle3.py diff --git a/example/nested.cpp b/example/nested.cpp new file mode 100644 index 00000000..543754f7 --- /dev/null +++ b/example/nested.cpp @@ -0,0 +1,44 @@ +// Example by Ralf W. Grosse-Kunstleve + +/* + This example shows how convert a nested Python tuple. + */ + +#include +#include + +namespace { + + boost::python::list + show_nested_tuples(boost::python::tuple outer) + { + boost::python::list result; + for (int i = 0; i < outer.size(); i++) { + boost::python::tuple inner( + BOOST_PYTHON_CONVERSION::from_python(outer[i].get(), + boost::python::type())); + for (int j = 0; j < inner.size(); j++) { + double x = BOOST_PYTHON_CONVERSION::from_python(inner[j].get(), + boost::python::type()); + char buf[128]; + sprintf(buf, "(%d,%d) %.6g", i, j, x); + result.append(BOOST_PYTHON_CONVERSION::to_python(std::string(buf))); + } + } + return result; + } + +} + +BOOST_PYTHON_MODULE_INIT(nested) +{ + try + { + boost::python::module_builder this_module("nested"); + this_module.def(show_nested_tuples, "show_nested_tuples"); + } + catch(...) + { + boost::python::handle_exception(); + } +} diff --git a/example/test_nested.py b/example/test_nested.py new file mode 100644 index 00000000..e9abbf0f --- /dev/null +++ b/example/test_nested.py @@ -0,0 +1,23 @@ +r'''>>> import nested + >>> s = nested.show_nested_tuples(((1,2,3), (4,5,6,7))) + >>> for l in s: + ... print l + (0,0) 1 + (0,1) 2 + (0,2) 3 + (1,0) 4 + (1,1) 5 + (1,2) 6 + (1,3) 7 +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_nested + return doctest.testmod(test_nested) + +if __name__ == '__main__': + import sys + sys.exit(run()[0]) From e552607c95cf513a8f3e1f3c1ce123c909356fd1 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 22 Sep 2001 17:51:10 +0000 Subject: [PATCH 138/369] const-ified list::size() and slice_proxy::size() [SVN r11212] --- include/boost/python/objects.hpp | 4 ++-- src/objects.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/python/objects.hpp b/include/boost/python/objects.hpp index 34052e1f..3b1a9094 100644 --- a/include/boost/python/objects.hpp +++ b/include/boost/python/objects.hpp @@ -101,7 +101,7 @@ class list : public object explicit list(std::size_t sz = 0); static PyTypeObject* type_obj(); static bool accepts(ref p); - std::size_t size(); + std::size_t size() const; ref operator[](std::size_t pos) const; proxy operator[](std::size_t pos); ref get_item(std::size_t pos) const; @@ -283,7 +283,7 @@ struct list::slice_proxy const list& operator=(const list& rhs); operator ref() const; operator list() const; - std::size_t size(); + std::size_t size() const; ref operator[](std::size_t pos) const; private: friend class list; diff --git a/src/objects.cpp b/src/objects.cpp index cc46b2ba..125a1eb8 100644 --- a/src/objects.cpp +++ b/src/objects.cpp @@ -362,7 +362,7 @@ bool list::accepts(ref p) return PyList_Check(p.get()); } -std::size_t list::size() +std::size_t list::size() const { return PyList_Size(get()); } @@ -467,7 +467,7 @@ list::slice_proxy::operator list() const return list(this->operator ref()); } -std::size_t list::slice_proxy::size() +std::size_t list::slice_proxy::size() const { return this->operator list().size(); } From e63451a9e7a545b7cac02e5756bd46e717251f0d Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 6 Oct 2001 18:19:15 +0000 Subject: [PATCH 139/369] regex, threads, and python will all build from the top level. If you build the 'test' target from the top level, it will run all regressions. Jamfile: subincludes for thread, python libs, and status for regression tests Jamrules: Use the new path-global rule to establish BOOST_ROOT correctly for all subprojects libs/regex/build/Jamfile Take advantage of correct BOOST_ROOT setting libs/python/build/Jamfile Search for python executable; don't try to build anything if it can't be found. don't build tests by default improved comments, organization, and naming. status/Jamfile Fixed references to config test files Failed tests now leave their stdout results in .error instead of removing it No test targets are dependencies of 'all' anymore Added comments Reorganized tools/build/Jambase Meant to check this in long ago. tools/build/allyourbase.jam Fixed SHELL_EXPORT setting, added SHELL_SET removed 'test' from the dependencies of 'all'; tests no longer run by default. Fixed the direction of slashes for Windows when ALL_LOCATE_TARGET is used. Added path-global rule for declaring path variables which may be relative rule in-invocation-subdir returns true if the current subproject is the one from which Jam was invoked rule protect-subdir is now used to protect subproject variables rule tokens-to-simple-path converts path tokens to a simplified path. tools/build/boost-base.jam Fixed bugs tools/build/jam_src/makedebugjam.bat Fixed a bug which prevented a final debug build tools/build/jam_src/search.c Fixed a bug of mine which caused LOCATE to be ignored (!). [SVN r11348] --- build/Jamfile | 136 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 88 insertions(+), 48 deletions(-) diff --git a/build/Jamfile b/build/Jamfile index 562aca1e..d597d055 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -5,13 +5,16 @@ # # 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 .test and .run -# .test runs the test when it is out-of-date, and the "all" target -# depends on it so that it it is built by default. .run runs +# .test runs the test when it is out-of-date, and the "test" +# pseudotarget depends on it. .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: @@ -38,6 +41,12 @@ # # 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. @@ -49,12 +58,21 @@ # declare the location of this subproject relative to the root subproject libs/python/build ; +# grab variables from command-line or environment. +local PYTHON_VERSION = $(PYTHON_VERSION) ; +local PYTHON_ROOT = $(PYTHON_ROOT) ; +local PYTHON_INCLUDES = $(PYTHON_INCLUDES) ; +local PYTHON_LIBS = $(PYTHON_LIBS) ; +local PYTHON_LIB_PATH = $(PYTHON_LIB_PATH) ; +local PYTHON_PROPERTIES = $(PYTHON_PROPERTIES) ; + # Do some OS-specific setup if $(NT) { + PYTHON_VERSION ?= 2.1 ; PYTHON_ROOT ?= c:/tools/python ; - PYTHON_INCLUDES ?= $(PYTHON_ROOT)/include <*>/usr/include/python2.1 ; - PYTHON_LIBS ?= c:/cygnus/lib/python2.1/config/libpython2.1.dll.a ; + PYTHON_INCLUDES ?= $(PYTHON_ROOT)/include <*>/usr/include/python$(PYTHON_VERSION) ; + PYTHON_LIBS ?= c:/cygnus/lib/python$(PYTHON_VERSION)/config/libpython$(PYTHON_VERSION).dll.a ; PYTHON_LIB_PATH = $(PYTHON_ROOT)/libs ; # common properties required for compiling any Python module. @@ -64,17 +82,20 @@ if $(NT) dynamic ; - SHELL_SET ?= "set " ; - SHELL_EXPORT ?= ; # shell variables are exported by default } else if $(UNIX) { - PYTHON_INCLUDES ?= /usr/include/python1.5 ; - PYTHON_LIBS ?= /usr/lib/python1.5/config/libpython1.5.a ; - SHELL_SET ?= "" ; - SHELL_EXPORT ?= "export " ; + PYTHON_VERSION ?= 1.5 ; + PYTHON_INCLUDES ?= /usr/include/python$(PYTHON_VERSION) ; + PYTHON_LIBS ?= /usr/lib/python$(PYTHON_VERSION)/config/libpython$(PYTHON_VERSION).a ; } +# how do we invoke python? +local PYTHON = $(PYTHON) ; +PYTHON ?= python ; +PYTHON = [ FAppendSuffix $(PYTHON:G=) : $(SUFEXE) ] ; +SEARCH on $(PYTHON) = $(PATH) ; + ####################### # @@ -82,10 +103,10 @@ else if $(UNIX) # # standard include requirements for anything using Boost.Python -BOOST_PYTHON_INCLUDES = $(BOOST_ROOT) $(PYTHON_INCLUDES) ; +local BOOST_PYTHON_INCLUDES = $(BOOST_ROOT) $(PYTHON_INCLUDES) ; # Base names of the source files for libboost_python -CPP_SOURCES = +local CPP_SOURCES = classes conversions extension_class functions init_function module_builder objects types cross_module ; @@ -117,13 +138,25 @@ rule boost-python : $(4) ; # pass on the default-BUILD, if any } +# boost-python-test name : sources : requirements : default-BUILD +# +# Just like boost-python, but the result becomes part of the test pseudotarget +# instead of being built by 'all' +rule boost-python-test +{ + type-DEPENDS test : $(<) ; + + local gSUPPRESS_FAKE_TARGETS = true ; + boost-python $(1) : $(2) : $(3) : $(4) ; +} + ####################### -# boost-python-test target : python-script sources : requirements : local-build : args +# boost-python-runtest target : python-script sources : requirements : local-build : args # # declare two python module tests: $(<).test which builds when out-of-date, and # $(<).run which builds unconditionally. -rule boost-python-test +rule boost-python-runtest { # tell Jam that the python script is relative to this directory SEARCH on $(>[1]) = $(SEARCH_SOURCE) ; @@ -131,28 +164,25 @@ rule boost-python-test # required command-line args can be specified in argument 5 # The user can add additional arguments in PYTHON_TEST_ARGS. local gPYTHON_TEST_ARGS = $(5) $(PYTHON_TEST_ARGS) ; - + # declare the two subsidiary tests. declare-local-target $(<:S=.test) : $(>) : $(PYTHON_PROPERTIES) : $(4) : PYTHON_TEST ; declare-local-target $(<:S=.run) : $(>) : $(PYTHON_PROPERTIES) : $(4) : PYTHON_RUNTEST ; } -# how do we invoke python? -PYTHON ?= python ; - # special rules for two new target types: PYTHON_TEST and PYTHON_RUNTEST. # These are identical except that PYTHON_TEST runs the test when out-of-date, and -# PYTHON_RUNTEST runs the test unconditionally. These are used by boost-python-test. +# PYTHON_RUNTEST runs the test unconditionally. These are used by boost-python-runtest. SUFPYTHON_TEST = .test ; gGENERATOR_FUNCTION(PYTHON_TEST) = python-test-target ; rule python-test-target # test-target : sources : { - python-test-aux $(<) : $(>) ; + python-runtest-aux $(<) : $(>) ; Clean clean : $(<) ; # remove the test-target as part of any clean operation type-DEPENDS test : $(<) ; MakeLocate $(<) : $(LOCATE_TARGET) ; } -actions python-test-target +actions python-test-target bind PYTHON { $(SHELL_SET)PYTHONPATH=$(PYTHONPATH) $(SHELL_EXPORT)PYTHONPATH @@ -163,18 +193,18 @@ SUFPYTHON_RUNTEST = .run ; gGENERATOR_FUNCTION(PYTHON_RUNTEST) = python-runtest-target ; rule python-runtest-target # test-target : sources : { - python-test-aux $(<) : $(>) ; + python-runtest-aux $(<) : $(>) ; NOTFILE $(<) ; ALWAYS $(<) ; } -actions python-runtest-target +actions python-runtest-target bind PYTHON { $(SHELL_SET)PYTHONPATH=$(PYTHONPATH) $(SHELL_EXPORT)PYTHONPATH $(PYTHON) "$(>)" $(ARGS) } -rule python-test-aux # target : sources +rule python-runtest-aux # target : sources { DEPENDS $(<) : $(>) ; @@ -196,50 +226,60 @@ rule python-test-aux # target : sources [ join-path $(TOP) libs python test ] # location of doctest $(PYTHONPATH) # base PYTHONPATH from environment : $(SPLITPATH) ] ; # platform path separator + + PYTHON on $(<) = $(PYTHON) ; + DEPENDS $(<) : $(PYTHON) ; } ############# comprehensive module and test ########### -boost-python boost_python_test : ../test/comprehensive.cpp ; -boost-python-test comprehensive : [ join-path $(DOTDOT) test comprehensive.py ] boost_python_test ; +boost-python-test boost_python_test : ../test/comprehensive.cpp ; + +boost-python-runtest comprehensive + : [ join-path $(DOTDOT) test comprehensive.py ] + boost_python_test ; ############# simple tests from ../example ############ -rule boost-python-example-test +rule boost-python-example-runtest { - boost-python $(<) : ../example/$(<).cpp ; - boost-python-test $(<) : [ join-path $(DOTDOT) example test_$(<).py ] $(<) ; + boost-python-test $(<) : ../example/$(<).cpp ; + boost-python-runtest $(<) : [ join-path $(DOTDOT) example test_$(<).py ] $(<) ; } -boost-python-example-test abstract ; -boost-python-example-test getting_started1 ; -boost-python-example-test getting_started2 ; -boost-python-example-test simple_vector ; -boost-python-example-test do_it_yourself_convts ; -boost-python-example-test pickle1 ; -boost-python-example-test pickle2 ; -boost-python-example-test pickle3 ; +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 ; -boost-python ivect : ../example/ivect.cpp ; -boost-python dvect : ../example/dvect.cpp ; -boost-python noncopyable_export : ../example/noncopyable_export.cpp ; -boost-python noncopyable_import : ../example/noncopyable_import.cpp ; +boost-python-test ivect : ../example/ivect.cpp ; +boost-python-test dvect : ../example/dvect.cpp ; +boost-python-test noncopyable_export : ../example/noncopyable_export.cpp ; +boost-python-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 -rule boost-python-multi-example-test # test-name : python-file libs +rule boost-python-multi-example-runtest # test-name : python-file libs { - boost-python-test $(<) : ../example/tst_$(<).py $(>) : : : $(PYTHON_VECT_ITERATIONS) ; + boost-python-runtest $(<) + : ../example/tst_$(<).py $(>) + : : : $(PYTHON_VECT_ITERATIONS) ; } + PYTHON_VECT_ITERATIONS ?= 10 ; -boost-python-multi-example-test dvect1 : ivect dvect ; -boost-python-multi-example-test dvect2 : ivect dvect ; +boost-python-multi-example-runtest dvect1 : ivect dvect ; +boost-python-multi-example-runtest dvect2 : ivect dvect ; -boost-python-multi-example-test ivect1 : ivect dvect ; -boost-python-multi-example-test ivect2 : ivect dvect ; +boost-python-multi-example-runtest ivect1 : ivect dvect ; +boost-python-multi-example-runtest ivect2 : ivect dvect ; -boost-python-multi-example-test noncopyable : noncopyable_import noncopyable_export ; +boost-python-multi-example-runtest + noncopyable : noncopyable_import noncopyable_export ; From a245bdbc2adcb44463b80b7a0d3f3003a3ec3b6e Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 31 Oct 2001 19:14:07 +0000 Subject: [PATCH 140/369] Modified Files: boost/python/detail: base_object.hpp - Changed template parameter to MixedCase cast.hpp - Killed off unused downcast_traits<> functions.hpp - Added commentary libs/python/src functions.cpp, types.cpp - Added comments tools/build TODO.txt - updated allyourbase.jam - fixed a nasty typo which caused all kinds of bugs boost-base.jam - changes to support the use of command files intel-win32-tools.jam - A feeble attempt at allowing intel to work without prior tool setup. More work needed msvc-tools.jam - A first cut at command file support tools/build/jam_src jam.h - Fixed MAXLINE for NT [SVN r11489] --- include/boost/python/detail/base_object.hpp | 14 +++++++------- include/boost/python/detail/cast.hpp | 16 ++++------------ include/boost/python/detail/functions.hpp | 9 +++++++-- src/functions.cpp | 7 +++++++ src/types.cpp | 9 +++++++++ 5 files changed, 34 insertions(+), 21 deletions(-) diff --git a/include/boost/python/detail/base_object.hpp b/include/boost/python/detail/base_object.hpp index 95a2805c..cf6bb528 100644 --- a/include/boost/python/detail/base_object.hpp +++ b/include/boost/python/detail/base_object.hpp @@ -21,10 +21,10 @@ 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 -struct base_object : python_type +template +struct base_object : PythonType { - typedef python_type base_python_type; + typedef PythonType base_python_type; // Initializes type and reference count. All other fields of base_python_type are 0 base_object(PyTypeObject* type_obj); @@ -41,8 +41,8 @@ typedef base_object python_type; // // base_object member function implementations // -template -base_object::base_object(PyTypeObject* type_obj) +template +base_object::base_object(PyTypeObject* type_obj) { base_python_type* bp = this; #if !defined(_MSC_VER) || defined(__STLPORT) @@ -53,8 +53,8 @@ base_object::base_object(PyTypeObject* type_obj) PyObject_INIT(bp, type_obj); } -template -inline base_object::~base_object() +template +inline base_object::~base_object() { Py_DECREF(ob_type); } diff --git a/include/boost/python/detail/cast.hpp b/include/boost/python/detail/cast.hpp index e047c0b3..67fe7b34 100644 --- a/include/boost/python/detail/cast.hpp +++ b/include/boost/python/detail/cast.hpp @@ -15,14 +15,6 @@ namespace boost { namespace python { namespace detail { - // The default way of converting a PyObject* or PyTypeObject* to a T* - template - struct downcast_traits - { - template - static T* cast(U* p) { return static_cast(p); } - }; - inline PyTypeObject* as_base_object(const PyTypeObject*, PyObject* p) { return reinterpret_cast(p); @@ -54,19 +46,19 @@ template struct downcast { downcast(PyObject* p) - : m_p(detail::downcast_traits::cast(detail::as_base_object((T*)0, p))) + : m_p(static_cast(detail::as_base_object((T*)0, p))) {} downcast(const PyObject* p) - : m_p(detail::downcast_traits::cast(detail::as_base_object((const T*)0, p))) + : m_p(static_cast(detail::as_base_object((const T*)0, p))) {} downcast(PyTypeObject* p) - : m_p(detail::downcast_traits::cast(p)) + : m_p(static_cast(p)) {} downcast(const PyTypeObject* p) - : m_p(detail::downcast_traits::cast(p)) + : m_p(static_cast(p)) {} operator T*() const { return m_p; } diff --git a/include/boost/python/detail/functions.hpp b/include/boost/python/detail/functions.hpp index 055255e7..16b8e16d 100644 --- a/include/boost/python/detail/functions.hpp +++ b/include/boost/python/detail/functions.hpp @@ -46,7 +46,7 @@ class function : public python_object private: struct type_object; private: - reference m_overloads; + reference m_overloads; // A linked list of the function overloads }; // wrapped_function_pointer<> -- @@ -66,7 +66,12 @@ struct wrapped_function_pointer : function private: PyObject* do_call(PyObject* args, PyObject* keywords) const - { return caller::call(m_pf, args, keywords); } + { + // This is where the boundary between the uniform Python function + // interface and the statically-checked C++ function interface is + // crossed. + return caller::call(m_pf, args, keywords); + } const char* description() const { return typeid(F).name(); } diff --git a/src/functions.cpp b/src/functions.cpp index 71b59136..a04e2e51 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -61,6 +61,8 @@ function::function() PyObject* function::call(PyObject* args, PyObject* keywords) const { + // Traverse the linked list of function overloads until we find one that + // matches. for (const function* f = this; f != 0; f = f->m_overloads.get()) { PyErr_Clear(); @@ -75,9 +77,14 @@ PyObject* function::call(PyObject* args, PyObject* keywords) const } } + // If we get here, no overloads matched the arguments + + // Allow the single-function error-reporting to take effect unless there was + // an overload if (m_overloads.get() == 0) return 0; + // Synthesize a more-explicit error message PyErr_Clear(); string message("No overloaded functions match ("); tuple arguments(ref(args, ref::increment_count)); diff --git a/src/types.cpp b/src/types.cpp index f8cf1ea6..add0ebf0 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -24,6 +24,11 @@ namespace { using detail::type_object_base; + // Define a family of forwarding functions that can be calle from a + // PyTypeObject's slots. These functions dispatch through a (virtual) member + // function pointer in the type_object_base, and handle exceptions in a + // uniform way, preventing us from having to rewrite the dispatching code over + // and over. PyObject* call(PyObject* obj, PyObject* (type_object_base::*f)(PyObject*) const) { try @@ -154,6 +159,10 @@ namespace { extern "C" { +// +// These functions actually go into the type object's slots, and dispatch to the +// "call" wrappers defined above. +// static PyObject* do_instance_repr(PyObject* obj) { return call(obj, &type_object_base::instance_repr); From 6cb4b790b9b328d99e8691704c2393fc96a6d703 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 1 Nov 2001 23:28:54 +0000 Subject: [PATCH 141/369] Python 2.2 pickle problems fixed. [SVN r11521] --- test/comprehensive.py | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/test/comprehensive.py b/test/comprehensive.py index 4ff34b48..2ac0704a 100644 --- a/test/comprehensive.py +++ b/test/comprehensive.py @@ -8,14 +8,11 @@ r''' // producing this work. // Revision History: +// 2001 Nov 01 Python 2.2 pickle problems fixed (rwgk) // 04 Mar 01 Changed name of extension module so it would work with DebugPython, // fixed exception message checking to work with Python 2.0 // (Dave Abrahams) -Load up the extension module - - >>> from boost_python_test import * - Automatic checking of the number and type of arguments. Foo's constructor takes a single long parameter. @@ -274,19 +271,12 @@ Pickle safety measures: ... except RuntimeError, err: print err[0] ... Incomplete pickle support (__dict_defines_state__ not set) - >>> class myrational(Rational): - ... __dict_defines_state__ = 1 # this is a lie but good enough for testing. - ... >>> r=myrational(3, 4) >>> r Rational(3, 4) >>> s=pickle.dumps(r) + >>> u=pickle.loads(s) - >>> class myworld(world): - ... def __init__(self): - ... world.__init__(self, 'anywhere') - ... self.x = 1 - ... >>> w = myworld() >>> w.greet() 'Hello from anywhere!' @@ -297,9 +287,6 @@ Pickle safety measures: ... Incomplete pickle support (__getstate_manages_dict__ not set) - >>> class myunsafeworld(myworld): - ... __getstate_manages_dict__ = 1 # this is a lie but good enough for testing. - ... >>> w = myunsafeworld() >>> w.greet() 'Hello from anywhere!' @@ -1191,6 +1178,23 @@ test methodologies for wrapping functions that return a pointer ''' #' +from boost_python_test import * + +# pickle requires these derived classes to be +# at the global scope of the module + +class myrational(Rational): + __dict_defines_state__ = 1 # this is a lie but good enough for testing. + +class myworld(world): + def __init__(self): + world.__init__(self, 'anywhere') + self.x = 1 + +class myunsafeworld(myworld): + __getstate_manages_dict__ = 1 # this is a lie but good enough for testing. + + def assert_integer_expected(err): """Handle a common error report which appears differently in Python 1.5.x and 2.0""" assert isinstance(err, TypeError) From b4a1a6c688d37d831fb7229feeb9f8c14a6015a4 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 2 Nov 2001 01:24:59 +0000 Subject: [PATCH 142/369] PYEXE=PYTHONPATH=. /usr/local/Python-1.5.2/bin/python [SVN r11523] --- build/irix_CC.mak | 4 ++-- build/linux_gcc.mak | 4 ++-- build/tru64_cxx.mak | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build/irix_CC.mak b/build/irix_CC.mak index e3a97781..ec387746 100644 --- a/build/irix_CC.mak +++ b/build/irix_CC.mak @@ -17,9 +17,9 @@ ROOT=$(HOME) BOOST=$(ROOT)/boost -PYEXE=/usr/local/Python-1.5.2/bin/python +PYEXE=PYTHONPATH=. /usr/local/Python-1.5.2/bin/python PYINC=-I/usr/local/Python-1.5.2/include/python1.5 -#PYEXE=/usr/local/Python-2.1/bin/python +#PYEXE=PYTHONPATH=. /usr/local/Python-2.1/bin/python #PYINC=-I/usr/local/Python-2.1/include/python2.1 STLPORTINC=-I$(BOOST)/boost/compatibility/cpp_c_headers diff --git a/build/linux_gcc.mak b/build/linux_gcc.mak index 64d61bab..ef643991 100644 --- a/build/linux_gcc.mak +++ b/build/linux_gcc.mak @@ -19,9 +19,9 @@ BOOST=$(ROOT)/boost PYEXE=PYTHONPATH=. /usr/bin/python PYINC=-I/usr/include/python1.5 -#PYEXE=/usr/local/Python-1.5.2/bin/python +#PYEXE=PYTHONPATH=. /usr/local/Python-1.5.2/bin/python #PYINC=-I/usr/local/Python-1.5.2/include/python1.5 -#PYEXE=/usr/local/Python-2.1/bin/python +#PYEXE=PYTHONPATH=. /usr/local/Python-2.1/bin/python #PYINC=-I/usr/local/Python-2.1/include/python2.1 STDOPTS=-fPIC -ftemplate-depth-21 diff --git a/build/tru64_cxx.mak b/build/tru64_cxx.mak index d06f3372..f996a0c1 100644 --- a/build/tru64_cxx.mak +++ b/build/tru64_cxx.mak @@ -17,9 +17,9 @@ ROOT=$(HOME) BOOST=$(ROOT)/boost -PYEXE=/usr/local/Python-1.5.2/bin/python +PYEXE=PYTHONPATH=. /usr/local/Python-1.5.2/bin/python PYINC=-I/usr/local/Python-1.5.2/include/python1.5 -#PYEXE=/usr/local/Python-2.1/bin/python +#PYEXE=PYTHONPATH=. /usr/local/Python-2.1/bin/python #PYINC=-I/usr/local/Python-2.1/include/python2.1 #STLPORTINC=-I/usr/local/STLport-4.1b3/stlport #STLPORTINC=-I/usr/local/STLport-4.1b4/stlport From b211f8a096c8902442fb5e655ed01928816d5909 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 10 Nov 2001 22:16:01 +0000 Subject: [PATCH 143/369] Modified Files: index.htm - fixed reference to CVS repository libs/python/build/Jamfile - first stab at metrowerks Pro7 support status/Jamfile - added RUN_ALL_TESTS variables to force tests to run tools/build/boost-build.jam - fix BOOST_BUILD_INSTALLATION setting tools/build/metrowerks-tools.jam - command file support tools/build/msvc-tools.jam - permanent command file support tools/build/intel-win32-tools.jam - made it an extension of msvc-tools.jam tools/build/gcc-tools.jam - made FINDLIBS change submitted by Toon Knapen tools/build/jam_src/variable.c - changed command-line/env. variable interpretation so that surrounding them with quotes causes no breaking at spaces. These files were converted from tabs to spaces: boost/python/conversions.hpp boost/python/reference.hpp boost/python/detail/base_object.hpp boost/python/detail/functions.hpp boost/python/detail/wrap_python.hpp libs/python/test/comprehensive.cpp tools/build/boost-base.jam tools/build/como-tools.jam [SVN r11652] --- build/Jamfile | 1 + include/boost/python/conversions.hpp | 22 ++--- include/boost/python/detail/base_object.hpp | 2 +- include/boost/python/detail/functions.hpp | 30 +++---- include/boost/python/detail/wrap_python.hpp | 6 +- include/boost/python/reference.hpp | 98 ++++++++++----------- test/comprehensive.cpp | 2 +- 7 files changed, 83 insertions(+), 78 deletions(-) diff --git a/build/Jamfile b/build/Jamfile index d597d055..eeb38d64 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -132,6 +132,7 @@ rule boost-python # standard requirements $(BOOST_PYTHON_INCLUDES) <*>$(PYTHON_LIB_PATH) + <*>$(PYTHON_LIB_PATH)/python22.lib <*>$(PYTHON_LIBS) $(PYTHON_PROPERTIES) diff --git a/include/boost/python/conversions.hpp b/include/boost/python/conversions.hpp index cf753e2d..c1a7d390 100644 --- a/include/boost/python/conversions.hpp +++ b/include/boost/python/conversions.hpp @@ -74,17 +74,17 @@ inline void xdecref_impl(PyObject* p) { Py_XDECREF(p); } template inline void decref(T* p) { - char* const raw_p = reinterpret_cast(p); - char* const p_base = raw_p - offsetof(PyObject, ob_refcnt); - decref_impl(reinterpret_cast(p_base)); + char* const raw_p = reinterpret_cast(p); + char* const p_base = raw_p - offsetof(PyObject, ob_refcnt); + decref_impl(reinterpret_cast(p_base)); } template inline void xdecref(T* p) { - char* const raw_p = reinterpret_cast(p); - char* const p_base = raw_p - offsetof(PyObject, ob_refcnt); - xdecref_impl(reinterpret_cast(p_base)); + char* const raw_p = reinterpret_cast(p); + char* const p_base = raw_p - offsetof(PyObject, ob_refcnt); + xdecref_impl(reinterpret_cast(p_base)); } namespace detail { @@ -294,22 +294,22 @@ inline PyObject* to_python(float f) inline PyObject* to_python(long l) { - return PyInt_FromLong(l); + return PyInt_FromLong(l); } inline PyObject* to_python(int x) { - return PyInt_FromLong(x); + return PyInt_FromLong(x); } inline PyObject* to_python(short x) { - return PyInt_FromLong(x); + return PyInt_FromLong(x); } inline PyObject* to_python(bool b) { - return PyInt_FromLong(b); + return PyInt_FromLong(b); } inline PyObject* to_python(void) @@ -319,7 +319,7 @@ inline PyObject* to_python(void) inline PyObject* to_python(const char* s) { - return PyString_FromString(s); + return PyString_FromString(s); } inline std::string from_python(PyObject* p, boost::python::type) diff --git a/include/boost/python/detail/base_object.hpp b/include/boost/python/detail/base_object.hpp index cf6bb528..19715876 100644 --- a/include/boost/python/detail/base_object.hpp +++ b/include/boost/python/detail/base_object.hpp @@ -48,7 +48,7 @@ base_object::base_object(PyTypeObject* type_obj) #if !defined(_MSC_VER) || defined(__STLPORT) std:: #endif - memset(bp, 0, sizeof(base_python_type)); + memset(bp, 0, sizeof(base_python_type)); Py_INCREF(type_obj); PyObject_INIT(bp, type_obj); } diff --git a/include/boost/python/detail/functions.hpp b/include/boost/python/detail/functions.hpp index 16b8e16d..eff05d65 100644 --- a/include/boost/python/detail/functions.hpp +++ b/include/boost/python/detail/functions.hpp @@ -59,13 +59,13 @@ class function : public python_object template struct wrapped_function_pointer : function { - typedef F ptr_fun; // pointer-to--function or pointer-to-member-function - - wrapped_function_pointer(ptr_fun pf) + 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 + 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 @@ -77,7 +77,7 @@ struct wrapped_function_pointer : function { return typeid(F).name(); } private: - const ptr_fun m_pf; + const ptr_fun m_pf; }; // raw_arguments_function @@ -87,13 +87,13 @@ struct wrapped_function_pointer : function template struct raw_arguments_function : function { - typedef Ret (*ptr_fun)(Args, Keywords); - - raw_arguments_function(ptr_fun pf) + typedef Ret (*ptr_fun)(Args, Keywords); + + raw_arguments_function(ptr_fun pf) : m_pf(pf) {} private: - PyObject* do_call(PyObject* args, PyObject* keywords) const + PyObject* do_call(PyObject* args, PyObject* keywords) const { ref dict(keywords ? ref(keywords, ref::increment_count) : @@ -108,7 +108,7 @@ struct raw_arguments_function : function { return typeid(ptr_fun).name(); } private: - const ptr_fun m_pf; + const ptr_fun m_pf; }; // virtual_function<> -- @@ -127,19 +127,19 @@ template class virtual_function : public function { public: - virtual_function(V virtual_function_ptr, D default_implementation) + 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; + PyObject* do_call(PyObject* args, PyObject* keywords) const; const char* description() const { return typeid(V).name(); } private: - const V m_virtual_function_ptr; + const V m_virtual_function_ptr; const D m_default_implementation; }; @@ -160,7 +160,7 @@ template 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); + return new_wrapped_function_aux(return_value(pmf), pmf); } template @@ -220,7 +220,7 @@ class bound_function : public python_object private: // data members for allocation/deallocation optimization bound_function* m_free_list_link; - static bound_function* free_list; + static bound_function* free_list; }; // Special functions designed to access data members of a wrapped C++ object. diff --git a/include/boost/python/detail/wrap_python.hpp b/include/boost/python/detail/wrap_python.hpp index b7a47513..373bbde4 100644 --- a/include/boost/python/detail/wrap_python.hpp +++ b/include/boost/python/detail/wrap_python.hpp @@ -90,5 +90,9 @@ typedef int pid_t; #if !defined(PY_MAJOR_VERSION) || PY_MAJOR_VERSION < 2 # define PyObject_INIT(op, typeobj) \ - ( (op)->ob_type = (typeobj), _Py_NewReference((PyObject *)(op)), (op) ) + ( (op)->ob_type = (typeobj), _Py_NewReference((PyObject *)(op)), (op) ) +#endif + +#ifdef __MWERKS__ +# pragma warn_possunwant off #endif diff --git a/include/boost/python/reference.hpp b/include/boost/python/reference.hpp index a1585099..4eb9ad51 100644 --- a/include/boost/python/reference.hpp +++ b/include/boost/python/reference.hpp @@ -42,31 +42,31 @@ BOOST_PYTHON_IMPORT_CONVERSION(py_ptr_conversions); template class reference - : public py_ptr_conversions, T> + : public py_ptr_conversions, T> { public: typedef T value_type; - reference(const reference& rhs) - : m_p(rhs.m_p) - { - Py_XINCREF(object()); - } + reference(const reference& rhs) + : m_p(rhs.m_p) + { + Py_XINCREF(object()); + } #if !defined(BOOST_MSVC6_OR_EARLIER) - template - reference(const reference& rhs) - : m_p(rhs.object()) - { - Py_XINCREF(object()); - } + template + reference(const reference& rhs) + : m_p(rhs.object()) + { + Py_XINCREF(object()); + } #endif - reference() : m_p(0) {} + reference() : m_p(0) {} // These are two ways of spelling the same thing, that we need to increment // the reference count on the pointer when we're initialized. - enum increment_count_t { increment_count }; + enum increment_count_t { increment_count }; enum allow_null { null_ok }; @@ -77,7 +77,7 @@ public: template reference(T2* x, increment_count_t) : m_p(expect_non_null(x)) { Py_INCREF(object()); } - + template reference(T2* x, allow_null) : m_p(x) {} @@ -85,49 +85,49 @@ public: template reference(T2* x, allow_null, increment_count_t) : m_p(x) { Py_XINCREF(object()); } - + template reference(T2* x, increment_count_t, allow_null) : m_p(x) { Py_XINCREF(object()); } - + #if !defined(BOOST_MSVC6_OR_EARLIER) - template - reference& operator=(const reference& rhs) - { - Py_XDECREF(object()); - m_p = rhs.m_p; - Py_XINCREF(object()); - return *this; - } + template + reference& operator=(const reference& rhs) + { + Py_XDECREF(object()); + m_p = rhs.m_p; + Py_XINCREF(object()); + return *this; + } #endif - reference& operator=(const reference& rhs) - { - Py_XINCREF(static_cast(rhs.m_p)); - Py_XDECREF(object()); - m_p = rhs.m_p; - return *this; - } + reference& operator=(const reference& rhs) + { + Py_XINCREF(static_cast(rhs.m_p)); + Py_XDECREF(object()); + m_p = rhs.m_p; + return *this; + } - ~reference() - { - Py_XDECREF(m_p); - } - - T& operator*() const { return *m_p; } + ~reference() + { + Py_XDECREF(m_p); + } + + T& operator*() 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* get() const { return m_p; } - T* release() - { - T* p = m_p; - m_p = 0; - return p; - } + T* release() + { + T* p = m_p; + m_p = 0; + return p; + } void reset() { Py_XDECREF(m_p); m_p = 0; } @@ -139,7 +139,7 @@ public: template void reset(T2* x, increment_count_t) { Py_XDECREF(m_p); m_p = expect_non_null(x); Py_INCREF(object()); } - + template void reset(T2* x, allow_null) { Py_XDECREF(m_p); m_p = x;} @@ -147,11 +147,11 @@ public: template void reset(T2* x, allow_null, increment_count_t) { Py_XDECREF(m_p); m_p = x; Py_XINCREF(object()); } - + template void reset(T2* x, increment_count_t, allow_null) { Py_XDECREF(m_p); m_p = x; Py_XINCREF(object()); } - + #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) private: template friend class shared_ptr; @@ -160,7 +160,7 @@ private: inline PyObject* object() const { return as_object(m_p); } - T* m_p; + T* m_p; }; typedef reference ref; diff --git a/test/comprehensive.cpp b/test/comprehensive.cpp index 427ed2d8..3571183e 100644 --- a/test/comprehensive.cpp +++ b/test/comprehensive.cpp @@ -157,7 +157,7 @@ int IntPairPythonClass::getattr(const IntPair& p, const std::string& s) PyErr_SetString(PyExc_AttributeError, s.c_str()); throw boost::python::error_already_set(); } -#if defined(__MWERKS__) && __MWERKS__ <= 0x2400 +#if defined(__MWERKS__) && __MWERKS__ <= 0x2405 return 0; #endif } From e38bc7cbcecc62e206ca9354cb09aa8beab21d89 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 14 Nov 2001 17:26:11 +0000 Subject: [PATCH 144/369] Pro7 compatibility [SVN r11677] --- include/boost/python/cross_module.hpp | 3 +++ include/boost/python/detail/extension_class.hpp | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/include/boost/python/cross_module.hpp b/include/boost/python/cross_module.hpp index 7c1fe507..dd1c47d2 100644 --- a/include/boost/python/cross_module.hpp +++ b/include/boost/python/cross_module.hpp @@ -169,6 +169,9 @@ struct export_converter_object_noncopyable : export_converter_object_base PyErr_SetString(PyExc_RuntimeError, "to_python(const T&) converter not exported"); throw import_error(); +#if defined(__MWERKS__) && __MWERKS__ <= 0x2406 + return 0; +#endif } virtual T* from_python_Ts(PyObject* p, boost::python::type t) { diff --git a/include/boost/python/detail/extension_class.hpp b/include/boost/python/detail/extension_class.hpp index d871ad6e..f7be9afb 100644 --- a/include/boost/python/detail/extension_class.hpp +++ b/include/boost/python/detail/extension_class.hpp @@ -233,6 +233,9 @@ class python_extension_class_converters } boost::python::detail::report_missing_instance_data(self, boost::python::detail::class_registry::class_object(), typeid(T)); throw boost::python::argument_error(); +#if defined(__MWERKS__) && __MWERKS__ <= 0x2406 + return 0; +#endif } // Convert to T* @@ -261,6 +264,9 @@ class python_extension_class_converters } boost::python::detail::report_missing_ptr_data(self, boost::python::detail::class_registry::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 From e7904fa67a1fa41a8fc535b3fd911c13b8596ae1 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 14 Nov 2001 17:32:08 +0000 Subject: [PATCH 145/369] add _d targets for debugging [SVN r11678] --- build/Jamfile | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/build/Jamfile b/build/Jamfile index eeb38d64..a76f372a 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -73,12 +73,13 @@ if $(NT) PYTHON_ROOT ?= c:/tools/python ; PYTHON_INCLUDES ?= $(PYTHON_ROOT)/include <*>/usr/include/python$(PYTHON_VERSION) ; PYTHON_LIBS ?= c:/cygnus/lib/python$(PYTHON_VERSION)/config/libpython$(PYTHON_VERSION).dll.a ; - PYTHON_LIB_PATH = $(PYTHON_ROOT)/libs ; + PYTHON_LIB_PATH ?= $(PYTHON_ROOT)/libs ; # common properties required for compiling any Python module. PYTHON_PROPERTIES ?= <*>SIZEOF_LONG=4 <*>USE_DL_IMPORT + _DEBUG dynamic ; @@ -90,6 +91,10 @@ else if $(UNIX) PYTHON_LIBS ?= /usr/lib/python$(PYTHON_VERSION)/config/libpython$(PYTHON_VERSION).a ; } +local PYTHON_VERSION_NODOT + = [ SUBST $(PYTHON_VERSION) ([0-9]*)\.([0-9]*) $1$2 ] + ; + # how do we invoke python? local PYTHON = $(PYTHON) ; PYTHON ?= python ; @@ -107,14 +112,22 @@ local BOOST_PYTHON_INCLUDES = $(BOOST_ROOT) $(PYTHON_INCLUDES) ; # Base names of the source files for libboost_python local CPP_SOURCES = - classes conversions extension_class functions - init_function module_builder objects types cross_module ; + types classes conversions extension_class functions + init_function module_builder objects cross_module ; lib libboost_python : ../src/$(CPP_SOURCES).cpp # requirements : $(BOOST_PYTHON_INCLUDES) true $(PYTHON_PROPERTIES) ; + +lib libboost_python_d : ../src/$(CPP_SOURCES).cpp + # requirements + : $(BOOST_PYTHON_INCLUDES) + true + $(PYTHON_PROPERTIES) + BOOST_DEBUG_PYTHON + ; ####################### @@ -123,8 +136,14 @@ lib libboost_python : ../src/$(CPP_SOURCES).cpp # Declare a boost python module. Return a list of the DLL files generated. rule boost-python { + local debug ; + if ( BOOST_DEBUG_PYTHON in $(3) ) || ( debug-python in $(BUILD) ) + { + debug = _d ; + } + # declare a DLL; add the boost python library to sources - dll $(<) : libboost_python $(>) + dll $(<) : libboost_python$(debug) $(>) # Requirements : $(3) # caller-specified requirements @@ -132,7 +151,7 @@ rule boost-python # standard requirements $(BOOST_PYTHON_INCLUDES) <*>$(PYTHON_LIB_PATH) - <*>$(PYTHON_LIB_PATH)/python22.lib + <*>$(PYTHON_LIB_PATH)/python$(PYTHON_VERSION_NODOT)$(debug).lib <*>$(PYTHON_LIBS) $(PYTHON_PROPERTIES) @@ -146,9 +165,12 @@ rule boost-python rule boost-python-test { type-DEPENDS test : $(<) ; + type-DEPENDS test_d : $(<)_d ; + NOTFILE test_d ; local gSUPPRESS_FAKE_TARGETS = true ; boost-python $(1) : $(2) : $(3) : $(4) ; + boost-python $(1)_d : $(2) : $(3) BOOST_DEBUG_PYTHON : $(4) ; } ####################### @@ -239,12 +261,17 @@ boost-python-runtest comprehensive : [ join-path $(DOTDOT) test comprehensive.py ] boost_python_test ; +boost-python-runtest comprehensive_d + : [ join-path $(DOTDOT) test comprehensive.py ] + boost_python_test_d ; + ############# simple tests from ../example ############ rule boost-python-example-runtest { boost-python-test $(<) : ../example/$(<).cpp ; boost-python-runtest $(<) : [ join-path $(DOTDOT) example test_$(<).py ] $(<) ; + boost-python-runtest $(<)_d : [ join-path $(DOTDOT) example test_$(<).py ] $(<)_d ; } From b7e10592272d61e90ca7c129109fa3576225aaba Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 14 Nov 2001 17:35:18 +0000 Subject: [PATCH 146/369] initial checkin [SVN r11679] --- include/boost/python/detail/void_adaptor.hpp | 39 ++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 include/boost/python/detail/void_adaptor.hpp diff --git a/include/boost/python/detail/void_adaptor.hpp b/include/boost/python/detail/void_adaptor.hpp new file mode 100644 index 00000000..c2ecc2b0 --- /dev/null +++ b/include/boost/python/detail/void_adaptor.hpp @@ -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 + 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 + void_adaptor make_void_adaptor(T const& f) + { + return void_adaptor(f); + } +}}} // namespace boost::python::detail + +#endif // VOID_ADAPTOR_DWA20011112_HPP + From 634d0848c894bcb3309209e62640105b6bab70c1 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 14 Nov 2001 17:37:07 +0000 Subject: [PATCH 147/369] got rid of the "rethrow error reporting" mechanism [SVN r11680] --- src/conversions.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/conversions.cpp b/src/conversions.cpp index 4bfe2011..c986f57b 100644 --- a/src/conversions.cpp +++ b/src/conversions.cpp @@ -14,6 +14,7 @@ // 03 Mar 01 added: converters for [plain] char (Ralf W. Grosse-Kunstleve) #include +#include #include #include #ifndef BOOST_NO_LIMITS @@ -23,15 +24,11 @@ namespace boost { namespace python { // IMPORTANT: this function may only be called from within a catch block! -void handle_exception() +PyObject* handle_exception_impl(object_functor_base const& f) { - try { - // re-toss the current exception so we can find out what type it is. - // NOTE: a heinous bug in MSVC6 causes exception objects re-thrown in - // this way to be double-destroyed. Thus, you must only use objects that - // can tolerate double-destruction with that compiler. Metrowerks - // Codewarrior doesn't suffer from this problem. - throw; + try + { + return f(); } catch(const boost::python::error_already_set&) { @@ -49,6 +46,13 @@ void handle_exception() { PyErr_SetString(PyExc_RuntimeError, "unidentifiable C++ exception"); } + return 0; +} + +void handle_exception(void (*f)()) +{ + handle_exception( + boost::python::detail::make_void_adaptor(f)); } namespace detail { @@ -116,7 +120,7 @@ T integer_from_python(PyObject* p, boost::python::type) PyErr_SetString(PyExc_ValueError, buffer); throw boost::python::argument_error(); } -#if defined(__MWERKS__) && __MWERKS__ <= 0x2400 +#if defined(__MWERKS__) && __MWERKS__ <= 0x2406 return 0; // Not smart enough to know that the catch clause always rethrows #endif } From 6e7f1bc257f596090c0a8a01b9126beaad9c38df Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 14 Nov 2001 17:41:17 +0000 Subject: [PATCH 148/369] Pro7 compatibility [SVN r11681] --- src/gen_extclass.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/gen_extclass.py b/src/gen_extclass.py index 57189a7d..b794dc2c 100644 --- a/src/gen_extclass.py +++ b/src/gen_extclass.py @@ -238,6 +238,9 @@ class python_extension_class_converters } boost::python::detail::report_missing_instance_data(self, boost::python::detail::class_registry::class_object(), typeid(T)); throw boost::python::argument_error(); +#if defined(__MWERKS__) && __MWERKS__ <= 0x2406 + return 0; +#endif } // Convert to T* @@ -266,6 +269,10 @@ class python_extension_class_converters } boost::python::detail::report_missing_ptr_data(self, boost::python::detail::class_registry::class_object(), typeid(T)); throw boost::python::argument_error(); +#if defined(__MWERKS__) && __MWERKS__ <= 0x2406 + PtrType x; + return x; +#endif } // Extract from obj a reference to the PtrType object which is holding a From aad05325a6e1426c508c68e126281cbf86edc759 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 14 Nov 2001 19:50:35 +0000 Subject: [PATCH 149/369] Pro7 compatibility use the new "no-rethrow" way of handling exceptions. [SVN r11682] --- test/comprehensive.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/test/comprehensive.cpp b/test/comprehensive.cpp index 3571183e..8eaac025 100644 --- a/test/comprehensive.cpp +++ b/test/comprehensive.cpp @@ -157,7 +157,7 @@ int IntPairPythonClass::getattr(const IntPair& p, const std::string& s) PyErr_SetString(PyExc_AttributeError, s.c_str()); throw boost::python::error_already_set(); } -#if defined(__MWERKS__) && __MWERKS__ <= 0x2405 +#if defined(__MWERKS__) && __MWERKS__ <= 0x2406 return 0; #endif } @@ -1139,12 +1139,7 @@ void init_module() BOOST_PYTHON_MODULE_INIT(boost_python_test) { - try { - bpl_test::init_module(); - } - catch(...) { - boost::python::handle_exception(); - } // Need a way to report other errors here + boost::python::handle_exception((void (*)())bpl_test::init_module); } CompareIntPairPythonClass::CompareIntPairPythonClass(boost::python::module_builder& m) From 5bec0d2d9817638ad63e4d6fa6ac40bd39e420b4 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 14 Nov 2001 20:06:18 +0000 Subject: [PATCH 150/369] fixes for intel [SVN r11690] --- build/Jamfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build/Jamfile b/build/Jamfile index a76f372a..c4b9a9c3 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -151,6 +151,7 @@ rule boost-python # standard requirements $(BOOST_PYTHON_INCLUDES) <*>$(PYTHON_LIB_PATH) + <*>$(PYTHON_LIB_PATH) <*>$(PYTHON_LIB_PATH)/python$(PYTHON_VERSION_NODOT)$(debug).lib <*>$(PYTHON_LIBS) $(PYTHON_PROPERTIES) @@ -239,6 +240,7 @@ rule python-runtest-aux # target : sources switch $(<) { case <*\\\\msvc\\\\*>* : ARGS on $(<) += --broken-auto-ptr ; + case <*\\\\intel-win32\\\\*>* : ARGS on $(<) += --broken-auto-ptr ; } # compute the PYTHONPATH environment variable that will allow the test to From 7d6ff83760235f9cb23db61716c44635a6dfbd99 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 14 Nov 2001 20:07:38 +0000 Subject: [PATCH 151/369] use the new "no-rethrow" way of handling exceptions. [SVN r11691] --- include/boost/python/errors.hpp | 39 ++++++++++++++++++++++++++++++++- src/extension_class.cpp | 16 +++++++++----- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/include/boost/python/errors.hpp b/include/boost/python/errors.hpp index a1cdbbb0..66f15587 100644 --- a/include/boost/python/errors.hpp +++ b/include/boost/python/errors.hpp @@ -9,13 +9,50 @@ #ifndef ERRORS_DWA052500_H_ # define ERRORS_DWA052500_H_ +# include + namespace boost { namespace python { struct error_already_set {}; struct argument_error : error_already_set {}; +struct object_functor_base +{ + typedef PyObject* result_type; + virtual PyObject* operator()() const = 0; + private: + static void* operator new(std::size_t); // don't allow dynamic allocation + void operator delete(void*); + void operator delete(void*, size_t); +}; + +template +struct object_functor : object_functor_base +{ + object_functor(T const& f) + : m_f(f) + { + } + + PyObject* operator()() const + { + return m_f(); + } + private: + T const& m_f; +}; + + // Handles exceptions caught just before returning to Python code. -void handle_exception(); +PyObject* handle_exception_impl(object_functor_base const& f); + +template +PyObject* handle_exception(T const& f) +{ + return handle_exception_impl(object_functor(f)); +} + +void handle_exception(void (*)()); template T* expect_non_null(T* x) diff --git a/src/extension_class.cpp b/src/extension_class.cpp index f71976b9..3815a19c 100644 --- a/src/extension_class.cpp +++ b/src/extension_class.cpp @@ -10,8 +10,9 @@ // 04 Mar 01 Use PyObject_INIT() instead of trying to hand-initialize (David Abrahams) #include -#include #include +#include +#include namespace boost { namespace python { namespace detail { @@ -484,16 +485,19 @@ void operator_dispatcher_dealloc(PyObject* self) int operator_dispatcher_coerce(PyObject** l, PyObject** r) { Py_INCREF(*l); - try + PyObject* new_r = handle_exception( + bind(operator_dispatcher::create, + ref(*r, ref::increment_count), + ref())); + if (new_r) { - *r = operator_dispatcher::create(ref(*r, ref::increment_count), ref()); + *r = new_r; + return 0; } - catch(...) + else { - handle_exception(); return -1; } - return 0; } From 76768120d404e7ee532daecc8f5470736e5ad003 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 14 Nov 2001 20:36:14 +0000 Subject: [PATCH 152/369] use the new "no-rethrow" way of handling exceptions. [SVN r11692] --- src/types.cpp | 256 ++++++++++++++++++++++++++++---------------------- 1 file changed, 143 insertions(+), 113 deletions(-) diff --git a/src/types.cpp b/src/types.cpp index add0ebf0..2e738c35 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -8,15 +8,18 @@ #include #include // for handle_exception() +#include #include #include +#include #include #include #include #include #include #include -#include +#include +#include namespace boost { namespace python { @@ -24,139 +27,169 @@ namespace { using detail::type_object_base; - // Define a family of forwarding functions that can be calle from a + // Define a family of forwarding functions that can be called from a // PyTypeObject's slots. These functions dispatch through a (virtual) member // function pointer in the type_object_base, and handle exceptions in a // uniform way, preventing us from having to rewrite the dispatching code over // and over. - PyObject* call(PyObject* obj, PyObject* (type_object_base::*f)(PyObject*) const) + + + // Given a function object f with signature + // + // PyObject* f(PyTypeObject*,PyObject*) + // + // calls f inside of handle_exception, and returns the result. If an exception + // is thrown by f, returns 0. + template + PyObject* obj_call(PyObject* obj, F const& f) { - try - { - return (static_cast(obj->ob_type)->*f)(obj); - } - catch(...) - { - handle_exception(); - return 0; - } + return handle_exception( + boost::bind(f, static_cast(obj->ob_type), obj)); } - // Naming this differently allows us to use it for functions returning long on - // compilers without partial ordering - template - R int_call(PyObject* obj, R (type_object_base::*f)(PyObject*) const) + + // int_converter/value_holder + // + // A simple function object which converts its argument to a PyObject*. We + // need this because handle_exception needs to return a PyObject*, even if the + // function being called is supposed to return int. It has two parts... + + // holds the value actually returned by the underlying function + template + struct value_holder : PyObject { - try + value_holder() : is_set(false), value(-1) {} + + // Tricky constructor allows us to grab the result even if rhs == 0. + explicit value_holder(value_holder const* rhs) + : is_set(rhs ? rhs->is_set : false), value(rhs ? rhs->value : -1) {} + + // true if the function object was ever called (false if an exception occurred) + bool is_set; + + // The returned value + T value; + }; + + // The function object + template + struct int_converter + { + typedef PyObject* result_type; + + PyObject* operator()(R const& x) { - return (static_cast(obj->ob_type)->*f)(obj); - } - catch(...) - { - handle_exception(); - return -1; + m_holder.is_set = true; + m_holder.value = x; + return &m_holder; // returns } + + value_holder m_holder; + }; + + // Call the given int-returning function object inside of handle_exception, + // returning a value_holder. F is a function object with "signature" + // + // R F(PyTypeObject*, PyObject*) + // + // where R is an integer type. + template + typename value_holder int_call_holder(PyObject* obj, F f) + { + return value_holder( + + // The int_converter object containing the value_holder is valid + // through the life of the full-expression, so we can construct from + // the pointer + static_cast*>( + handle_exception( + + boost::bind( + // Add an int_converter back-end to f + int_converter() + // Bind the object's type and the object itself into f + , boost::bind(f, static_cast(obj->ob_type), obj) + ) + + ) + ) + ); + } + + // Just like int_call_holder (above), but returns the integer directly. If F + // throws an exception, returns -1 + template + R int_call(PyObject* obj, F f) + { + value_holder const v(int_call_holder(obj, f)); + return v.value; + } + + // Implemented in terms of obj_call, above + PyObject* call(PyObject* obj, PyObject* (type_object_base::*f)(PyObject*) const) + { + return obj_call(obj, bind(f, _1, _2)); } // Implemented in terms of int_call, above int call(PyObject* obj, int (type_object_base::*f)(PyObject*) const) { - return int_call(obj, f); + return int_call(obj, bind(f, _1, _2)); } template PyObject* call(PyObject* obj, PyObject* (type_object_base::*f)(PyObject*, A1) const, A1 a1) { - try - { - return (static_cast(obj->ob_type)->*f)(obj, a1); - } - catch(...) - { - handle_exception(); - return 0; - } + return obj_call(obj, bind(f, _1, _2, a1)); } template int call(PyObject* obj, int (type_object_base::*f)(PyObject*, A1) const, A1 a1) { - try - { - return (static_cast(obj->ob_type)->*f)(obj, a1); - } - catch(...) - { - handle_exception(); - return -1; - } + return int_call(obj, bind(f, _1, _2, a1)); } template PyObject* call(PyObject* obj, PyObject* (type_object_base::*f)(PyObject*, A1, A2) const, A1 a1, A2 a2) { - try - { - return (static_cast(obj->ob_type)->*f)(obj, a1, a2); - } - catch(...) - { - handle_exception(); - return 0; - } + return obj_call(obj, bind(f, _1, _2, a1, a2)); } template int call(PyObject* obj, int (type_object_base::*f)(PyObject*, A1, A2) const, A1 a1, A2 a2) { - try - { - return (static_cast(obj->ob_type)->*f)(obj, a1, a2); - } - catch(...) - { - handle_exception(); - return -1; - } + return int_call(obj, bind(f, _1, _2, a1, a2)); } template int call(PyObject* obj, int (type_object_base::*f)(PyObject*, A1, A2, A3) const, A1 a1, A2 a2, A3 a3) { - try - { - return (static_cast(obj->ob_type)->*f)(obj, a1, a2, a3); - } - catch(...) - { - handle_exception(); - return -1; - } + return int_call(obj, bind(f, _1, _2, a1, a2, a3)); } int call_length_function(PyObject* obj, int (type_object_base::*f)(PyObject*) const) { - try + value_holder const r(int_call_holder(obj, bind(f, _1, _2))); + + if (!r.is_set) { - const int outcome = - (static_cast(obj->ob_type)->*f)(obj); - - if (outcome < 0) - { - PyErr_SetString(PyExc_ValueError, "__len__() should return >= 0"); - return -1; - } - return outcome; - } - catch(...) - { - handle_exception(); return -1; } - } + + const int outcome = r.value; + if (outcome >= 0) + return outcome; + PyErr_SetString(PyExc_ValueError, "__len__() should return >= 0"); + return -1; + } } // anonymous namespace +namespace detail { + // needed by void_adaptor (see void_adaptor.hpp) + PyObject arbitrary_object; +} + extern "C" { // @@ -202,7 +235,7 @@ static PyObject* do_instance_str(PyObject* obj) static long do_instance_hash(PyObject* obj) { - return int_call(obj, &type_object_base::instance_hash); + return int_call(obj, bind(&type_object_base::instance_hash, _1, _2)); } static PyObject* do_instance_call(PyObject* obj, PyObject* args, PyObject* keywords) @@ -212,15 +245,16 @@ static PyObject* do_instance_call(PyObject* obj, PyObject* args, PyObject* keywo static void do_instance_dealloc(PyObject* obj) { - try - { - static_cast(obj->ob_type) - ->instance_dealloc(obj); - } - catch(...) + PyObject* success = handle_exception( + // translate the void return value of instance_dealloc into a PyObject* + // that can indicate no error. + detail::make_void_adaptor( + bind(&type_object_base::instance_dealloc + , static_cast(obj->ob_type) + , obj))); + if (!success) { assert(!"exception during destruction!"); - handle_exception(); } } @@ -253,28 +287,22 @@ static PyObject* do_instance_mp_subscript(PyObject* obj, PyObject* index) static PyObject* do_instance_sq_item(PyObject* obj, int index) { - try + // This is an extension to standard class behavior. If sequence_length + // is implemented and n >= sequence_length(), raise an IndexError. That + // keeps users from having to worry about raising it themselves + const PyTypeObject* const type = obj->ob_type; + if (type->tp_as_sequence != 0 && type->tp_as_sequence->sq_length != 0 + && index >= type->tp_as_sequence->sq_length(obj)) { - const PyTypeObject* const type = obj->ob_type; - - // This is an extension to standard class behavior. If sequence_length - // is implemented and n >= sequence_length(), raise an IndexError. That - // keeps users from having to worry about raising it themselves - if (type->tp_as_sequence != 0 && type->tp_as_sequence->sq_length != 0 - && index >= type->tp_as_sequence->sq_length(obj)) - { - PyErr_SetString(PyExc_IndexError, type->tp_name); - return 0; - } - - return static_cast(obj->ob_type) - ->instance_sequence_item(obj, index); - } - catch(...) - { - handle_exception(); + PyErr_SetString(PyExc_IndexError, type->tp_name); return 0; } + + return handle_exception( + bind(&type_object_base::instance_sequence_item + , static_cast(obj->ob_type) + , obj + , index)); } static int do_instance_mp_ass_subscript(PyObject* obj, PyObject* index, PyObject* value) @@ -397,7 +425,10 @@ static PyObject* do_instance_nb_or(PyObject* obj, PyObject* other) static int do_instance_nb_coerce(PyObject**obj, PyObject**other) { - return call(*obj, &type_object_base::instance_number_coerce, obj, other); + // no call() overload for this oddball function, so we'll do it manually + return int_call( + *obj, bind( + &type_object_base::instance_number_coerce, _1, _2, obj, other)); } static PyObject* do_instance_nb_int(PyObject* obj) { @@ -1171,4 +1202,3 @@ int main() } #endif - From e6efa6e13e046dd7c412c92e4103085cc4098a98 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 15 Nov 2001 00:51:33 +0000 Subject: [PATCH 153/369] Fix minor gcc bug [SVN r11704] --- src/types.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types.cpp b/src/types.cpp index 2e738c35..3367dba8 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -94,7 +94,7 @@ namespace { // // where R is an integer type. template - typename value_holder int_call_holder(PyObject* obj, F f) + value_holder int_call_holder(PyObject* obj, F f) { return value_holder( From 0dbb780a2f8b6e52100a201ff10e41ac9fa5db57 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 15 Nov 2001 05:29:22 +0000 Subject: [PATCH 154/369] * Updated to new handle_exception() idiom for boost::python * Made Cygwin archiving reliable, even when the user supplies a path with backslashes ---------------------------------------------------------------------- Modified Files: tools/build/gcc-tools.jam tools/build/new/boost-build.jam boost/python/detail/config.hpp libs/python/build/Jamfile libs/python/example/do_it_yourself_convts.cpp libs/python/example/dvect.cpp libs/python/example/example1.cpp libs/python/example/getting_started1.cpp libs/python/example/getting_started2.cpp libs/python/example/ivect.cpp libs/python/example/nested.cpp libs/python/example/noncopyable_export.cpp libs/python/example/noncopyable_import.cpp libs/python/example/pickle1.cpp libs/python/example/pickle2.cpp libs/python/example/pickle3.cpp libs/python/example/richcmp1.cpp libs/python/example/richcmp2.cpp libs/python/example/richcmp3.cpp libs/python/example/rwgk1.cpp libs/python/example/simple_vector.cpp libs/python/test/comprehensive.cpp Added Files: libs/python/example/rwgk2.cpp libs/python/example/rwgk3.cpp ---------------------------------------------------------------------- [SVN r11705] --- build/Jamfile | 7 +- example/do_it_yourself_convts.cpp | 7 -- example/dvect.cpp | 8 -- example/example1.cpp | 33 +++----- example/getting_started1.cpp | 7 -- example/getting_started2.cpp | 7 -- example/ivect.cpp | 7 -- example/nested.cpp | 7 -- example/noncopyable_export.cpp | 7 -- example/noncopyable_import.cpp | 7 -- example/pickle1.cpp | 7 -- example/pickle2.cpp | 7 -- example/pickle3.cpp | 7 -- example/richcmp1.cpp | 3 - example/richcmp2.cpp | 3 - example/richcmp3.cpp | 3 - example/rwgk1.cpp | 19 +---- example/rwgk2.cpp | 50 ++++++++++++ example/rwgk3.cpp | 101 +++++++++++++++++++++++++ example/simple_vector.cpp | 7 -- include/boost/python/detail/config.hpp | 4 +- test/comprehensive.cpp | 7 +- 22 files changed, 171 insertions(+), 144 deletions(-) create mode 100644 example/rwgk2.cpp create mode 100644 example/rwgk3.cpp diff --git a/build/Jamfile b/build/Jamfile index c4b9a9c3..05efd4a1 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -136,7 +136,7 @@ lib libboost_python_d : ../src/$(CPP_SOURCES).cpp # Declare a boost python module. Return a list of the DLL files generated. rule boost-python { - local debug ; + local debug = "" ; if ( BOOST_DEBUG_PYTHON in $(3) ) || ( debug-python in $(BUILD) ) { debug = _d ; @@ -203,7 +203,9 @@ rule python-test-target # test-target : sources : { python-runtest-aux $(<) : $(>) ; Clean clean : $(<) ; # remove the test-target as part of any clean operation - type-DEPENDS test : $(<) ; + local debug = [ SUBST $(<:B) (_d)$ $1 ] ; + debug ?= "" ; + type-DEPENDS test$(debug) : $(<) ; MakeLocate $(<) : $(LOCATE_TARGET) ; } actions python-test-target bind PYTHON @@ -249,6 +251,7 @@ rule python-runtest-aux # target : sources $(gLOCATE($(>[1]))) # location of python test file $(gRUN_PATH($(<))) # location of module dependencies [ join-path $(TOP) libs python test ] # location of doctest + $(>:D) # directory of python driver file(s) $(PYTHONPATH) # base PYTHONPATH from environment : $(SPLITPATH) ] ; # platform path separator diff --git a/example/do_it_yourself_convts.cpp b/example/do_it_yourself_convts.cpp index 4d9c1c89..01be6ef6 100644 --- a/example/do_it_yourself_convts.cpp +++ b/example/do_it_yourself_convts.cpp @@ -107,8 +107,6 @@ BOOST_PYTHON_END_CONVERSION_NAMESPACE BOOST_PYTHON_MODULE_INIT(do_it_yourself_convts) { - try - { // Create an object representing this extension module. python::module_builder this_module("do_it_yourself_convts"); @@ -120,9 +118,4 @@ BOOST_PYTHON_MODULE_INIT(do_it_yourself_convts) // Add the member functions. ixset_class.def(&IndexingSet::add, "add"); ixset_class.def(&IndexingSet::get, "get"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } } diff --git a/example/dvect.cpp b/example/dvect.cpp index 4d109c96..fa1506fe 100644 --- a/example/dvect.cpp +++ b/example/dvect.cpp @@ -32,8 +32,6 @@ extern "C" void (*old_translator)(unsigned int, EXCEPTION_POINTERS*) BOOST_PYTHON_MODULE_INIT(dvect) { - try - { python::module_builder this_module("dvect"); python::class_builder dvect_class(this_module, "dvect"); @@ -47,10 +45,4 @@ BOOST_PYTHON_MODULE_INIT(dvect) # include "dvect_defs.cpp" # include "ivect_defs.cpp" - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } } - diff --git a/example/example1.cpp b/example/example1.cpp index 467ac0dc..7bc5a1b7 100644 --- a/example/example1.cpp +++ b/example/example1.cpp @@ -16,32 +16,21 @@ namespace hello { // Python requires an exported function called init in every // extension module. This is where we build the module contents. -extern "C" -#ifdef _WIN32 -__declspec(dllexport) -#endif -void inithello() +BOOST_PYTHON_MODULE_INIT(hello) { - try - { - // create an object representing this extension module - boost::python::module_builder hello("hello"); + // create an object representing this extension module + boost::python::module_builder hello("hello"); - // Create the Python type object for our extension class - boost::python::class_builder world_class(hello, "world"); + // Create the Python type object for our extension class + boost::python::class_builder world_class(hello, "world"); - // Add the __init__ function - world_class.def(boost::python::constructor()); - // Add a regular member function - world_class.def(&hello::world::get, "get"); + // Add the __init__ function + world_class.def(boost::python::constructor()); + // Add a regular member function + world_class.def(&hello::world::get, "get"); - // Add a regular function to the module - hello.def(hello::length, "length"); - } - catch(...) - { - boost::python::handle_exception(); // Deal with the exception for Python - } + // Add a regular function to the module + hello.def(hello::length, "length"); } // Win32 DLL boilerplate diff --git a/example/getting_started1.cpp b/example/getting_started1.cpp index c6a77723..2f180633 100644 --- a/example/getting_started1.cpp +++ b/example/getting_started1.cpp @@ -16,17 +16,10 @@ namespace python = boost::python; // extension module. This is where we build the module contents. BOOST_PYTHON_MODULE_INIT(getting_started1) { - try - { // Create an object representing this extension module. python::module_builder this_module("getting_started1"); // Add regular functions to the module. this_module.def(greet, "greet"); this_module.def(square, "square"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } } diff --git a/example/getting_started2.cpp b/example/getting_started2.cpp index 9121b1a0..04fbcc29 100644 --- a/example/getting_started2.cpp +++ b/example/getting_started2.cpp @@ -26,8 +26,6 @@ namespace python = boost::python; BOOST_PYTHON_MODULE_INIT(getting_started2) { - try - { // Create an object representing this extension module. python::module_builder this_module("getting_started2"); @@ -44,9 +42,4 @@ BOOST_PYTHON_MODULE_INIT(getting_started2) // Even better, invite() can also be made a member of hello_class!!! hello_class.def(invite, "invite"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } } diff --git a/example/ivect.cpp b/example/ivect.cpp index 848d693e..35662b10 100644 --- a/example/ivect.cpp +++ b/example/ivect.cpp @@ -32,8 +32,6 @@ extern "C" void (*old_translator)(unsigned int, EXCEPTION_POINTERS*) BOOST_PYTHON_MODULE_INIT(ivect) { - try - { python::module_builder this_module("ivect"); python::class_builder ivect_class(this_module, "ivect"); @@ -47,10 +45,5 @@ BOOST_PYTHON_MODULE_INIT(ivect) # include "dvect_defs.cpp" # include "ivect_defs.cpp" - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } } diff --git a/example/nested.cpp b/example/nested.cpp index 543754f7..a5632d16 100644 --- a/example/nested.cpp +++ b/example/nested.cpp @@ -32,13 +32,6 @@ namespace { BOOST_PYTHON_MODULE_INIT(nested) { - try - { boost::python::module_builder this_module("nested"); this_module.def(show_nested_tuples, "show_nested_tuples"); - } - catch(...) - { - boost::python::handle_exception(); - } } diff --git a/example/noncopyable_export.cpp b/example/noncopyable_export.cpp index b118abb8..3a81db75 100644 --- a/example/noncopyable_export.cpp +++ b/example/noncopyable_export.cpp @@ -18,8 +18,6 @@ extern "C" void (*old_translator)(unsigned int, EXCEPTION_POINTERS*) BOOST_PYTHON_MODULE_INIT(noncopyable_export) { - try - { python::module_builder this_module("noncopyable_export"); python::class_builder store_class(this_module, "store"); @@ -27,9 +25,4 @@ BOOST_PYTHON_MODULE_INIT(noncopyable_export) store_class.def(python::constructor()); store_class.def(&store::recall, "recall"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } } diff --git a/example/noncopyable_import.cpp b/example/noncopyable_import.cpp index 66c6457d..d4227642 100644 --- a/example/noncopyable_import.cpp +++ b/example/noncopyable_import.cpp @@ -31,8 +31,6 @@ extern "C" void (*old_translator)(unsigned int, EXCEPTION_POINTERS*) BOOST_PYTHON_MODULE_INIT(noncopyable_import) { - try - { python::module_builder this_module("noncopyable_import"); python::import_converters @@ -44,9 +42,4 @@ BOOST_PYTHON_MODULE_INIT(noncopyable_import) // However, to keep this example simple, we only define a // module-level function. this_module.def(add_stores, "add_stores"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } } diff --git a/example/pickle1.cpp b/example/pickle1.cpp index cdd78989..af041e72 100644 --- a/example/pickle1.cpp +++ b/example/pickle1.cpp @@ -41,8 +41,6 @@ namespace { // Avoid cluttering the global namespace. BOOST_PYTHON_MODULE_INIT(pickle1) { - try - { // Create an object representing this extension module. python::module_builder this_module("pickle1"); @@ -56,9 +54,4 @@ BOOST_PYTHON_MODULE_INIT(pickle1) // Support for pickle. world_class.def(world_getinitargs, "__getinitargs__"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } } diff --git a/example/pickle2.cpp b/example/pickle2.cpp index d6aa3201..576180ee 100644 --- a/example/pickle2.cpp +++ b/example/pickle2.cpp @@ -73,8 +73,6 @@ namespace { // Avoid cluttering the global namespace. BOOST_PYTHON_MODULE_INIT(pickle2) { - try - { // Create an object representing this extension module. python::module_builder this_module("pickle2"); @@ -92,9 +90,4 @@ BOOST_PYTHON_MODULE_INIT(pickle2) world_class.def(world_getinitargs, "__getinitargs__"); world_class.def(world_getstate, "__getstate__"); world_class.def(world_setstate, "__setstate__"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } } diff --git a/example/pickle3.cpp b/example/pickle3.cpp index cb598ae6..664bed0b 100644 --- a/example/pickle3.cpp +++ b/example/pickle3.cpp @@ -65,8 +65,6 @@ namespace { // Avoid cluttering the global namespace. BOOST_PYTHON_MODULE_INIT(pickle3) { - try - { // Create an object representing this extension module. python::module_builder this_module("pickle3"); @@ -85,11 +83,6 @@ BOOST_PYTHON_MODULE_INIT(pickle3) world_class.def_raw(world_getstate, "__getstate__"); world_class.def_raw(world_setstate, "__setstate__"); world_class.getstate_manages_dict(); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } } namespace { diff --git a/example/richcmp1.cpp b/example/richcmp1.cpp index 4dd74e1b..f59aae65 100644 --- a/example/richcmp1.cpp +++ b/example/richcmp1.cpp @@ -77,11 +77,8 @@ namespace { BOOST_PYTHON_MODULE_INIT(richcmp1) { - try { boost::python::module_builder this_module("richcmp1"); // The actual work is done in a separate function in order // to suppress a bogus VC60 warning. init_module(this_module); - } - catch (...) { boost::python::handle_exception(); } } diff --git a/example/richcmp2.cpp b/example/richcmp2.cpp index 213852b3..993c6800 100644 --- a/example/richcmp2.cpp +++ b/example/richcmp2.cpp @@ -55,11 +55,8 @@ namespace { BOOST_PYTHON_MODULE_INIT(richcmp2) { - try { boost::python::module_builder this_module("richcmp2"); // The actual work is done in a separate function in order // to suppress a bogus VC60 warning. init_module(this_module); - } - catch (...) { boost::python::handle_exception(); } } diff --git a/example/richcmp3.cpp b/example/richcmp3.cpp index 169e7f00..4be48fee 100644 --- a/example/richcmp3.cpp +++ b/example/richcmp3.cpp @@ -168,11 +168,8 @@ namespace { BOOST_PYTHON_MODULE_INIT(richcmp3) { - try { boost::python::module_builder this_module("richcmp3"); // The actual work is done in a separate function in order // to suppress a bogus VC60 warning. init_module(this_module); - } - catch (...) { boost::python::handle_exception(); } } diff --git a/example/rwgk1.cpp b/example/rwgk1.cpp index b21ae4d1..ca8bd22f 100644 --- a/example/rwgk1.cpp +++ b/example/rwgk1.cpp @@ -13,29 +13,12 @@ namespace python = boost::python; // Python requires an exported function called init in every // extension module. This is where we build the module contents. -extern "C" -#ifdef _WIN32 -__declspec(dllexport) -#endif -void initrwgk1() +BOOST_PYTHON_MODULE_INIT(rwgk1) { - try - { // Create an object representing this extension module. python::module_builder this_module("rwgk1"); // Add regular functions to the module. this_module.def(greet, "greet"); this_module.def(square, "square"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } } - -// Win32 DLL boilerplate -#if defined(_WIN32) -#include -extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) { return 1; } -#endif // _WIN32 diff --git a/example/rwgk2.cpp b/example/rwgk2.cpp new file mode 100644 index 00000000..35dce88f --- /dev/null +++ b/example/rwgk2.cpp @@ -0,0 +1,50 @@ +#include +#include + +namespace { // Avoid cluttering the global namespace. + + // A friendly class. + class world + { + private: + std::string country; + public: + world(const std::string& country) { this->country = country; } + std::string greet() const { return "Hello from " + country + "!"; } + }; + + // A function taking a world object as an argument. + std::string invite(const world& w) { + return w.greet() + " Please come soon!"; + } +} + +#include + +// Python requires an exported function called init in every +// extension module. This is where we build the module contents. +BOOST_PYTHON_MODULE_INIT(example2) +{ + // Create an object representing this extension module. + py::Module this_module("example2"); + + // Create the Python type object for our extension class. + py::ClassWrapper world_class(this_module, "world"); + + // Add the __init__ function. + world_class.def(py::Constructor()); + // Add a regular member function. + world_class.def(&world::greet, "greet"); + + // Add invite() as a regular function to the module. + this_module.def(invite, "invite"); + + // Even better, invite() can also be made a member of world_class!!! + world_class.def(invite, "invite"); +} + +// Win32 DLL boilerplate +#if defined(_WIN32) +#include +extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) { return 1; } +#endif // _WIN32 diff --git a/example/rwgk3.cpp b/example/rwgk3.cpp new file mode 100644 index 00000000..df17b28e --- /dev/null +++ b/example/rwgk3.cpp @@ -0,0 +1,101 @@ +#include +#include + +#define rangei(n) for (int i = 0; i < n; i++) + +namespace { // Avoid cluttering the global namespace. + + // A wrapper is used to define additional constructors. + // + struct vector_double_wrapper: std::vector + { + // Tell the compiler how to convert a base class object to + // this wrapper object. + vector_double_wrapper(PyObject*, const std::vector& vd) + : std::vector(vd) {} + + vector_double_wrapper(PyObject* self) + : std::vector() {} + + vector_double_wrapper(PyObject* self, const int n) + : std::vector(n) {} + + vector_double_wrapper(PyObject* self, py::Tuple tuple) + : std::vector(tuple.size()) + { + std::vector::iterator vd = begin(); + rangei(tuple.size()) + vd[i] = from_python(tuple[i].get(), py::Type()); // GCC BUG + } + }; + + double getitem(const std::vector& vd, const std::size_t key) { + return vd[key]; + } + + void setitem(std::vector& vd, const std::size_t key, + const double &d) { + std::vector::iterator vditer = vd.begin(); + vditer[key] = d; + } + + void delitem(std::vector& vd, const std::size_t key) { + std::vector::iterator vditer = vd.begin(); + vd.erase(&vditer[key]); + } + + // Convert vector_double to a regular Python tuple. + // + py::Tuple as_tuple(const std::vector& vd) + { + py::Tuple t(vd.size()); + rangei(vd.size()) t.set_item(i, py::Ptr(py::to_python(vd[i]))); // GCC BUG + return t; + } + + // Function returning a vector_double object to Python. + // + std::vector foo(const int n) + { + std::vector vd(n); + std::vector::iterator vditer = vd.begin(); + rangei(n) vditer[i] = double(i); + return vd; + } + + // Same as foo(), but avoid copying on return. + // + std::auto_ptr > bar(const int n) + { + std::auto_ptr > vdptr(new std::vector(n)); + std::vector::iterator vditer = vdptr->begin(); + rangei(n) vditer[i] = double(10 * i); + return vdptr; + } +} + +BOOST_PYTHON_MODULE_INIT(example3) +{ + py::Module this_module("example3"); + + py::ClassWrapper, vector_double_wrapper> + vector_double(this_module, "vector_double"); + + vector_double.def(py::Constructor<>()); + vector_double.def(py::Constructor()); + vector_double.def(py::Constructor()); + vector_double.def(&std::vector::size, "__len__"); + vector_double.def(getitem, "__getitem__"); + vector_double.def(setitem, "__setitem__"); + vector_double.def(delitem, "__delitem__"); + vector_double.def(as_tuple, "as_tuple"); + + this_module.def(foo, "foo"); + this_module.def(bar, "bar"); +} + +// Win32 DLL boilerplate +#if defined(_WIN32) +#include +extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) { return 1; } +#endif // _WIN32 diff --git a/example/simple_vector.cpp b/example/simple_vector.cpp index 3499c8f7..8c7ee0ce 100644 --- a/example/simple_vector.cpp +++ b/example/simple_vector.cpp @@ -85,8 +85,6 @@ namespace { // Avoid cluttering the global namespace. BOOST_PYTHON_MODULE_INIT(simple_vector) { - try - { python::module_builder this_module("simple_vector"); python::class_builder, vector_double_wrapper> @@ -103,9 +101,4 @@ BOOST_PYTHON_MODULE_INIT(simple_vector) this_module.def(foo, "foo"); this_module.def(bar, "bar"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } } diff --git a/include/boost/python/detail/config.hpp b/include/boost/python/detail/config.hpp index b6075368..f814aba0 100644 --- a/include/boost/python/detail/config.hpp +++ b/include/boost/python/detail/config.hpp @@ -58,9 +58,9 @@ # endif #if defined(_WIN32) || defined(__CYGWIN__) -# define BOOST_PYTHON_MODULE_INIT(name) extern "C" __declspec(dllexport) void init##name() +# 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) extern "C" void init##name() +# 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 // CONFIG_DWA052200_H_ diff --git a/test/comprehensive.cpp b/test/comprehensive.cpp index 8eaac025..7cd7e0ce 100644 --- a/test/comprehensive.cpp +++ b/test/comprehensive.cpp @@ -1128,7 +1128,7 @@ PyObject* raw(const boost::python::tuple& args, const boost::python::dictionary& return BOOST_PYTHON_CONVERSION::to_python(first->i_ + second + third + fourth); } -void init_module() +BOOST_PYTHON_MODULE_INIT(boost_python_test) { boost::python::module_builder boost_python_test("boost_python_test"); init_module(boost_python_test); @@ -1137,11 +1137,6 @@ void init_module() boost_python_test.add(new boost::python::meta_class); } -BOOST_PYTHON_MODULE_INIT(boost_python_test) -{ - boost::python::handle_exception((void (*)())bpl_test::init_module); -} - CompareIntPairPythonClass::CompareIntPairPythonClass(boost::python::module_builder& m) : boost::python::class_builder(m, "CompareIntPair") { From 6a6084ed0ecf81134527ac066d629127a249d312 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 2 Dec 2001 17:43:45 +0000 Subject: [PATCH 155/369] Metrowerks needs BOOST_NO_STD_LOCALE in config to be able to compile regex regex test Jamfile updates so that some tests will actually run warning suppression for condition.cpp unit-test rule now accepts input files updated metrowerks and borland to properly set up path for running tests ---------------------------------------------------------------------- Modified Files: boost/config/compiler/metrowerks.hpp libs/python/src/gen_function.py libs/regex/test/Jamfile Tag: thread-initial libs/thread/src/condition.cpp No tag tools/build/boost-base.jam tools/build/borland-tools.jam tools/build/metrowerks-tools.jam ---------------------------------------------------------------------- [SVN r11853] --- src/gen_function.py | 106 ++++++++++++++++++++++++++++++++------------ 1 file changed, 78 insertions(+), 28 deletions(-) diff --git a/src/gen_function.py b/src/gen_function.py index bebbc818..ac24ac18 100644 --- a/src/gen_function.py +++ b/src/gen_function.py @@ -12,15 +12,31 @@ def _find(s, sub, start=0, end=None): else: return pos -def _gen_common_key(key, n, args): +def _raise_no_argument(key, n, args): + raise IndexError(str(key) + " extra arg(s) not passed to gen_function") + +def _gen_common_key(key, n, args, fill = _raise_no_argument): + # import sys + # print >> sys.stderr, "_gen_common_key(", repr(key), ",", repr(n), ',', repr(args), ',', fill, ')' + # sys.stderr.flush() if len(key) > 0 and key in '123456789': - return str(args[int(key) - 1]) - elif key == 'x': - return str(n) + index = int(key) - 1; + + if index >= len(args): + return fill(key, n, args) + + arg = args[index] + if callable(arg): + return str(arg(key, n, args)) + else: + return str(arg) + elif key in ('x','n','-','+'): + return str(n + {'-':-1,'+':+1,'x':0,'n':0}[key]) else: return key -def _gen_arg(template, n, args, delimiter = '%'): +def _gen_arg(template, n, args, delimiter = '%', fill = _raise_no_argument): + result = '' i = 0 while i < len(template): # until the template is consumed @@ -33,13 +49,13 @@ def _gen_arg(template, n, args, delimiter = '%'): key = template[start - 1 : start] # the key character. If there were no # delimiters left, key will be empty - if key == 'n': + if 0 and key == 'n': result = result + `n` - else: - result = result + _gen_common_key(key, n, args) + else: + result = result + _gen_common_key(key, n, args, fill) i = start - + return result def gen_function(template, n, *args, **keywords): @@ -52,19 +68,46 @@ def gen_function(template, n, *args, **keywords): Sections of the template between '%{', '%}' pairs are ommitted if n == 0. - %n is transformed into the string representation of 1..n for each repetition - of n. + %n is transformed into the string representation of 1..n for each + repetition within %(...%). Elsewhere, %n is transformed into the + string representation of n + + %- is transformed into the string representation of 0..n-1 for + each repetition within %(...%). Elsewhere, %- is transformed into the + string representation of n-1. + + %+ is transformed into the string representation of 2..n+1 for + each repetition within %(...%). Elsewhere, %- is transformed into the + string representation of n+1. + + %x is always transformed into the string representation of n + + %z, where z is a digit, selects the corresponding additional + argument. If that argument is callable, it is called with three + arguments: + key - the string representation of 'z' + n - the iteration number + args - a tuple consisting of all the additional arguments to + this function + otherwise, the selected argument is converted to a string representation - %x, where x is a digit, is transformed into the corresponding additional - argument. for example, - >>> gen_function('%1 abc(%(int a%n%:, %));%{ // all args are ints%}', 2, 'void') - 'void abc(int a1, int a2); // all args are ints' + >>> gen_function('%1 abc%x(%(int a%n%:, %));%{ // all args are ints%}', 2, 'void') + 'void abc2(int a1, int a2); // all args are ints' + >>> gen_function('%1 abc(%(int a%n%:, %));%{ // all args are ints%}', 0, 'x') 'x abc();' + >>> gen_function('%1 abc(%(int a%n%:, %));%{ // all args are ints%}', 0, lambda key, n, args: 'abcd'[n]) + 'a abc();' + + >>> gen_function('%2 %1 abc(%(int a%n%:, %));%{ // all args are ints%}', 0, 'x', fill = lambda key, n, args: 'const') + 'const x abc();' + + >>> gen_function('abc%[k%:v%]', 0, fill = lambda key, n, args, value = None: '<' + key + ',' + value + '>') + 'abc' >>> template = ''' template ... static PyObject* call( %1(T::*pmf)(%(A%n%:, %))%2, PyObject* args, PyObject* /* keywords */ ) { @@ -123,6 +166,7 @@ def gen_function(template, n, *args, **keywords): } """ delimiter = keywords.get('delimiter', '%') + fill = keywords.get('fill', _raise_no_argument); result = '' i = 0 while i < len(template): # until the template is consumed @@ -135,7 +179,7 @@ def gen_function(template, n, *args, **keywords): key = template[start - 1 : start] # the key character. If there were no # delimiters left, key will be empty - pairs = { '(':')', '{':'}' } + pairs = { '(':')', '{':'}', '[':']' } if key in pairs.keys(): end = string.find(template, delimiter + pairs[key], start) @@ -146,23 +190,27 @@ def gen_function(template, n, *args, **keywords): if n > 0: result = result + gen_function(template[start:end], n, args, delimiter) else: - separator_pos = _find(template, delimiter + ':', start, end) - separator = template[separator_pos+2 : end] - - for x in range(1, n + 1): - result = result + _gen_arg(template[start:separator_pos], x, args, - delimiter) - if x != n: - result = result + separator + separator_pos = _find(template, delimiter + ':', + start, end) + remainder = template[separator_pos+2 : end] + + if key == '(': + for x in range(1, n + 1): + result = result + _gen_arg(template[start:separator_pos], x, args, + delimiter) + if x != n: + result = result + remainder + else: + result = result + fill(template[start:separator_pos], n, args, value = remainder) else: - result = result + _gen_common_key(key, n, args) + result = result + _gen_common_key(key, n, args, fill) i = delimiter_pos + 2 return result -def gen_functions(template, n, *args): +def gen_functions(template, n, *args, **keywords): r"""gen_functions(template, n, [args...]) -> string Call gen_function repeatedly with from 0..n and the given optional @@ -174,11 +222,13 @@ def gen_functions(template, n, *args): void abc(int a1, int a2); // all args are ints """ + fill = keywords.get('fill', _raise_no_argument); result = '' for x in range(n + 1): - result = result + apply(gen_function, (template, x) + args) + result = result + apply(gen_function, (template, x) + args, keywords) return result if __name__ == '__main__': import doctest - doctest.testmod() + import sys + doctest.testmod(sys.modules.get(__name__)) From ccfd4acbda8bbe980ff24c52608bd6ff7e8234a9 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 13 Dec 2001 18:17:38 +0000 Subject: [PATCH 156/369] factored out python.jam [SVN r12041] --- build/Jamfile | 220 +++++--------------------------------------------- 1 file changed, 22 insertions(+), 198 deletions(-) diff --git a/build/Jamfile b/build/Jamfile index 05efd4a1..c56bf47c 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -54,52 +54,18 @@ # 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 ; -# grab variables from command-line or environment. -local PYTHON_VERSION = $(PYTHON_VERSION) ; -local PYTHON_ROOT = $(PYTHON_ROOT) ; -local PYTHON_INCLUDES = $(PYTHON_INCLUDES) ; -local PYTHON_LIBS = $(PYTHON_LIBS) ; -local PYTHON_LIB_PATH = $(PYTHON_LIB_PATH) ; -local PYTHON_PROPERTIES = $(PYTHON_PROPERTIES) ; +# bring in the rules for python +SEARCH on python.jam = $(BOOST_BUILD_PATH) ; +include python.jam ; -# Do some OS-specific setup -if $(NT) +####################### +local rule bpl-test ( test-name : sources + ) { - PYTHON_VERSION ?= 2.1 ; - PYTHON_ROOT ?= c:/tools/python ; - PYTHON_INCLUDES ?= $(PYTHON_ROOT)/include <*>/usr/include/python$(PYTHON_VERSION) ; - PYTHON_LIBS ?= c:/cygnus/lib/python$(PYTHON_VERSION)/config/libpython$(PYTHON_VERSION).dll.a ; - PYTHON_LIB_PATH ?= $(PYTHON_ROOT)/libs ; - - # common properties required for compiling any Python module. - PYTHON_PROPERTIES ?= - <*>SIZEOF_LONG=4 - <*>USE_DL_IMPORT - _DEBUG - dynamic - ; - + boost-python-test $(test-name) : $(sources) libboost_python ; } -else if $(UNIX) -{ - PYTHON_VERSION ?= 1.5 ; - PYTHON_INCLUDES ?= /usr/include/python$(PYTHON_VERSION) ; - PYTHON_LIBS ?= /usr/lib/python$(PYTHON_VERSION)/config/libpython$(PYTHON_VERSION).a ; -} - -local PYTHON_VERSION_NODOT - = [ SUBST $(PYTHON_VERSION) ([0-9]*)\.([0-9]*) $1$2 ] - ; - -# how do we invoke python? -local PYTHON = $(PYTHON) ; -PYTHON ?= python ; -PYTHON = [ FAppendSuffix $(PYTHON:G=) : $(SUFEXE) ] ; -SEARCH on $(PYTHON) = $(PATH) ; ####################### @@ -107,9 +73,6 @@ SEARCH on $(PYTHON) = $(PATH) ; # Declare the boost python static link library # -# standard include requirements for anything using Boost.Python -local BOOST_PYTHON_INCLUDES = $(BOOST_ROOT) $(PYTHON_INCLUDES) ; - # Base names of the source files for libboost_python local CPP_SOURCES = types classes conversions extension_class functions @@ -121,162 +84,23 @@ lib libboost_python : ../src/$(CPP_SOURCES).cpp true $(PYTHON_PROPERTIES) ; -lib libboost_python_d : ../src/$(CPP_SOURCES).cpp - # requirements - : $(BOOST_PYTHON_INCLUDES) - true - $(PYTHON_PROPERTIES) - BOOST_DEBUG_PYTHON - ; -####################### - -# boost-python name : sources : requirements : default-BUILD -# -# Declare a boost python module. Return a list of the DLL files generated. -rule boost-python -{ - local debug = "" ; - if ( BOOST_DEBUG_PYTHON in $(3) ) || ( debug-python in $(BUILD) ) - { - debug = _d ; - } - - # declare a DLL; add the boost python library to sources - dll $(<) : libboost_python$(debug) $(>) - - # Requirements - : $(3) # caller-specified requirements - - # standard requirements - $(BOOST_PYTHON_INCLUDES) - <*>$(PYTHON_LIB_PATH) - <*>$(PYTHON_LIB_PATH) - <*>$(PYTHON_LIB_PATH)/python$(PYTHON_VERSION_NODOT)$(debug).lib - <*>$(PYTHON_LIBS) - $(PYTHON_PROPERTIES) - - : $(4) ; # pass on the default-BUILD, if any -} - -# boost-python-test name : sources : requirements : default-BUILD -# -# Just like boost-python, but the result becomes part of the test pseudotarget -# instead of being built by 'all' -rule boost-python-test -{ - type-DEPENDS test : $(<) ; - type-DEPENDS test_d : $(<)_d ; - NOTFILE test_d ; - - local gSUPPRESS_FAKE_TARGETS = true ; - boost-python $(1) : $(2) : $(3) : $(4) ; - boost-python $(1)_d : $(2) : $(3) BOOST_DEBUG_PYTHON : $(4) ; -} - -####################### - -# boost-python-runtest target : python-script sources : requirements : local-build : args -# -# declare two python module tests: $(<).test which builds when out-of-date, and -# $(<).run which builds unconditionally. -rule boost-python-runtest -{ - # tell Jam that the python script is relative to this directory - SEARCH on $(>[1]) = $(SEARCH_SOURCE) ; - - # required command-line args can be specified in argument 5 - # The user can add additional arguments in PYTHON_TEST_ARGS. - local gPYTHON_TEST_ARGS = $(5) $(PYTHON_TEST_ARGS) ; - - # declare the two subsidiary tests. - declare-local-target $(<:S=.test) : $(>) : $(PYTHON_PROPERTIES) : $(4) : PYTHON_TEST ; - declare-local-target $(<:S=.run) : $(>) : $(PYTHON_PROPERTIES) : $(4) : PYTHON_RUNTEST ; -} - -# special rules for two new target types: PYTHON_TEST and PYTHON_RUNTEST. -# These are identical except that PYTHON_TEST runs the test when out-of-date, and -# PYTHON_RUNTEST runs the test unconditionally. These are used by boost-python-runtest. -SUFPYTHON_TEST = .test ; -gGENERATOR_FUNCTION(PYTHON_TEST) = python-test-target ; -rule python-test-target # test-target : sources : -{ - python-runtest-aux $(<) : $(>) ; - Clean clean : $(<) ; # remove the test-target as part of any clean operation - local debug = [ SUBST $(<:B) (_d)$ $1 ] ; - debug ?= "" ; - type-DEPENDS test$(debug) : $(<) ; - MakeLocate $(<) : $(LOCATE_TARGET) ; -} -actions python-test-target bind PYTHON -{ - $(SHELL_SET)PYTHONPATH=$(PYTHONPATH) - $(SHELL_EXPORT)PYTHONPATH - $(PYTHON) "$(>)" $(ARGS) > "$(<)" -} - -SUFPYTHON_RUNTEST = .run ; -gGENERATOR_FUNCTION(PYTHON_RUNTEST) = python-runtest-target ; -rule python-runtest-target # test-target : sources : -{ - python-runtest-aux $(<) : $(>) ; - NOTFILE $(<) ; - ALWAYS $(<) ; -} -actions python-runtest-target bind PYTHON -{ - $(SHELL_SET)PYTHONPATH=$(PYTHONPATH) - $(SHELL_EXPORT)PYTHONPATH - $(PYTHON) "$(>)" $(ARGS) -} - -rule python-runtest-aux # target : sources -{ - DEPENDS $(<) : $(>) ; - - ARGS on $(<) += $(gPYTHON_TEST_ARGS) ; - - # Some tests need an extra command-line arg if built with - # msvc. Checking the target grist is a cheap way to - # find out. - switch $(<) - { - case <*\\\\msvc\\\\*>* : ARGS on $(<) += --broken-auto-ptr ; - case <*\\\\intel-win32\\\\*>* : ARGS on $(<) += --broken-auto-ptr ; - } - - # compute the PYTHONPATH environment variable that will allow the test to - # find all of the modules on which it depends. - PYTHONPATH on $(<) = [ join - $(gLOCATE($(>[1]))) # location of python test file - $(gRUN_PATH($(<))) # location of module dependencies - [ join-path $(TOP) libs python test ] # location of doctest - $(>:D) # directory of python driver file(s) - $(PYTHONPATH) # base PYTHONPATH from environment - : $(SPLITPATH) ] ; # platform path separator - - PYTHON on $(<) = $(PYTHON) ; - DEPENDS $(<) : $(PYTHON) ; -} - ############# comprehensive module and test ########### -boost-python-test boost_python_test : ../test/comprehensive.cpp ; +bpl-test boost_python_test + : ../test/comprehensive.cpp ; boost-python-runtest comprehensive - : [ join-path $(DOTDOT) test comprehensive.py ] - boost_python_test ; - -boost-python-runtest comprehensive_d - : [ join-path $(DOTDOT) test comprehensive.py ] - boost_python_test_d ; + : ../test/comprehensive.py boost_python_test libboost_python ; ############# simple tests from ../example ############ -rule boost-python-example-runtest +local rule boost-python-example-runtest ( name ) { - boost-python-test $(<) : ../example/$(<).cpp ; - boost-python-runtest $(<) : [ join-path $(DOTDOT) example test_$(<).py ] $(<) ; - boost-python-runtest $(<)_d : [ join-path $(DOTDOT) example test_$(<).py ] $(<)_d ; + bpl-test $(name) + : ../example/$(name).cpp ; + + boost-python-runtest $(name) + : ../example/test_$(name).py $(name) ; } @@ -290,18 +114,18 @@ boost-python-example-runtest pickle2 ; boost-python-example-runtest pickle3 ; -boost-python-test ivect : ../example/ivect.cpp ; -boost-python-test dvect : ../example/dvect.cpp ; -boost-python-test noncopyable_export : ../example/noncopyable_export.cpp ; -boost-python-test noncopyable_import : ../example/noncopyable_import.cpp ; +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 -rule boost-python-multi-example-runtest # test-name : python-file libs +local rule boost-python-multi-example-runtest ( test-name : modules + ) { - boost-python-runtest $(<) - : ../example/tst_$(<).py $(>) + boost-python-runtest $(test-name) + : ../example/tst_$(test-name).py $(modules) libboost_python : : : $(PYTHON_VECT_ITERATIONS) ; } From d05cc7ccec6ceb8cf3153de04fa789e4d0e5b2f4 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 13 Dec 2001 18:18:52 +0000 Subject: [PATCH 157/369] integrating scott snyder's changes [SVN r12042] --- doc/special.html | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/doc/special.html b/doc/special.html index 46ca0791..a72ec671 100644 --- a/doc/special.html +++ b/doc/special.html @@ -287,6 +287,35 @@ bignum_class.def(&rmod, "__rmod__"); found first (be it ``int`` or ``float'') will be used for either of the two types. +

    Inplace Operators

    +

    + Boost.Python can also be used to expose inplace numeric operations + (i.e., += and so forth). These operators must be wrapped + manually, as described in the previous section. For example, suppose + the class BigNum has an operator+=: + +

    +BigNum& operator+= (BigNum const& right);
    +
    + + This can be exposed by first writing a wrapper function: + +
    +BigNum& iadd (BigNum& self, const BigNum& right)
    +{
    +  return self += right;
    +}
    +
    + + and then exposing the wrapper with + +
    +bignum_class.def(&iadd, "__iadd__");
    +
    + + + +

    Coercion

    From 2f6e3cc09d5b588ecbca99879260c63d36eb2042 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 13 Dec 2001 18:22:03 +0000 Subject: [PATCH 158/369] Integrating scott snyder's inplace operator improvements [SVN r12043] --- src/types.cpp | 149 ++++++++++++++++++++++++++++++++++++++++- test/comprehensive.cpp | 48 ++++++++++++- 2 files changed, 194 insertions(+), 3 deletions(-) diff --git a/src/types.cpp b/src/types.cpp index 3367dba8..fe108225 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -455,6 +455,61 @@ static PyObject* do_instance_nb_hex(PyObject* obj) return call(obj, &type_object_base::instance_number_hex); } +static PyObject* do_instance_nb_inplace_add(PyObject* obj, PyObject* other) +{ + return call(obj, &type_object_base::instance_number_inplace_add, other); +} + +static PyObject* do_instance_nb_inplace_subtract(PyObject* obj, PyObject* other) +{ + return call(obj, &type_object_base::instance_number_inplace_subtract, other); +} + +static PyObject* do_instance_nb_inplace_multiply(PyObject* obj, PyObject* other) +{ + return call(obj, &type_object_base::instance_number_inplace_multiply, other); +} + +static PyObject* do_instance_nb_inplace_divide(PyObject* obj, PyObject* other) +{ + return call(obj, &type_object_base::instance_number_inplace_divide, other); +} + +static PyObject* do_instance_nb_inplace_remainder(PyObject* obj, PyObject* other) +{ + return call(obj, &type_object_base::instance_number_inplace_remainder, other); +} + +static PyObject* do_instance_nb_inplace_power(PyObject* obj, PyObject* exponent, PyObject* modulus) +{ + return call(obj, &type_object_base::instance_number_inplace_power, exponent, modulus); +} + +static PyObject* do_instance_nb_inplace_lshift(PyObject* obj, PyObject* other) +{ + return call(obj, &type_object_base::instance_number_inplace_lshift, other); +} + +static PyObject* do_instance_nb_inplace_rshift(PyObject* obj, PyObject* other) +{ + return call(obj, &type_object_base::instance_number_inplace_rshift, other); +} + +static PyObject* do_instance_nb_inplace_and(PyObject* obj, PyObject* other) +{ + return call(obj, &type_object_base::instance_number_inplace_and, other); +} + +static PyObject* do_instance_nb_inplace_or(PyObject* obj, PyObject* other) +{ + return call(obj, &type_object_base::instance_number_inplace_or, other); +} + +static PyObject* do_instance_nb_inplace_xor(PyObject* obj, PyObject* other) +{ + return call(obj, &type_object_base::instance_number_inplace_xor, other); +} + } // extern "C" namespace @@ -511,6 +566,41 @@ bool add_capability_richcompare(type_object_base::capability capability, PyTypeO return false; } +#if PYTHON_API_VERSION >= 1010 +# define ENABLE_INPLACE_CAPABILITY1 \ + dest->tp_flags |= Py_TPFLAGS_HAVE_INPLACEOPS; +#else +# define ENABLE_INPLACE_CAPABILITY1 +#endif +#define ENABLE_INPLACE_CAPABILITY(field) \ + case type_object_base::number_##field: \ + create_method_table_if_null(dest->tp_as_number); \ + dest->tp_as_number->nb_##field = &do_instance_nb_##field; \ + detail::shared_pod_manager::replace_if_equal(dest->tp_as_number); \ + ENABLE_INPLACE_CAPABILITY1 \ + return true + +bool add_capability_inplace(type_object_base::capability capability, PyTypeObject* dest) +{ + assert(dest != 0); + switch (capability) + { + ENABLE_INPLACE_CAPABILITY (inplace_add); + ENABLE_INPLACE_CAPABILITY (inplace_subtract); + ENABLE_INPLACE_CAPABILITY (inplace_multiply); + ENABLE_INPLACE_CAPABILITY (inplace_divide); + ENABLE_INPLACE_CAPABILITY (inplace_remainder); + ENABLE_INPLACE_CAPABILITY (inplace_power); + ENABLE_INPLACE_CAPABILITY (inplace_lshift); + ENABLE_INPLACE_CAPABILITY (inplace_rshift); + ENABLE_INPLACE_CAPABILITY (inplace_and); + ENABLE_INPLACE_CAPABILITY (inplace_or); + ENABLE_INPLACE_CAPABILITY (inplace_xor); + default: + return false; + } +} + #define ENABLE_MAPPING_CAPABILITY(field) \ case type_object_base::mapping_##field: \ create_method_table_if_null(dest); \ @@ -626,6 +716,8 @@ namespace detail { return; if(add_capability_richcompare(capability, dest_)) return; + if(add_capability_inplace(capability, dest_)) + return; if(add_capability_mapping(capability, dest_->tp_as_mapping)) return; if(add_capability_sequence(capability, dest_->tp_as_sequence)) @@ -970,7 +1062,7 @@ PyObject* type_object_base::instance_number_divmod(PyObject*, PyObject*) const PyObject* type_object_base::instance_number_power(PyObject*, PyObject*, PyObject*) const { - return unimplemented("instance_number_divmod"); + return unimplemented("instance_number_power"); } PyObject* type_object_base::instance_number_negative(PyObject*) const @@ -1053,6 +1145,61 @@ PyObject* type_object_base::instance_number_hex(PyObject*) const return unimplemented("instance_number_hex"); } +PyObject* type_object_base::instance_number_inplace_add(PyObject*, PyObject*) const +{ + return unimplemented("instance_number_inplace_add"); +} + +PyObject* type_object_base::instance_number_inplace_subtract(PyObject*, PyObject*) const +{ + return unimplemented("instance_number_inplace_subtract"); +} + +PyObject* type_object_base::instance_number_inplace_multiply(PyObject*, PyObject*) const +{ + return unimplemented("instance_number_inplace_multiply"); +} + +PyObject* type_object_base::instance_number_inplace_divide(PyObject*, PyObject*) const +{ + return unimplemented("instance_number_inplace_divide"); +} + +PyObject* type_object_base::instance_number_inplace_remainder(PyObject*, PyObject*) const +{ + return unimplemented("instance_number_inplace_remainder"); +} + +PyObject* type_object_base::instance_number_inplace_power(PyObject*, PyObject*, PyObject*) const +{ + return unimplemented("instance_number_inplace_power"); +} + +PyObject* type_object_base::instance_number_inplace_lshift(PyObject*, PyObject*) const +{ + return unimplemented("instance_number_inplace_lshift"); +} + +PyObject* type_object_base::instance_number_inplace_rshift(PyObject*, PyObject*) const +{ + return unimplemented("instance_number_inplace_rshift"); +} + +PyObject* type_object_base::instance_number_inplace_and(PyObject*, PyObject*) const +{ + return unimplemented("instance_number_inplace_and"); +} + +PyObject* type_object_base::instance_number_inplace_or(PyObject*, PyObject*) const +{ + return unimplemented("instance_number_inplace_or"); +} + +PyObject* type_object_base::instance_number_inplace_xor(PyObject*, PyObject*) const +{ + return unimplemented("instance_number_inplace_xor"); +} + PyObject* type_object_base::instance_lt(PyObject*, PyObject*) const { return unimplemented("instance_lt"); diff --git a/test/comprehensive.cpp b/test/comprehensive.cpp index 7cd7e0ce..61f56407 100644 --- a/test/comprehensive.cpp +++ b/test/comprehensive.cpp @@ -667,7 +667,7 @@ int total_Ints = 0; struct Int { - explicit Int(int i) : i_(i) { + explicit Int(int i) : i_(i), j_(0) { #ifndef NDEBUG ++total_Ints; #endif @@ -675,12 +675,29 @@ struct Int #ifndef NDEBUG ~Int() { --total_Ints; } - Int(const Int& rhs) : i_(rhs.i_) { ++total_Ints; } + Int(const Int& rhs) : i_(rhs.i_), j_(rhs.j_) { ++total_Ints; } #endif int i() const { return i_; } + int j() const { return j_; } int i_; + int j_; + + Int& operator +=(Int const& r) { ++j_; i_ += r.i_; return *this; } + Int& operator -=(Int const& r) { ++j_; i_ -= r.i_; return *this; } + Int& operator *=(Int const& r) { ++j_; i_ *= r.i_; return *this; } + Int& operator /=(Int const& r) { ++j_; i_ /= r.i_; return *this; } + Int& operator %=(Int const& r) { ++j_; i_ %= r.i_; return *this; } + Int& ipow (Int const& r) { ++j_; + int o=i_; + for (int k=1; k>=(Int const& r) { ++j_; i_ >>= r.i_; return *this; } + Int& operator &=(Int const& r) { ++j_; i_ &= r.i_; return *this; } + Int& operator |=(Int const& r) { ++j_; i_ |= r.i_; return *this; } + Int& operator ^=(Int const& r) { ++j_; i_ ^= r.i_; return *this; } }; Int operator+(Int const & l, Int const & r) { return Int(l.i_ + r.i_); } @@ -868,6 +885,19 @@ namespace bpl_test { double freal(const std::complex& c) { return c.real(); } double fimag(std::complex c) { return c.imag(); } + // Wrappers for inplace operators. + Int& int_iadd(Int& self, const Int& r) { self += r; return self; } + Int& int_isub(Int& self, const Int& r) { self -= r; return self; } + Int& int_imul(Int& self, const Int& r) { self *= r; return self; } + Int& int_idiv(Int& self, const Int& r) { self /= r; return self; } + Int& int_imod(Int& self, const Int& r) { self %= r; return self; } + Int& int_ipow(Int& self, const Int& r) { self.ipow (r); return self; } + Int& int_ilshift(Int& self, const Int& r) { self <<= r; return self; } + Int& int_irshift(Int& self, const Int& r) { self >>= r; return self; } + Int& int_iand(Int& self, const Int& r) { self &= r; return self; } + Int& int_ior(Int& self, const Int& r) { self |= r; return self; } + Int& int_ixor(Int& self, const Int& r) { self ^= r; return self; } + /************************************************************/ /* */ /* init the module */ @@ -1042,6 +1072,7 @@ void init_module(boost::python::module_builder& m) boost::python::class_builder int_class(m, "Int"); int_class.def(boost::python::constructor()); int_class.def(&Int::i, "i"); + int_class.def(&Int::j, "j"); // wrap homogeneous operators int_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub | boost::python::op_neg | @@ -1061,6 +1092,19 @@ void init_module(boost::python::module_builder& m) boost::python::left_operand()); // export non-operator function as heterogeneous reverse-argument operator int_class.def(&rmul, "__rmul__"); + + // inplace operators. + int_class.def(&int_iadd, "__iadd__"); + int_class.def(&int_isub, "__isub__"); + int_class.def(&int_imul, "__imul__"); + int_class.def(&int_idiv, "__idiv__"); + int_class.def(&int_imod, "__imod__"); + int_class.def(&int_ipow, "__ipow__"); + int_class.def(&int_ilshift, "__ilshift__"); + int_class.def(&int_irshift, "__irshift__"); + int_class.def(&int_iand, "__iand__"); + int_class.def(&int_ior, "__ior__"); + int_class.def(&int_ixor, "__ixor__"); boost::python::class_builder enum_owner(m, "EnumOwner"); From 160451b210d12071f378d8c0e13c2297dcb3ca19 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 13 Dec 2001 18:23:10 +0000 Subject: [PATCH 159/369] Integrating scott snyder's inplace operator improvements Fixed Python 2.2 incompatibility [SVN r12044] --- test/comprehensive.py | 64 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 8 deletions(-) diff --git a/test/comprehensive.py b/test/comprehensive.py index 2ac0704a..b4ae5679 100644 --- a/test/comprehensive.py +++ b/test/comprehensive.py @@ -318,26 +318,37 @@ Special member attributes. Tests courtesy of Barry Scott >> df = DerivedFromFoo() - >>> dir(df) - [] >>> dir(DerivedFromFoo) ['__del__', '__doc__', '__init__', '__module__', 'fred'] + + >>> df = DerivedFromFoo() >>> df.__dict__ {} - >>> df.fred.__doc__ 'Docs for DerivedFromFoo.fred' + >>> db = DerivedFromBase() - >>> dir(db) - [] - >>> dir(DerivedFromBase) - ['__doc__', '__module__', 'fred', 'i_am_derived_from_base'] >>> db.__dict__ {} >>> db.fred.__doc__ 'Docs for DerivedFromBase.fred' + >>> import sys + >>> if sys.version_info[0] < 2 or ( sys.version_info[0] == 2 and + ... sys.version_info[1] < 2 ): + ... assert dir(df) == [] + ... assert dir(db) == [] + ... assert dir(DerivedFromBase) == [ + ... '__doc__', '__module__', 'fred', 'i_am_derived_from_base'] + ... else: + ... assert dir(df) == [ + ... '__del__', '__doc__', '__init__', '__module__', 'add_len', + ... 'call_add_len', 'call_pure', 'fred', 'mumble', 'set'] + ... assert dir(db) == ['__doc__', '__module__', 'fred' + ... , 'i_am_base', 'i_am_derived_from_base'] + ... assert dir(DerivedFromBase) == [ + ... '__doc__', '__module__', 'fred', 'i_am_base', 'i_am_derived_from_base'] + Special member functions in action >>> del df Deleting DerivedFromFoo @@ -1058,6 +1069,43 @@ test inheritB2 Traceback (innermost last): TypeError: bad operand type(s) for pow() + >>> ii = Int(1) + >>> ii += Int(2) + >>> ii.i() + 3 + >>> ii -= Int(1) + >>> ii.i() + 2 + >>> ii *= Int(3) + >>> ii.i() + 6 + >>> ii /= Int(2) + >>> ii.i() + 3 + >>> ii <<= Int(2) + >>> ii.i() + 12 + >>> ii >>= Int(1) + >>> ii.i() + 6 + >>> ii &= Int(5) + >>> ii.i() + 4 + >>> ii |= Int(9) + >>> ii.i() + 13 + >>> ii ^= Int(7) + >>> ii.i() + 10 + >>> ii %= Int(4) + >>> ii.i() + 2 + >>> ii **= Int(3) + >>> ii.i() + 8 + >>> ii.j() + 11 + Test operator export to a subclass # force method table sharing From a365fa610936a312fdc9602c01afefb5f12cbb59 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 13 Dec 2001 19:43:35 +0000 Subject: [PATCH 160/369] many fixes [SVN r12054] --- include/boost/python/classes.hpp | 91 +++++++++++ include/boost/python/detail/types.hpp | 18 ++- include/boost/python/detail/wrap_python.hpp | 20 ++- src/classes.cpp | 69 ++++++++ src/gen_arg_tuple_size.py | 132 +++++++++++++++ src/gen_function.py | 171 ++++++++++---------- 6 files changed, 414 insertions(+), 87 deletions(-) create mode 100644 src/gen_arg_tuple_size.py diff --git a/include/boost/python/classes.hpp b/include/boost/python/classes.hpp index 2d69e81e..f88f1000 100644 --- a/include/boost/python/classes.hpp +++ b/include/boost/python/classes.hpp @@ -78,6 +78,19 @@ class instance PyObject* gt(PyObject* other); PyObject* ge(PyObject* other); + // Inplace operations. + PyObject* inplace_add(PyObject* other); + PyObject* inplace_subtract(PyObject* other); + PyObject* inplace_multiply(PyObject* other); + PyObject* inplace_divide(PyObject* other); + PyObject* inplace_remainder(PyObject* other); + PyObject* inplace_power(PyObject* exponent, PyObject* modulus); + PyObject* inplace_lshift(PyObject* other); + PyObject* inplace_rshift(PyObject* other); + PyObject* inplace_and(PyObject* other); + PyObject* inplace_or(PyObject* other); + PyObject* inplace_xor(PyObject* other); + private: // noncopyable, without the size bloat instance(const instance&); void operator=(const instance&); @@ -178,6 +191,18 @@ class class_t PyObject* instance_number_oct(PyObject*) const; PyObject* instance_number_hex(PyObject*) const; + PyObject* instance_number_inplace_add(PyObject*, PyObject*) const; + PyObject* instance_number_inplace_subtract(PyObject*, PyObject*) const; + PyObject* instance_number_inplace_multiply(PyObject*, PyObject*) const; + PyObject* instance_number_inplace_divide(PyObject*, PyObject*) const; + PyObject* instance_number_inplace_remainder(PyObject*, PyObject*) const; + PyObject* instance_number_inplace_power(PyObject*, PyObject*, PyObject*) const; + PyObject* instance_number_inplace_lshift(PyObject*, PyObject*) const; + PyObject* instance_number_inplace_rshift(PyObject*, PyObject*) const; + PyObject* instance_number_inplace_and(PyObject*, PyObject*) const; + PyObject* instance_number_inplace_or(PyObject*, PyObject*) const; + PyObject* instance_number_inplace_xor(PyObject*, PyObject*) const; + private: // Implement rich comparisons PyObject* instance_lt(PyObject*, PyObject*) const; PyObject* instance_le(PyObject*, PyObject*) const; @@ -493,6 +518,72 @@ PyObject* class_t::instance_number_hex(PyObject* obj) const return downcast(obj)->hex(); } +template +PyObject* class_t::instance_number_inplace_add(PyObject* obj, PyObject* other) const +{ + return downcast(obj)->inplace_add(other); +} + +template +PyObject* class_t::instance_number_inplace_subtract(PyObject* obj, PyObject* other) const +{ + return downcast(obj)->inplace_subtract(other); +} + +template +PyObject* class_t::instance_number_inplace_multiply(PyObject* obj, PyObject* other) const +{ + return downcast(obj)->inplace_multiply(other); +} + +template +PyObject* class_t::instance_number_inplace_divide(PyObject* obj, PyObject* other) const +{ + return downcast(obj)->inplace_divide(other); +} + +template +PyObject* class_t::instance_number_inplace_remainder(PyObject* obj, PyObject* other) const +{ + return downcast(obj)->inplace_remainder(other); +} + +template +PyObject* class_t::instance_number_inplace_power(PyObject* obj, PyObject* exponent, PyObject* modulus) const +{ + return downcast(obj)->inplace_power(exponent, modulus); +} + +template +PyObject* class_t::instance_number_inplace_lshift(PyObject* obj, PyObject* other) const +{ + return downcast(obj)->inplace_lshift(other); +} + +template +PyObject* class_t::instance_number_inplace_rshift(PyObject* obj, PyObject* other) const +{ + return downcast(obj)->inplace_rshift(other); +} + +template +PyObject* class_t::instance_number_inplace_and(PyObject* obj, PyObject* other) const +{ + return downcast(obj)->inplace_and(other); +} + +template +PyObject* class_t::instance_number_inplace_or(PyObject* obj, PyObject* other) const +{ + return downcast(obj)->inplace_or(other); +} + +template +PyObject* class_t::instance_number_inplace_xor(PyObject* obj, PyObject* other) const +{ + return downcast(obj)->inplace_xor(other); +} + template PyObject* class_t::instance_lt(PyObject* obj, PyObject* other) const { diff --git a/include/boost/python/detail/types.hpp b/include/boost/python/detail/types.hpp index 2d0d0f6b..954e0213 100644 --- a/include/boost/python/detail/types.hpp +++ b/include/boost/python/detail/types.hpp @@ -57,7 +57,11 @@ class type_object_base : public python_type 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_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); @@ -116,6 +120,18 @@ class type_object_base : public python_type 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; diff --git a/include/boost/python/detail/wrap_python.hpp b/include/boost/python/detail/wrap_python.hpp index 373bbde4..1ad88ab6 100644 --- a/include/boost/python/detail/wrap_python.hpp +++ b/include/boost/python/detail/wrap_python.hpp @@ -35,12 +35,13 @@ // than MSVC on Win32 // #if defined(_WIN32) -# ifdef __GNUC__ - +# 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 +# define WORD_BIT 32 +# define hypot _hypot +# include +# endif # if !defined(PY_MAJOR_VERSION) || PY_MAJOR_VERSION < 2 # define HAVE_CLOCK # define HAVE_STRFTIME @@ -71,6 +72,13 @@ typedef int pid_t; # define _MSC_VER 900 # endif +# include +# undef hypot // undo the evil #define left by Python. + +# elif defined(__BORLANDC__) +# include +# undef HAVE_HYPOT +# define HAVE_HYPOT 1 # elif defined(_MSC_VER) # include // prevents Python.h from defining LONGLONG_MAX, LONGLONG_MIN, and ULONGLONG_MAX # endif @@ -95,4 +103,6 @@ typedef int pid_t; #ifdef __MWERKS__ # pragma warn_possunwant off +#elif _MSC_VER +# pragma warning(disable:4786) #endif diff --git a/src/classes.cpp b/src/classes.cpp index a44c3c0a..75f8a01a 100644 --- a/src/classes.cpp +++ b/src/classes.cpp @@ -766,6 +766,64 @@ PyObject* instance::ge(PyObject* other) return callback::call_method(this, "__ge__", other); } +PyObject* instance::inplace_add(PyObject* other) +{ + return callback::call_method(this, "__iadd__", other); +} + +PyObject* instance::inplace_subtract(PyObject* other) +{ + return callback::call_method(this, "__isub__", other); +} + +PyObject* instance::inplace_multiply(PyObject* other) +{ + return callback::call_method(this, "__imul__", other); +} + +PyObject* instance::inplace_divide(PyObject* other) +{ + return callback::call_method(this, "__idiv__", other); +} + +PyObject* instance::inplace_remainder(PyObject* other) +{ + return callback::call_method(this, "__imod__", other); +} + +PyObject* instance::inplace_power(PyObject* exponent, PyObject* modulus) +{ + if (modulus == Py_None) + return callback::call_method(this, "__ipow__", exponent); + else + return callback::call_method(this, "__ipow__", exponent, modulus); +} + +PyObject* instance::inplace_lshift(PyObject* other) +{ + return callback::call_method(this, "__ilshift__", other); +} + +PyObject* instance::inplace_rshift(PyObject* other) +{ + return callback::call_method(this, "__irshift__", other); +} + +PyObject* instance::inplace_and(PyObject* other) +{ + return callback::call_method(this, "__iand__", other); +} + +PyObject* instance::inplace_or(PyObject* other) +{ + return callback::call_method(this, "__ior__", other); +} + +PyObject* instance::inplace_xor(PyObject* other) +{ + return callback::call_method(this, "__ixor__", other); +} + namespace { struct named_capability { @@ -783,6 +841,17 @@ namespace { { "__le__", detail::type_object_base::richcompare }, { "__eq__", detail::type_object_base::richcompare }, { "__ne__", detail::type_object_base::richcompare }, + { "__iadd__", detail::type_object_base::number_inplace_add }, + { "__isub__", detail::type_object_base::number_inplace_subtract }, + { "__imul__", detail::type_object_base::number_inplace_multiply }, + { "__idiv__", detail::type_object_base::number_inplace_divide }, + { "__imod__", detail::type_object_base::number_inplace_remainder }, + { "__ipow__", detail::type_object_base::number_inplace_power }, + { "__ilshift__", detail::type_object_base::number_inplace_lshift }, + { "__irshift__", detail::type_object_base::number_inplace_rshift }, + { "__iand__", detail::type_object_base::number_inplace_and }, + { "__ixor__", detail::type_object_base::number_inplace_xor }, + { "__ior__", detail::type_object_base::number_inplace_or }, { "__repr__", detail::type_object_base::repr }, { "__str__", detail::type_object_base::str }, { "__call__", detail::type_object_base::call }, diff --git a/src/gen_arg_tuple_size.py b/src/gen_arg_tuple_size.py new file mode 100644 index 00000000..68e379cb --- /dev/null +++ b/src/gen_arg_tuple_size.py @@ -0,0 +1,132 @@ +# (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 + +from gen_function import * +import string + +header = '''// (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 %d-argument member functions and %d-argument free +// functions by gen_arg_tuple_size.python +''' + +_cv_qualifiers = ('', ' const', ' volatile', ' const volatile') + +def gen_arg_tuple_size(member_function_args, free_function_args = None): + if free_function_args is None: + free_function_args = member_function_args + 1 + + return_none = '''; + return detail::none();''' + + return (header % (member_function_args, free_function_args) + + ''' +#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 struct arg_tuple_size; + +# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__BORLANDC__) + +''' + + gen_functions( +'''template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = %n); +}; + +''', free_function_args) + + + '\n' + + gen_functions( +'''template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = %+); +}; + +''', member_function_args, '') + + +'''# 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 +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. + +''' + + gen_functions( +'''template +char_array<%n> arg_tuple_size_helper(R (*)(%(A%+%:, %))); + +''', free_function_args) + + + reduce(lambda x,y: x+'\n'+y + , map( + lambda cv: gen_functions( +'''template +char_array<%+> arg_tuple_size_helper(R (A0::*)(%(A%+%:, %))%1); + +''', member_function_args, cv) + , _cv_qualifiers)) + + ''' +template +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 +''') + +if __name__ == '__main__': + import sys + + if len(sys.argv) == 1: + member_function_args = 5 + free_function_args = 6 + else: + member_function_args = int(sys.argv[1]) + if len(sys.argv) > 2: + free_function_args = int(sys.argv[2]) + else: + free_function_args = member_function_args + + print gen_arg_tuple_size(member_function_args, free_function_args) + + diff --git a/src/gen_function.py b/src/gen_function.py index ac24ac18..dba53c3b 100644 --- a/src/gen_function.py +++ b/src/gen_function.py @@ -1,3 +1,60 @@ +r""" +>>> template = ''' template +... static PyObject* call( %1(T::*pmf)(%(A%+%:, %))%2, PyObject* args, PyObject* ) { +... PyObject* self; +... %( PyObject* a%+; +... %) if (!PyArg_ParseTuple(args, const_cast("O%(O%)"), &self%(, &a%+%))) +... return 0; +... T& target = from_python(self, type()); +... %3to_python((target.*pmf)(%( +... from_python(a%+, type())%:,%) +... ));%4 +... }''' + +>>> print gen_function(template, 0, 'R ', '', 'return ', '') + template + static PyObject* call( R (T::*pmf)(), PyObject* args, PyObject* ) { + PyObject* self; + if (!PyArg_ParseTuple(args, const_cast("O"), &self)) + return 0; + T& target = from_python(self, type()); + return to_python((target.*pmf)( + )); + } + +>>> print gen_function(template, 2, 'R ', '', 'return ', '') + template + static PyObject* call( R (T::*pmf)(A1, A2), PyObject* args, PyObject* ) { + PyObject* self; + PyObject* a1; + PyObject* a2; + if (!PyArg_ParseTuple(args, const_cast("OOO"), &self, &a1, &a2)) + return 0; + T& target = from_python(self, type()); + return to_python((target.*pmf)( + from_python(a1, type()), + from_python(a2, type()) + )); + } + +>>> print gen_function(template, 3, 'void ', ' const', '', '\n'+8*' ' + 'return none();') + template + static PyObject* call( void (T::*pmf)(A1, A2, A3) const, PyObject* args, PyObject* ) { + PyObject* self; + PyObject* a1; + PyObject* a2; + PyObject* a3; + if (!PyArg_ParseTuple(args, const_cast("OOOO"), &self, &a1, &a2, &a3)) + return 0; + T& target = from_python(self, type()); + to_python((target.*pmf)( + from_python(a1, type()), + from_python(a2, type()), + from_python(a3, type()) + )); + return none(); + } +""" import string def _find(s, sub, start=0, end=None): @@ -35,19 +92,19 @@ def _gen_common_key(key, n, args, fill = _raise_no_argument): else: return key -def _gen_arg(template, n, args, delimiter = '%', fill = _raise_no_argument): +def _gen_arg(template, n, args, fill = _raise_no_argument): result = '' i = 0 while i < len(template): # until the template is consumed - # consume everything up to the first delimiter - delimiter_pos = _find(template, delimiter, i) + # consume everything up to the first '%' + delimiter_pos = _find(template, '%', i) result = result + template[i:delimiter_pos] - # The start position of whatever comes after the delimiter+key + # The start position of whatever comes after the '%'+key start = delimiter_pos + 2 key = template[start - 1 : start] # the key character. If there were no - # delimiters left, key will be empty + # '%'s left, key will be empty if 0 and key == 'n': result = result + `n` @@ -64,7 +121,7 @@ def gen_function(template, n, *args, **keywords): Generate a function declaration based on the given template. Sections of the template between '%(', '%)' pairs are repeated n times. If '%:' - appears in the middle, it denotes the beginning of a delimiter. + appears in the middle, it denotes the beginning of a '%'. Sections of the template between '%{', '%}' pairs are ommitted if n == 0. @@ -95,7 +152,7 @@ def gen_function(template, n, *args, **keywords): for example, >>> gen_function('%1 abc%x(%(int a%n%:, %));%{ // all args are ints%}', 2, 'void') - 'void abc2(int a1, int a2); // all args are ints' + 'void abc2(int a0, int a1); // all args are ints' >>> gen_function('%1 abc(%(int a%n%:, %));%{ // all args are ints%}', 0, 'x') 'x abc();' @@ -109,102 +166,54 @@ def gen_function(template, n, *args, **keywords): >>> gen_function('abc%[k%:v%]', 0, fill = lambda key, n, args, value = None: '<' + key + ',' + value + '>') 'abc' - >>> template = ''' template - ... static PyObject* call( %1(T::*pmf)(%(A%n%:, %))%2, PyObject* args, PyObject* /* keywords */ ) { - ... PyObject* self; - ... %( PyObject* a%n; - ... %) if (!PyArg_ParseTuple(args, const_cast("O%(O%)"), &self%(, &a%n%))) - ... return 0; - ... T& target = from_python(self, type()); - ... %3to_python((target.*pmf)(%( - ... from_python(a%n, type())%:,%) - ... ));%4 - ... }''' - - >>> print gen_function(template, 0, 'R ', '', 'return ', '') - template - static PyObject* call( R (T::*pmf)(), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - if (!PyArg_ParseTuple(args, const_cast("O"), &self)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)( - )); - } - - >>> print gen_function(template, 2, 'R ', '', 'return ', '') - template - static PyObject* call( R (T::*pmf)(A1, A2), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - if (!PyArg_ParseTuple(args, const_cast("OOO"), &self, &a1, &a2)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)( - from_python(a1, type()), - from_python(a2, type()) - )); - } - - >>> print gen_function(template, 3, 'void ', ' const', '', '\n'+8*' ' + 'return none();') - template - static PyObject* call( void (T::*pmf)(A1, A2, A3) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - if (!PyArg_ParseTuple(args, const_cast("OOOO"), &self, &a1, &a2, &a3)) - return 0; - T& target = from_python(self, type()); - to_python((target.*pmf)( - from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()) - )); - return none(); - } """ - delimiter = keywords.get('delimiter', '%') + expand = (lambda s, n = n: + apply(gen_function, (s, n) + args, keywords)) + fill = keywords.get('fill', _raise_no_argument); result = '' i = 0 while i < len(template): # until the template is consumed - # consume everything up to the first delimiter - delimiter_pos = _find(template, delimiter, i) + # consume everything up to the first '%' + delimiter_pos = _find(template, '%', i) result = result + template[i:delimiter_pos] - # The start position of whatever comes after the delimiter+key + # The start position of whatever comes after the '%'+key start = delimiter_pos + 2 key = template[start - 1 : start] # the key character. If there were no - # delimiters left, key will be empty + # '%'s left, key will be empty pairs = { '(':')', '{':'}', '[':']' } if key in pairs.keys(): - end = string.find(template, delimiter + pairs[key], start) - assert end >= 0, "Matching '" + delimiter + pairs[key] +"' not found!" + end = string.find(template, '%' + pairs[key], start) + assert end >= 0, "Matching '" + '%' + pairs[key] +"' not found!" delimiter_pos = end if key == '{': if n > 0: - result = result + gen_function(template[start:end], n, args, delimiter) + result = result + expand(template[start:end]) else: - separator_pos = _find(template, delimiter + ':', - start, end) + separator_pos = _find(template, '%:', start, end) remainder = template[separator_pos+2 : end] if key == '(': - for x in range(1, n + 1): - result = result + _gen_arg(template[start:separator_pos], x, args, - delimiter) - if x != n: - result = result + remainder + for x in range(n): + + iteration = expand( + template[start:separator_pos], x) + + result = result + expand(iteration, x) + + if x != n - 1: + result = result + expand(remainder, x) else: - result = result + fill(template[start:separator_pos], n, args, value = remainder) + function_result = fill( + template[start:separator_pos], n, args, value = remainder) + result = result + expand(function_result) else: - result = result + _gen_common_key(key, n, args, fill) + result = result + expand(_gen_common_key(key, n, args, fill)) i = delimiter_pos + 2 @@ -218,8 +227,8 @@ def gen_functions(template, n, *args, **keywords): >>> print gen_functions('%1 abc(%(int a%n%:, %));%{ // all args are ints%}\n', 2, 'void'), void abc(); - void abc(int a1); // all args are ints - void abc(int a1, int a2); // all args are ints + void abc(int a0); // all args are ints + void abc(int a0, int a1); // all args are ints """ fill = keywords.get('fill', _raise_no_argument); From c6fd3c47a4633221b41213ffb9f2249ee3f76b99 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 15 Dec 2001 04:57:18 +0000 Subject: [PATCH 161/369] Makefile and example setup batch file for Win32 Metrowerks Codewarrior 7. [SVN r12063] --- build/win32_mwcc.mak | 149 +++++++++++++++++++++++++++++++++++++ build/win32_mwcc_setup.bat | 2 + 2 files changed, 151 insertions(+) create mode 100755 build/win32_mwcc.mak create mode 100755 build/win32_mwcc_setup.bat diff --git a/build/win32_mwcc.mak b/build/win32_mwcc.mak new file mode 100755 index 00000000..ac054c07 --- /dev/null +++ b/build/win32_mwcc.mak @@ -0,0 +1,149 @@ +# Usage: +# +# make copy Copy the sources and tests +# make Compile all sources +# make test Run doctest tests +# make clean Remove all object files +# make del Remove the sources and tests +# +# Revision history: +# 14 Dec 01 derived from vc60.mak (R.W. Grosse-Kunstleve) + +ROOT=R: +BOOST_WIN="$(ROOT)\boostdev" +BOOST_UNIX=$(HOME)/boost + +#PYEXE="C:\Program files\Python\python.exe" +#PYINC=-I"C:\Program files\Python\include" +#PYLIB="C:\Program files\Python\libs\python15.lib" +PYEXE="C:\Python21\python.exe" +PYINC=-I"C:\Python21\include" +PYLIB="C:\Python21\libs\python21.lib" + +STDOPTS=-gccinc -prefix UseDLLPrefix.h +WARNOPTS=-warn on,nounusedexpr,nounused +OPTOPTS=-O + +CPP=mwcc +CPPOPTS=$(STDOPTS) $(WARNOPTS) $(OPTOPTS) \ + $(STLPORTINC) $(STLPORTOPTS) -I$(BOOST_WIN) $(PYINC) + +LD=mwld +LDOPTS=-export dllexport -shared + +OBJ=classes.obj conversions.obj extension_class.obj functions.obj \ + init_function.obj module_builder.obj \ + objects.obj types.obj cross_module.obj + +.SUFFIXES: .obj .cpp + +all: libboost_python.lib \ + boost_python_test.pyd \ + abstract.pyd \ + getting_started1.pyd getting_started2.pyd \ + simple_vector.pyd \ + do_it_yourself_convts.pyd \ + nested.pyd \ + pickle1.pyd pickle2.pyd pickle3.pyd \ + noncopyable_export.pyd noncopyable_import.pyd \ + ivect.pyd dvect.pyd \ + richcmp1.pyd richcmp2.pyd richcmp3.pyd + +libboost_python.lib: $(OBJ) + $(LD) -library -o libboost_python.lib $(OBJ) + +boost_python_test.pyd: $(OBJ) comprehensive.obj + $(LD) $(LDOPTS) $(OBJ) comprehensive.obj $(PYLIB) -o boost_python_test.pyd + +abstract.pyd: $(OBJ) abstract.obj + $(LD) $(LDOPTS) $(OBJ) abstract.obj $(PYLIB) -o abstract.pyd + +getting_started1.pyd: $(OBJ) getting_started1.obj + $(LD) $(LDOPTS) $(OBJ) getting_started1.obj $(PYLIB) -o getting_started1.pyd + +getting_started2.pyd: $(OBJ) getting_started2.obj + $(LD) $(LDOPTS) $(OBJ) getting_started2.obj $(PYLIB) -o getting_started2.pyd + +simple_vector.pyd: $(OBJ) simple_vector.obj + $(LD) $(LDOPTS) $(OBJ) simple_vector.obj $(PYLIB) -o simple_vector.pyd + +do_it_yourself_convts.pyd: $(OBJ) do_it_yourself_convts.obj + $(LD) $(LDOPTS) $(OBJ) do_it_yourself_convts.obj $(PYLIB) -o do_it_yourself_convts.pyd + +nested.pyd: $(OBJ) nested.obj + $(LD) $(LDOPTS) $(OBJ) nested.obj $(PYLIB) -o nested.pyd + +pickle1.pyd: $(OBJ) pickle1.obj + $(LD) $(LDOPTS) $(OBJ) pickle1.obj $(PYLIB) -o pickle1.pyd + +pickle2.pyd: $(OBJ) pickle2.obj + $(LD) $(LDOPTS) $(OBJ) pickle2.obj $(PYLIB) -o pickle2.pyd + +pickle3.pyd: $(OBJ) pickle3.obj + $(LD) $(LDOPTS) $(OBJ) pickle3.obj $(PYLIB) -o pickle3.pyd + +noncopyable_export.pyd: $(OBJ) noncopyable_export.obj + $(LD) $(LDOPTS) $(OBJ) noncopyable_export.obj $(PYLIB) -o noncopyable_export.pyd + +noncopyable_import.pyd: $(OBJ) noncopyable_import.obj + $(LD) $(LDOPTS) $(OBJ) noncopyable_import.obj $(PYLIB) -o noncopyable_import.pyd + +ivect.pyd: $(OBJ) ivect.obj + $(LD) $(LDOPTS) $(OBJ) ivect.obj $(PYLIB) -o ivect.pyd + +dvect.pyd: $(OBJ) dvect.obj + $(LD) $(LDOPTS) $(OBJ) dvect.obj $(PYLIB) -o dvect.pyd + +richcmp1.pyd: $(OBJ) richcmp1.obj + $(LD) $(LDOPTS) $(OBJ) richcmp1.obj $(PYLIB) -o richcmp1.pyd + +richcmp2.pyd: $(OBJ) richcmp2.obj + $(LD) $(LDOPTS) $(OBJ) richcmp2.obj $(PYLIB) -o richcmp2.pyd + +richcmp3.pyd: $(OBJ) richcmp3.obj + $(LD) $(LDOPTS) $(OBJ) richcmp3.obj $(PYLIB) -o richcmp3.pyd + +.cpp.obj: + $(CPP) $(CPPOPTS) -c $*.cpp + +test: + $(PYEXE) comprehensive.py + $(PYEXE) test_abstract.py + $(PYEXE) test_getting_started1.py + $(PYEXE) test_getting_started2.py + $(PYEXE) test_simple_vector.py + $(PYEXE) test_do_it_yourself_convts.py + $(PYEXE) test_nested.py + $(PYEXE) test_pickle1.py + $(PYEXE) test_pickle2.py + $(PYEXE) test_pickle3.py + $(PYEXE) test_cross_module.py + $(PYEXE) test_richcmp1.py + $(PYEXE) test_richcmp2.py + $(PYEXE) test_richcmp3.py + +clean: + -del *.obj + -del *.lib + -del *.exp + -del *.idb + -del *.pyd + -del *.pyc + +softlinks: + python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) softlinks + +unlink: + python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) unlink + +cp: + python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) cp + +rm: + python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) rm + +copy: + $(PYEXE) $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) copy + +del: + $(PYEXE) $(BOOST_WIN)\libs\python\build\filemgr.py $(BOOST_WIN) del diff --git a/build/win32_mwcc_setup.bat b/build/win32_mwcc_setup.bat new file mode 100755 index 00000000..d42a60cf --- /dev/null +++ b/build/win32_mwcc_setup.bat @@ -0,0 +1,2 @@ +"c:\program files\metrowerks\codewarrior\other metrowerks tools\command line tools\cwenv.bat" +set MWWinx86LibraryFiles=MSL_All-DLL_x86.lib;gdi32.lib;user32.lib;kernel32.lib From 3a86a69964fb3d53f7672861c4ac7d160ae78342 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 15 Dec 2001 04:59:11 +0000 Subject: [PATCH 162/369] Restore Python <2.2 compatibility (config.h, pyconfig.h). [SVN r12064] --- include/boost/python/detail/wrap_python.hpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/include/boost/python/detail/wrap_python.hpp b/include/boost/python/detail/wrap_python.hpp index 1ad88ab6..b6e23b66 100644 --- a/include/boost/python/detail/wrap_python.hpp +++ b/include/boost/python/detail/wrap_python.hpp @@ -72,11 +72,19 @@ typedef int pid_t; # define _MSC_VER 900 # endif -# include +# if PY_MAJOR_VERSION < 2 || PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 2 +# include +# else +# include +# endif # undef hypot // undo the evil #define left by Python. # elif defined(__BORLANDC__) -# include +# if PY_MAJOR_VERSION < 2 || PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 2 +# include +# else +# include +# endif # undef HAVE_HYPOT # define HAVE_HYPOT 1 # elif defined(_MSC_VER) From 5134fb2ec18a96bd9735c39873b0ba670627f1e2 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 15 Dec 2001 22:59:48 +0000 Subject: [PATCH 163/369] scott snyder's fixes to maintain 1.5.2 compatibility [SVN r12065] --- src/types.cpp | 10 ++---- test/comprehensive.py | 84 +++++++++++++++++++++++-------------------- 2 files changed, 49 insertions(+), 45 deletions(-) diff --git a/src/types.cpp b/src/types.cpp index fe108225..c7e1f167 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -566,18 +566,12 @@ bool add_capability_richcompare(type_object_base::capability capability, PyTypeO return false; } -#if PYTHON_API_VERSION >= 1010 -# define ENABLE_INPLACE_CAPABILITY1 \ - dest->tp_flags |= Py_TPFLAGS_HAVE_INPLACEOPS; -#else -# define ENABLE_INPLACE_CAPABILITY1 -#endif #define ENABLE_INPLACE_CAPABILITY(field) \ case type_object_base::number_##field: \ create_method_table_if_null(dest->tp_as_number); \ dest->tp_as_number->nb_##field = &do_instance_nb_##field; \ detail::shared_pod_manager::replace_if_equal(dest->tp_as_number); \ - ENABLE_INPLACE_CAPABILITY1 \ + dest->tp_flags |= Py_TPFLAGS_HAVE_INPLACEOPS; \ return true bool add_capability_inplace(type_object_base::capability capability, PyTypeObject* dest) @@ -585,6 +579,7 @@ bool add_capability_inplace(type_object_base::capability capability, PyTypeObjec assert(dest != 0); switch (capability) { +#if PYTHON_API_VERSION >= 1010 ENABLE_INPLACE_CAPABILITY (inplace_add); ENABLE_INPLACE_CAPABILITY (inplace_subtract); ENABLE_INPLACE_CAPABILITY (inplace_multiply); @@ -596,6 +591,7 @@ bool add_capability_inplace(type_object_base::capability capability, PyTypeObjec ENABLE_INPLACE_CAPABILITY (inplace_and); ENABLE_INPLACE_CAPABILITY (inplace_or); ENABLE_INPLACE_CAPABILITY (inplace_xor); +#endif default: return false; } diff --git a/test/comprehensive.py b/test/comprehensive.py index b4ae5679..c49a4add 100644 --- a/test/comprehensive.py +++ b/test/comprehensive.py @@ -334,7 +334,8 @@ Special member attributes. Tests courtesy of Barry Scott >> import sys - >>> if sys.version_info[0] < 2 or ( sys.version_info[0] == 2 and + >>> if not sys.__dict__.has_key('version_info') or \ + ... sys.version_info[0] < 2 or ( sys.version_info[0] == 2 and ... sys.version_info[1] < 2 ): ... assert dir(df) == [] ... assert dir(db) == [] @@ -1069,43 +1070,6 @@ test inheritB2 Traceback (innermost last): TypeError: bad operand type(s) for pow() - >>> ii = Int(1) - >>> ii += Int(2) - >>> ii.i() - 3 - >>> ii -= Int(1) - >>> ii.i() - 2 - >>> ii *= Int(3) - >>> ii.i() - 6 - >>> ii /= Int(2) - >>> ii.i() - 3 - >>> ii <<= Int(2) - >>> ii.i() - 12 - >>> ii >>= Int(1) - >>> ii.i() - 6 - >>> ii &= Int(5) - >>> ii.i() - 4 - >>> ii |= Int(9) - >>> ii.i() - 13 - >>> ii ^= Int(7) - >>> ii.i() - 10 - >>> ii %= Int(4) - >>> ii.i() - 2 - >>> ii **= Int(3) - >>> ii.i() - 8 - >>> ii.j() - 11 - Test operator export to a subclass # force method table sharing @@ -1226,6 +1190,50 @@ test methodologies for wrapping functions that return a pointer ''' #' +__test__ = {} +import sys + +# Inplace ops only exist in python 2.1 or later. +if sys.hexversion >= 0x02010000: + __test__['inplacetests'] = r''' + >>> ii = Int(1) + >>> ii += Int(2) + >>> ii.i() + 3 + >>> ii -= Int(1) + >>> ii.i() + 2 + >>> ii *= Int(3) + >>> ii.i() + 6 + >>> ii /= Int(2) + >>> ii.i() + 3 + >>> ii <<= Int(2) + >>> ii.i() + 12 + >>> ii >>= Int(1) + >>> ii.i() + 6 + >>> ii &= Int(5) + >>> ii.i() + 4 + >>> ii |= Int(9) + >>> ii.i() + 13 + >>> ii ^= Int(7) + >>> ii.i() + 10 + >>> ii %= Int(4) + >>> ii.i() + 2 + >>> ii **= Int(3) + >>> ii.i() + 8 + >>> ii.j() + 11 +''' + from boost_python_test import * # pickle requires these derived classes to be From f9e6933840ffe0af5049eae3dcb73633ec8cce33 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 16 Dec 2001 06:00:03 +0000 Subject: [PATCH 164/369] Use "call", otherwise the "set" command is not executed. [SVN r12066] --- build/win32_mwcc_setup.bat | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/win32_mwcc_setup.bat b/build/win32_mwcc_setup.bat index d42a60cf..30f84be8 100755 --- a/build/win32_mwcc_setup.bat +++ b/build/win32_mwcc_setup.bat @@ -1,2 +1,2 @@ -"c:\program files\metrowerks\codewarrior\other metrowerks tools\command line tools\cwenv.bat" -set MWWinx86LibraryFiles=MSL_All-DLL_x86.lib;gdi32.lib;user32.lib;kernel32.lib +call "c:\program files\metrowerks\codewarrior\other metrowerks tools\command line tools\cwenv.bat" +set MWWinx86LibraryFiles=MSL_All-DLL_x86.lib;gdi32.lib;user32.lib;kernel32.lib From e65ca4ccac7bfa510f10d011d85502c108b1b64d Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 16 Dec 2001 17:58:23 +0000 Subject: [PATCH 165/369] Python 1.5 compatibility fixes [SVN r12072] --- test/comprehensive.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/comprehensive.cpp b/test/comprehensive.cpp index 61f56407..d25b131a 100644 --- a/test/comprehensive.cpp +++ b/test/comprehensive.cpp @@ -1093,6 +1093,7 @@ void init_module(boost::python::module_builder& m) // export non-operator function as heterogeneous reverse-argument operator int_class.def(&rmul, "__rmul__"); +#if PYTHON_API_VERSION >= 1010 // inplace operators. int_class.def(&int_iadd, "__iadd__"); int_class.def(&int_isub, "__isub__"); @@ -1105,6 +1106,7 @@ void init_module(boost::python::module_builder& m) int_class.def(&int_iand, "__iand__"); int_class.def(&int_ior, "__ior__"); int_class.def(&int_ixor, "__ixor__"); +#endif boost::python::class_builder enum_owner(m, "EnumOwner"); From bed2c8a371b2e181c5215604629abb641b9751df Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 16 Dec 2001 18:20:26 +0000 Subject: [PATCH 166/369] no message [SVN r12076] --- include/boost/python/detail/config.hpp | 12 +++++++----- include/boost/python/detail/wrap_python.hpp | 8 +++++--- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/include/boost/python/detail/config.hpp b/include/boost/python/detail/config.hpp index f814aba0..ff22e78e 100644 --- a/include/boost/python/detail/config.hpp +++ b/include/boost/python/detail/config.hpp @@ -57,10 +57,12 @@ # define BOOST_CSTD_ std # endif -#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 +# 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_ diff --git a/include/boost/python/detail/wrap_python.hpp b/include/boost/python/detail/wrap_python.hpp index b6e23b66..34a9c2b5 100644 --- a/include/boost/python/detail/wrap_python.hpp +++ b/include/boost/python/detail/wrap_python.hpp @@ -72,7 +72,7 @@ typedef int pid_t; # define _MSC_VER 900 # endif -# if PY_MAJOR_VERSION < 2 || PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 2 +# if PY_MAJOR_VERSION < 2 || PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 2 # include # else # include @@ -80,7 +80,7 @@ typedef int pid_t; # 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 +# if PY_MAJOR_VERSION < 2 || PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 2 # include # else # include @@ -88,7 +88,9 @@ typedef int pid_t; # undef HAVE_HYPOT # define HAVE_HYPOT 1 # elif defined(_MSC_VER) -# include // prevents Python.h from defining LONGLONG_MAX, LONGLONG_MIN, and ULONGLONG_MAX +# ifdef __cplusplus +# include // prevents Python.h from defining LONGLONG_MAX, LONGLONG_MIN, and ULONGLONG_MAX +# endif # endif #endif // _WIN32 From 291c36df05902fd1d73cd6131ba42c17f592b4fe Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 17 Dec 2001 05:49:24 +0000 Subject: [PATCH 167/369] Integrated Scott Snyder's nested class patch [SVN r12080] --- doc/exporting_classes.html | 6 ++++++ include/boost/python/class_builder.hpp | 16 ++++++++++++++++ test/comprehensive.cpp | 20 ++++++++++++++++++++ test/comprehensive.hpp | 4 ++++ test/comprehensive.py | 10 +++++++++- 5 files changed, 55 insertions(+), 1 deletion(-) diff --git a/doc/exporting_classes.html b/doc/exporting_classes.html index e5932e70..61c5ef88 100644 --- a/doc/exporting_classes.html +++ b/doc/exporting_classes.html @@ -98,6 +98,12 @@ Notes:
    • Any function added to a class whose initial argument matches the class (or any base) will act like a member function in Python. + +
    • To define a nested class, just pass the enclosing +class_builder (instead of a module_builder) as the +first argument to the nested class_builder's constructor. + +

    We can even make a subclass of hello.world: diff --git a/include/boost/python/class_builder.hpp b/include/boost/python/class_builder.hpp index 4a9ec1b2..fe2a7b74 100644 --- a/include/boost/python/class_builder.hpp +++ b/include/boost/python/class_builder.hpp @@ -25,6 +25,22 @@ class class_builder module.add(ref(as_object(m_class.get()), ref::increment_count), name); } + template + class_builder(class_builder& cls, const char* name) + : m_class(new detail::extension_class(name)) + { + cls.add(ref(as_object(m_class.get()), ref::increment_count), name); + } + + template + class_builder(detail::extension_class* cls, + const char* name) + : m_class(new detail::extension_class(name)) + { + cls->set_attribute(name, + ref(as_object(m_class.get()), ref::increment_count)); + } + ~class_builder() {} diff --git a/test/comprehensive.cpp b/test/comprehensive.cpp index d25b131a..6c7cc4d3 100644 --- a/test/comprehensive.cpp +++ b/test/comprehensive.cpp @@ -67,6 +67,16 @@ Foo::PythonClass::PythonClass(boost::python::module_builder& m) def(&Foo::add_len, "add_len", &FooCallback::default_add_len); // Since pure() is pure virtual, we are leaving it undefined. + + // And the nested classes. + boost::python::class_builder foo_a(*this, "Foo_A"); + foo_a.def(boost::python::constructor<>()); + foo_a.def(&Foo::Foo_A::mumble, "mumble"); + + boost::python::class_builder foo_b(get_extension_class(), + "Foo_B"); + foo_b.def(boost::python::constructor<>()); + foo_b.def(&Foo::Foo_B::mumble, "mumble"); } BarPythonClass::BarPythonClass(boost::python::module_builder& m) @@ -223,6 +233,16 @@ const char* Foo::mumble() return "mumble"; } +const char* Foo::Foo_A::mumble() +{ + return "mumble a"; +} + +const char* Foo::Foo_B::mumble() +{ + return "mumble b"; +} + void Foo::set(long x) { m_x = x; diff --git a/test/comprehensive.hpp b/test/comprehensive.hpp index ed90f061..deb68a88 100644 --- a/test/comprehensive.hpp +++ b/test/comprehensive.hpp @@ -42,6 +42,10 @@ class Foo // prohibit copying, proving that it doesn't choke std::string call_pure(); // call a pure virtual fuction int call_add_len(const char* s) const; // virtual function with a default implementation + // A couple nested classs. + struct Foo_A { const char* mumble(); }; + struct Foo_B { const char* mumble(); }; + private: // by default, sum the held value and the length of s virtual int add_len(const char* s) const; diff --git a/test/comprehensive.py b/test/comprehensive.py index c49a4add..7d0bec79 100644 --- a/test/comprehensive.py +++ b/test/comprehensive.py @@ -230,6 +230,14 @@ Polymorphism also works: >>> baz.get_foo_value(polymorphic_foo) 1000 +Simple nested class test: + >>> foo_a = Foo.Foo_A() + >>> foo_a.mumble() + 'mumble a' + >>> foo_b = Foo.Foo_B() + >>> foo_b.mumble() + 'mumble b' + Pickling tests: >>> world.__module__ @@ -343,7 +351,7 @@ Special member attributes. Tests courtesy of Barry Scott Date: Mon, 17 Dec 2001 16:59:54 +0000 Subject: [PATCH 168/369] Integrating Andreas Zieringer's shared library implementation. Modified Files: classes.hpp conversions.hpp cross_module.hpp errors.hpp module_builder.hpp objects.hpp operators.hpp detail/config.hpp detail/extension_class.hpp detail/functions.hpp detail/init_function.hpp detail/signatures.hpp detail/singleton.hpp detail/types.hpp detail/void_adaptor.hpp [SVN r12083] --- include/boost/python/detail/config.hpp | 64 +++++++++++++++++++ .../boost/python/detail/extension_class.hpp | 22 +++---- include/boost/python/detail/functions.hpp | 4 +- include/boost/python/detail/init_function.hpp | 2 +- include/boost/python/detail/signatures.hpp | 2 +- include/boost/python/detail/singleton.hpp | 2 +- include/boost/python/detail/types.hpp | 6 +- include/boost/python/detail/void_adaptor.hpp | 2 +- 8 files changed, 84 insertions(+), 20 deletions(-) diff --git a/include/boost/python/detail/config.hpp b/include/boost/python/detail/config.hpp index ff22e78e..0fc1093a 100644 --- a/include/boost/python/detail/config.hpp +++ b/include/boost/python/detail/config.hpp @@ -65,4 +65,68 @@ # endif # endif +/***************************************************************************** + * + * Set up dll import/export options: + * + ****************************************************************************/ + +// backwards compatibility: +#ifdef BOOST_RE_STATIC_LIB +# define BOOST_PYTHON_STATIC_LINK +#endif + +#if defined(BOOST_MSVC) && defined(_DLL) +# define BOOST_PYTHON_HAS_DLL_RUNTIME +#endif + +#if defined(__BORLANDC__) && defined(_RTLDLL) +# define BOOST_PYTHON_HAS_DLL_RUNTIME +#endif + +#if defined(__ICL) && defined(_DLL) +# define BOOST_PYTHON_HAS_DLL_RUNTIME +#endif + +#if defined(BOOST_PYTHON_HAS_DLL_RUNTIME) && !defined(BOOST_PYTHON_STATIC_LINK) +# if defined(BOOST_PYTHON_SOURCE) +# define BOOST_PYTHON_DECL __declspec(dllexport) +# define BOOST_PYTHON_BUILD_DLL +# else +# define BOOST_PYTHON_DECL __declspec(dllimport) +# endif +#endif + +#ifndef BOOST_PYTHON_DECL +# define BOOST_PYTHON_DECL +#endif + +#if (defined(BOOST_MSVC) || defined(__BORLANDC__)) && !defined(BOOST_PYTHON_NO_LIB) && !defined(BOOST_PYTHON_SOURCE) +# include +#endif + +// Borland C++ Fix/error check: +#if defined(__BORLANDC__) +# if (__BORLANDC__ == 0x550) || (__BORLANDC__ == 0x551) + // problems with std::basic_string and dll RTL: +# if defined(_RTLDLL) && defined(_RWSTD_COMPILE_INSTANTIATE) +# ifdef BOOST_PYTHON_BUILD_DLL +# error _RWSTD_COMPILE_INSTANTIATE must not be defined when building regex++ as a DLL +# else +# pragma warn defining _RWSTD_COMPILE_INSTANTIATE when linking to the DLL version of the RTL may produce memory corruption problems in std::basic_string, as a result of separate versions of basic_string's static data in the RTL and you're exe/dll: be warned!! +# endif +# endif +# ifndef _RTLDLL + // this is harmless for a staic link: +# define _RWSTD_COMPILE_INSTANTIATE +# endif +# endif + // + // VCL support: + // if we're building a console app then there can't be any VCL (can there?) +# if !defined(__CONSOLE__) && !defined(_NO_VCL) +# define BOOST_PYTHON_USE_VCL +# endif +#endif + #endif // CONFIG_DWA052200_H_ diff --git a/include/boost/python/detail/extension_class.hpp b/include/boost/python/detail/extension_class.hpp index f7be9afb..00f9b6b4 100644 --- a/include/boost/python/detail/extension_class.hpp +++ b/include/boost/python/detail/extension_class.hpp @@ -52,12 +52,12 @@ template struct operand_select; template struct choose_unary_op; template struct define_operator; -meta_class* extension_meta_class(); -extension_instance* get_extension_instance(PyObject* p); -void report_missing_instance_data(extension_instance*, class_t*, const std::type_info&); -void report_missing_ptr_data(extension_instance*, class_t*, const std::type_info&); -void report_missing_class_object(const std::type_info&); -void report_released_smart_pointer(const std::type_info&); +BOOST_PYTHON_DECL meta_class* extension_meta_class(); +BOOST_PYTHON_DECL extension_instance* get_extension_instance(PyObject* p); +BOOST_PYTHON_DECL void report_missing_instance_data(extension_instance*, class_t*, const std::type_info&); +BOOST_PYTHON_DECL void report_missing_ptr_data(extension_instance*, class_t*, const std::type_info&); +BOOST_PYTHON_DECL void report_missing_class_object(const std::type_info&); +BOOST_PYTHON_DECL void report_released_smart_pointer(const std::type_info&); template T* check_non_null(T* p) @@ -71,7 +71,7 @@ template class held_instance; typedef void* (*conversion_function_ptr)(void*); -struct base_class_info +struct BOOST_PYTHON_DECL base_class_info { base_class_info(extension_class_base* t, conversion_function_ptr f) :class_object(t), convert(f) @@ -85,7 +85,7 @@ typedef base_class_info derived_class_info; struct add_operator_base; -class extension_class_base : public class_t +class BOOST_PYTHON_DECL extension_class_base : public class_t { public: extension_class_base(const char* name); @@ -378,7 +378,7 @@ namespace detail { template class instance_holder; -class read_only_setattr_function : public function +class BOOST_PYTHON_DECL read_only_setattr_function : public function { public: read_only_setattr_function(const char* name); @@ -725,7 +725,7 @@ public: // Abstract base class for all obj holders. Base for template class // instance_holder<>, below. -class instance_holder_base +class BOOST_PYTHON_DECL instance_holder_base { public: virtual ~instance_holder_base() {} @@ -813,7 +813,7 @@ class instance_ptr_holder : public instance_holder PtrType m_ptr; }; -class extension_instance : public instance +class BOOST_PYTHON_DECL extension_instance : public instance { public: extension_instance(PyTypeObject* class_); diff --git a/include/boost/python/detail/functions.hpp b/include/boost/python/detail/functions.hpp index eff05d65..486d73f9 100644 --- a/include/boost/python/detail/functions.hpp +++ b/include/boost/python/detail/functions.hpp @@ -29,7 +29,7 @@ class extension_instance; // function -- // the common base class for all overloadable function and method objects // supplied by the library. -class function : public python_object +class BOOST_PYTHON_DECL function : public python_object { public: function(); @@ -201,7 +201,7 @@ inline function* new_virtual_function( // 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 +class BOOST_PYTHON_DECL bound_function : public python_object { public: static bound_function* create(const ref& target, const ref& fn); diff --git a/include/boost/python/detail/init_function.hpp b/include/boost/python/detail/init_function.hpp index c0c50272..69df703d 100644 --- a/include/boost/python/detail/init_function.hpp +++ b/include/boost/python/detail/init_function.hpp @@ -230,7 +230,7 @@ struct init_function } }; -class init : public function +class BOOST_PYTHON_DECL init : public function { private: // override function hook PyObject* do_call(PyObject* args, PyObject* keywords) const; diff --git a/include/boost/python/detail/signatures.hpp b/include/boost/python/detail/signatures.hpp index 2be75b52..e216f688 100644 --- a/include/boost/python/detail/signatures.hpp +++ b/include/boost/python/detail/signatures.hpp @@ -17,7 +17,7 @@ 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 {}; +struct BOOST_PYTHON_DECL void_t {}; } // An envelope in which type information can be delivered for the purposes diff --git a/include/boost/python/detail/singleton.hpp b/include/boost/python/detail/singleton.hpp index 07d794ac..3e7d91af 100644 --- a/include/boost/python/detail/singleton.hpp +++ b/include/boost/python/detail/singleton.hpp @@ -13,7 +13,7 @@ namespace boost { namespace python { namespace detail { -struct empty {}; +struct BOOST_PYTHON_DECL empty {}; template struct singleton : Base { diff --git a/include/boost/python/detail/types.hpp b/include/boost/python/detail/types.hpp index 954e0213..f4e62f88 100644 --- a/include/boost/python/detail/types.hpp +++ b/include/boost/python/detail/types.hpp @@ -37,7 +37,7 @@ namespace detail { class instance_holder_base; -class type_object_base : public python_type +class BOOST_PYTHON_DECL type_object_base : public python_type { public: explicit type_object_base(PyTypeObject* type_type); @@ -327,7 +327,7 @@ PyObject* reprable::instance_repr(PyObject* obj) const // 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 + class BOOST_PYTHON_DECL shared_pod_manager { typedef std::pair holder; typedef std::vector storage; @@ -394,7 +394,7 @@ PyObject* reprable::instance_repr(PyObject* obj) const }; - void add_capability(type_object_base::capability capability, + BOOST_PYTHON_DECL 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 diff --git a/include/boost/python/detail/void_adaptor.hpp b/include/boost/python/detail/void_adaptor.hpp index c2ecc2b0..3d60e4bf 100644 --- a/include/boost/python/detail/void_adaptor.hpp +++ b/include/boost/python/detail/void_adaptor.hpp @@ -8,7 +8,7 @@ namespace boost { namespace python { namespace detail { - extern PyObject arbitrary_object; + BOOST_PYTHON_DECL extern PyObject arbitrary_object; template struct void_adaptor From d4b215a66b1e2c6f18df61ae2e5d79ce66a146f0 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 17 Dec 2001 17:00:53 +0000 Subject: [PATCH 169/369] Integrating Andreas Zieringer's shared lib changes Modified Files: build/Jamfile build/win32_mwcc_setup.bat src/classes.cpp src/conversions.cpp src/cross_module.cpp src/extension_class.cpp src/functions.cpp src/init_function.cpp src/module_builder.cpp src/objects.cpp src/types.cpp [SVN r12084] --- build/Jamfile | 8 +++++++- src/classes.cpp | 2 ++ src/conversions.cpp | 2 ++ src/cross_module.cpp | 2 ++ src/extension_class.cpp | 2 ++ src/functions.cpp | 2 ++ src/init_function.cpp | 2 ++ src/module_builder.cpp | 2 ++ src/objects.cpp | 2 ++ src/types.cpp | 2 ++ 10 files changed, 25 insertions(+), 1 deletion(-) diff --git a/build/Jamfile b/build/Jamfile index c56bf47c..78d1e84a 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -84,7 +84,13 @@ lib libboost_python : ../src/$(CPP_SOURCES).cpp true $(PYTHON_PROPERTIES) ; - +dll libboost_python$(SUFDLL[1]) : ../src/$(CPP_SOURCES).cpp + # requirements + : $(BOOST_PYTHON_INCLUDES) + true + BOOST_RE_BUILD_DLL=1 + $(PYTHON_PROPERTIES) ; + ############# comprehensive module and test ########### bpl-test boost_python_test : ../test/comprehensive.cpp ; diff --git a/src/classes.cpp b/src/classes.cpp index 75f8a01a..c721ef5c 100644 --- a/src/classes.cpp +++ b/src/classes.cpp @@ -11,6 +11,8 @@ // 03 Mar 01 added: pickle safety measures (Ralf W. Grosse-Kunstleve) // 03 Mar 01 bug fix: use bound_function::create() (instead of new bound_function) +#define BOOST_PYTHON_SOURCE + #include #include #include diff --git a/src/conversions.cpp b/src/conversions.cpp index c986f57b..f1534dd9 100644 --- a/src/conversions.cpp +++ b/src/conversions.cpp @@ -13,6 +13,8 @@ // 04 Mar 01 std::complex<> fixes for MSVC (Dave Abrahams) // 03 Mar 01 added: converters for [plain] char (Ralf W. Grosse-Kunstleve) +#define BOOST_PYTHON_SOURCE + #include #include #include diff --git a/src/cross_module.cpp b/src/cross_module.cpp index ea5a08de..5949be4d 100644 --- a/src/cross_module.cpp +++ b/src/cross_module.cpp @@ -8,6 +8,8 @@ 17 Apr 01 merged into boost CVS trunk (Ralf W. Grosse-Kunstleve) */ +#define BOOST_PYTHON_SOURCE + # include namespace python = boost::python; # include // MSVC6.0SP4 does not know std::fprintf diff --git a/src/extension_class.cpp b/src/extension_class.cpp index 3815a19c..e9183c82 100644 --- a/src/extension_class.cpp +++ b/src/extension_class.cpp @@ -9,6 +9,8 @@ // Revision History: // 04 Mar 01 Use PyObject_INIT() instead of trying to hand-initialize (David Abrahams) +#define BOOST_PYTHON_SOURCE + #include #include #include diff --git a/src/functions.cpp b/src/functions.cpp index a04e2e51..ecbacf4e 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -9,6 +9,8 @@ // Revision History: // Mar 01 01 Use PyObject_INIT() instead of trying to hand-initialize (David Abrahams) +#define BOOST_PYTHON_SOURCE + #include #include #include diff --git a/src/init_function.cpp b/src/init_function.cpp index 1667724c..1ebfa501 100644 --- a/src/init_function.cpp +++ b/src/init_function.cpp @@ -6,6 +6,8 @@ // The author gratefully acknowleges the support of Dragon Systems, Inc., in // producing this work. +#define BOOST_PYTHON_SOURCE + #include #include #include diff --git a/src/module_builder.cpp b/src/module_builder.cpp index 57eec75f..bd04a89c 100644 --- a/src/module_builder.cpp +++ b/src/module_builder.cpp @@ -6,6 +6,8 @@ // The author gratefully acknowleges the support of Dragon Systems, Inc., in // producing this work. +#define BOOST_PYTHON_SOURCE + #include namespace boost { namespace python { diff --git a/src/objects.cpp b/src/objects.cpp index 125a1eb8..70257388 100644 --- a/src/objects.cpp +++ b/src/objects.cpp @@ -8,6 +8,8 @@ // TODO: Move inline implementations from objects.cpp here +#define BOOST_PYTHON_SOURCE + #include #include diff --git a/src/types.cpp b/src/types.cpp index c7e1f167..f411aa42 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -6,6 +6,8 @@ // The author gratefully acknowleges the support of Dragon Systems, Inc., in // producing this work. +#define BOOST_PYTHON_SOURCE + #include #include // for handle_exception() #include From 460f3aebe9a68918fae1e328b85712cbea91ce3a Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 17 Dec 2001 17:24:41 +0000 Subject: [PATCH 170/369] inital checkin [SVN r12086] --- .../python/detail/python_library_include.hpp | 182 ++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 include/boost/python/detail/python_library_include.hpp diff --git a/include/boost/python/detail/python_library_include.hpp b/include/boost/python/detail/python_library_include.hpp new file mode 100644 index 00000000..903f02be --- /dev/null +++ b/include/boost/python/detail/python_library_include.hpp @@ -0,0 +1,182 @@ +/* + * + * Copyright (c) 1998-2000 + * Dr John Maddock + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Dr John Maddock makes no representations + * about the suitability of this software for any purpose. + * It is provided "as is" without express or implied warranty. + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_libary_include.hpp + * VERSION see + * DESCRIPTION: Automatic library inclusion for Borland/Microsoft compilers. + * Note this is an internal header file included + * by regex.hpp, do not include on its own. + */ + + +#ifndef BOOST_REGEX_LIBRARY_INCLUDE_HPP +#define BOOST_REGEX_LIBRARY_INCLUDE_HPP +#ifndef BOOST_REGEX_NO_LIB + +#if defined(BOOST_MSVC) && !defined(BOOST_REGEX_BUILD_DLL) +#ifdef __SGI_STL_PORT + #ifdef _DLL + // All these are multithreaded: + #if defined(_DEBUG) && defined(__STL_DEBUG) + #pragma comment(lib, "vc6-stlport-re300ddl.lib") + #elif defined(_DEBUG) + #pragma comment(lib, "vc6-stlport-re300dl.lib") + #elif defined(BOOST_REGEX_STATIC_LINK) + // static regex lib, dll runtime + #pragma comment(lib, "vc6-stlport-re300ls.lib") + #else // DEBUG + #pragma comment(lib, "vc6-stlport-re300l.lib") + #endif // _DEBUG + #else // _DLL + #ifdef _MT + #if defined(_DEBUG) && defined(__STL_DEBUG) + #pragma comment(lib, "vc6-stlport-re300ddm.lib") + #elif defined(_DEBUG) + #pragma comment(lib, "vc6-stlport-re300dm.lib") + #else //_DEBUG + #pragma comment(lib, "vc6-stlport-re300m.lib") + #endif //_DEBUG + #else //_MT + // STLPort does not support single threaded builds: + #error STLPort does not support single threaded builds + #endif //_MT + #endif //_DLL +#elif _MSC_VER < 1300 + #ifdef _DLL + // All these are multithreaded: + #ifdef _DEBUG + #pragma comment(lib, "vc6-re300dl.lib") + #elif defined(BOOST_REGEX_STATIC_LINK) + // static regex lib, dll runtime + #pragma comment(lib, "vc6-re300ls.lib") + #else // DEBUG + #pragma comment(lib, "vc6-re300l.lib") + #endif // _DEBUG + #else // _DLL + #ifdef _MT + #ifdef _DEBUG + #pragma comment(lib, "vc6-re300dm.lib") + #else //_DEBUG + #pragma comment(lib, "vc6-re300m.lib") + #endif //_DEBUG + #else //_MT + #ifdef _DEBUG + #pragma comment(lib, "vc6-re300d.lib") + #else //_DEBUG + #pragma comment(lib, "vc6-re300.lib") + #endif //_DEBUG + #endif //_MT + #endif //_DLL +#else + #ifdef _DLL + // All these are multithreaded: + #ifdef _DEBUG + #pragma comment(lib, "vc7-re300dl.lib") + #elif defined(BOOST_REGEX_STATIC_LINK) + // static regex lib, dll runtime + #pragma comment(lib, "vc7-re300ls.lib") + #else // DEBUG + #pragma comment(lib, "vc7-re300l.lib") + #endif // _DEBUG + #else // _DLL + #ifdef _MT + #ifdef _DEBUG + #pragma comment(lib, "vc7-re300dm.lib") + #else //_DEBUG + #pragma comment(lib, "vc7-re300m.lib") + #endif //_DEBUG + #else //_MT + #ifdef _DEBUG + #pragma comment(lib, "vc7-re300d.lib") + #else //_DEBUG + #pragma comment(lib, "vc7-re300.lib") + #endif //_DEBUG + #endif //_MT + #endif //_DLL +#endif // __SGI_STL_PORT +#endif //BOOST_MSVC + + +#if defined(__BORLANDC__) && !defined(BOOST_REGEX_BUILD_DLL) + + #if __BORLANDC__ < 0x550 + + #ifdef BOOST_REGEX_USE_VCL + + #ifdef _RTLDLL + #pragma comment(lib, "bcb4re300lv.lib") + #else + #pragma comment(lib, "bcb4re300v.lib") + #endif + + #else // VCL + + #ifdef _RTLDLL + #ifdef __MT__ + #pragma comment(lib, "bcb4re300lm.lib") + #else // __MT__ + #pragma comment(lib, "bcb4re300l.lib") + #endif // __MT__ + #else //_RTLDLL + #ifdef __MT__ + #pragma comment(lib, "bcb4re300m.lib") + #else // __MT__ + #pragma comment(lib, "bcb4re300.lib") + #endif // __MT__ + #endif // _RTLDLL + + #endif // VCL + + #else // C++ Builder 5: + + #ifdef BOOST_REGEX_USE_VCL + + #ifdef _RTLDLL + #pragma comment(lib, "bcb5re300lv.lib") + #else + #pragma comment(lib, "bcb5re300v.lib") + #endif + + #else // VCL + + #ifdef _RTLDLL + #ifdef __MT__ + #pragma comment(lib, "bcb5re300lm.lib") + #else // __MT__ + #pragma comment(lib, "bcb5re300l.lib") + #endif // __MT__ + #else //_RTLDLL + #ifdef __MT__ + #pragma comment(lib, "bcb5re300m.lib") + #else // __MT__ + #pragma comment(lib, "bcb5re300.lib") + #endif // __MT__ + #endif // _RTLDLL + + #endif // VCL + + #endif + +#endif //__BORLANDC__ + +#endif //BOOST_REGEX_NO_LIB + +#endif // BOOST_REGEX_LIBRARY_INCLUDE_HPP + + + + From c494649ddef5160217f8a2aa5ba3134130e136c9 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 18 Dec 2001 21:00:07 +0000 Subject: [PATCH 171/369] fix a bug with instance::power reported by Scott Snyder. [SVN r12119] --- src/classes.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/classes.cpp b/src/classes.cpp index c721ef5c..f51d1a2f 100644 --- a/src/classes.cpp +++ b/src/classes.cpp @@ -11,8 +11,6 @@ // 03 Mar 01 added: pickle safety measures (Ralf W. Grosse-Kunstleve) // 03 Mar 01 bug fix: use bound_function::create() (instead of new bound_function) -#define BOOST_PYTHON_SOURCE - #include #include #include @@ -645,7 +643,7 @@ PyObject* instance::divmod(PyObject* other) PyObject* instance::power(PyObject* exponent, PyObject* modulus) { - if (as_object(modulus->ob_type) == Py_None) + if (as_object(modulus) == Py_None) return callback::call_method(this, "__pow__", exponent); else return callback::call_method(this, "__pow__", exponent, modulus); From 1f78c7408592a4ce634bc7268c5a910b6e0c6b05 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 24 Dec 2001 19:27:39 +0000 Subject: [PATCH 172/369] fixes [SVN r12146] --- Jamfile | 39 + build/Jamfile | 22 +- doc/new-conversions.html | 326 +++++++ doc/new-conversions.txt | 111 +++ example/simple_vector.cpp | 2 +- include/boost/python/call.hpp | 210 +++++ include/boost/python/classes.hpp | 6 +- include/boost/python/conversions.hpp | 53 +- include/boost/python/convert.hpp | 84 ++ include/boost/python/converter/body.hpp | 68 ++ include/boost/python/converter/class.hpp | 56 ++ include/boost/python/converter/handle.hpp | 91 ++ .../boost/python/converter/registration.hpp | 83 ++ include/boost/python/converter/registry.hpp | 74 ++ include/boost/python/converter/source.hpp | 80 ++ .../boost/python/converter/source_holder.hpp | 24 + include/boost/python/converter/target.hpp | 173 ++++ include/boost/python/converter/type_id.hpp | 200 +++++ include/boost/python/converter/unwrap.hpp | 192 ++++ include/boost/python/converter/unwrapper.hpp | 53 ++ .../boost/python/converter/unwrapper_base.hpp | 25 + include/boost/python/converter/wrap.hpp | 145 +++ include/boost/python/converter/wrapper.hpp | 69 ++ include/boost/python/cross_module.hpp | 110 +-- .../boost/python/detail/arg_tuple_size.hpp | 233 +++++ include/boost/python/detail/base_object.hpp | 6 +- include/boost/python/detail/call_object.hpp | 66 ++ include/boost/python/detail/caller.hpp | 27 + include/boost/python/detail/config.hpp | 18 +- .../python/detail/python_library_include.hpp | 1 + include/boost/python/detail/returning.hpp | 846 ++++++++++++++++++ include/boost/python/detail/types.hpp | 4 - include/boost/python/detail/void_adaptor.hpp | 2 +- include/boost/python/detail/wrap_python.hpp | 46 +- include/boost/python/errors.hpp | 42 +- include/boost/python/export.hpp | 20 + include/boost/python/make_function.hpp | 40 + include/boost/python/module.hpp | 12 + include/boost/python/module_builder.hpp | 39 +- include/boost/python/object/class.hpp | 103 +++ .../boost/python/object/class_unwrapper.hpp | 40 + include/boost/python/object/construct.hpp | 24 + include/boost/python/object/forward.hpp | 33 + include/boost/python/object/function.hpp | 36 + include/boost/python/object/make_holder.hpp | 124 +++ include/boost/python/object/value_holder.hpp | 80 ++ include/boost/python/objects.hpp | 223 +++-- include/boost/python/operators.hpp | 2 +- src/classes.cpp | 4 +- src/conversions.cpp | 99 +- src/converter/body.cpp | 18 + src/converter/handle.cpp | 35 + src/converter/registry.cpp | 177 ++++ src/converter/type_id.cpp | 67 ++ src/converter/unwrap.cpp | 35 + src/converter/unwrapper.cpp | 24 + src/converter/wrapper.cpp | 30 + src/cross_module.cpp | 117 +-- src/errors.cpp | 68 ++ src/extension_class.cpp | 25 +- src/gen_call.py | 82 ++ src/gen_returning.py | 191 ++++ src/module_builder.cpp | 16 +- src/object/class.cpp | 165 ++++ src/object/function.cpp | 95 ++ src/objects.cpp | 126 +-- src/types.cpp | 126 +-- test/complicated.hpp | 39 + test/m1.cpp | 281 ++++++ test/m2.cpp | 197 ++++ test/module_tail.cpp | 39 + test/newtest.py | 95 ++ test/simple_type.hpp | 14 + 73 files changed, 5947 insertions(+), 581 deletions(-) create mode 100644 Jamfile create mode 100644 doc/new-conversions.html create mode 100644 doc/new-conversions.txt create mode 100644 include/boost/python/call.hpp create mode 100644 include/boost/python/convert.hpp create mode 100644 include/boost/python/converter/body.hpp create mode 100644 include/boost/python/converter/class.hpp create mode 100644 include/boost/python/converter/handle.hpp create mode 100644 include/boost/python/converter/registration.hpp create mode 100644 include/boost/python/converter/registry.hpp create mode 100644 include/boost/python/converter/source.hpp create mode 100644 include/boost/python/converter/source_holder.hpp create mode 100644 include/boost/python/converter/target.hpp create mode 100644 include/boost/python/converter/type_id.hpp create mode 100644 include/boost/python/converter/unwrap.hpp create mode 100644 include/boost/python/converter/unwrapper.hpp create mode 100644 include/boost/python/converter/unwrapper_base.hpp create mode 100644 include/boost/python/converter/wrap.hpp create mode 100644 include/boost/python/converter/wrapper.hpp create mode 100644 include/boost/python/detail/arg_tuple_size.hpp create mode 100644 include/boost/python/detail/call_object.hpp create mode 100644 include/boost/python/detail/caller.hpp create mode 100644 include/boost/python/detail/returning.hpp create mode 100644 include/boost/python/export.hpp create mode 100644 include/boost/python/make_function.hpp create mode 100644 include/boost/python/module.hpp create mode 100644 include/boost/python/object/class.hpp create mode 100644 include/boost/python/object/class_unwrapper.hpp create mode 100644 include/boost/python/object/construct.hpp create mode 100644 include/boost/python/object/forward.hpp create mode 100644 include/boost/python/object/function.hpp create mode 100644 include/boost/python/object/make_holder.hpp create mode 100644 include/boost/python/object/value_holder.hpp create mode 100644 src/converter/body.cpp create mode 100644 src/converter/handle.cpp create mode 100644 src/converter/registry.cpp create mode 100644 src/converter/type_id.cpp create mode 100644 src/converter/unwrap.cpp create mode 100644 src/converter/unwrapper.cpp create mode 100644 src/converter/wrapper.cpp create mode 100644 src/errors.cpp create mode 100644 src/gen_call.py create mode 100644 src/gen_returning.py create mode 100644 src/object/class.cpp create mode 100644 src/object/function.cpp create mode 100644 test/complicated.hpp create mode 100644 test/m1.cpp create mode 100644 test/m2.cpp create mode 100644 test/module_tail.cpp create mode 100644 test/newtest.py create mode 100644 test/simple_type.hpp diff --git a/Jamfile b/Jamfile new file mode 100644 index 00000000..18372684 --- /dev/null +++ b/Jamfile @@ -0,0 +1,39 @@ +subproject libs/python ; + +# bring in the rules for python +SEARCH on python.jam = $(BOOST_BUILD_PATH) ; +include python.jam ; + +PYTHON_PROPERTIES + += <*>"-inline deferred" + <*>$(BOOST_ROOT)/boost/compatibility/cpp_c_headers + BOOST_PYTHON_DYNAMIC_LIB + ; + + +dll bpl + : + src/converter/body.cpp + src/converter/handle.cpp + src/converter/registry.cpp + src/converter/wrapper.cpp + src/converter/unwrap.cpp + src/converter/unwrapper.cpp + src/converter/type_id.cpp + src/object/class.cpp + src/object/function.cpp + src/errors.cpp + : + $(PYTHON_PROPERTIES) + BOOST_PYTHON_SOURCE + ; + +extension m1 : test/m1.cpp bpl # BOOST_PYTHON_TRACE + : + : debug-python ; + +extension m2 : test/m2.cpp bpl # BOOST_PYTHON_TRACE + : + : debug-python ; + +boost-python-runtest try : test/newtest.py m1 m2 : : debug-python ; \ No newline at end of file diff --git a/build/Jamfile b/build/Jamfile index 78d1e84a..7fd8c285 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -61,6 +61,8 @@ subproject libs/python/build ; SEARCH on python.jam = $(BOOST_BUILD_PATH) ; include python.jam ; +local PYTHON_PROPERTIES = $(PYTHON_PROPERTIES) BOOST_PYTHON_DYNAMIC_LIB ; + ####################### local rule bpl-test ( test-name : sources + ) { @@ -75,21 +77,27 @@ local rule bpl-test ( test-name : sources + ) # 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 ; + types classes conversions extension_class functions + init_function module_builder objects cross_module errors + ; -lib libboost_python : ../src/$(CPP_SOURCES).cpp +lib libboost_python_static : ../src/$(CPP_SOURCES).cpp # requirements : $(BOOST_PYTHON_INCLUDES) true + BOOST_PYTHON_STATIC_LIB=1 $(PYTHON_PROPERTIES) ; -dll libboost_python$(SUFDLL[1]) : ../src/$(CPP_SOURCES).cpp +dll libboost_python + # $(SUFDLL[1]) + : ../src/$(CPP_SOURCES).cpp # requirements - : $(BOOST_PYTHON_INCLUDES) + : $(BOOST_PYTHON_INCLUDES) true - BOOST_RE_BUILD_DLL=1 - $(PYTHON_PROPERTIES) ; + dynamic + BOOST_PYTHON_HAS_DLL_RUNTIME=1 + $(PYTHON_PROPERTIES) + ; ############# comprehensive module and test ########### bpl-test boost_python_test diff --git a/doc/new-conversions.html b/doc/new-conversions.html new file mode 100644 index 00000000..cd8a5b19 --- /dev/null +++ b/doc/new-conversions.html @@ -0,0 +1,326 @@ + + + + +A New Type Conversion Mechanism for Boost.Python + + + + +

    + +

    A New Type Conversion Mechanism for Boost.Python

    + +

    By David Abrahams. + +

    Introduction

    + +This document describes a redesign of the mechanism for automatically +converting objects between C++ and Python. The current implementation +uses two functions for any type T: + +
    +U from_python(PyObject*, type<T>);
    +void to_python(V);
    +
    + +where U is convertible to T and T is convertible to V. These functions +are at the heart of C++/Python interoperability in Boost.Python, so +why would we want to change them? There are many reasons: + +

    Bugs

    +

    Firstly, the current mechanism relies on a common C++ compiler +bug. This is not just embarrassing: as compilers get to be more +conformant, the library stops working. The issue, in detail, is the +use of inline friend functions in templates to generate +conversions. It is a very powerful, and legal technique as long as +it's used correctly: + +

    +template <class Derived>
    +struct add_some_functions
    +{
    +     friend return-type some_function1(..., Derived cv-*-&-opt, ...);
    +     friend return-type some_function2(..., Derived cv-*-&-opt, ...);
    +};
    +
    +template <class T>
    +struct some_template : add_some_functions<some_template<T> >
    +{
    +};
    +
    + +The add_some_functions template generates free functions +which operate on Derived, or on related types. Strictly +speaking the related types are not just cv-qualified Derived +values, pointers and/or references. Section 3.4.2 in the standard +describes exactly which types you must use as parameters to these +functions if you want the functions to be found +(there is also a less-technical description in section 11.5.1 of +C++PL3 [1]). Suffice it to say that +with the current design, the from_python and +to_python functions are not supposed to be callable under any +conditions! + +

    Compilation and Linking Time

    + +The conversion functions generated for each wrapped class using the +above technique are not function templates, but regular functions. The +upshot is that they must all be generated regardless of whether +they are actually used. Generating all of those functions can slow +down module compilation, and resolving the references can slow down +linking. + +

    Efficiency

    + +The conversion functions are primarily used in (member) function +wrappers to convert the arguments and return values. Being functions, +converters have no interface which allows us to ask "will the +conversion succeed?" without calling the function. Since the +return value of the function must be the object to be passed as an +argument, Boost.Python currently uses C++ exception-handling to detect +an unsuccessful conversion. It's not a particularly good use of +exception-handling, since the failure is not handled very far from +where it occurred. More importantly, it means that C++ exceptions are +thrown during overload resolution as we seek an overload that matches +the arguments passed. Depending on the implementation, this approach +can result in significant slowdowns. + +

    It is also unclear that the current library generates a minimal +amount of code for any type conversion. Many of the conversion +functions are nontrivial, and partly because of compiler limitations, +they are declared inline. Also, we could have done a better +job separating the type-specific conversion code from the code which +is type-independent. + +

    Cross-module Support

    + +The current strategy requires every module to contain the definition +of conversions it uses. In general, a new module can never supply +conversion code which is used by another module. Ralf Grosse-Kunstleve +designed a clever system which imports conversions directly from one +library into another using some explicit declarations, but it has some +disadvantages also: + +
      +
    1. The system Ullrich Koethe designed for implicit conversion between +wrapped classes related through inheritance does not currently work if +the classes are defined in separate modules. + +
    2. The writer of the importing module is required to know the name of +the module supplying the imported conversions. + +
    3. There can be only one way to extract any given C++ type from a +Python object in a given module. +
    + +The first item might be addressed by moving Boost.Python into a shared +library, but the other two cannot. Ralf turned the limitation in item +two into a feature: the required module is loaded implicitly when a +conversion it defines is invoked. We will probably want to provide +that functionality anyway, but it's not clear that we should require +the declaration of all such conversions. The final item is a more +serious limitation. If, for example, new numeric types are defined in +separate modules, and these types can all be converted to +doubles, we have to choose just one conversion method. + +

    Ease-of-use

    + +One persistent source of confusion for users of Boost.Python has been +the fact that conversions for a class are not be visible at +compile-time until the declaration of that class has been seen. When +the user tries to expose a (member) function operating on or returning +an instance of the class in question, compilation fails...even though +the user goes on to expose the class in the same translation unit! + +

    +The new system lifts all compile-time checks for the existence of +particular type conversions and replaces them with runtime checks, in +true Pythonic style. While this might seem cavalier, the compile-time +checks are actually not much use in the current system if many classes +are wrapped in separate modules, since the checks are based only on +the user's declaration that the conversions exist. + +

    The New Design

    + +

    Motivation

    + +The new design was heavily influenced by a desire to generate as +little code as possible in extension modules. Some of Boost.Python's +clients are enormous projects where link time is proportional to the +amount of object code, and there are many Python extension modules. As +such, we try to keep type-specific conversion code out of modules +other than the one the converters are defined in, and rely as much as +possible on centralized control through a shared library. + +

    The Basics

    + +The library contains a registry which maps runtime type +identifiers (actually an extension of std::type_info which +preserves references and constness) to entries containing type +converters. An entry can contain only one converter from C++ to Python +(wrapper), but many converters from Python to C++ +(unwrappers). What should happen if +multiple modules try to register wrappers for the same type?. Wrappers +and unwrappers are known as body objects, and are accessed +by the user and the library (in its function-wrapping code) through +corresponding handle (wrap<T> and +unwrap<T>) objects. The handle objects are +extremely lightweight, and delegate all of their operations to +the corresponding body. + +

    +When a handle object is constructed, it accesses the +registry to find a corresponding body that can convert the +handle's constructor argument. Actually the registry record for any +type +Tused in a module is looked up only once and stored in a +static registration<T> object for efficiency. For +example, if the handle is an unwrap<Foo&> object, +the entry for Foo& is looked up in the +registry, and each unwrapper it contains is queried +to determine if it can convert the +PyObject* with which the unwrap was constructed. If +a body object which can perform the conversion is found, a pointer to +it is stored in the handle. A body object may at any point store +additional data in the handle to speed up the conversion process. + +

    +Now that the handle has been constructed, the user can ask it whether +the conversion can be performed. All handles can be tested as though +they were convertible to bool; a true value +indicates success. If the user forges ahead and tries to do the +conversion without checking when no conversion is possible, an +exception will be thrown as usual. The conversion itself is performed +by the body object. + +

    Handling complex conversions

    + +

    Some conversions may require a dynamic allocation. For example, +when a Python tuple is converted to a std::vector<double> +const&, we need some storage into which to construct the +vector so that a reference to it can be formed. Furthermore, multiple +conversions of the same type may need to be "active" +simultaneously, so we can't keep a single copy of the storage +anywhere. We could keep the storage in the body object, and +have the body clone itself in case the storage is used, but in that +case the storage in the body which lives in the registry is never +used. If the storage was actually an object of the target type (the +safest way in C++), we'd have to find a way to construct one for the +body in the registry, since it may not have a default constructor. + +

    +The most obvious way out of this quagmire is to allocate the object using a +new-expression, and store a pointer to it in the handle. Since +the body object knows everything about the data it needs to +allocate (if any), it is also given responsibility for destroying that +data. When the handle is destroyed it asks the body +object to tear down any data it may have stored there. In many ways, +you can think of the body as a "dynamically-determined +vtable" for the handle. + +

    Eliminating Redundancy

    + +If you look at the current Boost.Python code, you'll see that there +are an enormous number of conversion functions generated for each +wrapped class. For a given class T, functions are generated +to extract the following types from_python: + +
    +T*
    +T const*
    +T const* const&
    +T* const&
    +T&
    +T const&
    +T
    +std::auto_ptr<T>&
    +std::auto_ptr<T>
    +std::auto_ptr<T> const&
    +boost::shared_ptr<T>&
    +boost::shared_ptr<T>
    +boost::shared_ptr<T> const&
    +
    + +Most of these are implemented in terms of just a few conversions, and +if you're lucky, they will be inlined and cause no extra +overhead. In the new system, however, a significant amount of data +will be associated with each type that needs to be converted. We +certainly don't want to register a separate unwrapper object for all +of the above types. + +

    Fortunately, much of the redundancy can be eliminated. For example, +if we generate an unwrapper for T&, we don't need an +unwrapper for T const& or T. Accordingly, the user's +request to wrap/unwrap a given type is translated at compile-time into +a request which helps to eliminate redundancy. The rules used to +unwrap a type are: + +

      +
    1. Treat built-in types specially: when unwrapping a value or + constant reference to one of these, use a value for the target + type. It will bind to a const reference if neccessary, and more + importantly, avoids having to dynamically allocate room for + an lvalue of types which can be cheaply copied. +
    2. + Reduce everything else to a reference to an un-cv-qualified type + where possible. Since cv-qualification is lost on Python + anyway, there's no point in trying to convert to a + const&. What about conversions + to values like the tuple->vector example above? It seems to me + that we don't want to make a vector<double>& + (non-const) converter available for that case. We may need to + rethink this slightly. +
    + +

    To handle the problem described above in item 2, we modify the +procedure slightly. To unwrap any non-scalar T, we seek an +unwrapper for add_reference<T>::type. Unwrappers for +T const& always return T&, and are +registered under both T & and +T const&. + +

    For compilers not supporting partial specialization, unwrappers for +T const& must return T const& +(since constness can't be stripped), but a separate unwrapper object +need to be registered for T & and +T const& anyway, for the same reasons. + +We may want to make it possible to compile as +though partial specialization were unavailable even on compilers where +it is available, in case modules could be compiled by different +compilers with compatible ABIs (e.g. Intel C++ and MSVC6). + +

    Efficient Argument Conversion

    + +Since type conversions are primarily used in function wrappers, an +optimization is provided for the case where a group of conversions are +used together. Each handle class has a corresponding +"_more" class which does the same job, but has a +trivial destructor. Instead of asking each "_more" +handle to destroy its own body, it is linked into an endogenous list +managed by the first (ordinary) handle. The wrap and +unwrap destructors are responsible for traversing that list +and asking each body class to tear down its +handle. This mechanism is also used to determine if all of +the argument/return-value conversions can succeed with a single +function call in the function wrapping code. We +might need to handle return values in a separate step for Python +callbacks, since the availablility of a conversion won't be known +until the result object is retrieved. + +
    +
    +

    References

    + +

    [1]B. Stroustrup, The C++ Programming Language +Special Edition Addison-Wesley, ISBN 0-201-70073-5. + +


    +

    Revised 19 December 2001

    +

    © Copyright David Abrahams, 2001

    + + + + diff --git a/doc/new-conversions.txt b/doc/new-conversions.txt new file mode 100644 index 00000000..1540e199 --- /dev/null +++ b/doc/new-conversions.txt @@ -0,0 +1,111 @@ +This hierarchy contains converter handle classes. + + + +-------------+ + | noncopyable | + +-------------+ + ^ + | A common base class used so that + +--------+--------+ conversions can be linked into a + | conversion_base | chain for efficient argument + +-----------------+ conversion + ^ + | + +---------+-----------+ + | | ++-----------+----+ +------+-------+ only used for +| unwrap_more | | wrap_more | chaining, and don't manage any ++----------------+ +--------------+ resources. + ^ ^ + | | + +-----+-----+ +-------+-+ These converters are what users + | unwrap | | wrap | actually touch, but they do so + +-----------+ +---------+ through a type generator which + minimizes the number of converters + that must be generated, so they + + +Each unwrap, unwrap_more, wrap, wrap_more converter holds +a reference to an appropriate converter object + +This hierarchy contains converter body classes + + Exposes use/release which + are needed in case the converter + +-----------+ in the registry needs to be + | converter | cloned. That occurs when a + +-----------+ unwrap target type is not + ^ contained within the Python object. + | + +------------------+-----+ + | | + +--------+-------+ Exposes | + | unwrapper_base | convertible() | + +----------------+ | + ^ | + | | + +--------+----+ +-----+-----+ + | unwrapper| | wrapper| + +-------------+ +-----------+ + Exposes T convert(PyObject*) Exposes PyObject* convert(T) + + +unwrap: + + constructed with a PyObject*, whose reference count is + incremented. + + find the registry entry for the target type + + look in the collection of converters for one which claims to be + able to convert the PyObject to the target type. + + stick a pointer to the unwrapper in the unwrap object + + when unwrap is queried for convertibility, it checks to see + if it has a pointer to an unwrapper. + + on conversion, the unwrapper is asked to allocate an + implementation if the unwrap object isn't already holding + one. The unwrap object "takes ownership" of the unwrapper's + implementation. No memory allocation will actually take place + unless this is a value conversion. + + on destruction, the unwrapper is asked to free any implementation + held by the unwrap object. No memory deallocation actually + takes place unless this is a value conversion + + on destruction, the reference count on the held PyObject is + decremented. + + We need to make sure that by default, you can't instantiate + callback<> for reference and pointer return types: although the + unwrappers may exist, they may convert by-value, which would cause + the referent to be destroyed upon return. + +wrap: + + find the registry entry for the source type + + see if there is a converter. If found, stick a pointer to it in + the wrap object. + + when queried for convertibility, it checks to see if it has a + pointer to a converter. + + on conversion, a reference to the target PyObject is held by the + converter. Generally, the PyObject will have been created by the + converter, but in certain cases it may be a pre-existing object, + whose reference count will have been incremented. + + when a wrap x is used to return from a C++ function, + x.release() is returned so that x no longer holds a reference to + the PyObject when destroyed. + + Otherwise, on destruction, any PyObject still held has its + reference-count decremented. + + +When a converter is created by the user, the appropriate element must +be added to the registry; when it is destroyed, it must be removed +from the registry. diff --git a/example/simple_vector.cpp b/example/simple_vector.cpp index 8c7ee0ce..e0f9e85e 100644 --- a/example/simple_vector.cpp +++ b/example/simple_vector.cpp @@ -91,7 +91,7 @@ BOOST_PYTHON_MODULE_INIT(simple_vector) vector_double(this_module, "vector_double"); vector_double.def(python::constructor<>()); - vector_double.def(python::constructor()); + vector_double.def(python::constructor()); vector_double.def(python::constructor()); vector_double.def(&std::vector::size, "__len__"); vector_double.def(getitem, "__getitem__"); diff --git a/include/boost/python/call.hpp b/include/boost/python/call.hpp new file mode 100644 index 00000000..bdda879d --- /dev/null +++ b/include/boost/python/call.hpp @@ -0,0 +1,210 @@ +// 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_call.py + +#ifndef CALL_DWA20011214_HPP +# define CALL_DWA20011214_HPP + +# include + +namespace boost { namespace python { + +template +PyObject* call(R (*f)(), PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (*f)(A0), PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (*f)(A0, A1), PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (*f)(A0, A1, A2), PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (*f)(A0, A1, A2, A3), PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (*f)(A0, A1, A2, A3, A4), PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (*f)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +// Member functions +template +PyObject* call(R (A0::*f)(), PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (A0::*f)(A1), PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (A0::*f)(A1, A2), PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (A0::*f)(A1, A2, A3), PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (A0::*f)(A1, A2, A3, A4), PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5), PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (A0::*f)() const, PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (A0::*f)(A1) const, PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (A0::*f)(A1, A2) const, PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (A0::*f)(A1, A2, A3) const, PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (A0::*f)(A1, A2, A3, A4) const, PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (A0::*f)() volatile, PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (A0::*f)(A1) volatile, PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (A0::*f)(A1, A2) volatile, PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (A0::*f)(A1, A2, A3) volatile, PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (A0::*f)(A1, A2, A3, A4) volatile, PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5) volatile, PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (A0::*f)() const volatile, PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (A0::*f)(A1) const volatile, PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (A0::*f)(A1, A2) const volatile, PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (A0::*f)(A1, A2, A3) const volatile, PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (A0::*f)(A1, A2, A3, A4) const volatile, PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +template +PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5) const volatile, PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + + +}} // namespace boost::python + +#endif // CALL_DWA20011214_HPP + diff --git a/include/boost/python/classes.hpp b/include/boost/python/classes.hpp index f88f1000..548a57db 100644 --- a/include/boost/python/classes.hpp +++ b/include/boost/python/classes.hpp @@ -20,7 +20,7 @@ namespace boost { namespace python { // A simple type which acts something like a built-in Python class obj. -class instance +class BOOST_PYTHON_DECL instance : public boost::python::detail::python_object { public: @@ -105,7 +105,7 @@ class instance template class meta_class; namespace detail { - class class_base : public type_object_base + class BOOST_PYTHON_DECL class_base : public type_object_base { public: class_base(PyTypeObject* meta_class_obj, string name, tuple bases, const dictionary& name_space); @@ -344,7 +344,7 @@ int class_t::instance_mapping_ass_subscript(PyObject* obj, PyObject* key, PyO return 0; } -void adjust_slice_indices(PyObject* obj, int& start, int& finish); +void BOOST_PYTHON_DECL adjust_slice_indices(PyObject* obj, int& start, int& finish); template PyObject* class_t::instance_sequence_slice(PyObject* obj, int start, int finish) const diff --git a/include/boost/python/conversions.hpp b/include/boost/python/conversions.hpp index c1a7d390..aa07547f 100644 --- a/include/boost/python/conversions.hpp +++ b/include/boost/python/conversions.hpp @@ -122,61 +122,68 @@ BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // Converters // PyObject* to_python(long); -long from_python(PyObject* p, boost::python::type); +BOOST_PYTHON_DECL long from_python(PyObject* p, boost::python::type); long from_python(PyObject* p, boost::python::type); -PyObject* to_python(unsigned long); -unsigned long from_python(PyObject* p, boost::python::type); +BOOST_PYTHON_DECL PyObject* to_python(unsigned long); +BOOST_PYTHON_DECL unsigned long from_python(PyObject* p, boost::python::type); unsigned long from_python(PyObject* p, boost::python::type); PyObject* to_python(int); -int from_python(PyObject*, boost::python::type); +BOOST_PYTHON_DECL int from_python(PyObject*, boost::python::type); int from_python(PyObject*, boost::python::type); -PyObject* to_python(unsigned int); -unsigned int from_python(PyObject*, boost::python::type); +BOOST_PYTHON_DECL PyObject* to_python(unsigned int); +BOOST_PYTHON_DECL unsigned int from_python(PyObject*, boost::python::type); unsigned int from_python(PyObject*, boost::python::type); PyObject* to_python(short); -short from_python(PyObject*, boost::python::type); +BOOST_PYTHON_DECL short from_python(PyObject*, boost::python::type); short from_python(PyObject*, boost::python::type); -PyObject* to_python(unsigned short); -unsigned short from_python(PyObject*, boost::python::type); +BOOST_PYTHON_DECL PyObject* to_python(unsigned short); +BOOST_PYTHON_DECL unsigned short from_python(PyObject*, boost::python::type); unsigned short from_python(PyObject*, boost::python::type); -PyObject* to_python(char); -char from_python(PyObject*, boost::python::type); +BOOST_PYTHON_DECL PyObject* to_python(char); +BOOST_PYTHON_DECL char from_python(PyObject*, boost::python::type); char from_python(PyObject*, boost::python::type); -PyObject* to_python(signed char); -signed char from_python(PyObject*, boost::python::type); +BOOST_PYTHON_DECL PyObject* to_python(signed char); +BOOST_PYTHON_DECL signed char from_python(PyObject*, boost::python::type); signed char from_python(PyObject*, boost::python::type); -PyObject* to_python(unsigned char); -unsigned char from_python(PyObject*, boost::python::type); +BOOST_PYTHON_DECL PyObject* to_python(unsigned char); +BOOST_PYTHON_DECL unsigned char from_python(PyObject*, boost::python::type); unsigned char from_python(PyObject*, boost::python::type); +# ifndef BOOST_MSVC6_OR_EARLIER PyObject* to_python(float); float from_python(PyObject*, boost::python::type); -float from_python(PyObject*, boost::python::type); - PyObject* to_python(double); double from_python(PyObject*, boost::python::type); +# else +BOOST_PYTHON_DECL PyObject* to_python(float); +BOOST_PYTHON_DECL float from_python(PyObject*, boost::python::type); +BOOST_PYTHON_DECL PyObject* to_python(double); +BOOST_PYTHON_DECL double from_python(PyObject*, boost::python::type); +# endif +float from_python(PyObject*, boost::python::type); + double from_python(PyObject*, boost::python::type); PyObject* to_python(bool); -bool from_python(PyObject*, boost::python::type); +BOOST_PYTHON_DECL bool from_python(PyObject*, boost::python::type); bool from_python(PyObject*, boost::python::type); -PyObject* to_python(void); -void from_python(PyObject*, boost::python::type); +BOOST_PYTHON_DECL PyObject* to_python(void); +BOOST_PYTHON_DECL void from_python(PyObject*, boost::python::type); PyObject* to_python(const char* s); -const char* from_python(PyObject*, boost::python::type); +BOOST_PYTHON_DECL const char* from_python(PyObject*, boost::python::type); -PyObject* to_python(const std::string& s); -std::string from_python(PyObject*, boost::python::type); +BOOST_PYTHON_DECL PyObject* to_python(const std::string& s); +BOOST_PYTHON_DECL std::string from_python(PyObject*, boost::python::type); std::string from_python(PyObject*, boost::python::type); inline PyObject* to_python(const std::complex& x) diff --git a/include/boost/python/convert.hpp b/include/boost/python/convert.hpp new file mode 100644 index 00000000..5614bd3b --- /dev/null +++ b/include/boost/python/convert.hpp @@ -0,0 +1,84 @@ +// 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 CONVERT_DWA20011129_HPP +# define CONVERT_DWA20011129_HPP + +# include +# include +# include +# include + +namespace boost { namespace python { + +namespace detail +{ + template + struct converter_gen + { + typedef T value_type; + typedef typename converter::source::type source_t; + typedef converter::wrap_ wrap_t; + typedef converter::wrap_more_ wrap_more_t; + + typedef typename converter::target::type target_t; + typedef converter::unwrap_ unwrap_t; + typedef converter::unwrap_more_ unwrap_more_t; + }; +} + +template +struct wrap : detail::converter_gen::wrap_t +{ + typedef typename detail::converter_gen::wrap_t base_t; + typedef typename detail::converter_gen::source_t source_t; +}; + +template +struct wrap_more : detail::converter_gen::wrap_more_t +{ + typedef typename detail::converter_gen::wrap_more_t base_t; + typedef typename detail::converter_gen::source_t source_t; + wrap_more(converter::handle& prev); +}; + +template +struct unwrap : detail::converter_gen::unwrap_t +{ + typedef typename detail::converter_gen::unwrap_t base_t; + unwrap(PyObject*); +}; + +template +struct unwrap_more : detail::converter_gen::unwrap_more_t +{ + typedef typename detail::converter_gen::unwrap_more_t base_t; + unwrap_more(PyObject*, converter::handle& prev); +}; + +// +// implementations +// +template +inline wrap_more::wrap_more(converter::handle& prev) + : base_t(prev) +{ +} + +template +inline unwrap::unwrap(PyObject* source) + : base_t(source) +{ +} + +template +inline unwrap_more::unwrap_more(PyObject* source, converter::handle& prev) + : base_t(source, prev) +{ +} + +}} // namespace boost::python + +#endif // CONVERT_DWA20011129_HPP diff --git a/include/boost/python/converter/body.hpp b/include/boost/python/converter/body.hpp new file mode 100644 index 00000000..c8d932a0 --- /dev/null +++ b/include/boost/python/converter/body.hpp @@ -0,0 +1,68 @@ +// 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 BODY_DWA2001127_HPP +# define BODY_DWA2001127_HPP +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +struct BOOST_PYTHON_EXPORT handle; + +namespace registry +{ + class entry; +} + +struct BOOST_PYTHON_EXPORT body +{ + public: + body(type_id_t key); + virtual ~body() {} + + // default implementation is a no-op + virtual void destroy_handle(handle*) const; + + type_id_t key() const; + + protected: + // true iff the registry is still alive + bool can_unregister() const; + + private: + // called when the registry is destroyed, to prevent it from being + // unregistered. + void do_not_unregister(); + friend class registry::entry; + + private: + type_id_t m_key; + bool m_can_unregister; +}; + +// +// implementations +// +inline body::body(type_id_t key) + : m_key(key) + , m_can_unregister(true) +{ +} + +inline type_id_t body::key() const +{ + return m_key; +} + +inline bool body::can_unregister() const +{ + return m_can_unregister; +} + +}}} // namespace boost::python::converter + +#endif // BODY_DWA2001127_HPP diff --git a/include/boost/python/converter/class.hpp b/include/boost/python/converter/class.hpp new file mode 100644 index 00000000..305ec448 --- /dev/null +++ b/include/boost/python/converter/class.hpp @@ -0,0 +1,56 @@ +// 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 CLASS_DWA20011215_HPP +# define CLASS_DWA20011215_HPP + +# include +# include + +namespace boost { namespace python { namespace converter { + +struct class_unwrapper_base +{ + class_unwrapper_base(type_id_t sought_type); + void* +}; + +template +struct class_unwrapper +{ + struct ref_unwrapper : unwrapper + { + bool convertible(PyObject* p) const + { + return p->ob_type == &SimpleType; + } + + simple const& convert(PyObject* p, void*&) const + { + return static_cast(p)->x; + } + + }; + +# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + struct const_ref_unwrapper : unwrapper + { + bool convertible(PyObject* p) const + { + return p->ob_type == &SimpleType; + } + + simple const& convert(PyObject* p, void*&) const + { + return static_cast(p)->x; + } + + }; +# endif +}; + +}}} // namespace boost::python::converter + +#endif // CLASS_DWA20011215_HPP diff --git a/include/boost/python/converter/handle.hpp b/include/boost/python/converter/handle.hpp new file mode 100644 index 00000000..16a50b38 --- /dev/null +++ b/include/boost/python/converter/handle.hpp @@ -0,0 +1,91 @@ +// 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 HANDLE_DWA20011130_HPP +# define HANDLE_DWA20011130_HPP +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +struct BOOST_PYTHON_EXPORT body; + +// The common base class for unwrap_ and wrap_ handle objects. They +// share a common base so that handles can be linked into a chain +// within a function wrapper which is managed by a single object. +struct BOOST_PYTHON_EXPORT handle : boost::noncopyable +{ + public: // member functions + + // All constructors take a body* passed from the derived class. + // + // Constructors taking a handle links this into a chain of + // handles, for more efficient management in function wrappers + handle(body* body); + handle(body* body, handle& prev); + + // returns true iff all handles in the chain can convert their + // arguments + bool convertible() const; + + // safe_bool idiom from Peter Dimov: provides handles to/from + // bool without enabling handles to integer types/void*. + private: + struct dummy { inline void nonnull() {} }; + typedef void (dummy::*safe_bool)(); + public: + inline operator safe_bool() const; + inline safe_bool operator!() const; + + protected: // member functions for derived classes + // Get the body we hold + inline body* get_body() const; + + // Release all bodies in the chain, in reverse order of + // initialization. Only actually called for the head of the chain. + void destroy(); + + private: + // Holds implementation + body* m_body; + + // handle for next argument, if any. + handle* m_next; +}; + +// +// implementations +// +inline handle::handle(body* body, handle& prev) + : m_body(body), m_next(0) +{ + prev.m_next = this; +} + +inline handle::handle(body* body) + : m_body(body), m_next(0) +{ +} + +inline handle::operator handle::safe_bool() const +{ + return convertible() ? &dummy::nonnull : 0; +} + +inline handle::safe_bool handle::operator!() const +{ + return convertible() ? 0 : &dummy::nonnull; +} + +inline body* handle::get_body() const +{ + return m_body; +} + +}}} // namespace boost::python::converter + +#endif // HANDLE_DWA20011130_HPP diff --git a/include/boost/python/converter/registration.hpp b/include/boost/python/converter/registration.hpp new file mode 100644 index 00000000..0d85d1d7 --- /dev/null +++ b/include/boost/python/converter/registration.hpp @@ -0,0 +1,83 @@ +// 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 REGISTRATION_DWA20011130_HPP +# define REGISTRATION_DWA20011130_HPP +# include +# include +# include +# include +# ifdef BOOST_PYTHON_TRACE +# include +# endif + +namespace boost { namespace python { namespace converter { + +struct BOOST_PYTHON_EXPORT wrapper_base; +struct BOOST_PYTHON_EXPORT unwrapper_base; + +// This class is really sort of a "templated namespace". It manages a +// static data member which refers to the registry entry for T. This +// reference is acquired once to reduce the burden of multiple +// dictionary lookups at runtime. +template +struct registration +{ + public: // member functions + // Return a converter which can convert the given Python object to + // T, or 0 if no such converter exists + static unwrapper_base* unwrapper(PyObject*); + + // Return a converter which can convert T to a Python object, or 0 + // if no such converter exists + static wrapper_base* wrapper(); + + private: // helper functions + static registry::entry* entry(); + static registry::entry* find_entry(); + + private: // data members + static registry::entry* m_registry_entry; +}; + +// because this is static POD data it will be initialized to zero +template +registry::entry* registration::m_registry_entry; + +template +registry::entry* registration::find_entry() +{ + return registry::find(type_id()); +} + +template +inline registry::entry* registration::entry() +{ + if (!m_registry_entry) + m_registry_entry = find_entry(); + return m_registry_entry; +} + +template +unwrapper_base* registration::unwrapper(PyObject* p) +{ +# ifdef BOOST_PYTHON_TRACE + std::cout << "retrieving unwrapper for " << type_id() << std::endl; +# endif + return entry()->unwrapper(p); +} + +template +wrapper_base* registration::wrapper() +{ +# ifdef BOOST_PYTHON_TRACE + std::cout << "retrieving wrapper for " << type_id() << std::endl; +# endif + return entry()->wrapper(); +} + +}}} // namespace boost::python::converter + +#endif // REGISTRATION_DWA20011130_HPP diff --git a/include/boost/python/converter/registry.hpp b/include/boost/python/converter/registry.hpp new file mode 100644 index 00000000..30eeba8d --- /dev/null +++ b/include/boost/python/converter/registry.hpp @@ -0,0 +1,74 @@ +// 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 REGISTRY_DWA20011127_HPP +# define REGISTRY_DWA20011127_HPP +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +struct BOOST_PYTHON_EXPORT wrapper_base; +struct BOOST_PYTHON_EXPORT unwrapper_base; + +// This namespace acts as a sort of singleton +namespace registry +{ + // These are the elements stored in the registry + class BOOST_PYTHON_EXPORT entry + { + public: // member functions + entry(); + ~entry(); + + // Return a converter appropriate for converting the given + // Python object from_python to the C++ type with which this + // converter is associated in the registry, or 0 if no such + // converter exists. + unwrapper_base* unwrapper(PyObject*) const; + + // Return a converter appropriate for converting a C++ object + // whose type this entry is associated with in the registry to a + // Python object, or 0 if no such converter exists. + wrapper_base* wrapper() const; + + // Conversion classes use these functions to register + // themselves. + void insert(wrapper_base&); + void remove(wrapper_base&); + + void insert(unwrapper_base&); + void remove(unwrapper_base&); + + private: // types + typedef std::list unwrappers; + + private: // helper functions + unwrappers::iterator find(unwrapper_base const&); + + private: // data members + + // The collection of from_python converters for the associated + // C++ type. + unwrappers m_unwrappers; + + // The unique to_python converter for the associated C++ type. + converter::wrapper_base* m_wrapper; + }; + + BOOST_PYTHON_EXPORT entry* find(type_id_t); + + BOOST_PYTHON_EXPORT void insert(wrapper_base& x); + BOOST_PYTHON_EXPORT void insert(unwrapper_base& x); + BOOST_PYTHON_EXPORT void remove(wrapper_base& x); + BOOST_PYTHON_EXPORT void remove(unwrapper_base& x); +} + +}}} // namespace boost::python::converter + +#endif // REGISTRY_DWA20011127_HPP diff --git a/include/boost/python/converter/source.hpp b/include/boost/python/converter/source.hpp new file mode 100644 index 00000000..9af1cf49 --- /dev/null +++ b/include/boost/python/converter/source.hpp @@ -0,0 +1,80 @@ +// 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 SOURCE_DWA20011119_HPP +# define SOURCE_DWA20011119_HPP +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +// source -- +// +// This type generator (see +// ../../../more/generic_programming.html#type_generator) is used +// to select the argument type to use when converting T to a PyObject* + +template struct source; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +// Since for some strange reason temporaries can't be bound to const +// volatile references (8.5.3/5 in the C++ standard), we cannot use a +// const volatile reference as the standard for values and references. +template +struct source +{ + typedef T const& type; +}; + +// This will handle the following: +// T const volatile& -> T const volatile& +// T volatile& -> T const volatile& +// T const& -> T const& +// T& -> T const& +template +struct source +{ + typedef T const& type; +}; + +template +struct source +{ + typedef T const* type; +}; + +template +struct source +{ + typedef T const* type; +}; + +// Deal with references to pointers +template +struct source +{ + typedef T const* type; +}; + +template +struct source +{ + typedef T const* type; +}; +# else +template +struct source +{ + typedef typename add_reference< + typename add_const::type + >::type type; +}; +# endif + +}}} // namespace boost::python::converter + +#endif // SOURCE_DWA20011119_HPP diff --git a/include/boost/python/converter/source_holder.hpp b/include/boost/python/converter/source_holder.hpp new file mode 100644 index 00000000..f2c774f9 --- /dev/null +++ b/include/boost/python/converter/source_holder.hpp @@ -0,0 +1,24 @@ +// 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 SOURCE_HOLDER_DWA20011215_HPP +# define SOURCE_HOLDER_DWA20011215_HPP + +namespace boost { namespace python { namespace converter { + +struct source_holder_base +{ +}; + +template +struct source_holder : source_holder_base +{ + source_holder(T x) : value(x) {} + T value; +}; + +}}} // namespace boost::python::converter + +#endif // SOURCE_HOLDER_DWA20011215_HPP diff --git a/include/boost/python/converter/target.hpp b/include/boost/python/converter/target.hpp new file mode 100644 index 00000000..6effb996 --- /dev/null +++ b/include/boost/python/converter/target.hpp @@ -0,0 +1,173 @@ +// 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 TARGET_DWA20011119_HPP +# define TARGET_DWA20011119_HPP +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +// target -- +// +// This type generator (see +// ../../../more/generic_programming.html#type_generator) is used +// to select the return type of the appropriate converter for +// unwrapping a given type. + +// Strategy: +// +// 1. reduce everything to a common, un-cv-qualified reference +// type where possible. This will save on registering many different +// converter types. +// +// 2. Treat built-in types specially: when unwrapping a value or +// constant reference to one of these, use a value for the target +// type. It will bind to a const reference if neccessary, and more +// importantly, avoids having to dynamically allocate room for +// an lvalue of types which can be cheaply copied. +// +// In the tables below, "cv" stands for the set of all possible +// cv-qualifications. + +// Target Source +// int int +// int const& int +// int& int& +// int volatile& int volatile& +// int const volatile& int const volatile& + +// On compilers supporting partial specialization: +// +// Target Source +// T T& +// T cv& T& +// T cv* T* +// T cv*const& T* +// T cv*& T*& <- should this be legal? +// T cv*volatile& T*& <- should this be legal? +// T cv*const volatile& T*& <- should this be legal? + +// On others: +// +// Target Source +// T T& +// T cv& T cv& +// T cv* T cv* +// T cv*cv& T cv*cv& + +// As you can see, in order to handle the same range of types without +// partial specialization, more converters need to be registered. + +template +struct target +{ + // Some pointer types are handled in a more sophisticated way on + // compilers supporting partial specialization. + BOOST_STATIC_CONSTANT(bool, use_identity = (::boost::is_scalar::value)); + + typedef typename mpl::select_type< + use_identity + , T + , typename add_reference::type>::type + >::type type; +}; + +// When partial specialization is not present, we'll simply need to +// register many more converters. +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +template +struct target +{ + typedef typename remove_cv::type& type; +}; + +template +struct target +{ + typedef typename remove_cv::type* type; +}; + +// Handle T*-cv for completeness. Function arguments in a signature +// are never actually cv-qualified, but who knows how these converters +// might be used, or whether compiler bugs lurk which make it seem +// otherwise? +template +struct target +{ + typedef typename remove_cv::type* type; +}; + +template +struct target +{ + typedef typename remove_cv::type* type; +}; + +template +struct target +{ + typedef typename remove_cv::type* type; +}; + +// non-const references to pointers should be handled by the +// specialization for T&, above. +template +struct target +{ + typedef typename remove_cv::type* type; +}; +# endif + +// Fortunately, we can handle T const& where T is an arithmetic type +// by explicit specialization. These specializations will cause value +// and const& arguments to be converted to values, rather than to +// references. +# define BOOST_PYTHON_UNWRAP_VALUE(T) \ +template <> \ +struct target \ +{ \ + typedef T type; \ +}; \ +template <> \ +struct target \ +{ \ + typedef T type; \ +}; \ +template <> \ +struct target \ +{ \ + typedef T type; \ +}; \ +template <> \ +struct target \ +{ \ + typedef T type; \ +}; \ +template <> \ +struct target \ +{ \ + typedef T type; \ +} + +BOOST_PYTHON_UNWRAP_VALUE(char); +BOOST_PYTHON_UNWRAP_VALUE(unsigned char); +BOOST_PYTHON_UNWRAP_VALUE(signed char); +BOOST_PYTHON_UNWRAP_VALUE(unsigned int); +BOOST_PYTHON_UNWRAP_VALUE(signed int); +BOOST_PYTHON_UNWRAP_VALUE(unsigned short); +BOOST_PYTHON_UNWRAP_VALUE(signed short); +BOOST_PYTHON_UNWRAP_VALUE(unsigned long); +BOOST_PYTHON_UNWRAP_VALUE(signed long); +BOOST_PYTHON_UNWRAP_VALUE(char const*); + +}}} // namespace boost::python::converter + +#endif // TARGET_DWA20011119_HPP diff --git a/include/boost/python/converter/type_id.hpp b/include/boost/python/converter/type_id.hpp new file mode 100644 index 00000000..ddc04266 --- /dev/null +++ b/include/boost/python/converter/type_id.hpp @@ -0,0 +1,200 @@ +// 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 TYPE_ID_DWA20011127_HPP +# define TYPE_ID_DWA20011127_HPP +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + + +namespace boost { namespace python { namespace converter { + +// a portable mechanism for identifying types at runtime across modules. + +namespace detail +{ + template class dummy; +} + +// for this compiler at least, cross-shared-library type_info +// comparisons don't work, so use typeid(x).name() instead. It's not +// yet clear what the best default strategy is. +# if defined(__GNUC__) && __GNUC__ >= 3 +# define BOOST_PYTHON_TYPE_ID_NAME +# endif + +# if 1 +struct type_id_t : totally_ordered +{ + enum decoration { const_ = 0x1, volatile_ = 0x2, reference = 0x4 }; + +# ifdef BOOST_PYTHON_TYPE_ID_NAME +typedef char const* base_id_t; +# else +typedef std::type_info const* base_id_t; +# endif + + type_id_t(base_id_t, decoration decoration); + + bool operator<(type_id_t const& rhs) const; + bool operator==(type_id_t const& rhs) const; + friend BOOST_PYTHON_EXPORT std::ostream& operator<<(std::ostream&, type_id_t const&); + + private: + decoration m_decoration; + base_id_t m_base_type; +}; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct is_reference_to_const +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +template +struct is_reference_to_const +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +template +struct is_reference_to_volatile +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +template +struct is_reference_to_volatile +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; +# else +template +struct is_const_help +{ + typedef typename mpl::select_type< + is_const::value + , type_traits::yes_type + , type_traits::no_type + >::type type; +}; + +template +struct is_volatile_help +{ + typedef typename mpl::select_type< + is_volatile::value + , type_traits::yes_type + , type_traits::no_type + >::type type; +}; + +template +typename is_const_help::type reference_to_const_helper(V&); + +type_traits::no_type +reference_to_const_helper(...); + +template +struct is_reference_to_const +{ + static T t; + BOOST_STATIC_CONSTANT( + bool, value + = sizeof(reference_to_const_helper(t)) == sizeof(type_traits::yes_type)); +}; + +template +typename is_volatile_help::type reference_to_volatile_helper(V&); +type_traits::no_type reference_to_volatile_helper(...); + +template +struct is_reference_to_volatile +{ + static T t; + BOOST_STATIC_CONSTANT( + bool, value + = sizeof(reference_to_volatile_helper(t)) == sizeof(type_traits::yes_type)); +}; +# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +template +inline type_id_t type_id(detail::dummy* = 0) +{ + return type_id_t( +# ifdef BOOST_PYTHON_TYPE_ID_NAME + typeid(T).name() +# else + &typeid(T) +# endif + , type_id_t::decoration( + (is_const::value || is_reference_to_const::value + ? type_id_t::const_ : 0) + | (is_volatile::value || is_reference_to_volatile::value + ? type_id_t::volatile_ : 0) + | (is_reference::value ? type_id_t::reference : 0) + ) + ); +} + +inline type_id_t::type_id_t(base_id_t base_t, decoration decoration) + : m_decoration(decoration) + , m_base_type(base_t) +{ +} + +inline bool type_id_t::operator<(type_id_t const& rhs) const +{ + return m_decoration < rhs.m_decoration + || m_decoration == rhs.m_decoration +# ifdef BOOST_PYTHON_TYPE_ID_NAME + && std::strcmp(m_base_type, rhs.m_base_type) < 0; +# else + && m_base_type->before(*rhs.m_base_type); +# endif +} + +inline bool type_id_t::operator==(type_id_t const& rhs) const +{ + return m_decoration == rhs.m_decoration +# ifdef BOOST_PYTHON_TYPE_ID_NAME + && !std::strcmp(m_base_type, rhs.m_base_type); +# else + && *m_base_type == *rhs.m_base_type; +# endif +} + +# else +// This is the type which is used to identify a type +typedef char const* type_id_t; + +// This is a workaround for a silly MSVC bug +// Converts a compile-time type to its corresponding runtime identifier. +template +type_id_t type_id(detail::dummy* = 0) +{ + return typeid(T).name(); +} +# endif + +struct BOOST_PYTHON_EXPORT type_id_before +{ + bool operator()(type_id_t const& x, type_id_t const& y) const; +}; + +BOOST_PYTHON_EXPORT std::ostream& operator<<(std::ostream&, type_id_t const&); + +}}} // namespace boost::python::converter + +#endif // TYPE_ID_DWA20011127_HPP diff --git a/include/boost/python/converter/unwrap.hpp b/include/boost/python/converter/unwrap.hpp new file mode 100644 index 00000000..6dda61fb --- /dev/null +++ b/include/boost/python/converter/unwrap.hpp @@ -0,0 +1,192 @@ +// 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 UNWRAP_BASE_DWA20011130_HPP +# define UNWRAP_BASE_DWA20011130_HPP + +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +template struct unwrapper; +struct BOOST_PYTHON_EXPORT body; + +struct BOOST_PYTHON_EXPORT unwrap_base : handle +{ + public: // member functions + inline unwrap_base(PyObject* source, body*, handle& prev); + inline unwrap_base(PyObject* source, body*); + inline PyObject* source() const; + + private: // data members + PyObject* m_source; +}; + +// These converters will be used by the function wrappers. They don't +// manage any resources, but are instead linked into a chain which is +// managed by an instance of unwrap_ or wrap_. +template +struct unwrap_more_ : unwrap_base +{ + public: // member functions + // Construction + unwrap_more_(PyObject* source, handle& prev); + + // invoke the conversion or throw an exception if unsuccessful + T operator*(); + + protected: // constructor + // this constructor is only for the use of unwrap_ + unwrap_more_(PyObject* source); + + private: // helper functions + // Return the unwrapper which will convert the given Python object + // to T, or 0 if no such converter exists + static unwrapper_base* lookup(PyObject*); + + private: + // unspecified storage which may be allocated by the unwrapper to + // do value conversions. + mutable void* m_storage; + friend class unwrapper; +}; + +// specialization for PyObject* +template <> +struct unwrap_more_ + : unwrap_base +{ + public: // member functions + // Construction + unwrap_more_(PyObject* source, handle& prev) + : unwrap_base(source, m_unwrapper, prev) + { + } + + + // invoke the conversion or throw an exception if unsuccessful + PyObject* operator*() + { + return source(); + } + + bool convertible(PyObject*) const + { + return true; + } + + protected: // constructor + // this constructor is only for the use of unwrap_ + unwrap_more_(PyObject* source) + : unwrap_base(source, m_unwrapper) + + { + } + private: + static BOOST_PYTHON_EXPORT unwrapper_base* m_unwrapper; +}; + +template +struct unwrap_ : unwrap_more_ +{ + unwrap_(PyObject* source); + ~unwrap_(); +}; + +// +// implementations +// +inline unwrap_base::unwrap_base(PyObject* source, body* body, handle& prev) + : handle(body, prev) + , m_source(source) +{ +} + +inline unwrap_base::unwrap_base(PyObject* source, body* body) + : handle(body) + , m_source(source) +{ +} + +inline PyObject* unwrap_base::source() const +{ + return m_source; +} + +template +inline unwrapper_base* unwrap_more_::lookup(PyObject* source) +{ + // Find the converters registered for T and get a unwrapper + // appropriate for the source object + return registration::unwrapper(source); +} + +template +unwrap_more_::unwrap_more_(PyObject* source, handle& prev) + : unwrap_base(source, lookup(source), prev) + , m_storage(0) +{ +} + +template +unwrap_more_::unwrap_more_(PyObject* source) + : unwrap_base(source, lookup(source)) + , m_storage(0) +{ +} + +# if 0 +template <> +inline unwrap_more_::unwrap_more_(PyObject* source, handle& prev) + : unwrap_base(source, m_unwrapper, prev) +{ +} + +template <> +inline unwrap_more_::unwrap_more_(PyObject* source) + : unwrap_base(source, m_unwrapper) + +{ +} + +template <> +inline PyObject* unwrap_more_::operator*() +{ + return source(); +} + +template <> +inline bool unwrap_more_::convertible(PyObject*) const +{ + return true; +} +# endif +template +inline unwrap_::unwrap_(PyObject* source) + : unwrap_more_(source) +{ +} + +template +T unwrap_more_::operator*() +{ + return static_cast*>( + get_body())->do_conversion(this); +} + +template +unwrap_::~unwrap_() +{ + destroy(); +} + +}}} // namespace boost::python::converter + +#endif // UNWRAP_BASE_DWA20011130_HPP diff --git a/include/boost/python/converter/unwrapper.hpp b/include/boost/python/converter/unwrapper.hpp new file mode 100644 index 00000000..a30ff522 --- /dev/null +++ b/include/boost/python/converter/unwrapper.hpp @@ -0,0 +1,53 @@ +// 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 UNWRAPPER_DWA2001127_HPP +# define UNWRAPPER_DWA2001127_HPP + +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +template struct unwrap_more_; + +// Abstract base for all unwrappers of Ts +template +struct unwrapper : unwrapper_base +{ + public: + unwrapper(); + + T do_conversion(unwrap_more_ const* handle) const; + + private: + virtual T convert(PyObject*, void*&) const = 0; + + private: // body required interface implementation + void destroy_handle(handle*) const {} +}; + +// +// implementations +// +template +unwrapper::unwrapper() + : unwrapper_base(type_id()) +{ +} + +// We could think about making this virtual in an effort to get its +// code generated in the module where the unwrapper is defined, but +// it's not clear that it's a good tradeoff. +template +T unwrapper::do_conversion(unwrap_more_ const* handle) const +{ + return convert(handle->source(), handle->m_storage); +} + +}}} // namespace boost::python::converter + +#endif // UNWRAPPER_DWA2001127_HPP diff --git a/include/boost/python/converter/unwrapper_base.hpp b/include/boost/python/converter/unwrapper_base.hpp new file mode 100644 index 00000000..54e2e54c --- /dev/null +++ b/include/boost/python/converter/unwrapper_base.hpp @@ -0,0 +1,25 @@ +// 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 UNWRAPPER_BASE_DWA20011215_HPP +# define UNWRAPPER_BASE_DWA20011215_HPP +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +struct BOOST_PYTHON_EXPORT unwrapper_base : body +{ + public: + unwrapper_base(type_id_t); // registers + ~unwrapper_base(); // unregisters + virtual bool convertible(PyObject*) const = 0; +}; + +}}} // namespace boost::python::converter + +#endif // UNWRAPPER_BASE_DWA20011215_HPP diff --git a/include/boost/python/converter/wrap.hpp b/include/boost/python/converter/wrap.hpp new file mode 100644 index 00000000..91c9de86 --- /dev/null +++ b/include/boost/python/converter/wrap.hpp @@ -0,0 +1,145 @@ +// 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 WRAP_DWA2001127_HPP +# define WRAP_DWA2001127_HPP +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +struct BOOST_PYTHON_EXPORT wrapper_base; + +template struct wrapper; + +struct wrap_base : handle +{ + public: // member functions + wrap_base(body*, handle& prev); + wrap_base(body*); + PyObject* release(); + + public: // accessor, really only for wrappers + PyObject*& target() const; + + protected: + void hold_result(PyObject*) const; + + private: + mutable PyObject* m_target; +}; + +template +struct wrap_more_ : wrap_base +{ + protected: + typedef T source_t; + + public: // member functions + wrap_more_(handle& prev); + + PyObject* operator()(source_t) const; + + protected: // constructor for wrap_, below + wrap_more_(); + + private: // helper functions + static wrapper_base* lookup(); + + private: + friend class wrapper; +}; + +template +struct wrap_ : wrap_more_ +{ + typedef typename wrap_more_::source_t source_t; + public: // member functions + wrap_(); + ~wrap_(); +}; + +// +// implementations +// + +inline wrap_base::wrap_base(body* body, handle& prev) + : handle(body, prev), + m_target(0) +{ +} + +inline wrap_base::wrap_base(body* body) + : handle(body), + m_target(0) +{ +} + +inline PyObject*& wrap_base::target() const +{ + return m_target; +} + +inline void wrap_base::hold_result(PyObject* p) const +{ + assert(m_target == 0); + m_target = p; +} + +inline PyObject* wrap_base::release() +{ + PyObject* result = m_target; + m_target = 0; + return result; +} + +template +inline wrapper_base* wrap_more_::lookup() +{ + // Find the converters registered for T and get a wrapper + // appropriate for the source object + return registration::wrapper(); +} + +template +inline wrap_more_::wrap_more_(handle& prev) + : wrap_base(lookup(), prev) +{ + +} + +template +PyObject* wrap_more_::operator()(source_t x) const +{ + return static_cast*>( + get_body())->do_conversion(*this, source_holder(x)); +} + +template +wrap_more_::wrap_more_() + : wrap_base(lookup()) +{ +} + +template +wrap_::wrap_() + : wrap_more_() +{ +} + +template +wrap_::~wrap_() +{ + destroy(); +} + +}}} // namespace boost::python::converter + +#endif // WRAP_DWA2001127_HPP diff --git a/include/boost/python/converter/wrapper.hpp b/include/boost/python/converter/wrapper.hpp new file mode 100644 index 00000000..ada5e8cb --- /dev/null +++ b/include/boost/python/converter/wrapper.hpp @@ -0,0 +1,69 @@ +// 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 WRAPPER_DWA2001127_HPP +# define WRAPPER_DWA2001127_HPP +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +struct source_holder_base; +struct wrap_base; +template struct wrap_more_; + +struct BOOST_PYTHON_EXPORT wrapper_base : body +{ + public: + wrapper_base(type_id_t); // registers + ~wrapper_base(); // unregisters + + virtual PyObject* do_conversion(wrap_base const&, source_holder_base const&) const = 0; +}; + +template +struct wrapper : wrapper_base +{ + public: + wrapper(); + + PyObject* do_conversion(wrap_base const&, source_holder_base const&) const; + + // This does the actual conversion + virtual PyObject* convert(T source) const = 0; +}; + +// +// implementations +// + +template +wrapper::wrapper() + : wrapper_base(type_id()) +{ +} + + +template +PyObject* wrapper::do_conversion(wrap_base const& handle_, source_holder_base const& data_) const +{ + // Casting pointers instead of references suppresses a CWPro7 bug. + wrap_more_ const& handle = *static_cast const*>(&handle_); + source_holder const& data = *static_cast const*>(&data_); + if (handle.target() == 0) + { + handle.hold_result(convert(data.value)); + } + return handle.target(); +} + +}}} // namespace boost::python::converter + +#endif // WRAPPER_DWA2001127_HPP diff --git a/include/boost/python/cross_module.hpp b/include/boost/python/cross_module.hpp index dd1c47d2..f5ca315d 100644 --- a/include/boost/python/cross_module.hpp +++ b/include/boost/python/cross_module.hpp @@ -18,26 +18,28 @@ # include namespace boost { namespace python { - struct import_error : error_already_set {}; - struct export_error : error_already_set {}; -}} + struct BOOST_PYTHON_DECL import_error: error_already_set {}; + struct BOOST_PYTHON_DECL export_error : error_already_set {}; -namespace boost { namespace python { namespace detail { +namespace detail +{ // Concept: throw exception if api_major is changed // show warning on stderr if api_minor is changed -const int export_converters_api_major = 4; -const int export_converters_api_minor = 1; -extern const char* converters_attribute_name; -void* import_converter_object(const std::string& module_name, - const std::string& py_class_name, - const std::string& attribute_name); -void check_export_converters_api(const int importing_major, - const int importing_minor, - const int imported_major, - const int imported_minor); + const int export_converters_api_major = 4; + const int export_converters_api_minor = 1; + extern BOOST_PYTHON_DECL const char* converters_attribute_name; + BOOST_PYTHON_DECL void* import_converter_object(const std::string& module_name, + const std::string& py_class_name, + const std::string& attribute_name); + BOOST_PYTHON_DECL void check_export_converters_api(const int importing_major, + const int importing_minor, + const int imported_major, + const int imported_minor); -}}} +} + +}} // namespace boost::python // forward declaration namespace boost { namespace python { namespace detail { @@ -232,56 +234,56 @@ struct export_converter_object : export_converter_object_noncopyable } }; -namespace detail { +namespace detail +{ /* This class template is instantiated by import_converters. Its purpose is to import the converter_object via the Python API. The actual import is only done once. The pointer to the imported converter object is kept in the static data member imported_converters. - */ -template -class import_extension_class - : public python_import_extension_class_converters -{ - public: - inline import_extension_class(const char* module, const char* py_class) { - m_module = module; - m_py_class = py_class; - } +*/ + template + class import_extension_class + : public python_import_extension_class_converters + { + public: + inline import_extension_class(const char* module, const char* py_class) { + m_module = module; + m_py_class = py_class; + } - static boost::python::export_converter_object_base* get_converters(); + static boost::python::export_converter_object_base* get_converters(); - private: - static std::string m_module; - static std::string m_py_class; - static boost::python::export_converter_object_base* imported_converters; -}; + private: + static std::string m_module; + static std::string m_py_class; + static boost::python::export_converter_object_base* imported_converters; + }; -template std::string import_extension_class::m_module; -template std::string import_extension_class::m_py_class; -template -boost::python::export_converter_object_base* -import_extension_class::imported_converters = 0; + template std::string import_extension_class::m_module; + template std::string import_extension_class::m_py_class; + template + boost::python::export_converter_object_base* + import_extension_class::imported_converters = 0; -template -boost::python::export_converter_object_base* -import_extension_class::get_converters() { - if (imported_converters == 0) { - void* cobject - = import_converter_object(m_module, m_py_class, - converters_attribute_name); - imported_converters - = static_cast*>(cobject); - check_export_converters_api( - export_converters_api_major, - export_converters_api_minor, - imported_converters->get_api_major(), - imported_converters->get_api_minor()); + template + boost::python::export_converter_object_base* + import_extension_class::get_converters() { + if (imported_converters == 0) { + void* cobject + = import_converter_object(m_module, m_py_class, + converters_attribute_name); + imported_converters + = static_cast*>(cobject); + check_export_converters_api( + export_converters_api_major, + export_converters_api_minor, + imported_converters->get_api_major(), + imported_converters->get_api_minor()); + } + return imported_converters; } - return imported_converters; -} - }}} // namespace boost::python::detail namespace boost { namespace python { diff --git a/include/boost/python/detail/arg_tuple_size.hpp b/include/boost/python/detail/arg_tuple_size.hpp new file mode 100644 index 00000000..e6b6ccc1 --- /dev/null +++ b/include/boost/python/detail/arg_tuple_size.hpp @@ -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 struct arg_tuple_size; + +# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__BORLANDC__) + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 0); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 1); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 2); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 3); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 4); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 5); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 6); +}; + + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 1); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 2); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 3); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 4); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 5); +}; + +template +struct arg_tuple_size +{ + 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 +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 +char_array<0> arg_tuple_size_helper(R (*)()); + +template +char_array<1> arg_tuple_size_helper(R (*)(A1)); + +template +char_array<2> arg_tuple_size_helper(R (*)(A1, A2)); + +template +char_array<3> arg_tuple_size_helper(R (*)(A1, A2, A3)); + +template +char_array<4> arg_tuple_size_helper(R (*)(A1, A2, A3, A4)); + +template +char_array<5> arg_tuple_size_helper(R (*)(A1, A2, A3, A4, A5)); + +template +char_array<6> arg_tuple_size_helper(R (*)(A1, A2, A3, A4, A5, A6)); + +template +char_array<1> arg_tuple_size_helper(R (A0::*)()); + +template +char_array<2> arg_tuple_size_helper(R (A0::*)(A1)); + +template +char_array<3> arg_tuple_size_helper(R (A0::*)(A1, A2)); + +template +char_array<4> arg_tuple_size_helper(R (A0::*)(A1, A2, A3)); + +template +char_array<5> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4)); + +template +char_array<6> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4, A5)); + + +template +char_array<1> arg_tuple_size_helper(R (A0::*)() const); + +template +char_array<2> arg_tuple_size_helper(R (A0::*)(A1) const); + +template +char_array<3> arg_tuple_size_helper(R (A0::*)(A1, A2) const); + +template +char_array<4> arg_tuple_size_helper(R (A0::*)(A1, A2, A3) const); + +template +char_array<5> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4) const); + +template +char_array<6> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4, A5) const); + + +template +char_array<1> arg_tuple_size_helper(R (A0::*)() volatile); + +template +char_array<2> arg_tuple_size_helper(R (A0::*)(A1) volatile); + +template +char_array<3> arg_tuple_size_helper(R (A0::*)(A1, A2) volatile); + +template +char_array<4> arg_tuple_size_helper(R (A0::*)(A1, A2, A3) volatile); + +template +char_array<5> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4) volatile); + +template +char_array<6> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4, A5) volatile); + + +template +char_array<1> arg_tuple_size_helper(R (A0::*)() const volatile); + +template +char_array<2> arg_tuple_size_helper(R (A0::*)(A1) const volatile); + +template +char_array<3> arg_tuple_size_helper(R (A0::*)(A1, A2) const volatile); + +template +char_array<4> arg_tuple_size_helper(R (A0::*)(A1, A2, A3) const volatile); + +template +char_array<5> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4) const volatile); + +template +char_array<6> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4, A5) const volatile); + + +template +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 + diff --git a/include/boost/python/detail/base_object.hpp b/include/boost/python/detail/base_object.hpp index 19715876..d92b3972 100644 --- a/include/boost/python/detail/base_object.hpp +++ b/include/boost/python/detail/base_object.hpp @@ -13,7 +13,6 @@ # define BASE_OBJECT_DWA051600_H_ # include -# include // really just for type<> # include # include @@ -45,10 +44,7 @@ template base_object::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)); + BOOST_CSTD_::memset(bp, 0, sizeof(base_python_type)); Py_INCREF(type_obj); PyObject_INIT(bp, type_obj); } diff --git a/include/boost/python/detail/call_object.hpp b/include/boost/python/detail/call_object.hpp new file mode 100644 index 00000000..5595e5c0 --- /dev/null +++ b/include/boost/python/detail/call_object.hpp @@ -0,0 +1,66 @@ +// 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 CALL_OBJECT_DWA20011222_HPP +# define CALL_OBJECT_DWA20011222_HPP +# include +# include +# include + +namespace boost { namespace python { + +namespace detail +{ + // A function object adaptor which turns a function returning R into + // an "equivalent" function returning void, but taking an R& in + // which the adapted function's result is stored. + template + struct return_by_reference + { + typedef void return_type; + + return_by_reference(R& result, F f) + : m_result(result) + , m_f(f) + { + } + + void operator()() const + { + m_result = m_f(); + } + + R& m_result; + F m_f; + }; + + // An object generator for the above adaptors + template + return_by_reference bind_return(R& result, F f) + { + return return_by_reference(result, f); + } + + // Given a function object f with signature + // + // R f(PyTypeObject*,PyObject*) + // + // calls f inside of handle_exception_impl, placing f's result in + // ret. Returns true iff an exception is thrown by f, leaving ret + // unmodified. + template + bool call_object(R& ret, PyObject* obj, F f) + { + return handle_exception( + detail::bind_return( + ret + , boost::bind( + f, static_cast(obj->ob_type), obj))); + } +} // namespace detail + +}} // namespace boost::python + +#endif // CALL_OBJECT_DWA20011222_HPP diff --git a/include/boost/python/detail/caller.hpp b/include/boost/python/detail/caller.hpp new file mode 100644 index 00000000..95c6dc7a --- /dev/null +++ b/include/boost/python/detail/caller.hpp @@ -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 +# include + +namespace boost { namespace python { namespace detail { + +struct caller +{ + typedef PyObject* result_type; + + template + PyObject* operator()(F f, PyObject* args, PyObject* keywords) + { + return call(f, args, keywords); + } +}; + +}}} // namespace boost::python::detail + +#endif // CALLER_DWA20011214_HPP diff --git a/include/boost/python/detail/config.hpp b/include/boost/python/detail/config.hpp index 0fc1093a..498fa07a 100644 --- a/include/boost/python/detail/config.hpp +++ b/include/boost/python/detail/config.hpp @@ -59,9 +59,9 @@ # 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() +# 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() +# 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 @@ -72,23 +72,23 @@ ****************************************************************************/ // backwards compatibility: -#ifdef BOOST_RE_STATIC_LIB +#ifdef BOOST_PYTHON_STATIC_LIB # define BOOST_PYTHON_STATIC_LINK #endif -#if defined(BOOST_MSVC) && defined(_DLL) +#if defined(BOOST_MSVC) && defined(_DLL) && !defined(BOOST_PYTHON_HAS_DLL_RUNTIME) # define BOOST_PYTHON_HAS_DLL_RUNTIME #endif -#if defined(__BORLANDC__) && defined(_RTLDLL) +#if defined(__BORLANDC__) && defined(_RTLDLL) && !defined(BOOST_PYTHON_HAS_DLL_RUNTIME) # define BOOST_PYTHON_HAS_DLL_RUNTIME #endif -#if defined(__ICL) && defined(_DLL) +#if defined(__ICL) && defined(_DLL) && !defined(BOOST_PYTHON_HAS_DLL_RUNTIME) # define BOOST_PYTHON_HAS_DLL_RUNTIME #endif -#if defined(BOOST_PYTHON_HAS_DLL_RUNTIME) && !defined(BOOST_PYTHON_STATIC_LINK) +#if defined(BOOST_PYTHON_DYNAMIC_LIB) && defined(_WIN32) // && !defined(BOOST_PYTHON_STATIC_LINK) # if defined(BOOST_PYTHON_SOURCE) # define BOOST_PYTHON_DECL __declspec(dllexport) # define BOOST_PYTHON_BUILD_DLL @@ -102,7 +102,7 @@ #endif #if (defined(BOOST_MSVC) || defined(__BORLANDC__)) && !defined(BOOST_PYTHON_NO_LIB) && !defined(BOOST_PYTHON_SOURCE) -# include +// # include #endif // Borland C++ Fix/error check: @@ -117,7 +117,7 @@ # endif # endif # ifndef _RTLDLL - // this is harmless for a staic link: + // this is harmless for a static link: # define _RWSTD_COMPILE_INSTANTIATE # endif # endif diff --git a/include/boost/python/detail/python_library_include.hpp b/include/boost/python/detail/python_library_include.hpp index 903f02be..d2b78c6e 100644 --- a/include/boost/python/detail/python_library_include.hpp +++ b/include/boost/python/detail/python_library_include.hpp @@ -1,3 +1,4 @@ +#error obsolete /* * * Copyright (c) 1998-2000 diff --git a/include/boost/python/detail/returning.hpp b/include/boost/python/detail/returning.hpp new file mode 100644 index 00000000..28f1846e --- /dev/null +++ b/include/boost/python/detail/returning.hpp @@ -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 +# include +# include +# include +# include + +namespace boost { namespace python { namespace detail { + +// Calling C++ from Python +template +struct returning +{ + template + static PyObject* call(R (A0::*pmf)(), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + + // find the result converter + wrap_more r(c0); + if (!c0) return 0; + return r( ((*c0).*pmf)() ); + }; + template + static PyObject* call(R (A0::*pmf)(A1), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + + // find the result converter + wrap_more r(c1); + if (!c0) return 0; + return r( ((*c0).*pmf)(*c1) ); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + + // find the result converter + wrap_more r(c2); + if (!c0) return 0; + return r( ((*c0).*pmf)(*c1, *c2) ); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + + // find the result converter + wrap_more r(c3); + if (!c0) return 0; + return r( ((*c0).*pmf)(*c1, *c2, *c3) ); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + + // find the result converter + wrap_more r(c4); + if (!c0) return 0; + return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) ); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + unwrap_more c5(PyTuple_GET_ITEM(args, 5), c4); + + // find the result converter + wrap_more r(c5); + if (!c0) return 0; + return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5) ); + }; + + template + static PyObject* call(R (A0::*pmf)() const, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + + // find the result converter + wrap_more r(c0); + if (!c0) return 0; + return r( ((*c0).*pmf)() ); + }; + template + static PyObject* call(R (A0::*pmf)(A1) const, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + + // find the result converter + wrap_more r(c1); + if (!c0) return 0; + return r( ((*c0).*pmf)(*c1) ); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2) const, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + + // find the result converter + wrap_more r(c2); + if (!c0) return 0; + return r( ((*c0).*pmf)(*c1, *c2) ); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3) const, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + + // find the result converter + wrap_more r(c3); + if (!c0) return 0; + return r( ((*c0).*pmf)(*c1, *c2, *c3) ); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + + // find the result converter + wrap_more r(c4); + if (!c0) return 0; + return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) ); + }; + template + 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 c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + unwrap_more c5(PyTuple_GET_ITEM(args, 5), c4); + + // find the result converter + wrap_more r(c5); + if (!c0) return 0; + return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5) ); + }; + + template + static PyObject* call(R (A0::*pmf)() volatile, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + + // find the result converter + wrap_more r(c0); + if (!c0) return 0; + return r( ((*c0).*pmf)() ); + }; + template + static PyObject* call(R (A0::*pmf)(A1) volatile, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + + // find the result converter + wrap_more r(c1); + if (!c0) return 0; + return r( ((*c0).*pmf)(*c1) ); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2) volatile, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + + // find the result converter + wrap_more r(c2); + if (!c0) return 0; + return r( ((*c0).*pmf)(*c1, *c2) ); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3) volatile, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + + // find the result converter + wrap_more r(c3); + if (!c0) return 0; + return r( ((*c0).*pmf)(*c1, *c2, *c3) ); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) volatile, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + + // find the result converter + wrap_more r(c4); + if (!c0) return 0; + return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) ); + }; + template + 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 c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + unwrap_more c5(PyTuple_GET_ITEM(args, 5), c4); + + // find the result converter + wrap_more 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 + static PyObject* call(R (A0::*pmf)() const volatile, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + + // find the result converter + wrap_more r(c0); + if (!c0) return 0; + return r( ((*c0).*pmf)() ); + }; + template + static PyObject* call(R (A0::*pmf)(A1) const volatile, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + + // find the result converter + wrap_more r(c1); + if (!c0) return 0; + return r( ((*c0).*pmf)(*c1) ); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2) const volatile, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + + // find the result converter + wrap_more r(c2); + if (!c0) return 0; + return r( ((*c0).*pmf)(*c1, *c2) ); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3) const volatile, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + + // find the result converter + wrap_more r(c3); + if (!c0) return 0; + return r( ((*c0).*pmf)(*c1, *c2, *c3) ); + }; + template + 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 c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + + // find the result converter + wrap_more r(c4); + if (!c0) return 0; + return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) ); + }; + template + 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 c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + unwrap_more c5(PyTuple_GET_ITEM(args, 5), c4); + + // find the result converter + wrap_more 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; + return r( (*pf)() ); + }; + template + static PyObject* call(R (*pf)(A0), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + + // find the result converter + wrap_more r(c0); + if (!c0) return 0; + return r( (*pf)(*c0) ); + }; + template + static PyObject* call(R (*pf)(A0, A1), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + + // find the result converter + wrap_more r(c1); + if (!c0) return 0; + return r( (*pf)(*c0, *c1) ); + }; + template + static PyObject* call(R (*pf)(A0, A1, A2), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + + // find the result converter + wrap_more r(c2); + if (!c0) return 0; + return r( (*pf)(*c0, *c1, *c2) ); + }; + template + static PyObject* call(R (*pf)(A0, A1, A2, A3), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + + // find the result converter + wrap_more r(c3); + if (!c0) return 0; + return r( (*pf)(*c0, *c1, *c2, *c3) ); + }; + template + static PyObject* call(R (*pf)(A0, A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + + // find the result converter + wrap_more r(c4); + if (!c0) return 0; + return r( (*pf)(*c0, *c1, *c2, *c3, *c4) ); + }; + template + static PyObject* call(R (*pf)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + unwrap_more c5(PyTuple_GET_ITEM(args, 5), c4); + + // find the result converter + wrap_more r(c5); + if (!c0) return 0; + return r( (*pf)(*c0, *c1, *c2, *c3, *c4, *c5) ); + }; +}; + +template <> +struct returning +{ + typedef void R; + template + static PyObject* call(R (A0::*pmf)(), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + + if (!c0) return 0; + ((*c0).*pmf)(); + return detail::none(); + }; + template + static PyObject* call(R (A0::*pmf)(A1), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + + if (!c0) return 0; + ((*c0).*pmf)(*c1); + return detail::none(); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + + if (!c0) return 0; + ((*c0).*pmf)(*c1, *c2); + return detail::none(); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + + if (!c0) return 0; + ((*c0).*pmf)(*c1, *c2, *c3); + return detail::none(); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + + if (!c0) return 0; + ((*c0).*pmf)(*c1, *c2, *c3, *c4); + return detail::none(); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + unwrap_more c5(PyTuple_GET_ITEM(args, 5), c4); + + if (!c0) return 0; + ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5); + return detail::none(); + }; + + template + static PyObject* call(R (A0::*pmf)() const, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + + if (!c0) return 0; + ((*c0).*pmf)(); + return detail::none(); + }; + template + static PyObject* call(R (A0::*pmf)(A1) const, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + + if (!c0) return 0; + ((*c0).*pmf)(*c1); + return detail::none(); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2) const, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + + if (!c0) return 0; + ((*c0).*pmf)(*c1, *c2); + return detail::none(); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3) const, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + + if (!c0) return 0; + ((*c0).*pmf)(*c1, *c2, *c3); + return detail::none(); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + + if (!c0) return 0; + ((*c0).*pmf)(*c1, *c2, *c3, *c4); + return detail::none(); + }; + template + 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 c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + unwrap_more c5(PyTuple_GET_ITEM(args, 5), c4); + + if (!c0) return 0; + ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5); + return detail::none(); + }; + + template + static PyObject* call(R (A0::*pmf)() volatile, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + + if (!c0) return 0; + ((*c0).*pmf)(); + return detail::none(); + }; + template + static PyObject* call(R (A0::*pmf)(A1) volatile, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + + if (!c0) return 0; + ((*c0).*pmf)(*c1); + return detail::none(); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2) volatile, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + + if (!c0) return 0; + ((*c0).*pmf)(*c1, *c2); + return detail::none(); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3) volatile, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + + if (!c0) return 0; + ((*c0).*pmf)(*c1, *c2, *c3); + return detail::none(); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) volatile, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + + if (!c0) return 0; + ((*c0).*pmf)(*c1, *c2, *c3, *c4); + return detail::none(); + }; + template + 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 c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + unwrap_more 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 + static PyObject* call(R (A0::*pmf)() const volatile, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + + if (!c0) return 0; + ((*c0).*pmf)(); + return detail::none(); + }; + template + static PyObject* call(R (A0::*pmf)(A1) const volatile, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + + if (!c0) return 0; + ((*c0).*pmf)(*c1); + return detail::none(); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2) const volatile, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + + if (!c0) return 0; + ((*c0).*pmf)(*c1, *c2); + return detail::none(); + }; + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3) const volatile, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + + if (!c0) return 0; + ((*c0).*pmf)(*c1, *c2, *c3); + return detail::none(); + }; + template + 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 c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + + if (!c0) return 0; + ((*c0).*pmf)(*c1, *c2, *c3, *c4); + return detail::none(); + }; + template + 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 c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + unwrap_more 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 + static PyObject* call(R (*pf)(A0), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + + if (!c0) return 0; + (*pf)(*c0); + return detail::none(); + }; + template + static PyObject* call(R (*pf)(A0, A1), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + + if (!c0) return 0; + (*pf)(*c0, *c1); + return detail::none(); + }; + template + static PyObject* call(R (*pf)(A0, A1, A2), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + + if (!c0) return 0; + (*pf)(*c0, *c1, *c2); + return detail::none(); + }; + template + static PyObject* call(R (*pf)(A0, A1, A2, A3), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + + if (!c0) return 0; + (*pf)(*c0, *c1, *c2, *c3); + return detail::none(); + }; + template + static PyObject* call(R (*pf)(A0, A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + + if (!c0) return 0; + (*pf)(*c0, *c1, *c2, *c3, *c4); + return detail::none(); + }; + template + static PyObject* call(R (*pf)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); + unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + unwrap_more 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 + diff --git a/include/boost/python/detail/types.hpp b/include/boost/python/detail/types.hpp index f4e62f88..2e69d24e 100644 --- a/include/boost/python/detail/types.hpp +++ b/include/boost/python/detail/types.hpp @@ -31,12 +31,8 @@ namespace boost { namespace python { -class string; - namespace detail { -class instance_holder_base; - class BOOST_PYTHON_DECL type_object_base : public python_type { public: diff --git a/include/boost/python/detail/void_adaptor.hpp b/include/boost/python/detail/void_adaptor.hpp index 3d60e4bf..3b4b2124 100644 --- a/include/boost/python/detail/void_adaptor.hpp +++ b/include/boost/python/detail/void_adaptor.hpp @@ -8,7 +8,7 @@ namespace boost { namespace python { namespace detail { - BOOST_PYTHON_DECL extern PyObject arbitrary_object; + extern BOOST_PYTHON_DECL PyObject arbitrary_object; template struct void_adaptor diff --git a/include/boost/python/detail/wrap_python.hpp b/include/boost/python/detail/wrap_python.hpp index 34a9c2b5..d0ad5dd2 100644 --- a/include/boost/python/detail/wrap_python.hpp +++ b/include/boost/python/detail/wrap_python.hpp @@ -34,36 +34,36 @@ // Some things we need in order to get Python.h to work with compilers other // than MSVC on Win32 // -#if defined(_WIN32) +#if defined(_WIN32) || defined(__CYGWIN__) # 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 +# if 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 # 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__) diff --git a/include/boost/python/errors.hpp b/include/boost/python/errors.hpp index 66f15587..b9eb4363 100644 --- a/include/boost/python/errors.hpp +++ b/include/boost/python/errors.hpp @@ -9,57 +9,31 @@ #ifndef ERRORS_DWA052500_H_ # define ERRORS_DWA052500_H_ +# include # include +# include namespace boost { namespace python { struct error_already_set {}; struct argument_error : error_already_set {}; -struct object_functor_base -{ - typedef PyObject* result_type; - virtual PyObject* operator()() const = 0; - private: - static void* operator new(std::size_t); // don't allow dynamic allocation - void operator delete(void*); - void operator delete(void*, size_t); -}; - -template -struct object_functor : object_functor_base -{ - object_functor(T const& f) - : m_f(f) - { - } - - PyObject* operator()() const - { - return m_f(); - } - private: - T const& m_f; -}; - - // Handles exceptions caught just before returning to Python code. -PyObject* handle_exception_impl(object_functor_base const& f); +// Returns true iff an exception was caught. +BOOST_PYTHON_DECL bool handle_exception_impl(function0); template -PyObject* handle_exception(T const& f) +bool handle_exception(T f) { - return handle_exception_impl(object_functor(f)); + return handle_exception_impl(function0(boost::ref(f))); } -void handle_exception(void (*)()); +BOOST_PYTHON_DECL PyObject* expect_non_null(PyObject* x); template T* expect_non_null(T* x) { - if (x == 0) - throw error_already_set(); - return x; + return (T*)expect_non_null((PyObject*)x); } }} // namespace boost::python diff --git a/include/boost/python/export.hpp b/include/boost/python/export.hpp new file mode 100644 index 00000000..1229dffe --- /dev/null +++ b/include/boost/python/export.hpp @@ -0,0 +1,20 @@ +// 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 EXPORT_DWA20011220_HPP +# define EXPORT_DWA20011220_HPP + +# include +# ifdef _WIN32 +# ifdef BOOST_PYTHON_SOURCE +# define BOOST_PYTHON_EXPORT __declspec(dllexport) +# else +# define BOOST_PYTHON_EXPORT __declspec(dllimport) +# endif +# else +# define BOOST_PYTHON_EXPORT +# endif + +#endif // EXPORT_DWA20011220_HPP diff --git a/include/boost/python/make_function.hpp b/include/boost/python/make_function.hpp new file mode 100644 index 00000000..d824c0a4 --- /dev/null +++ b/include/boost/python/make_function.hpp @@ -0,0 +1,40 @@ +// 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 MAKE_FUNCTION_DWA20011221_HPP +# define MAKE_FUNCTION_DWA20011221_HPP + +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { + +template +PyObject* make_function(F f) +{ + return new object::function( + object::py_function( + bind(detail::caller(), f, _1, _2))); +} + +template +PyObject* make_constructor(T* = 0, ArgList* = 0, Generator* = 0) +{ + enum { nargs = mpl::size::value }; + return new object::function( + object::py_function( + bind(detail::caller(), + object::make_holder + ::template apply::execute + , _1, _2))); +} + +}} // namespace boost::python + +#endif // MAKE_FUNCTION_DWA20011221_HPP diff --git a/include/boost/python/module.hpp b/include/boost/python/module.hpp new file mode 100644 index 00000000..c20279c3 --- /dev/null +++ b/include/boost/python/module.hpp @@ -0,0 +1,12 @@ +// 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 MODULE_DWA2001128_HPP +# define MODULE_DWA2001128_HPP + +# include +# include + +#endif // MODULE_DWA20011221_HPP diff --git a/include/boost/python/module_builder.hpp b/include/boost/python/module_builder.hpp index 6a8a9b4b..180a6200 100644 --- a/include/boost/python/module_builder.hpp +++ b/include/boost/python/module_builder.hpp @@ -16,30 +16,18 @@ namespace boost { namespace python { -class module_builder +class BOOST_PYTHON_DECL module_builder_base { public: // Create a module. REQUIRES: only one module_builder is created per module. - module_builder(const char* name); - ~module_builder(); + module_builder_base(const char* name); + ~module_builder_base(); // Add elements to the module void add(detail::function* x, const char* name); void add(PyTypeObject* x, const char* name = 0); void add(ref x, const char*name); - template - void def_raw(Fn fn, const char* name) - { - add(detail::new_raw_arguments_function(fn), name); - } - - template - void def(Fn fn, const char* name) - { - add(detail::new_wrapped_function(fn), name); - } - // Return true iff a module is currently being built. static bool initializing(); @@ -55,10 +43,29 @@ class module_builder static PyMethodDef initial_methods[1]; }; +class module_builder : public module_builder_base +{ + public: + module_builder(const char* name) + : module_builder_base(name) {} + + template + void def_raw(Fn fn, const char* name) + { + add(detail::new_raw_arguments_function(fn), name); + } + + template + void def(Fn fn, const char* name) + { + add(detail::new_wrapped_function(fn), name); + } +}; + // // inline implementations // -inline PyObject* module_builder::module() const +inline PyObject* module_builder_base::module() const { return m_module; } diff --git a/include/boost/python/object/class.hpp b/include/boost/python/object/class.hpp new file mode 100644 index 00000000..548d4053 --- /dev/null +++ b/include/boost/python/object/class.hpp @@ -0,0 +1,103 @@ +// 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 CLASS_DWA20011214_HPP +# define CLASS_DWA20011214_HPP + +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace object { + +template struct holder; + +// Base class for all holders +struct BOOST_PYTHON_EXPORT holder_base : noncopyable +{ + public: + holder_base(converter::type_id_t id); + virtual ~holder_base(); + virtual bool held_by_value() const = 0; + + holder_base* next() const; + converter::type_id_t type() const; + + void install(PyObject* inst); + + struct iterator_policies : default_iterator_policies + { + template + void increment(Iterator& p) + { + p.base() = p.base()->next(); + } + }; + + typedef iterator_adaptor< + holder_base* + , iterator_policies + , value_type_is + , reference_is + , pointer_is + , iterator_category_is > iterator; + + private: + converter::type_id_t m_type; + holder_base* m_next; +}; + +// Abstract base class which holds a Held, somehow. Provides a uniform +// way to get a pointer to the held object +template +struct holder : holder_base +{ + typedef Held held_type; + holder(); + virtual Held* target() = 0; +}; + +// Each extension instance will be one of these +struct instance +{ + PyObject_HEAD + holder_base* objects; +}; + +BOOST_PYTHON_EXPORT holder_base* find_holder_impl(PyObject*, converter::type_id_t); + +template +holder* find_holder(PyObject* p, T* = 0) +{ + return static_cast*>(find_holder_impl(p, converter::type_id())); +} + +BOOST_PYTHON_EXPORT PyTypeObject* class_metatype(); +BOOST_PYTHON_EXPORT PyTypeObject* class_type(); + +// +// implementation +// +inline holder_base* holder_base::next() const +{ + return m_next; +} + +inline converter::type_id_t holder_base::type() const +{ + return m_type; +} + +template +holder::holder() + : holder_base(converter::type_id()) +{ +} + +}}} // namespace boost::python::object + +#endif // CLASS_DWA20011214_HPP diff --git a/include/boost/python/object/class_unwrapper.hpp b/include/boost/python/object/class_unwrapper.hpp new file mode 100644 index 00000000..4fa441e1 --- /dev/null +++ b/include/boost/python/object/class_unwrapper.hpp @@ -0,0 +1,40 @@ +// 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 CLASS_UNWRAPPER_DWA20011221_HPP +# define CLASS_UNWRAPPER_DWA20011221_HPP + +# include +# include + +namespace boost { namespace python { namespace object { + +template +struct class_unwrapper +{ + private: + template + struct reference_unwrapper : converter::unwrapper + { + bool convertible(PyObject* p) const + { + return find_holder(p) != 0; + } + + Target convert(PyObject* p, void*&) const + { + return *find_holder(p)->target(); + } + }; + + reference_unwrapper m_reference; +# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + reference_unwrapper m_const_reference; +# endif +}; + +}}} // namespace boost::python::object + +#endif // CLASS_UNWRAPPER_DWA20011221_HPP diff --git a/include/boost/python/object/construct.hpp b/include/boost/python/object/construct.hpp new file mode 100644 index 00000000..3ff701d2 --- /dev/null +++ b/include/boost/python/object/construct.hpp @@ -0,0 +1,24 @@ +// 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 CONSTRUCT_DWA20011215_HPP +# define CONSTRUCT_DWA20011215_HPP + +namespace boost { namespace python { namespace object { + +template +struct construct +{ + static + template +# include +# include +# include + +namespace boost { namespace python { namespace object { + +// A little metaprogram which selects the type to pass through an +// intermediate forwarding function when the destination argument type +// is T. +template +struct forward +{ + typedef typename mpl::select_type< + is_scalar::value | is_reference::value + , T + , reference_wrapper< + typename add_const::type + > + >::type type; +}; + +}}} // namespace boost::python::object + +#endif // FORWARD_DWA20011215_HPP diff --git a/include/boost/python/object/function.hpp b/include/boost/python/object/function.hpp new file mode 100644 index 00000000..f550e8dc --- /dev/null +++ b/include/boost/python/object/function.hpp @@ -0,0 +1,36 @@ +// 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 FUNCTION_DWA20011214_HPP +# define FUNCTION_DWA20011214_HPP + +# include +# include +# include + +namespace boost { namespace python { namespace object { + +// We use boost::function to avoid generating lots of virtual tables +typedef boost::function2 py_function; + +struct BOOST_PYTHON_EXPORT function : PyObject +{ + function(py_function); + ~function(); + + PyObject* call(PyObject*, PyObject*) const; + private: + py_function m_fn; +}; + +extern BOOST_PYTHON_EXPORT PyTypeObject function_type; + +// +// implementations +// + +}}} // namespace boost::python::object + +#endif // FUNCTION_DWA20011214_HPP diff --git a/include/boost/python/object/make_holder.hpp b/include/boost/python/object/make_holder.hpp new file mode 100644 index 00000000..fb5ec382 --- /dev/null +++ b/include/boost/python/object/make_holder.hpp @@ -0,0 +1,124 @@ +// 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 MAKE_HOLDER_DWA20011215_HPP +# define MAKE_HOLDER_DWA20011215_HPP + +# include +# include +# include +# include + +namespace boost { namespace python { namespace object { + + +template struct undefined; +template +struct eval +{ +# if defined(BOOST_MSVC) && BOOST_MSVC <= 1200 + // based on the (non-conforming) MSVC trick from MPL + template + struct unarymetafunction_vc : UnaryMetaFunction {}; + + // illegal C++ which causes VC to admit that unarymetafunction_vc + // can have a nested template: + template<> + struct unarymetafunction_vc + { + template struct apply; + }; + + typedef typename unarymetafunction_vc< + ::boost::mpl::detail::msvc_never_true::value + >::template apply::type type; +# else + typedef typename UnaryMetaFunction::template apply::type type; +# endif +}; + + +template struct make_holder; + +template <> +struct make_holder<0> +{ + template + struct apply + { + typedef typename eval::type holder; + static void execute( + PyObject* p) + { + (new holder(p))->install(p); + } + }; +}; + + +template <> +struct make_holder<1> +{ + template + struct apply + { + typedef typename eval::type holder; + typedef typename mpl::at<0,ArgList>::type t0; + typedef typename forward::type f0; + + static void execute( + PyObject* p + , t0 a0) + { + (new holder(p, f0(a0)))->install(p); + } + }; +}; + +template <> +struct make_holder<2> +{ + template + struct apply + { + typedef typename eval::type holder; + typedef typename mpl::at<0,ArgList>::type t0; + typedef typename forward::type f0; + typedef typename mpl::at<1,ArgList>::type t1; + typedef typename forward::type f1; + + static void execute( + PyObject* p, t0 a0, t1 a1) + { + (new holder(p, f0(a0), f1(a1)))->install(p); + } + }; +}; + +template <> +struct make_holder<3> +{ + template + struct apply + { + typedef typename eval::type holder; + typedef typename mpl::at<0,ArgList>::type t0; + typedef typename forward::type f0; + typedef typename mpl::at<1,ArgList>::type t1; + typedef typename forward::type f1; + typedef typename mpl::at<2,ArgList>::type t2; + typedef typename forward::type f2; + + static void execute( + PyObject* p, t0 a0, t1 a1, t2 a2) + { + (new holder(p, f0(a0), f1(a1), f2(a2)))->install(p); + } + }; +}; + +}}} // namespace boost::python::object + +#endif // MAKE_HOLDER_DWA20011215_HPP diff --git a/include/boost/python/object/value_holder.hpp b/include/boost/python/object/value_holder.hpp new file mode 100644 index 00000000..128d170b --- /dev/null +++ b/include/boost/python/object/value_holder.hpp @@ -0,0 +1,80 @@ +// 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 VALUE_HOLDER_DWA20011215_HPP +# define VALUE_HOLDER_DWA20011215_HPP + +# include + +namespace boost { namespace python { namespace object { + +template +struct value_holder : holder +{ + // Forward construction to the held object + value_holder(PyObject*) + : m_held() {} + + template + value_holder(PyObject*, A1 a1) + : m_held(a1) {} + + template + value_holder(PyObject*, A1 a1, A2 a2) + : m_held(a1, a2) {} + + template + value_holder(PyObject*, A1 a1, A2 a2, A3 a3) + : m_held(a1, a2, a3) {} + + template + value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) + : m_held(a1, a2, a3, a4) {} + + template + value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) + : m_held(a1, a2, a3, a4, a5) {} + + template + value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) + : m_held(a1, a2, a3, a4, a5, a6) {} + + template + value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) + : m_held(a1, a2, a3, a4, a5, a6, a7) {} + + template + value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) + : m_held(a1, a2, a3, a4, a5, a6, a7, a8) {} + + template + value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) + : m_held(a1, a2, a3, a4, a5, a6, a7, a8, a9) {} + + template + value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) + : m_held(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {} + + private: // required holder implementation + Held* target() { return &m_held; } + bool held_by_value() const { return true; } + + private: // data members + Held m_held; +}; + +// A generator metafunction which can be passed to make_holder +struct value_holder_generator +{ + template + struct apply + { + typedef value_holder type; + }; +}; + +}}} // namespace boost::python::object + +#endif // VALUE_HOLDER_DWA20011215_HPP diff --git a/include/boost/python/objects.hpp b/include/boost/python/objects.hpp index 3b1a9094..93173462 100644 --- a/include/boost/python/objects.hpp +++ b/include/boost/python/objects.hpp @@ -17,7 +17,7 @@ namespace boost { namespace python { -class object +class BOOST_PYTHON_DECL object { public: explicit object(ref p); @@ -32,15 +32,36 @@ class object ref m_p; }; -class tuple : public object +class tuple; + +class BOOST_PYTHON_DECL tuple_base : public object { public: - explicit tuple(std::size_t n = 0); - explicit tuple(ref p); + explicit tuple_base(std::size_t n = 0); + explicit tuple_base(ref p); + + static PyTypeObject* type_obj(); + static bool accepts(ref p); + std::size_t size() const; + ref operator[](std::size_t pos) const; + + void set_item(std::size_t pos, const ref& rhs); + + tuple slice(int low, int high) const; + + friend BOOST_PYTHON_DECL tuple operator+(const tuple&, const tuple&); + friend BOOST_PYTHON_DECL tuple& operator+=(tuple&, const tuple&); +}; + +class tuple : public tuple_base +{ + public: + explicit tuple(std::size_t n = 0) : tuple_base(n) {} + explicit tuple(ref p) : tuple_base(p) {} template tuple(const std::pair& x) - : object(ref(PyTuple_New(2))) + : tuple_base(ref(PyTuple_New(2))) { set_item(0, x.first); set_item(1, x.second); @@ -48,7 +69,7 @@ class tuple : public object template tuple(const First& first, const Second& second) - : object(ref(PyTuple_New(2))) + : tuple_base(ref(PyTuple_New(2))) { set_item(0, first); set_item(1, second); @@ -56,7 +77,7 @@ class tuple : public object template tuple(const First& first, const Second& second, const Third& third) - : object(ref(PyTuple_New(3))) + : tuple_base(ref(PyTuple_New(3))) { set_item(0, first); set_item(1, second); @@ -65,7 +86,7 @@ class tuple : public object template tuple(const First& first, const Second& second, const Third& third, const Fourth& fourth) - : object(ref(PyTuple_New(4))) + : tuple_base(ref(PyTuple_New(4))) { set_item(0, first); set_item(1, second); @@ -73,32 +94,31 @@ class tuple : public object set_item(3, fourth); } - static PyTypeObject* type_obj(); - static bool accepts(ref p); - std::size_t size() const; - ref operator[](std::size_t pos) const; - template void set_item(std::size_t pos, const T& rhs) { this->set_item(pos, make_ref(rhs)); } - - void set_item(std::size_t pos, const ref& rhs); - - tuple slice(int low, int high) const; - friend tuple operator+(const tuple&, const tuple&); - tuple& operator+=(const tuple& rhs); + void set_item(std::size_t pos, const ref& rhs) + { + tuple_base::set_item(pos, rhs); + } }; -class list : public object +class list; + +struct BOOST_PYTHON_DECL list_proxy; +struct BOOST_PYTHON_DECL list_slice_proxy; + +class BOOST_PYTHON_DECL list_base : public object { - struct proxy; - struct slice_proxy; + protected: + typedef list_proxy proxy; + typedef list_slice_proxy slice_proxy; public: - explicit list(ref p); - explicit list(std::size_t sz = 0); + explicit list_base(ref p); + explicit list_base(std::size_t sz = 0); static PyTypeObject* type_obj(); static bool accepts(ref p); std::size_t size() const; @@ -106,26 +126,14 @@ class list : public object proxy operator[](std::size_t pos); ref get_item(std::size_t pos) const; - template - void set_item(std::size_t pos, const T& x) - { this->set_item(pos, make_ref(x)); } void set_item(std::size_t pos, const ref& ); // void set_item(std::size_t pos, const object& ); - template - void insert(std::size_t index, const T& x) - { this->insert(index, make_ref(x)); } void insert(std::size_t index, const ref& item); - template - void push_back(const T& item) - { this->push_back(make_ref(item)); } void push_back(const ref& item); - template - void append(const T& item) - { this->append(make_ref(item)); } void append(const ref& item); list slice(int low, int high) const; @@ -135,7 +143,31 @@ class list : public object tuple as_tuple() const; }; -class string +class list : public list_base +{ + public: + explicit list(ref p) : list_base(p) {} + explicit list(std::size_t sz = 0) : list_base(sz) {} + template + void set_item(std::size_t pos, const T& x) + { this->set_item(pos, make_ref(x)); } + template + void insert(std::size_t index, const T& x) + { this->insert(index, make_ref(x)); } + template + void push_back(const T& item) + { this->push_back(make_ref(item)); } + template + void append(const T& item) + { this->append(make_ref(item)); } + + void set_item(std::size_t pos, const ref& x) { list_base::set_item(pos, x); } + void insert(std::size_t index, const ref& item) { list_base::insert(index, item); } + void push_back(const ref& item) { list_base::push_back(item); } + void append(const ref& item) { list_base::append(item); } +}; + +class BOOST_PYTHON_DECL string : public object, public boost::multipliable2 { public: @@ -175,48 +207,31 @@ class string friend string operator%(const string& format, const tuple& args); }; -class dictionary : public object +class dictionary; + +struct BOOST_PYTHON_DECL dictionary_proxy; + +class BOOST_PYTHON_DECL dictionary_base : public object { - private: - struct proxy; + protected: + typedef dictionary_proxy proxy; public: - explicit dictionary(ref p); - dictionary(); + explicit dictionary_base(ref p); + dictionary_base(); void clear(); static PyTypeObject* type_obj(); static bool accepts(ref p); public: - template - proxy operator[](const Key& key) - { return this->operator[](make_ref(key)); } proxy operator[](ref key); - - template - ref operator[](const Key& key) const - { return this->operator[](make_ref(key)); } ref operator[](ref key) const; - - template - ref get_item(const Key& key) const - { return this->get_item(make_ref(key)); } ref get_item(const ref& key) const; - - template - ref get_item(const Key& key, const Default& default_) const - { return this->get_item(make_ref(key), make_ref(default_)); } ref get_item(const ref& key, const ref& default_) const; - template - void set_item(const Key& key, const Value& value) - { this->set_item(make_ref(key), make_ref(value)); } void set_item(const ref& key, const ref& value); - template - void erase(const Key& key) - { this->erase(make_ref(key)); } void erase(ref key); // proxy operator[](const object& key); @@ -235,7 +250,7 @@ class dictionary : public object // TODO: iterator support }; -struct dictionary::proxy +struct BOOST_PYTHON_DECL dictionary_proxy { template const ref& operator=(const T& rhs) @@ -244,19 +259,63 @@ struct dictionary::proxy operator ref() const; private: - friend class dictionary; - proxy(const ref& dict, const ref& key); + friend class dictionary_base; + dictionary_proxy(const ref& dict, const ref& key); // This is needed to work around the very strange MSVC error report that the // return type of the built-in operator= differs from that of the ones // defined above. Couldn't hurt to make these un-assignable anyway, though. - const ref& operator=(const proxy&); // Not actually implemented + const ref& operator=(const dictionary_proxy&); // Not actually implemented private: ref m_dict; ref m_key; }; -struct list::proxy +class dictionary : public dictionary_base +{ + typedef dictionary_proxy proxy; + public: + explicit dictionary(ref p) : dictionary_base(p) {} + dictionary() : dictionary_base() {} + + template + proxy operator[](const Key& key) + { return this->operator[](make_ref(key)); } + proxy operator[](ref key) + { return dictionary_base::operator[](key); } + + template + ref operator[](const Key& key) const + { return this->operator[](make_ref(key)); } + ref operator[](ref key) const + { return dictionary_base::operator[](key); } + + template + ref get_item(const Key& key) const + { return this->get_item(make_ref(key)); } + ref get_item(const ref& key) const + { return dictionary_base::get_item(key); } + + template + ref get_item(const Key& key, const Default& default_) const + { return this->get_item(make_ref(key), make_ref(default_)); } + ref get_item(const ref& key, const ref& default_) const + { return dictionary_base::get_item(key, default_); } + + template + void set_item(const Key& key, const Value& value) + { this->set_item(make_ref(key), make_ref(value)); } + void set_item(const ref& key, const ref& value) + { dictionary_base::set_item(key, value); } + + template + void erase(const Key& key) + { this->erase(make_ref(key)); } + void erase(ref key) + { dictionary_base::erase(key); } +}; + +struct BOOST_PYTHON_DECL list_proxy { template const ref& operator=(const T& rhs) @@ -266,19 +325,19 @@ struct list::proxy operator ref() const; private: - friend class list; - proxy(const ref& list, std::size_t index); + friend class list_base; + list_proxy(const ref& list, std::size_t index); // This is needed to work around the very strange MSVC error report that the // return type of the built-in operator= differs from that of the ones // defined above. Couldn't hurt to make these un-assignable anyway, though. - const ref& operator=(const proxy&); // Not actually implemented + const ref& operator=(const list_proxy&); // Not actually implemented private: list m_list; std::size_t m_index; }; -struct list::slice_proxy +struct BOOST_PYTHON_DECL list_slice_proxy { const list& operator=(const list& rhs); operator ref() const; @@ -286,8 +345,8 @@ struct list::slice_proxy std::size_t size() const; ref operator[](std::size_t pos) const; private: - friend class list; - slice_proxy(const ref& list, int low, int high); + friend class list_base; + list_slice_proxy(const ref& list, int low, int high); private: ref m_list; int m_low, m_high; @@ -297,32 +356,32 @@ struct list::slice_proxy BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE -PyObject* to_python(const boost::python::tuple&); -boost::python::tuple from_python(PyObject* p, boost::python::type); +BOOST_PYTHON_DECL PyObject* to_python(const boost::python::tuple&); +BOOST_PYTHON_DECL boost::python::tuple from_python(PyObject* p, boost::python::type); inline boost::python::tuple from_python(PyObject* p, boost::python::type) { return from_python(p, boost::python::type()); } -PyObject* to_python(const boost::python::list&); -boost::python::list from_python(PyObject* p, boost::python::type); +BOOST_PYTHON_DECL PyObject* to_python(const boost::python::list&); +BOOST_PYTHON_DECL boost::python::list from_python(PyObject* p, boost::python::type); inline boost::python::list from_python(PyObject* p, boost::python::type) { return from_python(p, boost::python::type()); } -PyObject* to_python(const boost::python::string&); -boost::python::string from_python(PyObject* p, boost::python::type); +BOOST_PYTHON_DECL PyObject* to_python(const boost::python::string&); +BOOST_PYTHON_DECL boost::python::string from_python(PyObject* p, boost::python::type); inline boost::python::string from_python(PyObject* p, boost::python::type) { return from_python(p, boost::python::type()); } -PyObject* to_python(const boost::python::dictionary&); -boost::python::dictionary from_python(PyObject* p, boost::python::type); +BOOST_PYTHON_DECL PyObject* to_python(const boost::python::dictionary&); +BOOST_PYTHON_DECL boost::python::dictionary from_python(PyObject* p, boost::python::type); inline boost::python::dictionary from_python(PyObject* p, boost::python::type) { diff --git a/include/boost/python/operators.hpp b/include/boost/python/operators.hpp index 52e52eee..c766c8b6 100644 --- a/include/boost/python/operators.hpp +++ b/include/boost/python/operators.hpp @@ -31,7 +31,7 @@ namespace boost { namespace python { -tuple standard_coerce(ref l, ref r); +BOOST_PYTHON_DECL tuple standard_coerce(ref l, ref r); namespace detail { diff --git a/src/classes.cpp b/src/classes.cpp index f51d1a2f..b018c0ce 100644 --- a/src/classes.cpp +++ b/src/classes.cpp @@ -11,6 +11,8 @@ // 03 Mar 01 added: pickle safety measures (Ralf W. Grosse-Kunstleve) // 03 Mar 01 bug fix: use bound_function::create() (instead of new bound_function) +#define BOOST_PYTHON_SOURCE + #include #include #include @@ -997,7 +999,7 @@ namespace { } } -void adjust_slice_indices(PyObject* obj, int& start, int& finish) +BOOST_PYTHON_DECL void adjust_slice_indices(PyObject* obj, int& start, int& finish) { int length = callback::call_method(obj, "__len__"); diff --git a/src/conversions.cpp b/src/conversions.cpp index f1534dd9..e6b6161a 100644 --- a/src/conversions.cpp +++ b/src/conversions.cpp @@ -16,65 +16,16 @@ #define BOOST_PYTHON_SOURCE #include -#include +#include #include #include #ifndef BOOST_NO_LIMITS # include #endif -namespace boost { namespace python { - -// IMPORTANT: this function may only be called from within a catch block! -PyObject* handle_exception_impl(object_functor_base const& f) -{ - try - { - return f(); - } - catch(const boost::python::error_already_set&) - { - // The python error reporting has already been handled. - } - catch(const std::bad_alloc&) - { - PyErr_NoMemory(); - } - catch(const std::exception& x) - { - PyErr_SetString(PyExc_RuntimeError, x.what()); - } - catch(...) - { - PyErr_SetString(PyExc_RuntimeError, "unidentifiable C++ exception"); - } - return 0; -} - -void handle_exception(void (*f)()) -{ - handle_exception( - boost::python::detail::make_void_adaptor(f)); -} - -namespace detail { - - void expect_complex(PyObject* p) - { - if (!PyComplex_Check(p)) - { - PyErr_SetString(PyExc_TypeError, "expected a complex number"); - throw boost::python::argument_error(); - } - } - -} // namespace boost::python::detail - -}} // namespace boost::python - BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE -long from_python(PyObject* p, boost::python::type) +BOOST_PYTHON_DECL long from_python(PyObject* p, boost::python::type) { // Why am I clearing the error here before trying to convert? I know there's a reason... long result; @@ -86,7 +37,7 @@ long from_python(PyObject* p, boost::python::type) return result; } -double from_python(PyObject* p, boost::python::type) +BOOST_PYTHON_DECL double from_python(PyObject* p, boost::python::type) { double result; { @@ -151,48 +102,48 @@ PyObject* integer_to_python(T value) return to_python(value_as_long); } -int from_python(PyObject* p, boost::python::type type) +BOOST_PYTHON_DECL int from_python(PyObject* p, boost::python::type type) { return integer_from_python(p, type); } -PyObject* to_python(unsigned int i) +BOOST_PYTHON_DECL PyObject* to_python(unsigned int i) { return integer_to_python(i); } -unsigned int from_python(PyObject* p, boost::python::type type) +BOOST_PYTHON_DECL unsigned int from_python(PyObject* p, boost::python::type type) { return integer_from_python(p, type); } -short from_python(PyObject* p, boost::python::type type) +BOOST_PYTHON_DECL short from_python(PyObject* p, boost::python::type type) { return integer_from_python(p, type); } -float from_python(PyObject* p, boost::python::type) +BOOST_PYTHON_DECL float from_python(PyObject* p, boost::python::type) { return static_cast(from_python(p, boost::python::type())); } -PyObject* to_python(unsigned short i) +BOOST_PYTHON_DECL PyObject* to_python(unsigned short i) { return integer_to_python(i); } -unsigned short from_python(PyObject* p, boost::python::type type) +BOOST_PYTHON_DECL unsigned short from_python(PyObject* p, boost::python::type type) { return integer_from_python(p, type); } -PyObject* to_python(char c) +BOOST_PYTHON_DECL PyObject* to_python(char c) { if (c == '\0') return PyString_FromString(""); return PyString_FromStringAndSize(&c, 1); } -char from_python(PyObject* p, boost::python::type) +BOOST_PYTHON_DECL char from_python(PyObject* p, boost::python::type) { int l = -1; if (PyString_Check(p)) l = PyString_Size(p); @@ -204,37 +155,37 @@ char from_python(PyObject* p, boost::python::type) return PyString_AsString(p)[0]; } -PyObject* to_python(unsigned char i) +BOOST_PYTHON_DECL PyObject* to_python(unsigned char i) { return integer_to_python(i); } -unsigned char from_python(PyObject* p, boost::python::type type) +BOOST_PYTHON_DECL unsigned char from_python(PyObject* p, boost::python::type type) { return integer_from_python(p, type); } -PyObject* to_python(signed char i) +BOOST_PYTHON_DECL PyObject* to_python(signed char i) { return integer_to_python(i); } -signed char from_python(PyObject* p, boost::python::type type) +BOOST_PYTHON_DECL signed char from_python(PyObject* p, boost::python::type type) { return integer_from_python(p, type); } -PyObject* to_python(unsigned long x) +BOOST_PYTHON_DECL PyObject* to_python(unsigned long x) { return integer_to_python(x); } -unsigned long from_python(PyObject* p, boost::python::type type) +BOOST_PYTHON_DECL unsigned long from_python(PyObject* p, boost::python::type type) { return integer_from_python(p, type); } -void from_python(PyObject* p, boost::python::type) +BOOST_PYTHON_DECL void from_python(PyObject* p, boost::python::type) { if (p != Py_None) { PyErr_SetString(PyExc_TypeError, "expected argument of type None"); @@ -242,7 +193,7 @@ void from_python(PyObject* p, boost::python::type) } } -const char* from_python(PyObject* p, boost::python::type) +BOOST_PYTHON_DECL const char* from_python(PyObject* p, boost::python::type) { const char* s = PyString_AsString(p); if (!s) @@ -250,12 +201,12 @@ const char* from_python(PyObject* p, boost::python::type) return s; } -PyObject* to_python(const std::string& s) +BOOST_PYTHON_DECL PyObject* to_python(const std::string& s) { return PyString_FromStringAndSize(s.data(), s.size()); } -std::string from_python(PyObject* p, boost::python::type) +BOOST_PYTHON_DECL std::string from_python(PyObject* p, boost::python::type) { if (! PyString_Check(p)) { PyErr_SetString(PyExc_TypeError, "expected a string"); @@ -264,7 +215,7 @@ std::string from_python(PyObject* p, boost::python::type) return std::string(PyString_AsString(p), PyString_Size(p)); } -bool from_python(PyObject* p, boost::python::type) +BOOST_PYTHON_DECL bool from_python(PyObject* p, boost::python::type) { int value = from_python(p, boost::python::type()); if (value == 0) @@ -274,12 +225,12 @@ bool from_python(PyObject* p, boost::python::type) #ifdef BOOST_MSVC6_OR_EARLIER // An optimizer bug prevents these from being inlined. -PyObject* to_python(double d) +BOOST_PYTHON_DECL PyObject* to_python(double d) { return PyFloat_FromDouble(d); } -PyObject* to_python(float f) +BOOST_PYTHON_DECL PyObject* to_python(float f) { return PyFloat_FromDouble(f); } diff --git a/src/converter/body.cpp b/src/converter/body.cpp new file mode 100644 index 00000000..637f8c3e --- /dev/null +++ b/src/converter/body.cpp @@ -0,0 +1,18 @@ +// 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. +#include + +namespace boost { namespace python { namespace converter { + +// default implementation is a no-op. Most handles will not hold any +// data that needs to be managed. Unwrap objects which convert +// by-value are an exception. Fortunately, the concrete body subclass +// has that knowledge. +void body::destroy_handle(handle*) const +{ +} + +}}} // namespace boost::python::converter diff --git a/src/converter/handle.cpp b/src/converter/handle.cpp new file mode 100644 index 00000000..1a2b8c31 --- /dev/null +++ b/src/converter/handle.cpp @@ -0,0 +1,35 @@ +// 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. +#include +#include + +namespace boost { namespace python { namespace converter { + +bool handle::convertible() const +{ + for (handle const* p = this; p != 0; p = p->m_next) + { + if (p->m_body == 0) + return false; + } + return true; +} + +void handle::destroy() +{ + // Recurse down the chain releasing from tail to head + if (m_next != 0) + m_next->destroy(); + + // Our body knows how to destroy us. If we never got a body, + // there's nothing to do. + if (m_body) + m_body->destroy_handle(this); +} + +// void handle::dummy::nonnull() {} + +}}} // namespace boost::python::converter diff --git a/src/converter/registry.cpp b/src/converter/registry.cpp new file mode 100644 index 00000000..88d96637 --- /dev/null +++ b/src/converter/registry.cpp @@ -0,0 +1,177 @@ +// 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. + +# include +# include +# include +# include +# include +# include +# ifdef BOOST_PYTHON_TRACE +# include +# endif + +namespace boost { namespace python { namespace converter { + +namespace // +{ + typedef std::map registry_t; + + registry_t& entries() + { + static registry_t registry; + return registry; + } +} // namespace + +namespace registry +{ + entry* find(type_id_t type) + { + return &entries()[type]; + } + + entry::entry() + : m_wrapper(0) + { + } + + namespace // + { + // A UnaryFunction type which deletes its argument + struct delete_item + { + template + void operator()(T* x) const + { + delete x; + } + }; + + // A UnaryFunction type which returns true iff its argument is a + // unwrapper which can convert the given Python object. + struct convertible + { + convertible(PyObject* p) + : m_p(p) + {} + + bool operator()(unwrapper_base* converter) const + { + return converter->convertible(m_p); + } + + PyObject* m_p; + }; + } + + entry::~entry() + { + if (m_wrapper != 0) + m_wrapper->m_can_unregister = false; + + for (unwrappers::iterator p = m_unwrappers.begin(); p != m_unwrappers.end(); ++p) + { + (*p)->m_can_unregister = false; + } + } + + unwrapper_base* entry::unwrapper(PyObject* p) const + { + unwrappers::const_iterator q = + std::find_if(m_unwrappers.begin(), m_unwrappers.end(), convertible(p)); + + return q == m_unwrappers.end() ? 0 : *q; + } + + wrapper_base* entry::wrapper() const + { + return m_wrapper; + } + + entry::unwrappers::iterator entry::find(unwrapper_base const& x) + { + return std::find(m_unwrappers.begin(), m_unwrappers.end(), &x); + } + + void entry::insert(unwrapper_base& x) + { + unwrappers::iterator p = this->find(x); + + assert(p == m_unwrappers.end()); + if (p != m_unwrappers.end()) + { + throw std::runtime_error( + "trying to register unrapper which is already registered"); + } + m_unwrappers.push_back(&x); + } + + void entry::remove(unwrapper_base& x) + { + unwrappers::iterator p = find(x); + + // Be sure we're not removing a converter which hasn't been + // registered. + assert(p != m_unwrappers.end()); + if (p == m_unwrappers.end()) + { + throw std::runtime_error( + "trying to unregister unwrapper which is not registered"); + } + m_unwrappers.erase(p); + } + + void entry::insert(wrapper_base& x) + { + assert(m_wrapper == 0); // we have a problem otherwise + if (m_wrapper != 0) + { + throw std::runtime_error( + "trying to register wrapper for a type which already has a registered wrapper"); + } + m_wrapper = &x; + } + + void entry::remove(wrapper_base& x) + { + assert(m_wrapper == &x); + if (m_wrapper != &x) + { + throw std::runtime_error( + "trying to unregister a wrapper which is not registered"); + } + m_wrapper = 0; + } + + void insert(wrapper_base& w) + { +# ifdef BOOST_PYTHON_TRACE + std::cout << "inserting wrapper for " << w.key() << std::endl; +# endif + find(w.key())->insert(w); + } + + void insert(unwrapper_base& u) + { +# ifdef BOOST_PYTHON_TRACE + std::cout << "inserting unwrapper for " << u.key() << std::endl; +# endif + find(u.key())->insert(u); + } + + void remove(wrapper_base& w) + { + find(w.key())->remove(w); + } + + void remove(unwrapper_base& u) + { + find(u.key())->remove(u); + } +} // namespace registry + +}}} // namespace boost::python::converter diff --git a/src/converter/type_id.cpp b/src/converter/type_id.cpp new file mode 100644 index 00000000..86974638 --- /dev/null +++ b/src/converter/type_id.cpp @@ -0,0 +1,67 @@ +// 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. + +#include +#if !defined(__GNUC__) || __GNUC__ >= 3 || __SGI_STL_PORT +# include +#else +# include +#endif + +namespace boost { namespace python { namespace converter { + +#if 1 +bool type_id_before::operator()(type_id_t const& x, type_id_t const& y) const +{ + return x < y; +} + +BOOST_PYTHON_EXPORT std::ostream& operator<<(std::ostream& os, type_id_t const& x) +{ +# ifdef BOOST_PYTHON_TYPE_ID_NAME + os << x.m_base_type; +# else + os << x.m_base_type->name(); +# endif + // VC6 mistakenly distinguishes typeid(X) from typeid(X const) + // from typeid(X&)... so the name is already correct. I have it + // from Jason Shirk that VC7.0 has the same bug but it will be + // fixed in 7.1 +# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 + if (x.m_decoration & type_id_t::const_) + os << " const"; + if (x.m_decoration & type_id_t::volatile_) + os << " volatile"; + if (x.m_decoration & type_id_t::reference) + os << "&"; +# endif + return os; +} + +#else +bool type_id_before::operator()(type_id_t const& x, type_id_t const& y) const +{ + for (;;) + { + if (*y == 0) + { + return 0; + } + else if (*x == 0) + { + return 1; + } + else if (*x != *y) + { + return *x < *y; + } + ++x; + ++y; + } +} +#endif + +}}} // namespace boost::python::converter diff --git a/src/converter/unwrap.cpp b/src/converter/unwrap.cpp new file mode 100644 index 00000000..e0c09db6 --- /dev/null +++ b/src/converter/unwrap.cpp @@ -0,0 +1,35 @@ +// 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. + +#include + +namespace boost { namespace python { namespace converter { + +namespace +{ + struct pyobject_unwrapper : unwrapper_base + { + pyobject_unwrapper(); + bool convertible(PyObject*) const; + }; + + pyobject_unwrapper static_unwrapper; + + pyobject_unwrapper::pyobject_unwrapper() + : unwrapper_base(type_id()) + { + } + + bool pyobject_unwrapper::convertible(PyObject*) const + { + return true; + } +} + +BOOST_PYTHON_EXPORT unwrapper_base* +unwrap_more_::m_unwrapper = &static_unwrapper; + +}}} // namespace boost::python::converter diff --git a/src/converter/unwrapper.cpp b/src/converter/unwrapper.cpp new file mode 100644 index 00000000..2b0adbd0 --- /dev/null +++ b/src/converter/unwrapper.cpp @@ -0,0 +1,24 @@ +// 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. +#include +#include +#include + +namespace boost { namespace python { namespace converter { + +unwrapper_base::unwrapper_base(type_id_t key) + : body(key) +{ + registry::insert(*this); +} + +unwrapper_base::~unwrapper_base() +{ + if (can_unregister()) + registry::remove(*this); +} + +}}} // namespace boost::python::converter diff --git a/src/converter/wrapper.cpp b/src/converter/wrapper.cpp new file mode 100644 index 00000000..0d817217 --- /dev/null +++ b/src/converter/wrapper.cpp @@ -0,0 +1,30 @@ +// 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. + +#include +#include + +namespace boost { namespace python { namespace converter { + +wrapper_base::wrapper_base(type_id_t type) + : body(type) +{ + // static assertions for target. These would go in a header, + // but Metrowerks only respects BOOST_STATIC_ASSERT if it is in an + // instantiated function +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +#else +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + registry::insert(*this); +} + +wrapper_base::~wrapper_base() +{ + if (can_unregister()) + registry::remove(*this); +} + +}}} // namespace boost::python::converter diff --git a/src/cross_module.cpp b/src/cross_module.cpp index 5949be4d..2bce5a61 100644 --- a/src/cross_module.cpp +++ b/src/cross_module.cpp @@ -15,7 +15,8 @@ namespace python = boost::python; # include // MSVC6.0SP4 does not know std::fprintf # include // MSVC6.0SP4 does not know std::strcmp -namespace { +namespace +{ PyObject* get_module_dict(const char* module_name) { @@ -26,64 +27,68 @@ namespace { } } -namespace boost { namespace python { namespace detail { +namespace boost { namespace python { -const char* converters_attribute_name = "__converters__"; - -void* import_converter_object(const std::string& module_name, - const std::string& py_class_name, - const std::string& attribute_name) +namespace detail { - static std::string err; - PyObject* module_dict = get_module_dict(const_cast(module_name.c_str())); - PyObject* py_class = PyDict_GetItemString(module_dict, const_cast(py_class_name.c_str())); - if (py_class == 0) { - err = std::string("module ") + module_name + " has no attribute " + py_class_name; - PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); - throw python::import_error(); - } - python::ref c_obj(PyObject_GetAttrString(py_class, const_cast(attribute_name.c_str())), ref::null_ok); - if (c_obj.get() == 0) { - err = std::string("object ") + module_name + "." + py_class_name + BOOST_PYTHON_DECL const char* converters_attribute_name = "__converters__"; + + BOOST_PYTHON_DECL void* import_converter_object(const std::string& module_name, + const std::string& py_class_name, + const std::string& attribute_name) + { + static std::string err; + PyObject* module_dict = get_module_dict(const_cast(module_name.c_str())); + PyObject* py_class = PyDict_GetItemString(module_dict, const_cast(py_class_name.c_str())); + if (py_class == 0) { + err = std::string("module ") + module_name + " has no attribute " + py_class_name; + PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); + throw python::import_error(); + } + python::ref c_obj(PyObject_GetAttrString(py_class, const_cast(attribute_name.c_str())), ref::null_ok); + if (c_obj.get() == 0) { + err = std::string("object ") + module_name + "." + py_class_name + " has no attribute " + attribute_name; - PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); - throw python::import_error(); - } - if (! PyCObject_Check(c_obj.get())) { - err = std::string("object ") + module_name + "." + py_class_name + "." + PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); + throw python::import_error(); + } + if (! PyCObject_Check(c_obj.get())) { + err = std::string("object ") + module_name + "." + py_class_name + "." + attribute_name + " is not a PyCObject"; - PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); - throw python::import_error(); - } - return PyCObject_AsVoidPtr(c_obj.get()); + PyErr_SetString(PyExc_RuntimeError, const_cast(err.c_str())); + throw python::import_error(); + } + return PyCObject_AsVoidPtr(c_obj.get()); + } + + BOOST_PYTHON_DECL void check_export_converters_api(const int importing_major, + const int importing_minor, + const int imported_major, + const int imported_minor) + { + if (importing_major != imported_major) { + // Python uses fprintf(stderr, ...) for API warnings. + fprintf(stderr, + "Fatal: export_converters_api mismatch:" + " Importing module = %d.%d" + " Imported module = %d.%d\n", + importing_major, importing_minor, + imported_major, imported_minor); + PyErr_SetString(PyExc_RuntimeError, + "Fatal: export_converters_api mismatch"); + throw import_error(); + } + if (importing_minor != imported_minor) { + // Python uses fprintf(stderr, ...) for API warnings. + fprintf(stderr, + "Warning: export_converters_api mismatch:" + " Importing module = %d.%d" + " Imported module = %d.%d\n", + importing_major, importing_minor, + imported_major, imported_minor); + } + } + } -void check_export_converters_api(const int importing_major, - const int importing_minor, - const int imported_major, - const int imported_minor) -{ - if (importing_major != imported_major) { - // Python uses fprintf(stderr, ...) for API warnings. - fprintf(stderr, - "Fatal: export_converters_api mismatch:" - " Importing module = %d.%d" - " Imported module = %d.%d\n", - importing_major, importing_minor, - imported_major, imported_minor); - PyErr_SetString(PyExc_RuntimeError, - "Fatal: export_converters_api mismatch"); - throw import_error(); - } - if (importing_minor != imported_minor) { - // Python uses fprintf(stderr, ...) for API warnings. - fprintf(stderr, - "Warning: export_converters_api mismatch:" - " Importing module = %d.%d" - " Imported module = %d.%d\n", - importing_major, importing_minor, - imported_major, imported_minor); - } -} - -}}} // namespace boost::python::detail +}} // namespace boost::python::detail diff --git a/src/errors.cpp b/src/errors.cpp new file mode 100644 index 00000000..1290df50 --- /dev/null +++ b/src/errors.cpp @@ -0,0 +1,68 @@ +// 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 BOOST_PYTHON_SOURCE +# define BOOST_PYTHON_SOURCE +#endif + +#include + +namespace boost { namespace python { + +// IMPORTANT: this function may only be called from within a catch block! +BOOST_PYTHON_DECL bool handle_exception_impl(function0 f) +{ + try + { + f(); + return false; + } + catch(const boost::python::error_already_set&) + { + // The python error reporting has already been handled. + } + catch(const std::bad_alloc&) + { + PyErr_NoMemory(); + } + catch(const std::exception& x) + { + PyErr_SetString(PyExc_RuntimeError, x.what()); + } + catch(...) + { + PyErr_SetString(PyExc_RuntimeError, "unidentifiable C++ exception"); + } + return true; +} + +BOOST_PYTHON_DECL PyObject* expect_non_null(PyObject* x) +{ + if (x == 0) + throw error_already_set(); + return x; +} + +namespace detail { + + BOOST_PYTHON_DECL void expect_complex(PyObject* p) + { + if (!PyComplex_Check(p)) + { + PyErr_SetString(PyExc_TypeError, "expected a complex number"); + throw boost::python::argument_error(); + } + } + +// needed by void_adaptor (see void_adaptor.hpp) +BOOST_PYTHON_DECL PyObject arbitrary_object = { 0 }; + + +} // namespace boost::python::detail + +}} // namespace boost::python + + diff --git a/src/extension_class.cpp b/src/extension_class.cpp index e9183c82..f8bcf9ad 100644 --- a/src/extension_class.cpp +++ b/src/extension_class.cpp @@ -12,6 +12,7 @@ #define BOOST_PYTHON_SOURCE #include +#include #include #include #include @@ -52,7 +53,7 @@ BOOST_PYTHON_END_CONVERSION_NAMESPACE namespace boost { namespace python { -tuple standard_coerce(ref l, ref r) +BOOST_PYTHON_DECL tuple standard_coerce(ref l, ref r) { // Introduced sequence points for exception-safety. ref first(detail::operator_dispatcher::create(l, l)); @@ -487,21 +488,15 @@ void operator_dispatcher_dealloc(PyObject* self) int operator_dispatcher_coerce(PyObject** l, PyObject** r) { Py_INCREF(*l); - PyObject* new_r = handle_exception( - bind(operator_dispatcher::create, - ref(*r, ref::increment_count), - ref())); - if (new_r) - { - *r = new_r; - return 0; - } - else - { - return -1; - } -} + return handle_exception( + bind_return( + *r + , bind(operator_dispatcher::create, + ref(*r, ref::increment_count), + ref()))) + ? -1 : 0; +} #define PY_DEFINE_OPERATOR(id, symbol) \ PyObject* operator_dispatcher_call_##id(PyObject* left, PyObject* right) \ diff --git a/src/gen_call.py b/src/gen_call.py new file mode 100644 index 00000000..dd178648 --- /dev/null +++ b/src/gen_call.py @@ -0,0 +1,82 @@ +# (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 + +from gen_function import * +import string + +header = '''// 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 %d-argument member functions and %d-argument free +// functions by gen_call.py + +#ifndef CALL_DWA20011214_HPP +# define CALL_DWA20011214_HPP + +# include + +namespace boost { namespace python { + +''' +_cv_qualifiers = ('', ' const', ' volatile', ' const volatile') + +def gen_call(member_function_args, free_function_args = None): + if free_function_args is None: + free_function_args = member_function_args + 1 + + return (header % (member_function_args, free_function_args) + + gen_functions( +'''template +PyObject* call(R (*f)(%(A%n%:, %)), PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +''', free_function_args) + + +'''// Member functions +''' + + reduce(lambda x,y: x+y + , map(lambda cv: + gen_functions( +'''template +PyObject* call(R (A0::*f)(%(A%+%:, %))%1, PyObject* args, PyObject* keywords) +{ + return detail::returning::call(f, args, keywords); +} + +''' + , member_function_args, cv) + , _cv_qualifiers)) + + +''' +}} // namespace boost::python + +#endif // CALL_DWA20011214_HPP +''') + +if __name__ == '__main__': + import sys + + if len(sys.argv) == 1: + member_function_args = 5 + free_function_args = 6 + else: + member_function_args = int(sys.argv[1]) + if len(sys.argv) > 2: + free_function_args = int(sys.argv[2]) + else: + free_function_args = member_function_args + + print gen_call(member_function_args, free_function_args) + + diff --git a/src/gen_returning.py b/src/gen_returning.py new file mode 100644 index 00000000..2b112cc0 --- /dev/null +++ b/src/gen_returning.py @@ -0,0 +1,191 @@ +# (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 + +from gen_function import * +import string + +header = '''// (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 %d-argument member functions and %d-argument free +// functions by gen_returning.py +''' + +body_sections = ( +''' +#ifndef RETURNING_DWA20011201_HPP +# define RETURNING_DWA20011201_HPP + +//# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace detail { + +// Calling C++ from Python +template +struct returning +{ +''', +''' +''', +''' // Free functions +''', +'''}; + +template <> +struct returning +{ + typedef void R; +''', +''' +''', +''' + // Free functions +''', +'''}; + +}}} // namespace boost::python::detail + +#endif // RETURNING_DWA20011201_HPP +''') + +#' + +member_function = ''' template + static PyObject* call(R (A0::*pmf)(%(A%+%:, %))%1, PyObject* args, PyObject* /* keywords */ ) + { + // check that each of the arguments is convertible + unwrap c0(PyTuple_GET_ITEM(args, 0)); +%( unwrap_more c%+(PyTuple_GET_ITEM(args, %+), c%n); +%) +%[r%: // find the result converter + wrap_more r(c%n); +%] if (!c0) return 0; + %[r%:return r( %]((*c0).*pmf)(%(*c%+%:, %))%[r%: )%];%[v%: + return detail::none();%] + }; +''' + +free_function = '''%{ template <%(class A%n%:, %)> +%} static PyObject* call(R (*pf)(%(A%n%:, %)), PyObject*%{ args%}, PyObject* /* keywords */ ) + {%{ + // check that each of the arguments is convertible +%}%( unwrap%{_more%} c%n(PyTuple_GET_ITEM(args, %n)%{, c%-%}); +%)%[r%: + // find the result converter + wrap%{_more%} r%{(c%-)%};%]%{ + if (!c0) return 0;%} + %[r%:return r( %](*pf)(%(*c%n%:, %))%[r%: )%];%[v%: + return detail::none();%] + }; +''' + +def _returns_value(key, n, args, value): + if key == 'r': + return value + # pass the value through gen_function again for recursive expansion +# return apply(gen_function, (value, n) + args +# , {'fill': _returns_value}) + else: + assert key == 'v' + return '' + +def _returns_void(key, n, args, value): + if key == 'v': + return value + else: + assert key == 'r' + # return the empty string, ignoring the value + return '' + +_cv_qualifiers = ('', ' const', ' volatile', ' const volatile') + +_prefix = { +# ' const': ''' + +# // missing cv-qualified -> cv-unqualified member pointer conversions +# # if defined(__MWERKS__) && __MWERKS__ <=0x2406 || defined(BOOST_MSVC) && BOOST_MSVC <= 1200 || defined(__BORLANDC__) +# ''', + ' const volatile': ''' +// missing const volatile type traits +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +'''}; + +def gen_returning(member_function_args, free_function_args = None): + if free_function_args is None: + free_function_args = member_function_args + 1 + + return_none = '''; + return detail::none();''' + + return (header % (member_function_args, free_function_args) + + body_sections[0] + # + # functions returning results + # + + + reduce(lambda x,y: x+y + , map(lambda cv: + _prefix.get(cv,'') + + gen_functions(member_function, + member_function_args, cv, + fill = _returns_value) + '\n' + , _cv_qualifiers)) + + '''# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +''' +## endif // missing cv-qualified -> cv-unqualified member pointer conversions +#''' + # free functions + + gen_functions(free_function, free_function_args, fill = _returns_value) + + body_sections[3] + + # + # functions returning void + # + + + reduce(lambda x,y: x+y + , map(lambda cv: + _prefix.get(cv,'') + + gen_functions(member_function, + member_function_args, cv, fill = + _returns_void) + '\n' + , _cv_qualifiers)) + + + '''# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +''' +## endif // missing cv-qualified -> cv-unqualified member pointer conversions +#''' + # free functions + + gen_functions(free_function, free_function_args, fill = _returns_void) + + body_sections[6] + ) + +if __name__ == '__main__': + import sys + + if len(sys.argv) == 1: + member_function_args = 5 + free_function_args = 6 + else: + member_function_args = int(sys.argv[1]) + if len(sys.argv) > 2: + free_function_args = int(sys.argv[2]) + else: + free_function_args = member_function_args + + print gen_returning(member_function_args, free_function_args) + + diff --git a/src/module_builder.cpp b/src/module_builder.cpp index bd04a89c..0a195621 100644 --- a/src/module_builder.cpp +++ b/src/module_builder.cpp @@ -16,19 +16,19 @@ namespace { ref name_holder; } -bool module_builder::initializing() +bool module_builder_base::initializing() { return name_holder.get() != 0; } -string module_builder::name() +string module_builder_base::name() { // If this fails, you haven't created a module_builder object assert(initializing()); return string(name_holder); } -module_builder::module_builder(const char* name) +module_builder_base::module_builder_base(const char* name) : m_module(Py_InitModule(const_cast(name), initial_methods)) { // If this fails, you've created more than 1 module_builder object in your module @@ -36,29 +36,29 @@ module_builder::module_builder(const char* name) name_holder = ref(PyObject_GetAttrString(m_module, const_cast("__name__"))); } -module_builder::~module_builder() +module_builder_base::~module_builder_base() { name_holder.reset(); } void -module_builder::add(detail::function* x, const char* name) +module_builder_base::add(detail::function* x, const char* name) { reference f(x); // First take possession of the object. detail::function::add_to_namespace(f, name, PyModule_GetDict(m_module)); } -void module_builder::add(ref x, const char* name) +void module_builder_base::add(ref x, const char* name) { PyObject* dictionary = PyModule_GetDict(m_module); PyDict_SetItemString(dictionary, const_cast(name), x.get()); } -void module_builder::add(PyTypeObject* x, const char* name /*= 0*/) +void module_builder_base::add(PyTypeObject* x, const char* name /*= 0*/) { this->add(ref(as_object(x)), name ? name : x->tp_name); } -PyMethodDef module_builder::initial_methods[] = { { 0, 0, 0, 0 } }; +PyMethodDef module_builder_base::initial_methods[] = { { 0, 0, 0, 0 } }; }} // namespace boost::python diff --git a/src/object/class.cpp b/src/object/class.cpp new file mode 100644 index 00000000..cc3903e3 --- /dev/null +++ b/src/object/class.cpp @@ -0,0 +1,165 @@ +// 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. + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace python { namespace object { + +holder_base::holder_base(converter::type_id_t id) + : m_type(id) + , m_next(0) +{ +} + +holder_base::~holder_base() +{ +} + +//BOOST_PYTHON_EXPORT +PyTypeObject class_metatype_object = { + PyObject_HEAD_INIT(0)//&PyType_Type) + 0, + "Boost.Python.class", + PyType_Type.tp_basicsize, + 0, + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | // Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_BASETYPE, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, //&PyType_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, + // PyType_GenericNew /* tp_new */ +}; + +//BOOST_PYTHON_EXPORT +PyTypeObject class_type_object = { + PyObject_HEAD_INIT(0) //&class_metatype_object) + 0, + "Boost.Python.instance", + sizeof(instance), + 0, + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_BASETYPE, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, //&PyBaseObject_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew +}; + +BOOST_PYTHON_EXPORT PyTypeObject* class_metatype() +{ + if (class_metatype_object.tp_dict == 0) + { + class_metatype_object.ob_type = &PyType_Type; + class_metatype_object.tp_base = &PyType_Type; + if (PyType_Ready(&class_metatype_object)) + return 0; + } + Py_INCREF(&class_metatype_object); + return &class_metatype_object; +} + +BOOST_PYTHON_EXPORT PyTypeObject* class_type() +{ + if (class_type_object.tp_dict == 0) + { + class_type_object.ob_type = class_metatype(); + class_type_object.tp_base = &PyBaseObject_Type; + if (PyType_Ready(&class_type_object)) + return 0; + } + Py_INCREF(&class_type_object); + return &class_type_object; +} + +void holder_base::install(PyObject* self) +{ + assert(self->ob_type->ob_type == &class_metatype_object); + m_next = ((instance*)self)->objects; + ((instance*)self)->objects = this; +} + +BOOST_PYTHON_EXPORT holder_base* +find_holder_impl(PyObject* inst, converter::type_id_t type) +{ + if (inst->ob_type->ob_type != &class_metatype_object) + return 0; + instance* self = reinterpret_cast(inst); + + holder_base::iterator match = std::find_if( + holder_base::iterator(self->objects), holder_base::iterator(0) + , bind(std::equal_to() + , bind(mem_fn(&holder_base::type), _1) + , type)); + + return match != holder_base::iterator(0) + ? match.base() : 0; +} + +}}} // namespace boost::python::object diff --git a/src/object/function.cpp b/src/object/function.cpp new file mode 100644 index 00000000..4c2de3c7 --- /dev/null +++ b/src/object/function.cpp @@ -0,0 +1,95 @@ +// 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. + +#include + +namespace boost { namespace python { namespace object { + + +function::function(py_function implementation) + : m_fn(implementation) +{ + PyObject* p = this; + PyObject_INIT(p, &function_type); +} + +function::~function() +{ +} + +PyObject* function::call(PyObject* args, PyObject* keywords) const +{ + return m_fn(args, keywords); +} + +extern "C" +{ + // Stolen from Python's funcobject.c + static PyObject * + function_descr_get(PyObject *func, PyObject *obj, PyObject *type) + { + if (obj == Py_None) + obj = NULL; + return PyMethod_New(func, obj, type); + } + + static void + function_dealloc(PyObject* p) + { + delete static_cast(p); + } + + static PyObject * + function_call(PyObject *func, PyObject *arg, PyObject *kw) + { + return static_cast(func)->call(arg, kw); + } +} + +PyTypeObject function_type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + "Boost.Python.function", + sizeof(function), + 0, + (destructor)function_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, //(reprfunc)func_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + function_call, /* tp_call */ + 0, /* tp_str */ + 0, // PyObject_GenericGetAttr, /* tp_getattro */ + 0, // PyObject_GenericSetAttr, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT /* | Py_TPFLAGS_HAVE_GC */,/* tp_flags */ + 0, /* tp_doc */ + 0, // (traverseproc)func_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, //offsetof(PyFunctionObject, func_weakreflist), /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, // func_memberlist, /* tp_members */ + 0, //func_getsetlist, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + function_descr_get, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, //offsetof(PyFunctionObject, func_dict), /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, + 0 /* tp_new */ +}; + +}}} // namespace boost::python::object diff --git a/src/objects.cpp b/src/objects.cpp index 70257388..90417dac 100644 --- a/src/objects.cpp +++ b/src/objects.cpp @@ -51,42 +51,42 @@ PyObject* object::get() const BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE -PyObject* to_python(const boost::python::tuple& x) +BOOST_PYTHON_DECL PyObject* to_python(const boost::python::tuple& x) { return object_to_python(x); } -boost::python::tuple from_python(PyObject* p, boost::python::type type) +BOOST_PYTHON_DECL boost::python::tuple from_python(PyObject* p, boost::python::type type) { return boost::python::object_from_python(p, type); } -PyObject* to_python(const boost::python::list& x) +BOOST_PYTHON_DECL PyObject* to_python(const boost::python::list& x) { return object_to_python(x); } -boost::python::list from_python(PyObject* p, boost::python::type type) +BOOST_PYTHON_DECL boost::python::list from_python(PyObject* p, boost::python::type type) { return boost::python::object_from_python(p, type); } -PyObject* to_python(const boost::python::dictionary& x) +BOOST_PYTHON_DECL PyObject* to_python(const boost::python::dictionary& x) { return object_to_python(x); } -boost::python::dictionary from_python(PyObject* p, boost::python::type type) +BOOST_PYTHON_DECL boost::python::dictionary from_python(PyObject* p, boost::python::type type) { return boost::python::object_from_python(p, type); } -PyObject* to_python(const boost::python::string& x) +BOOST_PYTHON_DECL PyObject* to_python(const boost::python::string& x) { return object_to_python(x); } -boost::python::string from_python(PyObject* p, boost::python::type type) +BOOST_PYTHON_DECL boost::python::string from_python(PyObject* p, boost::python::type type) { return boost::python::object_from_python(p, type); } @@ -95,14 +95,14 @@ BOOST_PYTHON_END_CONVERSION_NAMESPACE namespace boost { namespace python { -tuple::tuple(std::size_t n) +tuple_base::tuple_base(std::size_t n) : object(ref(PyTuple_New(n))) { for (std::size_t i = 0; i < n; ++i) PyTuple_SET_ITEM(get(), i, detail::none()); } -tuple::tuple(ref p) +tuple_base::tuple_base(ref p) : object(p) { assert(accepts(p)); @@ -113,28 +113,28 @@ tuple::tuple(ref p) } } -PyTypeObject* tuple::type_obj() +PyTypeObject* tuple_base::type_obj() { return &PyTuple_Type; } -bool tuple::accepts(ref p) +bool tuple_base::accepts(ref p) { return PyTuple_Check(p.get()); } -std::size_t tuple::size() const +std::size_t tuple_base::size() const { return PyTuple_Size(get()); } -ref tuple::operator[](std::size_t pos) const +ref tuple_base::operator[](std::size_t pos) const { return ref(PyTuple_GetItem(get(), static_cast(pos)), ref::increment_count); } -void tuple::set_item(std::size_t pos, const ref& rhs) +void tuple_base::set_item(std::size_t pos, const ref& rhs) { int failed = PyTuple_SetItem( get(), static_cast(pos), ref(rhs).release()); // A reference is stolen here. @@ -142,14 +142,14 @@ void tuple::set_item(std::size_t pos, const ref& rhs) assert(failed == 0); } -tuple tuple::slice(int low, int high) const +tuple tuple_base::slice(int low, int high) const { return tuple(ref(PyTuple_GetSlice(get(), low, high))); } -tuple& tuple::operator+=(const tuple& rhs) +BOOST_PYTHON_DECL tuple& operator+=(tuple& self, const tuple& rhs) { - return *this = *this + rhs; + return self = self + rhs; } @@ -216,7 +216,7 @@ string& string::operator*=(unsigned int repeat_count) return *this; } -dictionary::dictionary(ref p) +dictionary_base::dictionary_base(ref p) : object(p) { assert(accepts(p)); @@ -227,49 +227,49 @@ dictionary::dictionary(ref p) } } -dictionary::dictionary() +dictionary_base::dictionary_base() : object(ref(PyDict_New())) {} -PyTypeObject* dictionary::type_obj() +PyTypeObject* dictionary_base::type_obj() { return &PyDict_Type; } -bool dictionary::accepts(ref p) +bool dictionary_base::accepts(ref p) { return PyDict_Check(p.get()); } -void dictionary::clear() +void dictionary_base::clear() { PyDict_Clear(get()); } -const ref& dictionary::proxy::operator=(const ref& rhs) +const ref& dictionary_proxy::operator=(const ref& rhs) { if (PyDict_SetItem(m_dict.get(), m_key.get(), rhs.get()) == -1) throw error_already_set(); return rhs; } -dictionary::proxy::operator ref() const +dictionary_proxy::operator ref() const { return ref(m_dict->ob_type->tp_as_mapping->mp_subscript(m_dict.get(), m_key.get()), ref::increment_count); } -dictionary::proxy::proxy(const ref& dict, const ref& key) +dictionary_proxy::dictionary_proxy(const ref& dict, const ref& key) : m_dict(dict), m_key(key) {} -dictionary::proxy dictionary::operator[](ref key) +dictionary_proxy dictionary_base::operator[](ref key) { return proxy(reference(), key); } -ref dictionary::operator[](ref key) const { +ref dictionary_base::operator[](ref key) const { // An odd MSVC bug causes the ".operator Ptr()" to be needed return proxy(reference(), key).operator ref(); } -ref dictionary::get_item(const ref& key) const +ref dictionary_base::get_item(const ref& key) const { return get_item(key, ref()); } -ref dictionary::get_item(const ref& key, const ref& default_) const +ref dictionary_base::get_item(const ref& key, const ref& default_) const { PyObject* value_or_null = PyDict_GetItem(get(), key.get()); if (value_or_null == 0 && !PyErr_Occurred()) @@ -278,22 +278,22 @@ ref dictionary::get_item(const ref& key, const ref& default_) const return ref(value_or_null, ref::increment_count); // Will throw if there was another error } -void dictionary::set_item(const ref& key, const ref& value) +void dictionary_base::set_item(const ref& key, const ref& value) { if (PyDict_SetItem(get(), key.get(), value.get()) == -1) throw error_already_set(); } -void dictionary::erase(ref key) { +void dictionary_base::erase(ref key) { if (PyDict_DelItem(get(), key.get()) == -1) throw error_already_set(); } -list dictionary::items() const { return list(ref(PyDict_Items(get()))); } -list dictionary::keys() const { return list(ref(PyDict_Keys(get()))); } -list dictionary::values() const { return list(ref(PyDict_Values(get()))); } +list dictionary_base::items() const { return list(ref(PyDict_Items(get()))); } +list dictionary_base::keys() const { return list(ref(PyDict_Keys(get()))); } +list dictionary_base::values() const { return list(ref(PyDict_Values(get()))); } -std::size_t dictionary::size() const { return static_cast(PyDict_Size(get())); } +std::size_t dictionary_base::size() const { return static_cast(PyDict_Size(get())); } string operator+(string x, string y) { @@ -338,7 +338,7 @@ tuple operator+(const tuple& x, const tuple& y) } -list::list(ref p) +list_base::list_base(ref p) : object(p) { assert(accepts(p)); @@ -349,97 +349,97 @@ list::list(ref p) } } -list::list(std::size_t sz) +list_base::list_base(std::size_t sz) : object(ref(PyList_New(sz))) { } -PyTypeObject* list::type_obj() +PyTypeObject* list_base::type_obj() { return &PyList_Type; } -bool list::accepts(ref p) +bool list_base::accepts(ref p) { return PyList_Check(p.get()); } -std::size_t list::size() const +std::size_t list_base::size() const { return PyList_Size(get()); } -ref list::operator[](std::size_t pos) const +ref list_base::operator[](std::size_t pos) const { return ref(PyList_GetItem(get(), pos), ref::increment_count); } -list::proxy list::operator[](std::size_t pos) +list_proxy list_base::operator[](std::size_t pos) { return proxy(reference(), pos); } -void list::insert(std::size_t index, const ref& item) +void list_base::insert(std::size_t index, const ref& item) { if (PyList_Insert(get(), index, item.get()) == -1) throw error_already_set(); } -void list::push_back(const ref& item) +void list_base::push_back(const ref& item) { if (PyList_Append(get(), item.get()) == -1) throw error_already_set(); } -void list::append(const ref& item) +void list_base::append(const ref& item) { this->push_back(item); } -list list::slice(int low, int high) const +list list_base::slice(int low, int high) const { return list(ref(PyList_GetSlice(get(), low, high))); } -list::slice_proxy list::slice(int low, int high) +list_slice_proxy list_base::slice(int low, int high) { - return slice_proxy(reference(), low, high); + return list_slice_proxy(reference(), low, high); } -void list::sort() +void list_base::sort() { if (PyList_Sort(get()) == -1) throw error_already_set(); } -void list::reverse() +void list_base::reverse() { if (PyList_Reverse(get()) == -1) throw error_already_set(); } -tuple list::as_tuple() const +tuple list_base::as_tuple() const { return tuple(ref(PyList_AsTuple(get()))); } -const ref& list::proxy::operator=(const ref& rhs) +const ref& list_proxy::operator=(const ref& rhs) { m_list.set_item(m_index, rhs); return rhs; } -list::proxy::operator ref() const +list_proxy::operator ref() const { return ref(PyList_GetItem(m_list.get(), m_index), ref::increment_count); } -ref list::get_item(std::size_t pos) const +ref list_base::get_item(std::size_t pos) const { return ref(PyList_GetItem(this->get(), pos), ref::increment_count); } -void list::set_item(std::size_t pos, const ref& rhs) +void list_base::set_item(std::size_t pos, const ref& rhs) { int result = PyList_SetItem(this->get(), pos, rhs.get()); if (result == -1) @@ -447,39 +447,39 @@ void list::set_item(std::size_t pos, const ref& rhs) Py_INCREF(rhs.get()); } -list::proxy::proxy(const ref& list, std::size_t index) +list_proxy::list_proxy(const ref& list, std::size_t index) : m_list(list), m_index(index) { } -const list& list::slice_proxy::operator=(const list& rhs) +const list& list_slice_proxy::operator=(const list& rhs) { if (PyList_SetSlice(m_list.get(), m_low, m_high, rhs.get()) == -1) throw error_already_set(); return rhs; } -list::slice_proxy::operator ref() const +list_slice_proxy::operator ref() const { return ref(PyList_GetSlice(m_list.get(), m_low, m_high)); } -list::slice_proxy::operator list() const +list_slice_proxy::operator list() const { return list(this->operator ref()); } -std::size_t list::slice_proxy::size() const +std::size_t list_slice_proxy::size() const { return this->operator list().size(); } -ref list::slice_proxy::operator[](std::size_t pos) const +ref list_slice_proxy::operator[](std::size_t pos) const { return this->operator list()[pos].operator ref(); } -list::slice_proxy::slice_proxy(const ref& list, int low, int high) +list_slice_proxy::list_slice_proxy(const ref& list, int low, int high) : m_list(list), m_low(low), m_high(high) { } diff --git a/src/types.cpp b/src/types.cpp index f411aa42..e76503d2 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -8,6 +8,7 @@ #define BOOST_PYTHON_SOURCE +#include #include #include // for handle_exception() #include @@ -25,9 +26,11 @@ namespace boost { namespace python { -namespace { - +namespace +{ using detail::type_object_base; + using detail::call_object; + // Define a family of forwarding functions that can be called from a // PyTypeObject's slots. These functions dispatch through a (virtual) member @@ -35,7 +38,6 @@ namespace { // uniform way, preventing us from having to rewrite the dispatching code over // and over. - // Given a function object f with signature // // PyObject* f(PyTypeObject*,PyObject*) @@ -43,88 +45,24 @@ namespace { // calls f inside of handle_exception, and returns the result. If an exception // is thrown by f, returns 0. template - PyObject* obj_call(PyObject* obj, F const& f) + PyObject* obj_call(PyObject* obj, F f) { - return handle_exception( - boost::bind(f, static_cast(obj->ob_type), obj)); + PyObject* result; + return call_object(result, obj, f) ? 0 : result; } - - // int_converter/value_holder - // - // A simple function object which converts its argument to a PyObject*. We - // need this because handle_exception needs to return a PyObject*, even if the - // function being called is supposed to return int. It has two parts... - - // holds the value actually returned by the underlying function - template - struct value_holder : PyObject - { - value_holder() : is_set(false), value(-1) {} - - // Tricky constructor allows us to grab the result even if rhs == 0. - explicit value_holder(value_holder const* rhs) - : is_set(rhs ? rhs->is_set : false), value(rhs ? rhs->value : -1) {} - - // true if the function object was ever called (false if an exception occurred) - bool is_set; - - // The returned value - T value; - }; - - // The function object - template - struct int_converter - { - typedef PyObject* result_type; - - PyObject* operator()(R const& x) - { - m_holder.is_set = true; - m_holder.value = x; - return &m_holder; // returns - } - - value_holder m_holder; - }; - - // Call the given int-returning function object inside of handle_exception, - // returning a value_holder. F is a function object with "signature" + // Call the given integer-returning function object inside of + // handle_exception, returning a value_holder. F is a function + // object with "signature" // // R F(PyTypeObject*, PyObject*) // // where R is an integer type. template - value_holder int_call_holder(PyObject* obj, F f) + R int_call(PyObject* obj, F f, R* = 0) { - return value_holder( - - // The int_converter object containing the value_holder is valid - // through the life of the full-expression, so we can construct from - // the pointer - static_cast*>( - handle_exception( - - boost::bind( - // Add an int_converter back-end to f - int_converter() - // Bind the object's type and the object itself into f - , boost::bind(f, static_cast(obj->ob_type), obj) - ) - - ) - ) - ); - } - - // Just like int_call_holder (above), but returns the integer directly. If F - // throws an exception, returns -1 - template - R int_call(PyObject* obj, F f) - { - value_holder const v(int_call_holder(obj, f)); - return v.value; + R result; + return call_object(result, obj, f) ? -1 : result; } // Implemented in terms of obj_call, above @@ -171,27 +109,18 @@ namespace { int call_length_function(PyObject* obj, int (type_object_base::*f)(PyObject*) const) { - value_holder const r(int_call_holder(obj, bind(f, _1, _2))); - - if (!r.is_set) - { + int result; + if (call_object(result, obj, bind(f, _1, _2))) return -1; - } - const int outcome = r.value; - if (outcome >= 0) - return outcome; + if (result >= 0) + return result; PyErr_SetString(PyExc_ValueError, "__len__() should return >= 0"); return -1; } } // anonymous namespace -namespace detail { - // needed by void_adaptor (see void_adaptor.hpp) - PyObject arbitrary_object; -} - extern "C" { // @@ -247,14 +176,11 @@ static PyObject* do_instance_call(PyObject* obj, PyObject* args, PyObject* keywo static void do_instance_dealloc(PyObject* obj) { - PyObject* success = handle_exception( - // translate the void return value of instance_dealloc into a PyObject* - // that can indicate no error. - detail::make_void_adaptor( + if (handle_exception( bind(&type_object_base::instance_dealloc - , static_cast(obj->ob_type) - , obj))); - if (!success) + , static_cast(obj->ob_type) + , obj)) + ) { assert(!"exception during destruction!"); } @@ -300,11 +226,9 @@ static PyObject* do_instance_sq_item(PyObject* obj, int index) return 0; } - return handle_exception( - bind(&type_object_base::instance_sequence_item - , static_cast(obj->ob_type) - , obj - , index)); + return obj_call( + obj + , bind(&type_object_base::instance_sequence_item, _1, _2, index)); } static int do_instance_mp_ass_subscript(PyObject* obj, PyObject* index, PyObject* value) diff --git a/test/complicated.hpp b/test/complicated.hpp new file mode 100644 index 00000000..123c53fe --- /dev/null +++ b/test/complicated.hpp @@ -0,0 +1,39 @@ +// 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 COMPLICATED_DWA20011215_HPP +# define COMPLICATED_DWA20011215_HPP +# include + +# include "simple_type.hpp" + +struct complicated +{ + complicated(simple const&, int = 0); + ~complicated(); + + int get_n() const; + + char* s; + int n; +}; + +inline complicated::complicated(simple const&s, int n) + : s(s.s), n(n) +{ + std::cout << "constructing complicated: " << this->s << ", " << n << std::endl; +} + +inline complicated::~complicated() +{ + std::cout << "destroying complicated: " << this->s << ", " << n << std::endl; +} + +inline int complicated::get_n() const +{ + return n; +} + +#endif // COMPLICATED_DWA20011215_HPP diff --git a/test/m1.cpp b/test/m1.cpp new file mode 100644 index 00000000..f4ad6390 --- /dev/null +++ b/test/m1.cpp @@ -0,0 +1,281 @@ +// 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. + +// Seems to be neccessary to suppress an ICE with MSVC +#include "boost/mpl/comparison/less.hpp" + +#include "simple_type.hpp" +#include "complicated.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" void +dealloc(PyObject* self) +{ + PyObject_Del(self); +} + +struct NoddyObject : PyObject +{ + int x; +}; + +PyTypeObject NoddyType = { + PyObject_HEAD_INIT(NULL) + 0, + "Noddy", + sizeof(NoddyObject), + 0, + dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ +}; + +struct SimpleObject : PyObject +{ + simple x; +}; + +PyTypeObject SimpleType = { + PyObject_HEAD_INIT(NULL) + 0, + "Simple", + sizeof(SimpleObject), + 0, + dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ +}; + +extern "C" PyObject* +new_noddy(PyObject* self, PyObject* args) +{ + NoddyObject* noddy; + + if (!PyArg_ParseTuple(args,":new_noddy")) + return NULL; + + noddy = PyObject_New(NoddyObject, &NoddyType); + noddy->x = 42; + + return (PyObject*)noddy; +} + +extern "C" PyObject* +new_simple(PyObject* self, PyObject* args) +{ + SimpleObject* simple; + + if (!PyArg_ParseTuple(args,":new_simple")) + return NULL; + + simple = PyObject_New(SimpleObject, &SimpleType); + simple->x.s = "hello, world"; + + return (PyObject*)simple; +} + +static PyMethodDef methods[] = { + { "new_noddy", new_noddy, METH_VARARGS }, + { "new_simple", new_simple, METH_VARARGS }, + {0, 0, 0, 0} +}; + +struct int_wrapper + : boost::python::converter::wrapper +{ + PyObject* convert(int const& x) const + { + return PyInt_FromLong(x); + } +}; + +struct simple_wrapper + : boost::python::converter::wrapper +{ + PyObject* convert(simple const& x) const + { + SimpleObject* p = PyObject_New(SimpleObject, &SimpleType); + p->x = x; + return p; + } +}; + +struct simple_ref_wrapper + : boost::python::converter::wrapper +{ + PyObject* convert(simple& x) const + { + SimpleObject* p = PyObject_New(SimpleObject, &SimpleType); + p->x = x; + return p; + } +}; + +struct native_int_unwrapper + : boost::python::converter::unwrapper +{ + bool convertible(PyObject* p) const + { + return PyInt_Check(p); + } + + int convert(PyObject* p, void*&) const + { + return PyInt_AsLong(p); + } +}; + +struct noddy_int_unwrapper + : boost::python::converter::unwrapper +{ + bool convertible(PyObject* p) const + { + return p->ob_type == &NoddyType; + } + + int convert(PyObject* p, void*&) const + { + return static_cast(p)->x; + } +}; + +struct noddy_int_ref_unwrapper + : boost::python::converter::unwrapper +{ + bool convertible(PyObject* p) const + { + return p->ob_type == &NoddyType; + } + + int& convert(PyObject* p, void*&) const + { + return static_cast(p)->x; + } +}; + +struct simple_ref_unwrapper + : boost::python::converter::unwrapper +{ + bool convertible(PyObject* p) const + { + return p->ob_type == &SimpleType; + } + + simple& convert(PyObject* p, void*&) const + { + return static_cast(p)->x; + } +}; + +struct simple_const_ref_unwrapper + : boost::python::converter::unwrapper +{ + bool convertible(PyObject* p) const + { + return p->ob_type == &SimpleType; + } + + simple const& convert(PyObject* p, void*&) const + { + return static_cast(p)->x; + } +}; + +int f(simple const& s) +{ + return strlen(s.s); +} + +simple const& g(simple const& x) +{ + return x; +} + +BOOST_PYTHON_MODULE_INIT(m1) +{ + PyObject* m1 = Py_InitModule(const_cast("m1"), methods); + + static int_wrapper wrap_int; + static simple_wrapper wrap_simple; + static native_int_unwrapper unwrap_int1; + static noddy_int_unwrapper unwrap_int2; + static noddy_int_ref_unwrapper unwrap_int3; + static simple_ref_unwrapper unwrap_simple; +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + // These compilers will need additional converters + static simple_const_ref_unwrapper unwrap_simple_const_ref; + static simple_ref_wrapper wrap_simple_ref; +#endif + static boost::python::object::class_unwrapper unwrap_complicated; + + PyObject* d = PyModule_GetDict(m1); + if (d == NULL) + return; + + if (PyDict_SetItemString( + d, "xclass", (PyObject *)boost::python::object::class_metatype()) < 0) + return; + + if (PyDict_SetItemString( + d, "xinst", (PyObject *)boost::python::object::class_type()) < 0) + return; + + if (PyDict_SetItemString( + d, "f", boost::python::make_function(f)) < 0) + return; + + if (PyDict_SetItemString( + d, "g", boost::python::make_function(g)) < 0) + return; + + if (PyDict_SetItemString( + d, "get_n", boost::python::make_function(&complicated::get_n)) < 0) + return; + + if (PyDict_SetItemString( + d, "init1" + , boost::python::make_constructor< + complicated + , boost::mpl::type_list + , boost::python::object::value_holder_generator>() + ) < 0) + return; + + if (PyDict_SetItemString( + d, "init2" + , boost::python::make_constructor< + complicated + , boost::mpl::type_list + , boost::python::object::value_holder_generator>() + ) < 0) + return; +} + +#include "module_tail.cpp" diff --git a/test/m2.cpp b/test/m2.cpp new file mode 100644 index 00000000..d2093a20 --- /dev/null +++ b/test/m2.cpp @@ -0,0 +1,197 @@ +// 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. + +#include +#include +#include "simple_type.hpp" + +using boost::python::wrap; +using boost::python::unwrap; + +extern "C" { + PyObject* + unwrap_simple(PyObject* self, PyObject* args) + { + PyObject* p; + if (!PyArg_ParseTuple(args, "O", &p)) + return 0; + + boost::python::unwrap in(p); + if (!in) + return 0; + + simple x = *in; + + return PyString_FromString(x.s); + }; + + PyObject* + unwrap_simple_ref(PyObject* self, PyObject* args) + { + PyObject* p; + if (!PyArg_ParseTuple(args, "O", &p)) + return 0; + + unwrap in(p); + if (!in) + return 0; + + simple& x = *in; + + return PyString_FromString(x.s); + }; + + PyObject* + unwrap_simple_const_ref(PyObject* self, PyObject* args) + { + PyObject* p; + if (!PyArg_ParseTuple(args, "O", &p)) + return 0; + + unwrap in(p); + if (!in) + return 0; + + simple const& x = *in; + + return PyString_FromString(x.s); + }; + + PyObject* + unwrap_int(PyObject* self, PyObject* args) + { + PyObject* p; + if (!PyArg_ParseTuple(args, "O", &p)) + return 0; + + unwrap in(p); + if (!in) + return 0; + + int x = *in; + + return PyInt_FromLong(x); + }; + + PyObject* + unwrap_int_ref(PyObject* self, PyObject* args) + { + PyObject* p; + if (!PyArg_ParseTuple(args, "O", &p)) + return 0; + + unwrap in(p); + if (!in) + return 0; + + int& x = *in; + + return PyInt_FromLong(x); + }; + + PyObject* + unwrap_int_const_ref(PyObject* self, PyObject* args) + { + PyObject* p; + if (!PyArg_ParseTuple(args, "O", &p)) + return 0; + + unwrap in(p); + if (!in) + return 0; + + int const& x = *in; + + return PyInt_FromLong(x); + }; + + // ------------------- +} +template struct xxxx; + +template +PyObject* +rewrap(PyObject* self, PyObject* args, xxxx* = 0) +{ + PyObject* p; + if (!PyArg_ParseTuple(args, "O", &p)) + return 0; + + boost::python::unwrap in(p); + if (!in) + return 0; + + boost::python::wrap out; + if (!out) + return 0; + + T x = *in; + return out(x); +} + +extern "C" +{ + PyObject* + wrap_simple(PyObject* self, PyObject* args) + { + return rewrap(self, args); + }; + + PyObject* + wrap_simple_ref(PyObject* self, PyObject* args) + { + return rewrap(self, args); + }; + + PyObject* + wrap_simple_const_ref(PyObject* self, PyObject* args) + { + return rewrap(self, args); + }; + + PyObject* + wrap_int(PyObject* self, PyObject* args) + { + return rewrap(self, args); + }; + + PyObject* + wrap_int_ref(PyObject* self, PyObject* args) + { + return rewrap(self, args); + }; + + PyObject* + wrap_int_const_ref(PyObject* self, PyObject* args) + { + return rewrap(self, args); + }; +} + +PyMethodDef initial_methods[] = +{ + { "unwrap_int", unwrap_int, METH_VARARGS, 0 }, + { "unwrap_int_ref", unwrap_int_ref, METH_VARARGS, 0 }, + { "unwrap_int_const_ref", unwrap_int_const_ref, METH_VARARGS, 0 }, + { "unwrap_simple", unwrap_simple, METH_VARARGS, 0 }, + { "unwrap_simple_ref", unwrap_simple_ref, METH_VARARGS, 0 }, + { "unwrap_simple_const_ref", unwrap_simple_const_ref, METH_VARARGS, 0 }, + + { "wrap_int", wrap_int, METH_VARARGS, 0 }, + { "wrap_int_ref", wrap_int_ref, METH_VARARGS, 0 }, + { "wrap_int_const_ref", wrap_int_const_ref, METH_VARARGS, 0 }, + { "wrap_simple", wrap_simple, METH_VARARGS, 0 }, + { "wrap_simple_ref", wrap_simple_ref, METH_VARARGS, 0 }, + { "wrap_simple_const_ref", wrap_simple_const_ref, METH_VARARGS, 0 }, + { 0, 0, 0, 0 } +}; + +BOOST_PYTHON_MODULE_INIT(m2) +{ + Py_InitModule(const_cast("m2"), initial_methods); +} + +#include "module_tail.cpp" diff --git a/test/module_tail.cpp b/test/module_tail.cpp new file mode 100644 index 00000000..6849bf83 --- /dev/null +++ b/test/module_tail.cpp @@ -0,0 +1,39 @@ +// 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. + +#if defined(_WIN32) +# ifdef __MWERKS__ +# pragma ANSI_strict off +# endif +# include +# ifdef __MWERKS__ +# pragma ANSI_strict reset +# endif + +extern "C" BOOL WINAPI DllMain ( HINSTANCE hInst, DWORD wDataSeg, LPVOID lpvReserved ); + +# ifdef BOOST_MSVC +extern "C" void structured_exception_translator(unsigned int, EXCEPTION_POINTERS*) +{ + throw; +} +# endif + +BOOL WINAPI DllMain( + HINSTANCE, //hDllInst + DWORD fdwReason, + LPVOID // lpvReserved + ) +{ +# ifdef BOOST_MSVC + _set_se_translator(structured_exception_translator); +# endif + (void)fdwReason; // warning suppression. + + return 1; +} +#endif // _WIN32 + diff --git a/test/newtest.py b/test/newtest.py new file mode 100644 index 00000000..783e2240 --- /dev/null +++ b/test/newtest.py @@ -0,0 +1,95 @@ +""" +>>> from m1 import * + +>>> from m2 import * + +>>> n = new_noddy() +>>> s = new_simple() +>>> unwrap_int(n) +42 +>>> unwrap_int_ref(n) +42 +>>> unwrap_int_const_ref(n) +42 +>>> unwrap_simple(s) +'hello, world' +>>> unwrap_simple_ref(s) +'hello, world' +>>> unwrap_simple_const_ref(s) +'hello, world' +>>> unwrap_int(5) +5 + +Can't get a reference to a built-in integer object +>>> try: +... unwrap_int_ref(7) +... except: pass +... else: print 'no exception' + +>>> try: +... unwrap_int_const_ref(9) +... except: pass +... else: print 'no exception' + +>>> wrap_int(n) +42 + +try: wrap_int_ref(n) +... except: pass +... else: print 'no exception' + +>>> wrap_int_const_ref(n) +42 + +>>> unwrap_simple_ref(wrap_simple(s)) +'hello, world' + +>>> unwrap_simple_ref(wrap_simple_ref(s)) +'hello, world' + +>>> unwrap_simple_ref(wrap_simple_const_ref(s)) +'hello, world' + +>>> f(s) +12 + +>>> unwrap_simple(g(s)) +'hello, world' + +>>> f(g(s)) +12 + +>>> C = xclass('C', (xinst,), {'__init__': init1, 'get_n': get_n}) +>>> c = C(s, 99) +>>> c.get_n() +99 + +>>> D = xclass('D', (xinst,), {'__init__': init2, 'get_n': get_n}) +>>> d = D(s) +>>> d.get_n() +0 + +""" + +def run(args = None): + + ### Strange bug somewhere: with Metrowerks: it will crash in + ### garbage-collection code unless traceback and sre have been + ### loaded before m1. + +# import traceback +# import sre +# import m2 +# import m1 + import sys + import doctest + + if args is not None: + sys.argv = args + # import sys + return doctest.testmod(sys.modules.get(__name__)) + +if __name__ == '__main__': + print "running..." + import sys + sys.exit(run()[0]) diff --git a/test/simple_type.hpp b/test/simple_type.hpp new file mode 100644 index 00000000..2df97cfd --- /dev/null +++ b/test/simple_type.hpp @@ -0,0 +1,14 @@ +// 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 SIMPLE_TYPE_DWA2001128_HPP +# define SIMPLE_TYPE_DWA2001128_HPP + +struct simple +{ + char* s; +}; + +#endif // SIMPLE_TYPE_DWA2001128_HPP From 14f6f8852646f649823774e4ed69877bb0edf17d Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 28 Dec 2001 13:26:36 +0000 Subject: [PATCH 173/369] irix_CC workaround; updated makefiles [SVN r12163] --- build/como.mak | 1 + build/filemgr.py | 1 + build/gcc.mak | 1 + build/irix_CC.mak | 10 +++++----- build/linux_gcc.mak | 10 +++++----- build/mingw32.mak | 2 +- build/tru64_cxx.mak | 10 +++++----- build/vc60.mak | 16 ++++++++-------- build/win32_mwcc.mak | 6 +++--- include/boost/python/detail/config.hpp | 9 +++++++++ 10 files changed, 39 insertions(+), 27 deletions(-) diff --git a/build/como.mak b/build/como.mak index 8f05e309..edf05f83 100644 --- a/build/como.mak +++ b/build/como.mak @@ -7,6 +7,7 @@ LIBSRC = \ classes.cpp \ conversions.cpp \ cross_module.cpp \ + errors.cpp \ extension_class.cpp \ functions.cpp \ init_function.cpp \ diff --git a/build/filemgr.py b/build/filemgr.py index 99f4ca30..93cef1cb 100644 --- a/build/filemgr.py +++ b/build/filemgr.py @@ -8,6 +8,7 @@ bpl_exa = "/libs/python/example" files = ( bpl_src + "/classes.cpp", bpl_src + "/conversions.cpp", +bpl_src + "/errors.cpp", bpl_src + "/extension_class.cpp", bpl_src + "/functions.cpp", bpl_src + "/init_function.cpp", diff --git a/build/gcc.mak b/build/gcc.mak index ce718f2b..b818030e 100644 --- a/build/gcc.mak +++ b/build/gcc.mak @@ -11,6 +11,7 @@ LIBSRC = \ classes.cpp \ conversions.cpp \ cross_module.cpp \ + errors.cpp \ extension_class.cpp \ functions.cpp \ init_function.cpp \ diff --git a/build/irix_CC.mak b/build/irix_CC.mak index ec387746..f7d6004e 100644 --- a/build/irix_CC.mak +++ b/build/irix_CC.mak @@ -17,10 +17,10 @@ ROOT=$(HOME) BOOST=$(ROOT)/boost -PYEXE=PYTHONPATH=. /usr/local/Python-1.5.2/bin/python -PYINC=-I/usr/local/Python-1.5.2/include/python1.5 -#PYEXE=PYTHONPATH=. /usr/local/Python-2.1/bin/python -#PYINC=-I/usr/local/Python-2.1/include/python2.1 +#PYEXE=PYTHONPATH=. /usr/local/Python-1.5.2/bin/python +#PYINC=-I/usr/local/Python-1.5.2/include/python1.5 +PYEXE=PYTHONPATH=. /usr/local_cci/Python-2.1.1/bin/python +PYINC=-I/usr/local_cci/Python-2.1.1/include/python2.1 STLPORTINC=-I$(BOOST)/boost/compatibility/cpp_c_headers STDOPTS= @@ -35,7 +35,7 @@ MAKEDEP=-M LD=CC -LANG:std -n32 -mips4 LDOPTS=-shared -OBJ=classes.o conversions.o extension_class.o functions.o \ +OBJ=classes.o conversions.o errors.o extension_class.o functions.o \ init_function.o module_builder.o \ objects.o types.o cross_module.o DEPOBJ=$(OBJ) \ diff --git a/build/linux_gcc.mak b/build/linux_gcc.mak index ef643991..3b466e7d 100644 --- a/build/linux_gcc.mak +++ b/build/linux_gcc.mak @@ -17,12 +17,12 @@ ROOT=$(HOME) BOOST=$(ROOT)/boost -PYEXE=PYTHONPATH=. /usr/bin/python -PYINC=-I/usr/include/python1.5 +#PYEXE=PYTHONPATH=. /usr/bin/python +#PYINC=-I/usr/include/python1.5 #PYEXE=PYTHONPATH=. /usr/local/Python-1.5.2/bin/python #PYINC=-I/usr/local/Python-1.5.2/include/python1.5 -#PYEXE=PYTHONPATH=. /usr/local/Python-2.1/bin/python -#PYINC=-I/usr/local/Python-2.1/include/python2.1 +PYEXE=PYTHONPATH=. /usr/local_cci/Python-2.1.1/bin/python +PYINC=-I/usr/local_cci/Python-2.1.1/include/python2.1 STDOPTS=-fPIC -ftemplate-depth-21 WARNOPTS= @@ -36,7 +36,7 @@ MAKEDEP=-M LD=$(CPP) LDOPTS=-shared -OBJ=classes.o conversions.o extension_class.o functions.o \ +OBJ=classes.o conversions.o errors.o extension_class.o functions.o \ init_function.o module_builder.o \ objects.o types.o cross_module.o DEPOBJ=$(OBJ) \ diff --git a/build/mingw32.mak b/build/mingw32.mak index bf590409..d8c31b68 100644 --- a/build/mingw32.mak +++ b/build/mingw32.mak @@ -52,7 +52,7 @@ CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) -I$(BOOST_WIN) $(PYINC) \ LD=g++ LDOPTS=-shared -OBJ=classes.o conversions.o extension_class.o functions.o \ +OBJ=classes.o conversions.o errors.o extension_class.o functions.o \ init_function.o module_builder.o \ objects.o types.o cross_module.o diff --git a/build/tru64_cxx.mak b/build/tru64_cxx.mak index f996a0c1..a64927b1 100644 --- a/build/tru64_cxx.mak +++ b/build/tru64_cxx.mak @@ -17,10 +17,10 @@ ROOT=$(HOME) BOOST=$(ROOT)/boost -PYEXE=PYTHONPATH=. /usr/local/Python-1.5.2/bin/python -PYINC=-I/usr/local/Python-1.5.2/include/python1.5 -#PYEXE=PYTHONPATH=. /usr/local/Python-2.1/bin/python -#PYINC=-I/usr/local/Python-2.1/include/python2.1 +#PYEXE=PYTHONPATH=. /usr/local/Python-1.5.2/bin/python +#PYINC=-I/usr/local/Python-1.5.2/include/python1.5 +PYEXE=PYTHONPATH=. /usr/local_cci/Python-2.1.1/bin/python +PYINC=-I/usr/local_cci/Python-2.1.1/include/python2.1 #STLPORTINC=-I/usr/local/STLport-4.1b3/stlport #STLPORTINC=-I/usr/local/STLport-4.1b4/stlport #STLPORTOPTS= \ @@ -46,7 +46,7 @@ LDOPTS=-shared -expect_unresolved 'Py*' -expect_unresolved '_Py*' #HIDDEN=-hidden -OBJ=classes.o conversions.o extension_class.o functions.o \ +OBJ=classes.o conversions.o errors.o extension_class.o functions.o \ init_function.o module_builder.o \ objects.o types.o cross_module.o DEPOBJ=$(OBJ) \ diff --git a/build/vc60.mak b/build/vc60.mak index a348de54..6f303791 100644 --- a/build/vc60.mak +++ b/build/vc60.mak @@ -14,14 +14,14 @@ ROOT=R: BOOST_WIN="$(ROOT)\boost" BOOST_UNIX=$(HOME)/boost -PYEXE="C:\Program files\Python\python.exe" -PYINC=/I"C:\Program files\Python\include" -PYLIB="C:\Program files\Python\libs\python15.lib" -#PYEXE="C:\Python21\python.exe" -#PYINC=/I"C:\Python21\include" -#PYLIB="C:\Python21\libs\python21.lib" +#PYEXE="C:\Program files\Python\python.exe" +#PYINC=/I"C:\Program files\Python\include" +#PYLIB="C:\Program files\Python\libs\python15.lib" +PYEXE="C:\Python21\python.exe" +PYINC=/I"C:\Python21\include" +PYLIB="C:\Python21\libs\python21.lib" -STDOPTS=/nologo /MD /GR /GX /Zm200 +STDOPTS=/nologo /MD /GR /GX /Zm200 /DBOOST_PYTHON_STATIC_LIB WARNOPTS= OPTOPTS= @@ -32,7 +32,7 @@ CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) /I$(BOOST_WIN) $(PYINC) \ LD=link.exe LDOPTS=/nologo /dll /incremental:no -OBJ=classes.obj conversions.obj extension_class.obj functions.obj \ +OBJ=classes.obj conversions.obj errors.obj extension_class.obj functions.obj \ init_function.obj module_builder.obj \ objects.obj types.obj cross_module.obj diff --git a/build/win32_mwcc.mak b/build/win32_mwcc.mak index ac054c07..c49af71c 100755 --- a/build/win32_mwcc.mak +++ b/build/win32_mwcc.mak @@ -10,7 +10,7 @@ # 14 Dec 01 derived from vc60.mak (R.W. Grosse-Kunstleve) ROOT=R: -BOOST_WIN="$(ROOT)\boostdev" +BOOST_WIN="$(ROOT)\boost" BOOST_UNIX=$(HOME)/boost #PYEXE="C:\Program files\Python\python.exe" @@ -20,7 +20,7 @@ PYEXE="C:\Python21\python.exe" PYINC=-I"C:\Python21\include" PYLIB="C:\Python21\libs\python21.lib" -STDOPTS=-gccinc -prefix UseDLLPrefix.h +STDOPTS=-gccinc -prefix UseDLLPrefix.h -DBOOST_PYTHON_STATIC_LIB WARNOPTS=-warn on,nounusedexpr,nounused OPTOPTS=-O @@ -31,7 +31,7 @@ CPPOPTS=$(STDOPTS) $(WARNOPTS) $(OPTOPTS) \ LD=mwld LDOPTS=-export dllexport -shared -OBJ=classes.obj conversions.obj extension_class.obj functions.obj \ +OBJ=classes.obj conversions.obj errors.obj extension_class.obj functions.obj \ init_function.obj module_builder.obj \ objects.obj types.obj cross_module.obj diff --git a/include/boost/python/detail/config.hpp b/include/boost/python/detail/config.hpp index 498fa07a..c79eb2ca 100644 --- a/include/boost/python/detail/config.hpp +++ b/include/boost/python/detail/config.hpp @@ -129,4 +129,13 @@ # endif #endif +#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 +// Work around a compiler bug. +// boost::python::detail::function has to be seen by the compiler before the +// boost::function class template. +namespace boost { namespace python { namespace detail { +class function; +}}} +#endif + #endif // CONFIG_DWA052200_H_ From 2eb2e52a79dbd4d24be54cda2b1cd864e8ca8e31 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 28 Dec 2001 23:52:01 +0000 Subject: [PATCH 174/369] workaround some compiler limitations [SVN r12165] --- .../boost/python/detail/extension_class.hpp | 54 +++++++++++-------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/include/boost/python/detail/extension_class.hpp b/include/boost/python/detail/extension_class.hpp index 00f9b6b4..05ebe229 100644 --- a/include/boost/python/detail/extension_class.hpp +++ b/include/boost/python/detail/extension_class.hpp @@ -38,20 +38,45 @@ template struct right_operand; enum without_downcast_t { without_downcast }; -namespace detail { +namespace detail +{ // forward declarations -class extension_instance; -class extension_class_base; -template class instance_holder; -template class instance_value_holder; -template class instance_ptr_holder; -template struct operand_select; + class extension_instance; + class extension_class_base; + template class instance_holder; + template class instance_value_holder; + template class instance_ptr_holder; + template struct operand_select; template struct choose_op; template struct choose_rop; template struct choose_unary_op; template struct define_operator; + class BOOST_PYTHON_DECL extension_instance : public instance + { + public: + extension_instance(PyTypeObject* class_); + ~extension_instance(); + + void add_implementation(std::auto_ptr holder); + + typedef std::vector held_objects; + const held_objects& wrapped_objects() const + { return m_wrapped_objects; } + private: + held_objects m_wrapped_objects; + }; + +} // namespace detail + +# ifndef BOOST_PYTHON_NO_TEMPLATE_EXPORT +BOOST_PYTHON_EXPORT_TEMPLATE_CLASS class_t; +BOOST_PYTHON_EXPORT_TEMPLATE_CLASS meta_class; +# endif + +namespace detail { + BOOST_PYTHON_DECL meta_class* extension_meta_class(); BOOST_PYTHON_DECL extension_instance* get_extension_instance(PyObject* p); BOOST_PYTHON_DECL void report_missing_instance_data(extension_instance*, class_t*, const std::type_info&); @@ -813,21 +838,6 @@ class instance_ptr_holder : public instance_holder PtrType m_ptr; }; -class BOOST_PYTHON_DECL extension_instance : public instance -{ - public: - extension_instance(PyTypeObject* class_); - ~extension_instance(); - - void add_implementation(std::auto_ptr holder); - - typedef std::vector held_objects; - const held_objects& wrapped_objects() const - { return m_wrapped_objects; } - private: - held_objects m_wrapped_objects; -}; - // // Template function implementations // From ed9bc835a267ff3fc5116708bb50c71d38868f3b Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 28 Dec 2001 23:56:10 +0000 Subject: [PATCH 175/369] Stuck the extension_class code in the DLL whenever possible Removed some flotsam [SVN r12166] --- include/boost/python/detail/config.hpp | 44 ++++++++++++++++++++------ 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/include/boost/python/detail/config.hpp b/include/boost/python/detail/config.hpp index c79eb2ca..97d84a79 100644 --- a/include/boost/python/detail/config.hpp +++ b/include/boost/python/detail/config.hpp @@ -76,19 +76,29 @@ # define BOOST_PYTHON_STATIC_LINK #endif -#if defined(BOOST_MSVC) && defined(_DLL) && !defined(BOOST_PYTHON_HAS_DLL_RUNTIME) -# define BOOST_PYTHON_HAS_DLL_RUNTIME +#if defined(__MWERKS__) +# define BOOST_PYTHON_NO_TEMPLATE_EXPORT #endif -#if defined(__BORLANDC__) && defined(_RTLDLL) && !defined(BOOST_PYTHON_HAS_DLL_RUNTIME) -# define BOOST_PYTHON_HAS_DLL_RUNTIME +#if defined(__GNUC__) +# define BOOST_PYTHON_IMPORT_TEMPLATE_KEYWORD extern +# define BOOST_PYTHON_EXPORT_TEMPLATE_KEYWORD extern #endif -#if defined(__ICL) && defined(_DLL) && !defined(BOOST_PYTHON_HAS_DLL_RUNTIME) -# define BOOST_PYTHON_HAS_DLL_RUNTIME +// Handle default cases +#ifndef BOOST_PYTHON_IMPORT_TEMPLATE_KEYWORD +# ifdef _WIN32 +# define BOOST_PYTHON_IMPORT_TEMPLATE_KEYWORD extern +# else +# define BOOST_PYTHON_IMPORT_TEMPLATE_KEYWORD +# endif #endif -#if defined(BOOST_PYTHON_DYNAMIC_LIB) && defined(_WIN32) // && !defined(BOOST_PYTHON_STATIC_LINK) +#ifndef BOOST_PYTHON_EXPORT_TEMPLATE_KEYWORD +# define BOOST_PYTHON_EXPORT_TEMPLATE_KEYWORD +#endif + +#if defined(BOOST_PYTHON_DYNAMIC_LIB) && defined(_WIN32) # if defined(BOOST_PYTHON_SOURCE) # define BOOST_PYTHON_DECL __declspec(dllexport) # define BOOST_PYTHON_BUILD_DLL @@ -101,10 +111,26 @@ # define BOOST_PYTHON_DECL #endif -#if (defined(BOOST_MSVC) || defined(__BORLANDC__)) && !defined(BOOST_PYTHON_NO_LIB) && !defined(BOOST_PYTHON_SOURCE) -// # include +#ifndef BOOST_PYTHON_DECL_TEMPLATE +# ifndef BOOST_PYTHON_NO_TEMPLATE_EXPORT +# define BOOST_PYTHON_DECL_TEMPLATE BOOST_PYTHON_DECL +# else +# define BOOST_PYTHON_DECL_TEMPLATE +# endif #endif +#if defined(BOOST_PYTHON_SOURCE) +# define BOOST_PYTHON_EXPORT BOOST_PYTHON_EXPORT_TEMPLATE_KEYWORD +#else +# define BOOST_PYTHON_EXPORT BOOST_PYTHON_IMPORT_TEMPLATE_KEYWORD +#endif + +# ifndef BOOST_PYTHON_EXPORT_TEMPLATE +# define BOOST_PYTHON_EXPORT_TEMPLATE BOOST_PYTHON_EXPORT template +# endif + +# define BOOST_PYTHON_EXPORT_TEMPLATE_CLASS BOOST_PYTHON_EXPORT template class BOOST_PYTHON_DECL + // Borland C++ Fix/error check: #if defined(__BORLANDC__) # if (__BORLANDC__ == 0x550) || (__BORLANDC__ == 0x551) From 94c0e947f5f6c03bd73ac66627de95f900d583e7 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 28 Dec 2001 23:59:02 +0000 Subject: [PATCH 176/369] Stuck the extension_class code in the DLL whenever possible Removed copyability restriction in class_base to enable the above [SVN r12167] --- include/boost/python/classes.hpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/include/boost/python/classes.hpp b/include/boost/python/classes.hpp index 548a57db..31af430f 100644 --- a/include/boost/python/classes.hpp +++ b/include/boost/python/classes.hpp @@ -128,6 +128,10 @@ namespace detail { private: // boost::python::type_object_base required interface implementation void instance_dealloc(PyObject*) const; // subclasses should not override this + + private: // noncopyable, without the size bloat + class_base(const class_base&); + void operator=(const class_base&); private: string m_name; @@ -141,11 +145,12 @@ namespace detail { // A type which acts a lot like a built-in Python class. T is the obj type, // so class_t is a very simple "class-alike". template -class class_t +class BOOST_PYTHON_DECL_TEMPLATE class_t : public boost::python::detail::class_base { public: class_t(meta_class* meta_class_obj, string name, tuple bases, const dictionary& name_space); + ~class_t(); // Standard Python functions. PyObject* call(PyObject* args, PyObject* keywords); @@ -218,15 +223,11 @@ class class_t private: // Implementation of boost::python::detail::class_base required interface void delete_instance(PyObject*) const; - - private: // noncopyable, without the size bloat - class_t(const class_t&); - void operator=(const class_t&); }; // The type of a class_t object. template -class meta_class +class BOOST_PYTHON_DECL_TEMPLATE meta_class : public boost::python::detail::reprable< boost::python::detail::callable< boost::python::detail::getattrable< @@ -264,6 +265,11 @@ class_t::class_t(meta_class* meta_class_obj, string name, tuple bases, con { } +template +class_t::~class_t() +{ +} + template void class_t::delete_instance(PyObject* obj) const { From dc831fb3f62897eb052d6e37fc8e64daa061a364 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 29 Dec 2001 00:00:19 +0000 Subject: [PATCH 177/369] Stuck the extension_class code in the DLL whenever possible [SVN r12168] --- src/extension_class.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/extension_class.cpp b/src/extension_class.cpp index f8bcf9ad..cc784ca6 100644 --- a/src/extension_class.cpp +++ b/src/extension_class.cpp @@ -11,6 +11,7 @@ #define BOOST_PYTHON_SOURCE +#include #include #include #include @@ -681,4 +682,9 @@ PyNumberMethods operator_dispatcher::number_methods = } // namespace detail +# ifndef BOOST_PYTHON_NO_TEMPLATE_EXPORT +template class BOOST_PYTHON_DECL meta_class; +template class BOOST_PYTHON_DECL class_t; +# endif + }} // namespace boost::python From 1247ff2543e8816a0c9f9ea2eaf39609a57aaffd Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 31 Dec 2001 17:02:43 +0000 Subject: [PATCH 178/369] *** empty log message *** [SVN r12177] --- include/boost/python/converter/unwrap.hpp | 31 +++-------------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/include/boost/python/converter/unwrap.hpp b/include/boost/python/converter/unwrap.hpp index 6dda61fb..4a2ea04c 100644 --- a/include/boost/python/converter/unwrap.hpp +++ b/include/boost/python/converter/unwrap.hpp @@ -11,6 +11,7 @@ # include # include # include +# include # include namespace boost { namespace python { namespace converter { @@ -55,7 +56,7 @@ struct unwrap_more_ : unwrap_base // unspecified storage which may be allocated by the unwrapper to // do value conversions. mutable void* m_storage; - friend class unwrapper; + typedef typename unwrapper_select::type unwrapper_t; }; // specialization for PyObject* @@ -142,32 +143,6 @@ unwrap_more_::unwrap_more_(PyObject* source) { } -# if 0 -template <> -inline unwrap_more_::unwrap_more_(PyObject* source, handle& prev) - : unwrap_base(source, m_unwrapper, prev) -{ -} - -template <> -inline unwrap_more_::unwrap_more_(PyObject* source) - : unwrap_base(source, m_unwrapper) - -{ -} - -template <> -inline PyObject* unwrap_more_::operator*() -{ - return source(); -} - -template <> -inline bool unwrap_more_::convertible(PyObject*) const -{ - return true; -} -# endif template inline unwrap_::unwrap_(PyObject* source) : unwrap_more_(source) @@ -178,7 +153,7 @@ template T unwrap_more_::operator*() { return static_cast*>( - get_body())->do_conversion(this); + get_body())->convert(this->m_source, this->m_storage); } template From 015b875a9ec0bc82016959bea34e18bc061965ea Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 1 Jan 2002 18:21:06 +0000 Subject: [PATCH 179/369] Convertibility checks now collect the auxiliary conversion data [SVN r12186] --- src/converter/registry.cpp | 50 +++++++++++++------------------------ src/converter/unwrap.cpp | 10 ++++---- src/converter/unwrapper.cpp | 7 ++++++ 3 files changed, 29 insertions(+), 38 deletions(-) diff --git a/src/converter/registry.cpp b/src/converter/registry.cpp index 88d96637..d247353c 100644 --- a/src/converter/registry.cpp +++ b/src/converter/registry.cpp @@ -39,35 +39,6 @@ namespace registry { } - namespace // - { - // A UnaryFunction type which deletes its argument - struct delete_item - { - template - void operator()(T* x) const - { - delete x; - } - }; - - // A UnaryFunction type which returns true iff its argument is a - // unwrapper which can convert the given Python object. - struct convertible - { - convertible(PyObject* p) - : m_p(p) - {} - - bool operator()(unwrapper_base* converter) const - { - return converter->convertible(m_p); - } - - PyObject* m_p; - }; - } - entry::~entry() { if (m_wrapper != 0) @@ -79,12 +50,25 @@ namespace registry } } - unwrapper_base* entry::unwrapper(PyObject* p) const + std::pair + entry::unwrapper(PyObject* p) const { - unwrappers::const_iterator q = - std::find_if(m_unwrappers.begin(), m_unwrappers.end(), convertible(p)); + unwrapper_base* body = 0; + void* data = 0; - return q == m_unwrappers.end() ? 0 : *q; + for (unwrappers::const_iterator q = m_unwrappers.begin(), + finish = m_unwrappers.end(); + q != finish; + ++q) + { + data = (*q)->can_convert(p); + if (data != 0) + { + body = *q; + break; + } + } + return std::make_pair(body,data); } wrapper_base* entry::wrapper() const diff --git a/src/converter/unwrap.cpp b/src/converter/unwrap.cpp index e0c09db6..33a7d7ae 100644 --- a/src/converter/unwrap.cpp +++ b/src/converter/unwrap.cpp @@ -13,7 +13,7 @@ namespace struct pyobject_unwrapper : unwrapper_base { pyobject_unwrapper(); - bool convertible(PyObject*) const; + void* can_convert(PyObject*) const; }; pyobject_unwrapper static_unwrapper; @@ -23,13 +23,13 @@ namespace { } - bool pyobject_unwrapper::convertible(PyObject*) const + void* pyobject_unwrapper::can_convert(PyObject*) const { - return true; + return non_null; } } -BOOST_PYTHON_EXPORT unwrapper_base* -unwrap_more_::m_unwrapper = &static_unwrapper; +BOOST_PYTHON_DECL std::pair +unwrap_more_::m_unwrapper(&static_unwrapper,&static_unwrapper); }}} // namespace boost::python::converter diff --git a/src/converter/unwrapper.cpp b/src/converter/unwrapper.cpp index 2b0adbd0..6279febf 100644 --- a/src/converter/unwrapper.cpp +++ b/src/converter/unwrapper.cpp @@ -21,4 +21,11 @@ unwrapper_base::~unwrapper_base() registry::remove(*this); } +namespace +{ + int arbitrary; +} + +void* const unwrapper_base::non_null = &arbitrary; + }}} // namespace boost::python::converter From e934be2d991249f2bf18ce58a520e40ef8abb113 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 1 Jan 2002 18:21:31 +0000 Subject: [PATCH 180/369] BOOST_PYTHON_EXPORT -> BOOST_PYTHON_DECL [SVN r12187] --- src/converter/type_id.cpp | 2 +- src/object/class.cpp | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/converter/type_id.cpp b/src/converter/type_id.cpp index 86974638..fc2db66a 100644 --- a/src/converter/type_id.cpp +++ b/src/converter/type_id.cpp @@ -19,7 +19,7 @@ bool type_id_before::operator()(type_id_t const& x, type_id_t const& y) const return x < y; } -BOOST_PYTHON_EXPORT std::ostream& operator<<(std::ostream& os, type_id_t const& x) +BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream& os, type_id_t const& x) { # ifdef BOOST_PYTHON_TYPE_ID_NAME os << x.m_base_type; diff --git a/src/object/class.cpp b/src/object/class.cpp index cc3903e3..bdd66a77 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -4,7 +4,7 @@ // "as is" without express or implied warranty, and with no claim as // to its suitability for any purpose. -#include +#include #include #include #include @@ -23,7 +23,6 @@ holder_base::~holder_base() { } -//BOOST_PYTHON_EXPORT PyTypeObject class_metatype_object = { PyObject_HEAD_INIT(0)//&PyType_Type) 0, @@ -68,7 +67,6 @@ PyTypeObject class_metatype_object = { // PyType_GenericNew /* tp_new */ }; -//BOOST_PYTHON_EXPORT PyTypeObject class_type_object = { PyObject_HEAD_INIT(0) //&class_metatype_object) 0, @@ -112,7 +110,7 @@ PyTypeObject class_type_object = { PyType_GenericNew }; -BOOST_PYTHON_EXPORT PyTypeObject* class_metatype() +BOOST_PYTHON_DECL PyTypeObject* class_metatype() { if (class_metatype_object.tp_dict == 0) { @@ -125,7 +123,7 @@ BOOST_PYTHON_EXPORT PyTypeObject* class_metatype() return &class_metatype_object; } -BOOST_PYTHON_EXPORT PyTypeObject* class_type() +BOOST_PYTHON_DECL PyTypeObject* class_type() { if (class_type_object.tp_dict == 0) { @@ -145,7 +143,7 @@ void holder_base::install(PyObject* self) ((instance*)self)->objects = this; } -BOOST_PYTHON_EXPORT holder_base* +BOOST_PYTHON_DECL holder_base* find_holder_impl(PyObject* inst, converter::type_id_t type) { if (inst->ob_type->ob_type != &class_metatype_object) From a7b844810789cb6c7daa7c61187d3e1a55ae09e1 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 1 Jan 2002 18:45:49 +0000 Subject: [PATCH 181/369] obsolete now that Boost.Python is in a shared lib. [SVN r12188] --- include/boost/python/export.hpp | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 include/boost/python/export.hpp diff --git a/include/boost/python/export.hpp b/include/boost/python/export.hpp deleted file mode 100644 index 1229dffe..00000000 --- a/include/boost/python/export.hpp +++ /dev/null @@ -1,20 +0,0 @@ -// 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 EXPORT_DWA20011220_HPP -# define EXPORT_DWA20011220_HPP - -# include -# ifdef _WIN32 -# ifdef BOOST_PYTHON_SOURCE -# define BOOST_PYTHON_EXPORT __declspec(dllexport) -# else -# define BOOST_PYTHON_EXPORT __declspec(dllimport) -# endif -# else -# define BOOST_PYTHON_EXPORT -# endif - -#endif // EXPORT_DWA20011220_HPP From ccd21d52549450c82284a71f2712e602f1feb212 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 1 Jan 2002 18:47:32 +0000 Subject: [PATCH 182/369] Accounting for by-value conversions Convertibility checks now collect the auxiliary conversion data [SVN r12189] --- include/boost/python/converter/class.hpp | 78 +++++++++++++----------- 1 file changed, 43 insertions(+), 35 deletions(-) diff --git a/include/boost/python/converter/class.hpp b/include/boost/python/converter/class.hpp index 305ec448..6e09a961 100644 --- a/include/boost/python/converter/class.hpp +++ b/include/boost/python/converter/class.hpp @@ -11,46 +11,54 @@ namespace boost { namespace python { namespace converter { -struct class_unwrapper_base -{ - class_unwrapper_base(type_id_t sought_type); - void* -}; - template struct class_unwrapper + : private unwrapper + , private unwrapper + , private unwrapper + , private unwrapper { - struct ref_unwrapper : unwrapper - { - bool convertible(PyObject* p) const - { - return p->ob_type == &SimpleType; - } - - simple const& convert(PyObject* p, void*&) const - { - return static_cast(p)->x; - } - - }; - -# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - struct const_ref_unwrapper : unwrapper - { - bool convertible(PyObject* p) const - { - return p->ob_type == &SimpleType; - } - - simple const& convert(PyObject* p, void*&) const - { - return static_cast(p)->x; - } - - }; -# endif + private: + void* can_convert(PyObject*) const; + T& convert(PyObject*, void*, boost::type) const; + T const& convert(PyObject*, void*, boost::type) const; + T* convert(PyObject*, void*, boost::type) const; + T const* convert(PyObject*, void*, boost::type) const; }; +// +// implementations +// +template +void* class_unwrapper::can_convert(PyObject* p) const +{ + return object::find_holder(p); +} + +template +T& class_unwrapper::convert(PyObject*, void* holder_, boost::type) const +{ + return *static_cast*>(holder_)->target(); +} + +template +T const& class_unwrapper::convert(PyObject*, void* holder_, boost::type) const +{ + return *static_cast*>(holder_)->target(); +} + +template +T* class_unwrapper::convert(PyObject*, void* holder_, boost::type) const +{ + return static_cast*>(holder_)->target(); +} + +template +T const* class_unwrapper::convert(PyObject*, void* holder_, boost::type) const +{ + return static_cast*>(holder_)->target(); +} + }}} // namespace boost::python::converter #endif // CLASS_DWA20011215_HPP From bfcb36927c98ca69095b482ebb159e06d2a7a654 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 1 Jan 2002 18:49:20 +0000 Subject: [PATCH 183/369] Accounting for by-value conversions [SVN r12190] --- include/boost/python/converter/target.hpp | 44 ++++++++++++++++------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/include/boost/python/converter/target.hpp b/include/boost/python/converter/target.hpp index 6effb996..f8f33171 100644 --- a/include/boost/python/converter/target.hpp +++ b/include/boost/python/converter/target.hpp @@ -33,8 +33,6 @@ namespace boost { namespace python { namespace converter { // importantly, avoids having to dynamically allocate room for // an lvalue of types which can be cheaply copied. // -// In the tables below, "cv" stands for the set of all possible -// cv-qualifications. // Target Source // int int @@ -46,10 +44,16 @@ namespace boost { namespace python { namespace converter { // On compilers supporting partial specialization: // // Target Source -// T T& -// T cv& T& -// T cv* T* -// T cv*const& T* +// T T const& +// T& T& +// T const& T const& +// T volatile T& +// T const volatile& T const& +// T* T* +// T const* T const* +// T volatile T* +// T const volatile* T const* +// T cv*const& same as T cv* // T cv*& T*& <- should this be legal? // T cv*volatile& T*& <- should this be legal? // T cv*const volatile& T*& <- should this be legal? @@ -75,7 +79,11 @@ struct target typedef typename mpl::select_type< use_identity , T - , typename add_reference::type>::type + , typename add_reference< + typename add_const< + typename remove_volatile::type + >::type + >::type >::type type; }; @@ -86,13 +94,23 @@ struct target template struct target { - typedef typename remove_cv::type& type; + typedef typename remove_volatile::type& type; +}; + +template +struct target +{ + typedef typename boost::mpl::select_type< + is_scalar::value + , typename remove_cv::type + , typename remove_volatile::type const& + >::type type; }; template struct target { - typedef typename remove_cv::type* type; + typedef typename remove_volatile::type* type; }; // Handle T*-cv for completeness. Function arguments in a signature @@ -102,19 +120,19 @@ struct target template struct target { - typedef typename remove_cv::type* type; + typedef typename remove_volatile::type* type; }; template struct target { - typedef typename remove_cv::type* type; + typedef typename remove_volatile::type* type; }; template struct target { - typedef typename remove_cv::type* type; + typedef typename remove_volatile::type* type; }; // non-const references to pointers should be handled by the @@ -122,7 +140,7 @@ struct target template struct target { - typedef typename remove_cv::type* type; + typedef typename remove_volatile::type* type; }; # endif From b2944a12debbac87919f7841d1547af5e1a97b45 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 1 Jan 2002 18:52:04 +0000 Subject: [PATCH 184/369] Convertibility checks now collect the auxiliary conversion data BOOST_PYTHON_EXPORT -> BOOST_PYTHON_DECL [SVN r12191] --- .../boost/python/converter/registration.hpp | 13 ++-- include/boost/python/converter/registry.hpp | 21 +++--- include/boost/python/converter/unwrap.hpp | 65 ++++++++++--------- include/boost/python/converter/unwrapper.hpp | 18 +---- .../boost/python/converter/unwrapper_base.hpp | 17 ++++- 5 files changed, 68 insertions(+), 66 deletions(-) diff --git a/include/boost/python/converter/registration.hpp b/include/boost/python/converter/registration.hpp index 0d85d1d7..b8a6326b 100644 --- a/include/boost/python/converter/registration.hpp +++ b/include/boost/python/converter/registration.hpp @@ -5,18 +5,19 @@ // to its suitability for any purpose. #ifndef REGISTRATION_DWA20011130_HPP # define REGISTRATION_DWA20011130_HPP -# include +# include # include # include -# include +# include +# include # ifdef BOOST_PYTHON_TRACE # include # endif namespace boost { namespace python { namespace converter { -struct BOOST_PYTHON_EXPORT wrapper_base; -struct BOOST_PYTHON_EXPORT unwrapper_base; +struct BOOST_PYTHON_DECL wrapper_base; +struct BOOST_PYTHON_DECL unwrapper_base; // This class is really sort of a "templated namespace". It manages a // static data member which refers to the registry entry for T. This @@ -28,7 +29,7 @@ struct registration public: // member functions // Return a converter which can convert the given Python object to // T, or 0 if no such converter exists - static unwrapper_base* unwrapper(PyObject*); + static std::pair unwrapper(PyObject*); // Return a converter which can convert T to a Python object, or 0 // if no such converter exists @@ -61,7 +62,7 @@ inline registry::entry* registration::entry() } template -unwrapper_base* registration::unwrapper(PyObject* p) +std::pair registration::unwrapper(PyObject* p) { # ifdef BOOST_PYTHON_TRACE std::cout << "retrieving unwrapper for " << type_id() << std::endl; diff --git a/include/boost/python/converter/registry.hpp b/include/boost/python/converter/registry.hpp index 30eeba8d..2023a732 100644 --- a/include/boost/python/converter/registry.hpp +++ b/include/boost/python/converter/registry.hpp @@ -7,20 +7,21 @@ # define REGISTRY_DWA20011127_HPP # include # include -# include +# include # include # include +# include namespace boost { namespace python { namespace converter { -struct BOOST_PYTHON_EXPORT wrapper_base; -struct BOOST_PYTHON_EXPORT unwrapper_base; +struct BOOST_PYTHON_DECL wrapper_base; +struct BOOST_PYTHON_DECL unwrapper_base; // This namespace acts as a sort of singleton namespace registry { // These are the elements stored in the registry - class BOOST_PYTHON_EXPORT entry + class BOOST_PYTHON_DECL entry { public: // member functions entry(); @@ -30,7 +31,7 @@ namespace registry // Python object from_python to the C++ type with which this // converter is associated in the registry, or 0 if no such // converter exists. - unwrapper_base* unwrapper(PyObject*) const; + std::pair unwrapper(PyObject*) const; // Return a converter appropriate for converting a C++ object // whose type this entry is associated with in the registry to a @@ -61,12 +62,12 @@ namespace registry converter::wrapper_base* m_wrapper; }; - BOOST_PYTHON_EXPORT entry* find(type_id_t); + BOOST_PYTHON_DECL entry* find(type_id_t); - BOOST_PYTHON_EXPORT void insert(wrapper_base& x); - BOOST_PYTHON_EXPORT void insert(unwrapper_base& x); - BOOST_PYTHON_EXPORT void remove(wrapper_base& x); - BOOST_PYTHON_EXPORT void remove(unwrapper_base& x); + BOOST_PYTHON_DECL void insert(wrapper_base& x); + BOOST_PYTHON_DECL void insert(unwrapper_base& x); + BOOST_PYTHON_DECL void remove(wrapper_base& x); + BOOST_PYTHON_DECL void remove(unwrapper_base& x); } }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/unwrap.hpp b/include/boost/python/converter/unwrap.hpp index 4a2ea04c..ffd0f081 100644 --- a/include/boost/python/converter/unwrap.hpp +++ b/include/boost/python/converter/unwrap.hpp @@ -12,22 +12,28 @@ # include # include # include -# include +# include +# include namespace boost { namespace python { namespace converter { template struct unwrapper; -struct BOOST_PYTHON_EXPORT body; +struct BOOST_PYTHON_DECL body; -struct BOOST_PYTHON_EXPORT unwrap_base : handle +struct BOOST_PYTHON_DECL unwrap_base : handle { public: // member functions - inline unwrap_base(PyObject* source, body*, handle& prev); - inline unwrap_base(PyObject* source, body*); + inline unwrap_base(PyObject* source, std::pair, handle& prev); + inline unwrap_base(PyObject* source, std::pair); inline PyObject* source() const; - + + protected: + inline PyObject*& source(); + inline void* data() const; + private: // data members PyObject* m_source; + void* m_data; }; // These converters will be used by the function wrappers. They don't @@ -47,15 +53,7 @@ struct unwrap_more_ : unwrap_base // this constructor is only for the use of unwrap_ unwrap_more_(PyObject* source); - private: // helper functions - // Return the unwrapper which will convert the given Python object - // to T, or 0 if no such converter exists - static unwrapper_base* lookup(PyObject*); - private: - // unspecified storage which may be allocated by the unwrapper to - // do value conversions. - mutable void* m_storage; typedef typename unwrapper_select::type unwrapper_t; }; @@ -78,9 +76,9 @@ struct unwrap_more_ return source(); } - bool convertible(PyObject*) const + void* can_convert(PyObject*) const { - return true; + return &m_unwrapper; } protected: // constructor @@ -91,7 +89,7 @@ struct unwrap_more_ { } private: - static BOOST_PYTHON_EXPORT unwrapper_base* m_unwrapper; + static BOOST_PYTHON_DECL std::pair m_unwrapper; }; template @@ -104,42 +102,47 @@ struct unwrap_ : unwrap_more_ // // implementations // -inline unwrap_base::unwrap_base(PyObject* source, body* body, handle& prev) - : handle(body, prev) +inline unwrap_base::unwrap_base( + PyObject* source, std::pair unwrapper, handle& prev) + : handle(unwrapper.first, prev) , m_source(source) + , m_data(unwrapper.second) { } -inline unwrap_base::unwrap_base(PyObject* source, body* body) - : handle(body) +inline unwrap_base::unwrap_base(PyObject* source, std::pair unwrapper) + : handle(unwrapper.first) , m_source(source) + , m_data(unwrapper.second) { } +inline void* unwrap_base::data() const +{ + return m_data; +} + inline PyObject* unwrap_base::source() const { return m_source; } -template -inline unwrapper_base* unwrap_more_::lookup(PyObject* source) +inline PyObject*& unwrap_base::source() { - // Find the converters registered for T and get a unwrapper - // appropriate for the source object - return registration::unwrapper(source); + return m_source; } template unwrap_more_::unwrap_more_(PyObject* source, handle& prev) - : unwrap_base(source, lookup(source), prev) - , m_storage(0) + : unwrap_base(source, + registration::unwrapper(source), + prev) { } template unwrap_more_::unwrap_more_(PyObject* source) - : unwrap_base(source, lookup(source)) - , m_storage(0) + : unwrap_base(source, registration::unwrapper(source)) { } @@ -153,7 +156,7 @@ template T unwrap_more_::operator*() { return static_cast*>( - get_body())->convert(this->m_source, this->m_storage); + get_body())->convert(this->source(), this->data(), boost::type()); } template diff --git a/include/boost/python/converter/unwrapper.hpp b/include/boost/python/converter/unwrapper.hpp index a30ff522..7f0609cf 100644 --- a/include/boost/python/converter/unwrapper.hpp +++ b/include/boost/python/converter/unwrapper.hpp @@ -9,6 +9,7 @@ # include # include # include +# include namespace boost { namespace python { namespace converter { @@ -21,13 +22,7 @@ struct unwrapper : unwrapper_base public: unwrapper(); - T do_conversion(unwrap_more_ const* handle) const; - - private: - virtual T convert(PyObject*, void*&) const = 0; - - private: // body required interface implementation - void destroy_handle(handle*) const {} + virtual T convert(PyObject*, void* data, boost::type) const = 0; }; // @@ -39,15 +34,6 @@ unwrapper::unwrapper() { } -// We could think about making this virtual in an effort to get its -// code generated in the module where the unwrapper is defined, but -// it's not clear that it's a good tradeoff. -template -T unwrapper::do_conversion(unwrap_more_ const* handle) const -{ - return convert(handle->source(), handle->m_storage); -} - }}} // namespace boost::python::converter #endif // UNWRAPPER_DWA2001127_HPP diff --git a/include/boost/python/converter/unwrapper_base.hpp b/include/boost/python/converter/unwrapper_base.hpp index 54e2e54c..ea437eb2 100644 --- a/include/boost/python/converter/unwrapper_base.hpp +++ b/include/boost/python/converter/unwrapper_base.hpp @@ -8,16 +8,27 @@ # include # include # include -# include +# include namespace boost { namespace python { namespace converter { -struct BOOST_PYTHON_EXPORT unwrapper_base : body +struct BOOST_PYTHON_DECL unwrapper_base : body { public: unwrapper_base(type_id_t); // registers ~unwrapper_base(); // unregisters - virtual bool convertible(PyObject*) const = 0; + + // Must return non-null iff the conversion will be successful. Any + // non-null pointer is acceptable, and will be passed on to the + // convert() function, so useful data can be stored there. + virtual void* can_convert(PyObject*) const = 0; + + protected: + // this is an arbitrary non-null pointer you can use to indicate success + static void* const non_null; + + private: // body required interface implementation + void destroy_handle(handle*) const {} }; }}} // namespace boost::python::converter From a179f87d54b4a7fc2e50aff59b109a1df6237889 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 1 Jan 2002 18:53:12 +0000 Subject: [PATCH 185/369] BOOST_PYTHON_EXPORT -> BOOST_PYTHON_DECL [SVN r12192] --- include/boost/python/converter/body.hpp | 7 +++---- include/boost/python/converter/handle.hpp | 7 +++---- include/boost/python/converter/type_id.hpp | 11 +++++------ include/boost/python/converter/wrap.hpp | 4 ++-- include/boost/python/converter/wrapper.hpp | 5 ++--- include/boost/python/object/class.hpp | 10 +++++----- include/boost/python/object/function.hpp | 6 +++--- 7 files changed, 23 insertions(+), 27 deletions(-) diff --git a/include/boost/python/converter/body.hpp b/include/boost/python/converter/body.hpp index c8d932a0..72653ee0 100644 --- a/include/boost/python/converter/body.hpp +++ b/include/boost/python/converter/body.hpp @@ -5,20 +5,19 @@ // to its suitability for any purpose. #ifndef BODY_DWA2001127_HPP # define BODY_DWA2001127_HPP -# include +# include # include -# include namespace boost { namespace python { namespace converter { -struct BOOST_PYTHON_EXPORT handle; +struct BOOST_PYTHON_DECL handle; namespace registry { class entry; } -struct BOOST_PYTHON_EXPORT body +struct BOOST_PYTHON_DECL body { public: body(type_id_t key); diff --git a/include/boost/python/converter/handle.hpp b/include/boost/python/converter/handle.hpp index 16a50b38..03671634 100644 --- a/include/boost/python/converter/handle.hpp +++ b/include/boost/python/converter/handle.hpp @@ -5,19 +5,18 @@ // to its suitability for any purpose. #ifndef HANDLE_DWA20011130_HPP # define HANDLE_DWA20011130_HPP -# include +# include # include # include -# include namespace boost { namespace python { namespace converter { -struct BOOST_PYTHON_EXPORT body; +struct BOOST_PYTHON_DECL body; // The common base class for unwrap_ and wrap_ handle objects. They // share a common base so that handles can be linked into a chain // within a function wrapper which is managed by a single object. -struct BOOST_PYTHON_EXPORT handle : boost::noncopyable +struct BOOST_PYTHON_DECL handle : boost::noncopyable { public: // member functions diff --git a/include/boost/python/converter/type_id.hpp b/include/boost/python/converter/type_id.hpp index ddc04266..c383c352 100644 --- a/include/boost/python/converter/type_id.hpp +++ b/include/boost/python/converter/type_id.hpp @@ -5,12 +5,11 @@ // to its suitability for any purpose. #ifndef TYPE_ID_DWA20011127_HPP # define TYPE_ID_DWA20011127_HPP -# include -# include +# include +# include # include # include # include -# include # include # include # include @@ -48,7 +47,7 @@ typedef std::type_info const* base_id_t; bool operator<(type_id_t const& rhs) const; bool operator==(type_id_t const& rhs) const; - friend BOOST_PYTHON_EXPORT std::ostream& operator<<(std::ostream&, type_id_t const&); + friend BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, type_id_t const&); private: decoration m_decoration; @@ -188,12 +187,12 @@ type_id_t type_id(detail::dummy* = 0) } # endif -struct BOOST_PYTHON_EXPORT type_id_before +struct BOOST_PYTHON_DECL type_id_before { bool operator()(type_id_t const& x, type_id_t const& y) const; }; -BOOST_PYTHON_EXPORT std::ostream& operator<<(std::ostream&, type_id_t const&); +BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, type_id_t const&); }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/wrap.hpp b/include/boost/python/converter/wrap.hpp index 91c9de86..e26cf0f6 100644 --- a/include/boost/python/converter/wrap.hpp +++ b/include/boost/python/converter/wrap.hpp @@ -9,13 +9,13 @@ # include # include # include -# include +# include # include # include namespace boost { namespace python { namespace converter { -struct BOOST_PYTHON_EXPORT wrapper_base; +struct BOOST_PYTHON_DECL wrapper_base; template struct wrapper; diff --git a/include/boost/python/converter/wrapper.hpp b/include/boost/python/converter/wrapper.hpp index ada5e8cb..49c32186 100644 --- a/include/boost/python/converter/wrapper.hpp +++ b/include/boost/python/converter/wrapper.hpp @@ -5,13 +5,12 @@ // to its suitability for any purpose. #ifndef WRAPPER_DWA2001127_HPP # define WRAPPER_DWA2001127_HPP -# include +# include # include # include # include # include # include -# include namespace boost { namespace python { namespace converter { @@ -19,7 +18,7 @@ struct source_holder_base; struct wrap_base; template struct wrap_more_; -struct BOOST_PYTHON_EXPORT wrapper_base : body +struct BOOST_PYTHON_DECL wrapper_base : body { public: wrapper_base(type_id_t); // registers diff --git a/include/boost/python/object/class.hpp b/include/boost/python/object/class.hpp index 548d4053..35085e5f 100644 --- a/include/boost/python/object/class.hpp +++ b/include/boost/python/object/class.hpp @@ -7,7 +7,7 @@ # define CLASS_DWA20011214_HPP # include -# include +# include # include # include # include @@ -17,7 +17,7 @@ namespace boost { namespace python { namespace object { template struct holder; // Base class for all holders -struct BOOST_PYTHON_EXPORT holder_base : noncopyable +struct BOOST_PYTHON_DECL holder_base : noncopyable { public: holder_base(converter::type_id_t id); @@ -68,7 +68,7 @@ struct instance holder_base* objects; }; -BOOST_PYTHON_EXPORT holder_base* find_holder_impl(PyObject*, converter::type_id_t); +BOOST_PYTHON_DECL holder_base* find_holder_impl(PyObject*, converter::type_id_t); template holder* find_holder(PyObject* p, T* = 0) @@ -76,8 +76,8 @@ holder* find_holder(PyObject* p, T* = 0) return static_cast*>(find_holder_impl(p, converter::type_id())); } -BOOST_PYTHON_EXPORT PyTypeObject* class_metatype(); -BOOST_PYTHON_EXPORT PyTypeObject* class_type(); +BOOST_PYTHON_DECL PyTypeObject* class_metatype(); +BOOST_PYTHON_DECL PyTypeObject* class_type(); // // implementation diff --git a/include/boost/python/object/function.hpp b/include/boost/python/object/function.hpp index f550e8dc..a0257676 100644 --- a/include/boost/python/object/function.hpp +++ b/include/boost/python/object/function.hpp @@ -7,7 +7,7 @@ # define FUNCTION_DWA20011214_HPP # include -# include +# include # include namespace boost { namespace python { namespace object { @@ -15,7 +15,7 @@ namespace boost { namespace python { namespace object { // We use boost::function to avoid generating lots of virtual tables typedef boost::function2 py_function; -struct BOOST_PYTHON_EXPORT function : PyObject +struct BOOST_PYTHON_DECL function : PyObject { function(py_function); ~function(); @@ -25,7 +25,7 @@ struct BOOST_PYTHON_EXPORT function : PyObject py_function m_fn; }; -extern BOOST_PYTHON_EXPORT PyTypeObject function_type; +extern BOOST_PYTHON_DECL PyTypeObject function_type; // // implementations From bdf68f092e6b7b94fa87b04d3da6c53c5f8fd16b Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 1 Jan 2002 18:55:23 +0000 Subject: [PATCH 186/369] Accounting for by-value conversions Convertibility checks now collect the auxiliary conversion data [SVN r12193] --- test/m1.cpp | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/test/m1.cpp b/test/m1.cpp index f4ad6390..809a0d63 100644 --- a/test/m1.cpp +++ b/test/m1.cpp @@ -14,8 +14,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -141,12 +141,12 @@ struct simple_ref_wrapper struct native_int_unwrapper : boost::python::converter::unwrapper { - bool convertible(PyObject* p) const + void* can_convert(PyObject* p) const { - return PyInt_Check(p); + return PyInt_Check(p) ? non_null : 0; } - int convert(PyObject* p, void*&) const + int convert(PyObject* p, void*, boost::type) const { return PyInt_AsLong(p); } @@ -155,12 +155,12 @@ struct native_int_unwrapper struct noddy_int_unwrapper : boost::python::converter::unwrapper { - bool convertible(PyObject* p) const + void* can_convert(PyObject* p) const { - return p->ob_type == &NoddyType; + return p->ob_type == &NoddyType ? non_null : 0; } - int convert(PyObject* p, void*&) const + int convert(PyObject* p, void*, boost::type) const { return static_cast(p)->x; } @@ -169,12 +169,12 @@ struct noddy_int_unwrapper struct noddy_int_ref_unwrapper : boost::python::converter::unwrapper { - bool convertible(PyObject* p) const + void* can_convert(PyObject* p) const { - return p->ob_type == &NoddyType; + return p->ob_type == &NoddyType ? non_null : 0; } - int& convert(PyObject* p, void*&) const + int& convert(PyObject* p, void*, boost::type) const { return static_cast(p)->x; } @@ -183,12 +183,12 @@ struct noddy_int_ref_unwrapper struct simple_ref_unwrapper : boost::python::converter::unwrapper { - bool convertible(PyObject* p) const + void* can_convert(PyObject* p) const { - return p->ob_type == &SimpleType; + return p->ob_type == &SimpleType ? non_null : 0; } - simple& convert(PyObject* p, void*&) const + simple& convert(PyObject* p, void*, boost::type) const { return static_cast(p)->x; } @@ -197,12 +197,12 @@ struct simple_ref_unwrapper struct simple_const_ref_unwrapper : boost::python::converter::unwrapper { - bool convertible(PyObject* p) const + void* can_convert(PyObject* p) const { - return p->ob_type == &SimpleType; + return p->ob_type == &SimpleType ? non_null : 0; } - simple const& convert(PyObject* p, void*&) const + simple const& convert(PyObject* p, void*, boost::type) const { return static_cast(p)->x; } @@ -228,12 +228,12 @@ BOOST_PYTHON_MODULE_INIT(m1) static noddy_int_unwrapper unwrap_int2; static noddy_int_ref_unwrapper unwrap_int3; static simple_ref_unwrapper unwrap_simple; + static simple_const_ref_unwrapper unwrap_simple_const_ref; #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION // These compilers will need additional converters - static simple_const_ref_unwrapper unwrap_simple_const_ref; static simple_ref_wrapper wrap_simple_ref; #endif - static boost::python::object::class_unwrapper unwrap_complicated; + static boost::python::converter::class_unwrapper unwrap_complicated; PyObject* d = PyModule_GetDict(m1); if (d == NULL) From 1201761ff399b73378d5a70a88cbd86bfb99938e Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 2 Jan 2002 17:53:34 +0000 Subject: [PATCH 187/369] initial checkin [SVN r12198] --- .../python/converter/unwrapper_select.hpp | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 include/boost/python/converter/unwrapper_select.hpp diff --git a/include/boost/python/converter/unwrapper_select.hpp b/include/boost/python/converter/unwrapper_select.hpp new file mode 100644 index 00000000..d60923af --- /dev/null +++ b/include/boost/python/converter/unwrapper_select.hpp @@ -0,0 +1,33 @@ +// 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 UNWRAPPER_SELECT_DWA20011229_HPP +# define UNWRAPPER_SELECT_DWA20011229_HPP + +namespace boost { namespace python { namespace converter { + +template struct unwrapper; + +// Select the type returned by unwrapper objects when unwrapping a +// given type. When unwrapping T const&, the unwrapper returns T&, so +// that the same unwrapper object can be used for both conversions (on +// a conforming compiler). +template +struct unwrapper_select +{ + typedef unwrapper type; +}; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct unwrapper_select +{ + typedef unwrapper type; +}; +# endif + +}}} // namespace boost::python::converter + +#endif // UNWRAPPER_SELECT_DWA20011229_HPP From 586e6178b49f3f7602852d7c1d31f7c94f3cd893 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 4 Jan 2002 02:06:21 +0000 Subject: [PATCH 188/369] commented [SVN r12209] --- test/m1.cpp | 73 +++++++++++++++++++++++++++++++++++++++---------- test/m2.cpp | 27 +++++++++++++++++- test/newtest.py | 6 ++++ 3 files changed, 90 insertions(+), 16 deletions(-) diff --git a/test/m1.cpp b/test/m1.cpp index 809a0d63..db450f77 100644 --- a/test/m1.cpp +++ b/test/m1.cpp @@ -5,7 +5,7 @@ // to its suitability for any purpose. // Seems to be neccessary to suppress an ICE with MSVC -#include "boost/mpl/comparison/less.hpp" +#include #include "simple_type.hpp" #include "complicated.hpp" @@ -21,12 +21,14 @@ #include #include +// Declare some straightforward extension types extern "C" void dealloc(PyObject* self) { PyObject_Del(self); } +// Noddy is a type we got from one of the Python sample files struct NoddyObject : PyObject { int x; @@ -50,6 +52,22 @@ PyTypeObject NoddyType = { 0, /*tp_hash */ }; +// Create a Noddy containing 42 +extern "C" PyObject* +new_noddy(PyObject* self, PyObject* args) +{ + NoddyObject* noddy; + + if (!PyArg_ParseTuple(args,":new_noddy")) + return NULL; + + noddy = PyObject_New(NoddyObject, &NoddyType); + noddy->x = 42; + + return (PyObject*)noddy; +} + +// Simple is a wrapper around a struct simple, which just contains a char* struct SimpleObject : PyObject { simple x; @@ -73,20 +91,7 @@ PyTypeObject SimpleType = { 0, /*tp_hash */ }; -extern "C" PyObject* -new_noddy(PyObject* self, PyObject* args) -{ - NoddyObject* noddy; - - if (!PyArg_ParseTuple(args,":new_noddy")) - return NULL; - - noddy = PyObject_New(NoddyObject, &NoddyType); - noddy->x = 42; - - return (PyObject*)noddy; -} - +// Create a Simple containing "hello, world" extern "C" PyObject* new_simple(PyObject* self, PyObject* args) { @@ -101,12 +106,21 @@ new_simple(PyObject* self, PyObject* args) return (PyObject*)simple; } +// Initial method table for the module static PyMethodDef methods[] = { { "new_noddy", new_noddy, METH_VARARGS }, { "new_simple", new_simple, METH_VARARGS }, {0, 0, 0, 0} }; +// +// Declare some wrappers/unwrappers to test the low-level conversion +// mechanism. See boost/python/converter/source.hpp,target.hpp for a +// description of how the type parameters to wrapper<> and unwrapper<> +// are selected. +// + +// Wrap an int by converting it to a Python Int struct int_wrapper : boost::python::converter::wrapper { @@ -116,6 +130,7 @@ struct int_wrapper } }; +// Wrap a simple by converting it to a Simple struct simple_wrapper : boost::python::converter::wrapper { @@ -127,6 +142,10 @@ struct simple_wrapper } }; +// wrap a mutable reference to a simple by converting it to a +// Simple. Normally we wouldn't do it this way, since modifications to +// the result clearly don't change the original object, but here we're +// just proving that the mechanism works. struct simple_ref_wrapper : boost::python::converter::wrapper { @@ -138,6 +157,9 @@ struct simple_ref_wrapper } }; +// extract an int from a Python Int by converting it to an int. Since +// int is a scalar type, we convert by-value. Since Python Ints are +// immutable, there's no non-const reference converter. struct native_int_unwrapper : boost::python::converter::unwrapper { @@ -152,6 +174,7 @@ struct native_int_unwrapper } }; +// Extract an int from a Noddy struct noddy_int_unwrapper : boost::python::converter::unwrapper { @@ -166,6 +189,7 @@ struct noddy_int_unwrapper } }; +// Extract a mutable reference to an int from a Noddy. struct noddy_int_ref_unwrapper : boost::python::converter::unwrapper { @@ -180,6 +204,7 @@ struct noddy_int_ref_unwrapper } }; +// Extract a mutable reference to a simple from a Simple struct simple_ref_unwrapper : boost::python::converter::unwrapper { @@ -194,6 +219,7 @@ struct simple_ref_unwrapper } }; +// Extract a const reference to a simple from a Simple struct simple_const_ref_unwrapper : boost::python::converter::unwrapper { @@ -208,11 +234,17 @@ struct simple_const_ref_unwrapper } }; +// +// Some C++ functions to expose to Python +// + +// Returns the length of s's held string int f(simple const& s) { return strlen(s.s); } +// A trivial passthru function for simple objects simple const& g(simple const& x) { return x; @@ -222,6 +254,7 @@ BOOST_PYTHON_MODULE_INIT(m1) { PyObject* m1 = Py_InitModule(const_cast("m1"), methods); + // Create the converters; they are self-registering/unregistering. static int_wrapper wrap_int; static simple_wrapper wrap_simple; static native_int_unwrapper unwrap_int1; @@ -233,32 +266,41 @@ BOOST_PYTHON_MODULE_INIT(m1) // These compilers will need additional converters static simple_ref_wrapper wrap_simple_ref; #endif + + // This unwrapper extracts pointers and references to the "complicated" class. static boost::python::converter::class_unwrapper unwrap_complicated; PyObject* d = PyModule_GetDict(m1); if (d == NULL) return; + // Insert the extension metaclass object if (PyDict_SetItemString( d, "xclass", (PyObject *)boost::python::object::class_metatype()) < 0) return; + // Insert the base class for all extension classes if (PyDict_SetItemString( d, "xinst", (PyObject *)boost::python::object::class_type()) < 0) return; + // Expose f() if (PyDict_SetItemString( d, "f", boost::python::make_function(f)) < 0) return; + // Expose g() if (PyDict_SetItemString( d, "g", boost::python::make_function(g)) < 0) return; + // Expose complicated's get_n() member function. See newtest.py + // for how it's used to build an extension class. if (PyDict_SetItemString( d, "get_n", boost::python::make_function(&complicated::get_n)) < 0) return; + // Expose complicated::complicated(simple const&, int) as init1 if (PyDict_SetItemString( d, "init1" , boost::python::make_constructor< @@ -268,6 +310,7 @@ BOOST_PYTHON_MODULE_INIT(m1) ) < 0) return; + // Expose complicated::complicated(simple const&) as init2 if (PyDict_SetItemString( d, "init2" , boost::python::make_constructor< diff --git a/test/m2.cpp b/test/m2.cpp index d2093a20..04750dd7 100644 --- a/test/m2.cpp +++ b/test/m2.cpp @@ -4,6 +4,13 @@ // "as is" without express or implied warranty, and with no claim as // to its suitability for any purpose. +// This module exercises the converters exposed in m1 at a low level +// by exposing raw Python extension functions that use wrap<> and +// unwrap<> objects. + +// Seems to be neccessary to suppress an ICE with MSVC +#include + #include #include #include "simple_type.hpp" @@ -11,7 +18,10 @@ using boost::python::wrap; using boost::python::unwrap; -extern "C" { +extern "C" +{ + // Get a simple (by value) from the argument, and return the + // string it holds. PyObject* unwrap_simple(PyObject* self, PyObject* args) { @@ -28,6 +38,8 @@ extern "C" { return PyString_FromString(x.s); }; + // Likewise, but demands that its possible to get a non-const + // reference to the simple. PyObject* unwrap_simple_ref(PyObject* self, PyObject* args) { @@ -44,6 +56,7 @@ extern "C" { return PyString_FromString(x.s); }; + // Likewise, with a const reference to the simple object. PyObject* unwrap_simple_const_ref(PyObject* self, PyObject* args) { @@ -60,6 +73,8 @@ extern "C" { return PyString_FromString(x.s); }; + // Get an int (by value) from the argument, and convert it to a + // Python Int. PyObject* unwrap_int(PyObject* self, PyObject* args) { @@ -76,6 +91,7 @@ extern "C" { return PyInt_FromLong(x); }; + // Get a non-const reference to an int from the argument PyObject* unwrap_int_ref(PyObject* self, PyObject* args) { @@ -92,6 +108,7 @@ extern "C" { return PyInt_FromLong(x); }; + // Get a const reference to an int from the argument. PyObject* unwrap_int_const_ref(PyObject* self, PyObject* args) { @@ -110,8 +127,12 @@ extern "C" { // ------------------- } + +// MSVC6 bug workaround template struct xxxx; +// rewrap extracts a T from the argument, then converts the T back +// to a PyObject* and returns it. template PyObject* rewrap(PyObject* self, PyObject* args, xxxx* = 0) @@ -134,6 +155,10 @@ rewrap(PyObject* self, PyObject* args, xxxx* = 0) extern "C" { + // + // Use rewrap to test simple, simple&, simple const&, int, + // int&, int const& + // PyObject* wrap_simple(PyObject* self, PyObject* args) { diff --git a/test/newtest.py b/test/newtest.py index 783e2240..b866258c 100644 --- a/test/newtest.py +++ b/test/newtest.py @@ -59,11 +59,17 @@ try: wrap_int_ref(n) >>> f(g(s)) 12 +Create an extension class which wraps "complicated" (init1 and get_n) +are a complicated constructor and member function, respectively. + >>> C = xclass('C', (xinst,), {'__init__': init1, 'get_n': get_n}) >>> c = C(s, 99) >>> c.get_n() 99 +Create another extension class which wraps "complicated" (init2 is a +different constructor -- no overloading yet). + >>> D = xclass('D', (xinst,), {'__init__': init2, 'get_n': get_n}) >>> d = D(s) >>> d.get_n() From 451aac806e9dc8938ad542bd8ecb8387415d8500 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 4 Jan 2002 20:15:49 +0000 Subject: [PATCH 189/369] remove extra semicolons [SVN r12214] --- include/boost/python/detail/returning.hpp | 124 +++++++++++----------- src/gen_returning.py | 4 +- test/m2.cpp | 24 ++--- 3 files changed, 76 insertions(+), 76 deletions(-) diff --git a/include/boost/python/detail/returning.hpp b/include/boost/python/detail/returning.hpp index 28f1846e..ed107d37 100644 --- a/include/boost/python/detail/returning.hpp +++ b/include/boost/python/detail/returning.hpp @@ -33,7 +33,7 @@ struct returning wrap_more r(c0); if (!c0) return 0; return r( ((*c0).*pmf)() ); - }; + } template static PyObject* call(R (A0::*pmf)(A1), PyObject* args, PyObject* /* keywords */ ) { @@ -45,7 +45,7 @@ struct returning wrap_more r(c1); if (!c0) return 0; return r( ((*c0).*pmf)(*c1) ); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2), PyObject* args, PyObject* /* keywords */ ) { @@ -58,7 +58,7 @@ struct returning wrap_more r(c2); if (!c0) return 0; return r( ((*c0).*pmf)(*c1, *c2) ); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3), PyObject* args, PyObject* /* keywords */ ) { @@ -72,7 +72,7 @@ struct returning wrap_more r(c3); if (!c0) return 0; return r( ((*c0).*pmf)(*c1, *c2, *c3) ); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ ) { @@ -87,7 +87,7 @@ struct returning wrap_more r(c4); if (!c0) return 0; return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) ); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ ) { @@ -103,7 +103,7 @@ struct returning wrap_more r(c5); if (!c0) return 0; return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5) ); - }; + } template static PyObject* call(R (A0::*pmf)() const, PyObject* args, PyObject* /* keywords */ ) @@ -115,7 +115,7 @@ struct returning wrap_more r(c0); if (!c0) return 0; return r( ((*c0).*pmf)() ); - }; + } template static PyObject* call(R (A0::*pmf)(A1) const, PyObject* args, PyObject* /* keywords */ ) { @@ -127,7 +127,7 @@ struct returning wrap_more r(c1); if (!c0) return 0; return r( ((*c0).*pmf)(*c1) ); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2) const, PyObject* args, PyObject* /* keywords */ ) { @@ -140,7 +140,7 @@ struct returning wrap_more r(c2); if (!c0) return 0; return r( ((*c0).*pmf)(*c1, *c2) ); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3) const, PyObject* args, PyObject* /* keywords */ ) { @@ -154,7 +154,7 @@ struct returning wrap_more r(c3); if (!c0) return 0; return r( ((*c0).*pmf)(*c1, *c2, *c3) ); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const, PyObject* args, PyObject* /* keywords */ ) { @@ -169,7 +169,7 @@ struct returning wrap_more r(c4); if (!c0) return 0; return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) ); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject* /* keywords */ ) { @@ -185,7 +185,7 @@ struct returning wrap_more r(c5); if (!c0) return 0; return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5) ); - }; + } template static PyObject* call(R (A0::*pmf)() volatile, PyObject* args, PyObject* /* keywords */ ) @@ -197,7 +197,7 @@ struct returning wrap_more r(c0); if (!c0) return 0; return r( ((*c0).*pmf)() ); - }; + } template static PyObject* call(R (A0::*pmf)(A1) volatile, PyObject* args, PyObject* /* keywords */ ) { @@ -209,7 +209,7 @@ struct returning wrap_more r(c1); if (!c0) return 0; return r( ((*c0).*pmf)(*c1) ); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2) volatile, PyObject* args, PyObject* /* keywords */ ) { @@ -222,7 +222,7 @@ struct returning wrap_more r(c2); if (!c0) return 0; return r( ((*c0).*pmf)(*c1, *c2) ); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3) volatile, PyObject* args, PyObject* /* keywords */ ) { @@ -236,7 +236,7 @@ struct returning wrap_more r(c3); if (!c0) return 0; return r( ((*c0).*pmf)(*c1, *c2, *c3) ); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) volatile, PyObject* args, PyObject* /* keywords */ ) { @@ -251,7 +251,7 @@ struct returning wrap_more r(c4); if (!c0) return 0; return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) ); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) volatile, PyObject* args, PyObject* /* keywords */ ) { @@ -267,7 +267,7 @@ struct returning wrap_more r(c5); if (!c0) return 0; return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5) ); - }; + } // missing const volatile type traits @@ -282,7 +282,7 @@ struct returning wrap_more r(c0); if (!c0) return 0; return r( ((*c0).*pmf)() ); - }; + } template static PyObject* call(R (A0::*pmf)(A1) const volatile, PyObject* args, PyObject* /* keywords */ ) { @@ -294,7 +294,7 @@ struct returning wrap_more r(c1); if (!c0) return 0; return r( ((*c0).*pmf)(*c1) ); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2) const volatile, PyObject* args, PyObject* /* keywords */ ) { @@ -307,7 +307,7 @@ struct returning wrap_more r(c2); if (!c0) return 0; return r( ((*c0).*pmf)(*c1, *c2) ); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3) const volatile, PyObject* args, PyObject* /* keywords */ ) { @@ -321,7 +321,7 @@ struct returning wrap_more r(c3); if (!c0) return 0; return r( ((*c0).*pmf)(*c1, *c2, *c3) ); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const volatile, PyObject* args, PyObject* /* keywords */ ) { @@ -336,7 +336,7 @@ struct returning wrap_more r(c4); if (!c0) return 0; return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) ); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const volatile, PyObject* args, PyObject* /* keywords */ ) { @@ -352,7 +352,7 @@ struct returning wrap_more r(c5); if (!c0) return 0; return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5) ); - }; + } # endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION @@ -361,7 +361,7 @@ struct returning // find the result converter wrap r; return r( (*pf)() ); - }; + } template static PyObject* call(R (*pf)(A0), PyObject* args, PyObject* /* keywords */ ) { @@ -372,7 +372,7 @@ struct returning wrap_more r(c0); if (!c0) return 0; return r( (*pf)(*c0) ); - }; + } template static PyObject* call(R (*pf)(A0, A1), PyObject* args, PyObject* /* keywords */ ) { @@ -384,7 +384,7 @@ struct returning wrap_more r(c1); if (!c0) return 0; return r( (*pf)(*c0, *c1) ); - }; + } template static PyObject* call(R (*pf)(A0, A1, A2), PyObject* args, PyObject* /* keywords */ ) { @@ -397,7 +397,7 @@ struct returning wrap_more r(c2); if (!c0) return 0; return r( (*pf)(*c0, *c1, *c2) ); - }; + } template static PyObject* call(R (*pf)(A0, A1, A2, A3), PyObject* args, PyObject* /* keywords */ ) { @@ -411,7 +411,7 @@ struct returning wrap_more r(c3); if (!c0) return 0; return r( (*pf)(*c0, *c1, *c2, *c3) ); - }; + } template static PyObject* call(R (*pf)(A0, A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ ) { @@ -426,7 +426,7 @@ struct returning wrap_more r(c4); if (!c0) return 0; return r( (*pf)(*c0, *c1, *c2, *c3, *c4) ); - }; + } template static PyObject* call(R (*pf)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ ) { @@ -442,7 +442,7 @@ struct returning wrap_more r(c5); if (!c0) return 0; return r( (*pf)(*c0, *c1, *c2, *c3, *c4, *c5) ); - }; + } }; template <> @@ -458,7 +458,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(); return detail::none(); - }; + } template static PyObject* call(R (A0::*pmf)(A1), PyObject* args, PyObject* /* keywords */ ) { @@ -469,7 +469,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(*c1); return detail::none(); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2), PyObject* args, PyObject* /* keywords */ ) { @@ -481,7 +481,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(*c1, *c2); return detail::none(); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3), PyObject* args, PyObject* /* keywords */ ) { @@ -494,7 +494,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(*c1, *c2, *c3); return detail::none(); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ ) { @@ -508,7 +508,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(*c1, *c2, *c3, *c4); return detail::none(); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ ) { @@ -523,7 +523,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5); return detail::none(); - }; + } template static PyObject* call(R (A0::*pmf)() const, PyObject* args, PyObject* /* keywords */ ) @@ -534,7 +534,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(); return detail::none(); - }; + } template static PyObject* call(R (A0::*pmf)(A1) const, PyObject* args, PyObject* /* keywords */ ) { @@ -545,7 +545,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(*c1); return detail::none(); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2) const, PyObject* args, PyObject* /* keywords */ ) { @@ -557,7 +557,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(*c1, *c2); return detail::none(); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3) const, PyObject* args, PyObject* /* keywords */ ) { @@ -570,7 +570,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(*c1, *c2, *c3); return detail::none(); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const, PyObject* args, PyObject* /* keywords */ ) { @@ -584,7 +584,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(*c1, *c2, *c3, *c4); return detail::none(); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject* /* keywords */ ) { @@ -599,7 +599,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5); return detail::none(); - }; + } template static PyObject* call(R (A0::*pmf)() volatile, PyObject* args, PyObject* /* keywords */ ) @@ -610,7 +610,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(); return detail::none(); - }; + } template static PyObject* call(R (A0::*pmf)(A1) volatile, PyObject* args, PyObject* /* keywords */ ) { @@ -621,7 +621,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(*c1); return detail::none(); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2) volatile, PyObject* args, PyObject* /* keywords */ ) { @@ -633,7 +633,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(*c1, *c2); return detail::none(); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3) volatile, PyObject* args, PyObject* /* keywords */ ) { @@ -646,7 +646,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(*c1, *c2, *c3); return detail::none(); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) volatile, PyObject* args, PyObject* /* keywords */ ) { @@ -660,7 +660,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(*c1, *c2, *c3, *c4); return detail::none(); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) volatile, PyObject* args, PyObject* /* keywords */ ) { @@ -675,7 +675,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5); return detail::none(); - }; + } // missing const volatile type traits @@ -689,7 +689,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(); return detail::none(); - }; + } template static PyObject* call(R (A0::*pmf)(A1) const volatile, PyObject* args, PyObject* /* keywords */ ) { @@ -700,7 +700,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(*c1); return detail::none(); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2) const volatile, PyObject* args, PyObject* /* keywords */ ) { @@ -712,7 +712,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(*c1, *c2); return detail::none(); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3) const volatile, PyObject* args, PyObject* /* keywords */ ) { @@ -725,7 +725,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(*c1, *c2, *c3); return detail::none(); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const volatile, PyObject* args, PyObject* /* keywords */ ) { @@ -739,7 +739,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(*c1, *c2, *c3, *c4); return detail::none(); - }; + } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const volatile, PyObject* args, PyObject* /* keywords */ ) { @@ -754,7 +754,7 @@ struct returning if (!c0) return 0; ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5); return detail::none(); - }; + } # endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION @@ -762,7 +762,7 @@ struct returning { (*pf)(); return detail::none(); - }; + } template static PyObject* call(R (*pf)(A0), PyObject* args, PyObject* /* keywords */ ) { @@ -772,7 +772,7 @@ struct returning if (!c0) return 0; (*pf)(*c0); return detail::none(); - }; + } template static PyObject* call(R (*pf)(A0, A1), PyObject* args, PyObject* /* keywords */ ) { @@ -783,7 +783,7 @@ struct returning if (!c0) return 0; (*pf)(*c0, *c1); return detail::none(); - }; + } template static PyObject* call(R (*pf)(A0, A1, A2), PyObject* args, PyObject* /* keywords */ ) { @@ -795,7 +795,7 @@ struct returning if (!c0) return 0; (*pf)(*c0, *c1, *c2); return detail::none(); - }; + } template static PyObject* call(R (*pf)(A0, A1, A2, A3), PyObject* args, PyObject* /* keywords */ ) { @@ -808,7 +808,7 @@ struct returning if (!c0) return 0; (*pf)(*c0, *c1, *c2, *c3); return detail::none(); - }; + } template static PyObject* call(R (*pf)(A0, A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ ) { @@ -822,7 +822,7 @@ struct returning if (!c0) return 0; (*pf)(*c0, *c1, *c2, *c3, *c4); return detail::none(); - }; + } template static PyObject* call(R (*pf)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ ) { @@ -837,7 +837,7 @@ struct returning if (!c0) return 0; (*pf)(*c0, *c1, *c2, *c3, *c4, *c5); return detail::none(); - }; + } }; }}} // namespace boost::python::detail diff --git a/src/gen_returning.py b/src/gen_returning.py index 2b112cc0..2c33cfe5 100644 --- a/src/gen_returning.py +++ b/src/gen_returning.py @@ -74,7 +74,7 @@ member_function = ''' template %] if (!c0) return 0; %[r%:return r( %]((*c0).*pmf)(%(*c%+%:, %))%[r%: )%];%[v%: return detail::none();%] - }; + } ''' free_function = '''%{ template <%(class A%n%:, %)> @@ -88,7 +88,7 @@ free_function = '''%{ template <%(class A%n%:, %)> if (!c0) return 0;%} %[r%:return r( %](*pf)(%(*c%n%:, %))%[r%: )%];%[v%: return detail::none();%] - }; + } ''' def _returns_value(key, n, args, value): diff --git a/test/m2.cpp b/test/m2.cpp index 04750dd7..377ce02e 100644 --- a/test/m2.cpp +++ b/test/m2.cpp @@ -36,7 +36,7 @@ extern "C" simple x = *in; return PyString_FromString(x.s); - }; + } // Likewise, but demands that its possible to get a non-const // reference to the simple. @@ -54,7 +54,7 @@ extern "C" simple& x = *in; return PyString_FromString(x.s); - }; + } // Likewise, with a const reference to the simple object. PyObject* @@ -71,7 +71,7 @@ extern "C" simple const& x = *in; return PyString_FromString(x.s); - }; + } // Get an int (by value) from the argument, and convert it to a // Python Int. @@ -89,7 +89,7 @@ extern "C" int x = *in; return PyInt_FromLong(x); - }; + } // Get a non-const reference to an int from the argument PyObject* @@ -106,7 +106,7 @@ extern "C" int& x = *in; return PyInt_FromLong(x); - }; + } // Get a const reference to an int from the argument. PyObject* @@ -123,7 +123,7 @@ extern "C" int const& x = *in; return PyInt_FromLong(x); - }; + } // ------------------- } @@ -163,37 +163,37 @@ extern "C" wrap_simple(PyObject* self, PyObject* args) { return rewrap(self, args); - }; + } PyObject* wrap_simple_ref(PyObject* self, PyObject* args) { return rewrap(self, args); - }; + } PyObject* wrap_simple_const_ref(PyObject* self, PyObject* args) { return rewrap(self, args); - }; + } PyObject* wrap_int(PyObject* self, PyObject* args) { return rewrap(self, args); - }; + } PyObject* wrap_int_ref(PyObject* self, PyObject* args) { return rewrap(self, args); - }; + } PyObject* wrap_int_const_ref(PyObject* self, PyObject* args) { return rewrap(self, args); - }; + } } PyMethodDef initial_methods[] = From acdae42fc538593b730f3d9ce58c6e771d1661f3 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 4 Jan 2002 20:49:20 +0000 Subject: [PATCH 190/369] work-around for cxx [SVN r12215] --- include/boost/python/detail/config.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/python/detail/config.hpp b/include/boost/python/detail/config.hpp index 97d84a79..886e2fa8 100644 --- a/include/boost/python/detail/config.hpp +++ b/include/boost/python/detail/config.hpp @@ -76,7 +76,7 @@ # define BOOST_PYTHON_STATIC_LINK #endif -#if defined(__MWERKS__) +#if defined(__MWERKS__) || (defined(__DECCXX_VER) && __DECCXX_VER <= 60290024) # define BOOST_PYTHON_NO_TEMPLATE_EXPORT #endif From e2623c5e82ed2c8af75a17b09c6b80e0182cf4fb Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 4 Jan 2002 23:32:23 +0000 Subject: [PATCH 191/369] fixes for gcc-3.0.3 [SVN r12221] --- include/boost/python/detail/wrap_python.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/boost/python/detail/wrap_python.hpp b/include/boost/python/detail/wrap_python.hpp index d0ad5dd2..3807eae1 100644 --- a/include/boost/python/detail/wrap_python.hpp +++ b/include/boost/python/detail/wrap_python.hpp @@ -47,7 +47,9 @@ typedef int pid_t; # define HAVE_STRERROR # endif # define NT_THREADS -# define WITH_THREAD +# if __GNUC__ < 3 || __GNUC__ == 3 && __GNUC_MINOR__ == 0 && __GNUC_PATCHLEVEL__ < 3 +# define WITH_THREAD +# endif # ifndef NETSCAPE_PI # define USE_SOCKET # endif From 8d27b4822507b72b63b3ffa834c5e874ddd71c16 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 5 Jan 2002 02:18:00 +0000 Subject: [PATCH 192/369] update for cxx 6.5 and irix_CC [SVN r12222] --- include/boost/python/detail/config.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/boost/python/detail/config.hpp b/include/boost/python/detail/config.hpp index 886e2fa8..c488cb64 100644 --- a/include/boost/python/detail/config.hpp +++ b/include/boost/python/detail/config.hpp @@ -76,7 +76,9 @@ # define BOOST_PYTHON_STATIC_LINK #endif -#if defined(__MWERKS__) || (defined(__DECCXX_VER) && __DECCXX_VER <= 60290024) +#if defined(__MWERKS__) \ + || (defined(__DECCXX_VER) && __DECCXX_VER <= 60590002) \ + || (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730) # define BOOST_PYTHON_NO_TEMPLATE_EXPORT #endif From b65f4ff963a6ea6a7962b5b221a2befd76d404df Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 6 Jan 2002 14:29:54 +0000 Subject: [PATCH 193/369] added inlines [SVN r12224] --- include/boost/python/call.hpp | 62 +++++++++++++++++------------------ 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/include/boost/python/call.hpp b/include/boost/python/call.hpp index bdda879d..b95a31d5 100644 --- a/include/boost/python/call.hpp +++ b/include/boost/python/call.hpp @@ -17,188 +17,188 @@ namespace boost { namespace python { template -PyObject* call(R (*f)(), PyObject* args, PyObject* keywords) +inline PyObject* call(R (*f)(), PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (*f)(A0), PyObject* args, PyObject* keywords) +inline PyObject* call(R (*f)(A0), PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (*f)(A0, A1), PyObject* args, PyObject* keywords) +inline PyObject* call(R (*f)(A0, A1), PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (*f)(A0, A1, A2), PyObject* args, PyObject* keywords) +inline PyObject* call(R (*f)(A0, A1, A2), PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (*f)(A0, A1, A2, A3), PyObject* args, PyObject* keywords) +inline PyObject* call(R (*f)(A0, A1, A2, A3), PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (*f)(A0, A1, A2, A3, A4), PyObject* args, PyObject* keywords) +inline PyObject* call(R (*f)(A0, A1, A2, A3, A4), PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (*f)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject* keywords) +inline PyObject* call(R (*f)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } // Member functions template -PyObject* call(R (A0::*f)(), PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)(), PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (A0::*f)(A1), PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)(A1), PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (A0::*f)(A1, A2), PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)(A1, A2), PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (A0::*f)(A1, A2, A3), PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)(A1, A2, A3), PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (A0::*f)(A1, A2, A3, A4), PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)(A1, A2, A3, A4), PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5), PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5), PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (A0::*f)() const, PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)() const, PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (A0::*f)(A1) const, PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)(A1) const, PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (A0::*f)(A1, A2) const, PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)(A1, A2) const, PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (A0::*f)(A1, A2, A3) const, PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)(A1, A2, A3) const, PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (A0::*f)(A1, A2, A3, A4) const, PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)(A1, A2, A3, A4) const, PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (A0::*f)() volatile, PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)() volatile, PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (A0::*f)(A1) volatile, PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)(A1) volatile, PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (A0::*f)(A1, A2) volatile, PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)(A1, A2) volatile, PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (A0::*f)(A1, A2, A3) volatile, PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)(A1, A2, A3) volatile, PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (A0::*f)(A1, A2, A3, A4) volatile, PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)(A1, A2, A3, A4) volatile, PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5) volatile, PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5) volatile, PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (A0::*f)() const volatile, PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)() const volatile, PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (A0::*f)(A1) const volatile, PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)(A1) const volatile, PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (A0::*f)(A1, A2) const volatile, PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)(A1, A2) const volatile, PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (A0::*f)(A1, A2, A3) const volatile, PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)(A1, A2, A3) const volatile, PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (A0::*f)(A1, A2, A3, A4) const volatile, PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)(A1, A2, A3, A4) const volatile, PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } template -PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5) const volatile, PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5) const volatile, PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } From 462b91fb0830dc5b23d21ee84bc249b3f666ac51 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 6 Jan 2002 14:30:46 +0000 Subject: [PATCH 194/369] Added min/max argument count checking [SVN r12225] --- include/boost/python/make_function.hpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/include/boost/python/make_function.hpp b/include/boost/python/make_function.hpp index d824c0a4..fddc640b 100644 --- a/include/boost/python/make_function.hpp +++ b/include/boost/python/make_function.hpp @@ -12,27 +12,30 @@ # include # include # include +# include namespace boost { namespace python { template -PyObject* make_function(F f) +objects::function* make_function(F f) { - return new object::function( - object::py_function( - bind(detail::caller(), f, _1, _2))); + return new objects::function( + objects::py_function( + bind(detail::caller(), f, _1, _2)) + , detail::arg_tuple_size::value); } template -PyObject* make_constructor(T* = 0, ArgList* = 0, Generator* = 0) +objects::function* make_constructor(T* = 0, ArgList* = 0, Generator* = 0) { enum { nargs = mpl::size::value }; - return new object::function( - object::py_function( + return new objects::function( + objects::py_function( bind(detail::caller(), - object::make_holder + objects::make_holder ::template apply::execute - , _1, _2))); + , _1, _2)) + , nargs + 1); } }} // namespace boost::python From 4b88b9eed19077136414ff961ff648fcf7c9d791 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 6 Jan 2002 14:31:27 +0000 Subject: [PATCH 195/369] Added most of the module_builder interface [SVN r12226] --- include/boost/python/module.hpp | 63 +++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/include/boost/python/module.hpp b/include/boost/python/module.hpp index c20279c3..b257b9ff 100644 --- a/include/boost/python/module.hpp +++ b/include/boost/python/module.hpp @@ -8,5 +8,68 @@ # include # include +# include +# include +# include + +namespace boost { namespace python { + +class BOOST_PYTHON_DECL module_base +{ + public: + // Create a module. REQUIRES: only one module is created per module. + module_base(const char* name); + ~module_base(); + + // Add elements to the module + void add(PyObject* x, const char* name); + void add(PyTypeObject* x, const char* name = 0); + void add(ref x, const char*name); + void add_overload(objects::function* x, const char* name); + + // Return true iff a module is currently being built. + static bool initializing(); + + // Return the name of the module currently being built. + // REQUIRES: initializing() == true + static string name(); + + // Return a pointer to the Python module object being built + PyObject* module() const; + + private: + PyObject* m_module; + static PyMethodDef initial_methods[1]; +}; + +class module : public module_base +{ + public: + module(const char* name) + : module_base(name) {} + +# if 0 + template + void def_raw(Fn fn, const char* name) + { + add(detail::new_raw_arguments_function(fn), name); + } +# endif + template + void def(Fn fn, const char* name) + { + add_overload(make_function(fn), name); + } +}; + +// +// inline implementations +// +inline PyObject* module_base::module() const +{ + return m_module; +} + +}} // namespace boost::python #endif // MODULE_DWA20011221_HPP From 8d56c529916bb3e12c0241ab3af50691d5b329b6 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 6 Jan 2002 14:32:51 +0000 Subject: [PATCH 196/369] simplification: I didn't really understand what I was dealing with, so I pared things down. [SVN r12227] --- include/boost/python/converter/source.hpp | 58 +++-------------------- 1 file changed, 7 insertions(+), 51 deletions(-) diff --git a/include/boost/python/converter/source.hpp b/include/boost/python/converter/source.hpp index 9af1cf49..94fdc5b8 100644 --- a/include/boost/python/converter/source.hpp +++ b/include/boost/python/converter/source.hpp @@ -17,63 +17,19 @@ namespace boost { namespace python { namespace converter { // ../../../more/generic_programming.html#type_generator) is used // to select the argument type to use when converting T to a PyObject* -template struct source; - -# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -// Since for some strange reason temporaries can't be bound to const -// volatile references (8.5.3/5 in the C++ standard), we cannot use a -// const volatile reference as the standard for values and references. template struct source { - typedef T const& type; -}; + BOOST_STATIC_CONSTANT(bool, use_identity = (::boost::is_pointer::value)); -// This will handle the following: -// T const volatile& -> T const volatile& -// T volatile& -> T const volatile& -// T const& -> T const& -// T& -> T const& -template -struct source -{ - typedef T const& type; -}; - -template -struct source -{ - typedef T const* type; -}; - -template -struct source -{ - typedef T const* type; -}; - -// Deal with references to pointers -template -struct source -{ - typedef T const* type; -}; - -template -struct source -{ - typedef T const* type; -}; -# else -template -struct source -{ - typedef typename add_reference< - typename add_const::type + typedef typename mpl::select_type< + use_identity + , T + , typename add_reference< + typename add_const::type + >::type >::type type; }; -# endif }}} // namespace boost::python::converter From 1cc65a47eb708d0569319481bda49ff8fe8ad247 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 6 Jan 2002 14:33:33 +0000 Subject: [PATCH 197/369] Added wrapper for PyObject* [SVN r12228] --- include/boost/python/converter/wrap.hpp | 29 +++++++++++++++++++--- include/boost/python/converter/wrapper.hpp | 2 ++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/include/boost/python/converter/wrap.hpp b/include/boost/python/converter/wrap.hpp index e26cf0f6..ec87f73d 100644 --- a/include/boost/python/converter/wrap.hpp +++ b/include/boost/python/converter/wrap.hpp @@ -16,6 +16,7 @@ namespace boost { namespace python { namespace converter { struct BOOST_PYTHON_DECL wrapper_base; +extern BOOST_PYTHON_DECL body& identity_wrapper; template struct wrapper; @@ -66,13 +67,33 @@ struct wrap_ : wrap_more_ ~wrap_(); }; + +// Specialization for PyObject* +template <> +struct wrap_more_ : wrap_base +{ + protected: + typedef PyObject* source_t; + + public: // member functions + wrap_more_(handle& prev) + : wrap_base(&identity_wrapper, prev) {} + + PyObject* operator()(source_t x) const { return x; } + + protected: // constructor for wrap_, below + wrap_more_() + : wrap_base(&identity_wrapper) {} + private: + friend class wrapper; +}; + // // implementations // - inline wrap_base::wrap_base(body* body, handle& prev) - : handle(body, prev), - m_target(0) + : handle(body, prev) + , m_target(0) { } @@ -119,7 +140,7 @@ template PyObject* wrap_more_::operator()(source_t x) const { return static_cast*>( - get_body())->do_conversion(*this, source_holder(x)); + this->get_body())->do_conversion(*this, source_holder(x)); } template diff --git a/include/boost/python/converter/wrapper.hpp b/include/boost/python/converter/wrapper.hpp index 49c32186..80afae46 100644 --- a/include/boost/python/converter/wrapper.hpp +++ b/include/boost/python/converter/wrapper.hpp @@ -27,6 +27,8 @@ struct BOOST_PYTHON_DECL wrapper_base : body virtual PyObject* do_conversion(wrap_base const&, source_holder_base const&) const = 0; }; +extern BOOST_PYTHON_DECL body& identity_wrapper; + template struct wrapper : wrapper_base { From fb333f36419cb3c32211d1c811c1d718d213419a Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 6 Jan 2002 14:34:14 +0000 Subject: [PATCH 198/369] Bug fix: convertability checks were missed in one case [SVN r12229] --- include/boost/python/detail/returning.hpp | 29 ++++++++++++----------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/include/boost/python/detail/returning.hpp b/include/boost/python/detail/returning.hpp index ed107d37..87aecac5 100644 --- a/include/boost/python/detail/returning.hpp +++ b/include/boost/python/detail/returning.hpp @@ -359,8 +359,9 @@ struct returning static PyObject* call(R (*pf)(), PyObject*, PyObject* /* keywords */ ) { // find the result converter - wrap r; - return r( (*pf)() ); + wrap c0; + if (!c0) return 0; + return c0( (*pf)() ); } template static PyObject* call(R (*pf)(A0), PyObject* args, PyObject* /* keywords */ ) @@ -369,9 +370,9 @@ struct returning unwrap c0(PyTuple_GET_ITEM(args, 0)); // find the result converter - wrap_more r(c0); + wrap_more c1(c0); if (!c0) return 0; - return r( (*pf)(*c0) ); + return c1( (*pf)(*c0) ); } template static PyObject* call(R (*pf)(A0, A1), PyObject* args, PyObject* /* keywords */ ) @@ -381,9 +382,9 @@ struct returning unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); // find the result converter - wrap_more r(c1); + wrap_more c2(c1); if (!c0) return 0; - return r( (*pf)(*c0, *c1) ); + return c2( (*pf)(*c0, *c1) ); } template static PyObject* call(R (*pf)(A0, A1, A2), PyObject* args, PyObject* /* keywords */ ) @@ -394,9 +395,9 @@ struct returning unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); // find the result converter - wrap_more r(c2); + wrap_more c3(c2); if (!c0) return 0; - return r( (*pf)(*c0, *c1, *c2) ); + return c3( (*pf)(*c0, *c1, *c2) ); } template static PyObject* call(R (*pf)(A0, A1, A2, A3), PyObject* args, PyObject* /* keywords */ ) @@ -408,9 +409,9 @@ struct returning unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); // find the result converter - wrap_more r(c3); + wrap_more c4(c3); if (!c0) return 0; - return r( (*pf)(*c0, *c1, *c2, *c3) ); + return c4( (*pf)(*c0, *c1, *c2, *c3) ); } template static PyObject* call(R (*pf)(A0, A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ ) @@ -423,9 +424,9 @@ struct returning unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); // find the result converter - wrap_more r(c4); + wrap_more c5(c4); if (!c0) return 0; - return r( (*pf)(*c0, *c1, *c2, *c3, *c4) ); + return c5( (*pf)(*c0, *c1, *c2, *c3, *c4) ); } template static PyObject* call(R (*pf)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ ) @@ -439,9 +440,9 @@ struct returning unwrap_more c5(PyTuple_GET_ITEM(args, 5), c4); // find the result converter - wrap_more r(c5); + wrap_more c6(c5); if (!c0) return 0; - return r( (*pf)(*c0, *c1, *c2, *c3, *c4, *c5) ); + return c6( (*pf)(*c0, *c1, *c2, *c3, *c4, *c5) ); } }; From 26d520af3cd25249987f0864cac66f1fc1683818 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 6 Jan 2002 14:35:27 +0000 Subject: [PATCH 199/369] avoiding naming conflict, object:: -> objects:: [SVN r12230] --- include/boost/python/converter/class.hpp | 10 +++++----- include/boost/python/object/class.hpp | 4 ++-- include/boost/python/object/class_unwrapper.hpp | 4 ++-- include/boost/python/object/construct.hpp | 4 ++-- include/boost/python/object/make_holder.hpp | 4 ++-- include/boost/python/object/value_holder.hpp | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/include/boost/python/converter/class.hpp b/include/boost/python/converter/class.hpp index 6e09a961..c6fef86a 100644 --- a/include/boost/python/converter/class.hpp +++ b/include/boost/python/converter/class.hpp @@ -32,31 +32,31 @@ struct class_unwrapper template void* class_unwrapper::can_convert(PyObject* p) const { - return object::find_holder(p); + return objects::find_holder(p); } template T& class_unwrapper::convert(PyObject*, void* holder_, boost::type) const { - return *static_cast*>(holder_)->target(); + return *static_cast*>(holder_)->target(); } template T const& class_unwrapper::convert(PyObject*, void* holder_, boost::type) const { - return *static_cast*>(holder_)->target(); + return *static_cast*>(holder_)->target(); } template T* class_unwrapper::convert(PyObject*, void* holder_, boost::type) const { - return static_cast*>(holder_)->target(); + return static_cast*>(holder_)->target(); } template T const* class_unwrapper::convert(PyObject*, void* holder_, boost::type) const { - return static_cast*>(holder_)->target(); + return static_cast*>(holder_)->target(); } }}} // namespace boost::python::converter diff --git a/include/boost/python/object/class.hpp b/include/boost/python/object/class.hpp index 35085e5f..b272d5fe 100644 --- a/include/boost/python/object/class.hpp +++ b/include/boost/python/object/class.hpp @@ -12,7 +12,7 @@ # include # include -namespace boost { namespace python { namespace object { +namespace boost { namespace python { namespace objects { template struct holder; @@ -98,6 +98,6 @@ holder::holder() { } -}}} // namespace boost::python::object +}}} // namespace boost::python::objects #endif // CLASS_DWA20011214_HPP diff --git a/include/boost/python/object/class_unwrapper.hpp b/include/boost/python/object/class_unwrapper.hpp index 4fa441e1..666c6e93 100644 --- a/include/boost/python/object/class_unwrapper.hpp +++ b/include/boost/python/object/class_unwrapper.hpp @@ -9,7 +9,7 @@ # include # include -namespace boost { namespace python { namespace object { +namespace boost { namespace python { namespace objects { template struct class_unwrapper @@ -35,6 +35,6 @@ struct class_unwrapper # endif }; -}}} // namespace boost::python::object +}}} // namespace boost::python::objects #endif // CLASS_UNWRAPPER_DWA20011221_HPP diff --git a/include/boost/python/object/construct.hpp b/include/boost/python/object/construct.hpp index 3ff701d2..1eb73e4a 100644 --- a/include/boost/python/object/construct.hpp +++ b/include/boost/python/object/construct.hpp @@ -6,7 +6,7 @@ #ifndef CONSTRUCT_DWA20011215_HPP # define CONSTRUCT_DWA20011215_HPP -namespace boost { namespace python { namespace object { +namespace boost { namespace python { namespace objects { template struct construct @@ -19,6 +19,6 @@ struct construct } }; -}}} // namespace boost::python::object +}}} // namespace boost::python::objects #endif // CONSTRUCT_DWA20011215_HPP diff --git a/include/boost/python/object/make_holder.hpp b/include/boost/python/object/make_holder.hpp index fb5ec382..76b3a5f4 100644 --- a/include/boost/python/object/make_holder.hpp +++ b/include/boost/python/object/make_holder.hpp @@ -11,7 +11,7 @@ # include # include -namespace boost { namespace python { namespace object { +namespace boost { namespace python { namespace objects { template struct undefined; @@ -119,6 +119,6 @@ struct make_holder<3> }; }; -}}} // namespace boost::python::object +}}} // namespace boost::python::objects #endif // MAKE_HOLDER_DWA20011215_HPP diff --git a/include/boost/python/object/value_holder.hpp b/include/boost/python/object/value_holder.hpp index 128d170b..a06afe84 100644 --- a/include/boost/python/object/value_holder.hpp +++ b/include/boost/python/object/value_holder.hpp @@ -8,7 +8,7 @@ # include -namespace boost { namespace python { namespace object { +namespace boost { namespace python { namespace objects { template struct value_holder : holder @@ -75,6 +75,6 @@ struct value_holder_generator }; }; -}}} // namespace boost::python::object +}}} // namespace boost::python::objects #endif // VALUE_HOLDER_DWA20011215_HPP From ab22e1b3a9b592837f73fb29de5feb275e440626 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 6 Jan 2002 14:36:28 +0000 Subject: [PATCH 200/369] Added most of the module_builder interface [SVN r12231] --- Jamfile | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/Jamfile b/Jamfile index 18372684..13cb04d7 100644 --- a/Jamfile +++ b/Jamfile @@ -13,17 +13,19 @@ PYTHON_PROPERTIES dll bpl : - src/converter/body.cpp - src/converter/handle.cpp - src/converter/registry.cpp - src/converter/wrapper.cpp - src/converter/unwrap.cpp - src/converter/unwrapper.cpp - src/converter/type_id.cpp - src/object/class.cpp - src/object/function.cpp - src/errors.cpp - : + src/converter/body.cpp + src/converter/handle.cpp + src/converter/registry.cpp + src/converter/wrapper.cpp + src/converter/unwrap.cpp + src/converter/unwrapper.cpp + src/converter/type_id.cpp + src/object/class.cpp + src/object/function.cpp + src/errors.cpp + src/module.cpp + src/objects.cpp + : $(PYTHON_PROPERTIES) BOOST_PYTHON_SOURCE ; From d598d0a4dbc3fad4426d6dc90b8d6d76c047fcd6 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 6 Jan 2002 14:39:34 +0000 Subject: [PATCH 201/369] added inlines [SVN r12232] --- src/gen_call.py | 4 +- test/m1.cpp | 99 ++++++++------------------- test/m2.cpp | 177 +++++++----------------------------------------- test/newtest.py | 21 ++---- 4 files changed, 61 insertions(+), 240 deletions(-) diff --git a/src/gen_call.py b/src/gen_call.py index dd178648..f609c0ae 100644 --- a/src/gen_call.py +++ b/src/gen_call.py @@ -36,7 +36,7 @@ def gen_call(member_function_args, free_function_args = None): return (header % (member_function_args, free_function_args) + gen_functions( '''template -PyObject* call(R (*f)(%(A%n%:, %)), PyObject* args, PyObject* keywords) +inline PyObject* call(R (*f)(%(A%n%:, %)), PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } @@ -49,7 +49,7 @@ PyObject* call(R (*f)(%(A%n%:, %)), PyObject* args, PyObject* keywords) , map(lambda cv: gen_functions( '''template -PyObject* call(R (A0::*f)(%(A%+%:, %))%1, PyObject* args, PyObject* keywords) +inline PyObject* call(R (A0::*f)(%(A%+%:, %))%1, PyObject* args, PyObject* keywords) { return detail::returning::call(f, args, keywords); } diff --git a/test/m1.cpp b/test/m1.cpp index db450f77..78471bfc 100644 --- a/test/m1.cpp +++ b/test/m1.cpp @@ -4,15 +4,13 @@ // "as is" without express or implied warranty, and with no claim as // to its suitability for any purpose. -// Seems to be neccessary to suppress an ICE with MSVC -#include - #include "simple_type.hpp" #include "complicated.hpp" #include #include #include #include +#include #include #include #include @@ -53,17 +51,10 @@ PyTypeObject NoddyType = { }; // Create a Noddy containing 42 -extern "C" PyObject* -new_noddy(PyObject* self, PyObject* args) +PyObject* new_noddy() { - NoddyObject* noddy; - - if (!PyArg_ParseTuple(args,":new_noddy")) - return NULL; - - noddy = PyObject_New(NoddyObject, &NoddyType); + NoddyObject* noddy = PyObject_New(NoddyObject, &NoddyType); noddy->x = 42; - return (PyObject*)noddy; } @@ -92,27 +83,13 @@ PyTypeObject SimpleType = { }; // Create a Simple containing "hello, world" -extern "C" PyObject* -new_simple(PyObject* self, PyObject* args) +PyObject* new_simple() { - SimpleObject* simple; - - if (!PyArg_ParseTuple(args,":new_simple")) - return NULL; - - simple = PyObject_New(SimpleObject, &SimpleType); + SimpleObject* simple = PyObject_New(SimpleObject, &SimpleType); simple->x.s = "hello, world"; - return (PyObject*)simple; } -// Initial method table for the module -static PyMethodDef methods[] = { - { "new_noddy", new_noddy, METH_VARARGS }, - { "new_simple", new_simple, METH_VARARGS }, - {0, 0, 0, 0} -}; - // // Declare some wrappers/unwrappers to test the low-level conversion // mechanism. See boost/python/converter/source.hpp,target.hpp for a @@ -252,7 +229,7 @@ simple const& g(simple const& x) BOOST_PYTHON_MODULE_INIT(m1) { - PyObject* m1 = Py_InitModule(const_cast("m1"), methods); + boost::python::module m1("m1"); // Create the converters; they are self-registering/unregistering. static int_wrapper wrap_int; @@ -262,63 +239,45 @@ BOOST_PYTHON_MODULE_INIT(m1) static noddy_int_ref_unwrapper unwrap_int3; static simple_ref_unwrapper unwrap_simple; static simple_const_ref_unwrapper unwrap_simple_const_ref; -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - // These compilers will need additional converters static simple_ref_wrapper wrap_simple_ref; -#endif // This unwrapper extracts pointers and references to the "complicated" class. static boost::python::converter::class_unwrapper unwrap_complicated; - PyObject* d = PyModule_GetDict(m1); - if (d == NULL) - return; - // Insert the extension metaclass object - if (PyDict_SetItemString( - d, "xclass", (PyObject *)boost::python::object::class_metatype()) < 0) - return; - + m1.add(boost::python::objects::class_metatype(), "xclass"); + // Insert the base class for all extension classes - if (PyDict_SetItemString( - d, "xinst", (PyObject *)boost::python::object::class_type()) < 0) - return; + m1.add(boost::python::objects::class_type(), "xinst"); + m1.def(new_noddy, "new_noddy"); + m1.def(new_simple, "new_simple"); + // Expose f() - if (PyDict_SetItemString( - d, "f", boost::python::make_function(f)) < 0) - return; + m1.def(f, "f"); // Expose g() - if (PyDict_SetItemString( - d, "g", boost::python::make_function(g)) < 0) - return; + m1.def(g, "g"); // Expose complicated's get_n() member function. See newtest.py // for how it's used to build an extension class. - if (PyDict_SetItemString( - d, "get_n", boost::python::make_function(&complicated::get_n)) < 0) - return; + m1.def(&complicated::get_n, "get_n"); // Expose complicated::complicated(simple const&, int) as init1 - if (PyDict_SetItemString( - d, "init1" - , boost::python::make_constructor< - complicated - , boost::mpl::type_list - , boost::python::object::value_holder_generator>() - ) < 0) - return; - - // Expose complicated::complicated(simple const&) as init2 - if (PyDict_SetItemString( - d, "init2" - , boost::python::make_constructor< - complicated - , boost::mpl::type_list - , boost::python::object::value_holder_generator>() - ) < 0) - return; + boost::python::objects::function* init = boost::python::make_constructor< + complicated + , boost::mpl::type_list + , boost::python::objects::value_holder_generator>(); + + boost::python::ref manager(init); + + init->add_overload( + boost::python::make_constructor< + complicated + , boost::mpl::type_list + , boost::python::objects::value_holder_generator>()); + + m1.add(manager, "init1"); } #include "module_tail.cpp" diff --git a/test/m2.cpp b/test/m2.cpp index 377ce02e..3c5267d0 100644 --- a/test/m2.cpp +++ b/test/m2.cpp @@ -7,10 +7,6 @@ // This module exercises the converters exposed in m1 at a low level // by exposing raw Python extension functions that use wrap<> and // unwrap<> objects. - -// Seems to be neccessary to suppress an ICE with MSVC -#include - #include #include #include "simple_type.hpp" @@ -22,106 +18,40 @@ extern "C" { // Get a simple (by value) from the argument, and return the // string it holds. - PyObject* - unwrap_simple(PyObject* self, PyObject* args) + PyObject* unwrap_simple(simple x) { - PyObject* p; - if (!PyArg_ParseTuple(args, "O", &p)) - return 0; - - boost::python::unwrap in(p); - if (!in) - return 0; - - simple x = *in; - return PyString_FromString(x.s); } // Likewise, but demands that its possible to get a non-const // reference to the simple. - PyObject* - unwrap_simple_ref(PyObject* self, PyObject* args) + PyObject* unwrap_simple_ref(simple& x) { - PyObject* p; - if (!PyArg_ParseTuple(args, "O", &p)) - return 0; - - unwrap in(p); - if (!in) - return 0; - - simple& x = *in; - return PyString_FromString(x.s); } // Likewise, with a const reference to the simple object. - PyObject* - unwrap_simple_const_ref(PyObject* self, PyObject* args) + PyObject* unwrap_simple_const_ref(simple const& x) { - PyObject* p; - if (!PyArg_ParseTuple(args, "O", &p)) - return 0; - - unwrap in(p); - if (!in) - return 0; - - simple const& x = *in; - return PyString_FromString(x.s); } // Get an int (by value) from the argument, and convert it to a // Python Int. - PyObject* - unwrap_int(PyObject* self, PyObject* args) + PyObject* unwrap_int(int x) { - PyObject* p; - if (!PyArg_ParseTuple(args, "O", &p)) - return 0; - - unwrap in(p); - if (!in) - return 0; - - int x = *in; - return PyInt_FromLong(x); } // Get a non-const reference to an int from the argument - PyObject* - unwrap_int_ref(PyObject* self, PyObject* args) + PyObject* unwrap_int_ref(int& x) { - PyObject* p; - if (!PyArg_ParseTuple(args, "O", &p)) - return 0; - - unwrap in(p); - if (!in) - return 0; - - int& x = *in; - return PyInt_FromLong(x); } // Get a const reference to an int from the argument. - PyObject* - unwrap_int_const_ref(PyObject* self, PyObject* args) + PyObject* unwrap_int_const_ref(int const& x) { - PyObject* p; - if (!PyArg_ParseTuple(args, "O", &p)) - return 0; - - unwrap in(p); - if (!in) - return 0; - - int const& x = *in; - return PyInt_FromLong(x); } @@ -134,89 +64,28 @@ template struct xxxx; // rewrap extracts a T from the argument, then converts the T back // to a PyObject* and returns it. template -PyObject* -rewrap(PyObject* self, PyObject* args, xxxx* = 0) +struct rewrap { - PyObject* p; - if (!PyArg_ParseTuple(args, "O", &p)) - return 0; - - boost::python::unwrap in(p); - if (!in) - return 0; - - boost::python::wrap out; - if (!out) - return 0; - - T x = *in; - return out(x); -} - -extern "C" -{ - // - // Use rewrap to test simple, simple&, simple const&, int, - // int&, int const& - // - PyObject* - wrap_simple(PyObject* self, PyObject* args) - { - return rewrap(self, args); - } - - PyObject* - wrap_simple_ref(PyObject* self, PyObject* args) - { - return rewrap(self, args); - } - - PyObject* - wrap_simple_const_ref(PyObject* self, PyObject* args) - { - return rewrap(self, args); - } - - PyObject* - wrap_int(PyObject* self, PyObject* args) - { - return rewrap(self, args); - } - - PyObject* - wrap_int_ref(PyObject* self, PyObject* args) - { - return rewrap(self, args); - } - - PyObject* - wrap_int_const_ref(PyObject* self, PyObject* args) - { - return rewrap(self, args); - } -} - -PyMethodDef initial_methods[] = -{ - { "unwrap_int", unwrap_int, METH_VARARGS, 0 }, - { "unwrap_int_ref", unwrap_int_ref, METH_VARARGS, 0 }, - { "unwrap_int_const_ref", unwrap_int_const_ref, METH_VARARGS, 0 }, - { "unwrap_simple", unwrap_simple, METH_VARARGS, 0 }, - { "unwrap_simple_ref", unwrap_simple_ref, METH_VARARGS, 0 }, - { "unwrap_simple_const_ref", unwrap_simple_const_ref, METH_VARARGS, 0 }, - - { "wrap_int", wrap_int, METH_VARARGS, 0 }, - { "wrap_int_ref", wrap_int_ref, METH_VARARGS, 0 }, - { "wrap_int_const_ref", wrap_int_const_ref, METH_VARARGS, 0 }, - { "wrap_simple", wrap_simple, METH_VARARGS, 0 }, - { "wrap_simple_ref", wrap_simple_ref, METH_VARARGS, 0 }, - { "wrap_simple_const_ref", wrap_simple_const_ref, METH_VARARGS, 0 }, - { 0, 0, 0, 0 } + static T f(T x) { return x; } }; BOOST_PYTHON_MODULE_INIT(m2) { - Py_InitModule(const_cast("m2"), initial_methods); + boost::python::module m2("m2"); + + m2.def(unwrap_int, "unwrap_int"); + m2.def(unwrap_int_ref, "unwrap_int_ref"); + m2.def(unwrap_int_const_ref, "unwrap_int_const_ref"); + m2.def(unwrap_simple, "unwrap_simple"); + m2.def(unwrap_simple_ref, "unwrap_simple_ref"); + m2.def(unwrap_simple_const_ref, "unwrap_simple_const_ref"); + + m2.def(&rewrap::f, "wrap_int"); + m2.def(&rewrap::f, "wrap_int_ref"); + m2.def(&rewrap::f, "wrap_int_const_ref"); + m2.def(&rewrap::f, "wrap_simple"); + m2.def(&rewrap::f, "wrap_simple_ref"); + m2.def(&rewrap::f, "wrap_simple_const_ref"); } #include "module_tail.cpp" diff --git a/test/newtest.py b/test/newtest.py index b866258c..d29ac129 100644 --- a/test/newtest.py +++ b/test/newtest.py @@ -20,16 +20,14 @@ >>> unwrap_int(5) 5 -Can't get a reference to a built-in integer object +Can't get a non-const reference to a built-in integer object >>> try: ... unwrap_int_ref(7) ... except: pass ... else: print 'no exception' ->>> try: -... unwrap_int_const_ref(9) -... except: pass -... else: print 'no exception' +>>> unwrap_int_const_ref(9) +9 >>> wrap_int(n) 42 @@ -63,16 +61,11 @@ Create an extension class which wraps "complicated" (init1 and get_n) are a complicated constructor and member function, respectively. >>> C = xclass('C', (xinst,), {'__init__': init1, 'get_n': get_n}) ->>> c = C(s, 99) ->>> c.get_n() +>>> c1 = C(s, 99) +>>> c1.get_n() 99 - -Create another extension class which wraps "complicated" (init2 is a -different constructor -- no overloading yet). - ->>> D = xclass('D', (xinst,), {'__init__': init2, 'get_n': get_n}) ->>> d = D(s) ->>> d.get_n() +>>> c2 = C(s) +>>> c2.get_n() 0 """ From 03fef3106d17d2b3e46dfc2175d047276f720cfd Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 6 Jan 2002 14:39:52 +0000 Subject: [PATCH 202/369] Bug fix: convertability checks were missed in one case [SVN r12233] --- src/gen_returning.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/gen_returning.py b/src/gen_returning.py index 2c33cfe5..80e3342b 100644 --- a/src/gen_returning.py +++ b/src/gen_returning.py @@ -84,29 +84,23 @@ free_function = '''%{ template <%(class A%n%:, %)> %}%( unwrap%{_more%} c%n(PyTuple_GET_ITEM(args, %n)%{, c%-%}); %)%[r%: // find the result converter - wrap%{_more%} r%{(c%-)%};%]%{ - if (!c0) return 0;%} - %[r%:return r( %](*pf)(%(*c%n%:, %))%[r%: )%];%[v%: + wrap%{_more%} c%n%{(c%-)%};%]%[not-void-and-0-arg%: + if (!c0) return 0;%] + %[r%:return c%n( %](*pf)(%(*c%n%:, %))%[r%: )%];%[v%: return detail::none();%] } ''' def _returns_value(key, n, args, value): - if key == 'r': + if key != 'v': return value - # pass the value through gen_function again for recursive expansion -# return apply(gen_function, (value, n) + args -# , {'fill': _returns_value}) else: - assert key == 'v' return '' def _returns_void(key, n, args, value): - if key == 'v': + if key == 'v' or key == 'not-void-and-0-arg' and n != 0: return value else: - assert key == 'r' - # return the empty string, ignoring the value return '' _cv_qualifiers = ('', ' const', ' volatile', ' const volatile') From cdac34efeaa77d6ea82606e731f3c46c795e62b4 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 6 Jan 2002 14:40:33 +0000 Subject: [PATCH 203/369] Added wrapper for PyObject* [SVN r12234] --- src/converter/wrapper.cpp | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/converter/wrapper.cpp b/src/converter/wrapper.cpp index 0d817217..567ff99d 100644 --- a/src/converter/wrapper.cpp +++ b/src/converter/wrapper.cpp @@ -12,12 +12,6 @@ namespace boost { namespace python { namespace converter { wrapper_base::wrapper_base(type_id_t type) : body(type) { - // static assertions for target. These would go in a header, - // but Metrowerks only respects BOOST_STATIC_ASSERT if it is in an - // instantiated function -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -#else -#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION registry::insert(*this); } @@ -27,4 +21,21 @@ wrapper_base::~wrapper_base() registry::remove(*this); } +namespace +{ + // This doesn't actually get called, but we need something to fill + // in the slot in the wrap class. + struct identity_wrapper_t : wrapper + { + PyObject* convert(PyObject* source) const + { + return source; + } + }; + + identity_wrapper_t identity_wrapper_object; +} + +BOOST_PYTHON_DECL body& identity_wrapper = identity_wrapper_object; + }}} // namespace boost::python::converter From 65c74e39761c0237581d0459d1db6775ec055478 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 6 Jan 2002 14:40:53 +0000 Subject: [PATCH 204/369] avoiding naming conflict, object:: -> objects:: [SVN r12235] --- src/object/class.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/object/class.cpp b/src/object/class.cpp index bdd66a77..1b855120 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -3,15 +3,13 @@ // 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. - #include -#include #include #include #include #include -namespace boost { namespace python { namespace object { +namespace boost { namespace python { namespace objects { holder_base::holder_base(converter::type_id_t id) : m_type(id) @@ -160,4 +158,4 @@ find_holder_impl(PyObject* inst, converter::type_id_t type) ? match.base() : 0; } -}}} // namespace boost::python::object +}}} // namespace boost::python::objects From 72aa7682352c5cfeb327810521168472ffd5adff Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 6 Jan 2002 14:41:51 +0000 Subject: [PATCH 205/369] Added overload capability [SVN r12236] --- src/object/function.cpp | 59 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/src/object/function.cpp b/src/object/function.cpp index 4c2de3c7..52a0456c 100644 --- a/src/object/function.cpp +++ b/src/object/function.cpp @@ -5,12 +5,16 @@ // to its suitability for any purpose. #include +#include -namespace boost { namespace python { namespace object { +namespace boost { namespace python { namespace objects { -function::function(py_function implementation) +function::function(py_function implementation, unsigned min_args, unsigned max_args) : m_fn(implementation) + , m_min_args(min_args) + , m_max_args(std::max(max_args,min_args)) + , m_overloads(0) { PyObject* p = this; PyObject_INIT(p, &function_type); @@ -18,22 +22,65 @@ function::function(py_function implementation) function::~function() { + PyObject* overloads = m_overloads; + Py_XDECREF(overloads); } PyObject* function::call(PyObject* args, PyObject* keywords) const { - return m_fn(args, keywords); + int nargs = PyTuple_GET_SIZE(args); + function const* f = this; + do + { + // Check for a plausible number of arguments + if (nargs >= f->m_min_args && nargs <= f->m_max_args) + { + // Call the function + PyObject* result = f->m_fn(args, keywords); + + // If the result is NULL but no error was set, m_fn failed + // the argument-matching test. + + // This assumes that all other error-reporters are + // well-behaved and never return NULL to python without + // setting an error. + if (result != 0 || PyErr_Occurred()) + return result; + } + f = f->m_overloads; + } + while (f); + // None of the overloads matched; time to generate the error message + argument_error(args, keywords); + return 0; +} + +void function::argument_error(PyObject* args, PyObject* keywords) const +{ + // This function needs to be improved to do better error reporting. + PyErr_BadArgument(); +} + +void function::add_overload(function* overload) +{ + function* parent = this; + + while (parent->m_overloads != 0) + { + parent = parent->m_overloads; + } + parent->m_overloads = overload; } extern "C" { // Stolen from Python's funcobject.c static PyObject * - function_descr_get(PyObject *func, PyObject *obj, PyObject *type) + function_descr_get(PyObject *func, PyObject *obj, PyObject *type_) { if (obj == Py_None) obj = NULL; - return PyMethod_New(func, obj, type); + return PyMethod_New(func, obj, type_); } static void @@ -92,4 +139,4 @@ PyTypeObject function_type = { 0 /* tp_new */ }; -}}} // namespace boost::python::object +}}} // namespace boost::python::objects From e83e8a8f1caf73c4068646b7c9b852b36910e690 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 7 Jan 2002 06:45:53 +0000 Subject: [PATCH 206/369] object::->objects:: [SVN r12237] --- include/boost/python/object/forward.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/python/object/forward.hpp b/include/boost/python/object/forward.hpp index cc9d65bb..88eefe6b 100644 --- a/include/boost/python/object/forward.hpp +++ b/include/boost/python/object/forward.hpp @@ -11,7 +11,7 @@ # include # include -namespace boost { namespace python { namespace object { +namespace boost { namespace python { namespace objects { // A little metaprogram which selects the type to pass through an // intermediate forwarding function when the destination argument type @@ -28,6 +28,6 @@ struct forward >::type type; }; -}}} // namespace boost::python::object +}}} // namespace boost::python::objects #endif // FORWARD_DWA20011215_HPP From 0dafa9e2299d0b0f629482ce03998d30f4dff0a7 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 7 Jan 2002 06:46:32 +0000 Subject: [PATCH 207/369] check number of arguments [SVN r12238] --- include/boost/python/object/function.hpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/include/boost/python/object/function.hpp b/include/boost/python/object/function.hpp index a0257676..ed7dd319 100644 --- a/include/boost/python/object/function.hpp +++ b/include/boost/python/object/function.hpp @@ -8,21 +8,30 @@ # include # include +# include # include -namespace boost { namespace python { namespace object { +namespace boost { namespace python { namespace objects { // We use boost::function to avoid generating lots of virtual tables typedef boost::function2 py_function; struct BOOST_PYTHON_DECL function : PyObject { - function(py_function); + function(py_function, unsigned min_args, unsigned max_args = 0); ~function(); PyObject* call(PyObject*, PyObject*) const; - private: + void add_overload(function* overload); + + private: // helper functions + void argument_error(PyObject* args, PyObject* keywords) const; + + private: // data members py_function m_fn; + unsigned m_min_args; + unsigned m_max_args; + function* m_overloads; }; extern BOOST_PYTHON_DECL PyTypeObject function_type; @@ -31,6 +40,6 @@ extern BOOST_PYTHON_DECL PyTypeObject function_type; // implementations // -}}} // namespace boost::python::object +}}} // namespace boost::python::objects #endif // FUNCTION_DWA20011214_HPP From 9923a4c4ff81a150fa5367cccd1b392908afe54e Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 7 Jan 2002 06:47:22 +0000 Subject: [PATCH 208/369] More "realism" [SVN r12239] --- include/boost/python/converter/class.hpp | 18 +++---- include/boost/python/object/class.hpp | 53 ++++++-------------- include/boost/python/object/value_holder.hpp | 12 +++-- src/object/class.cpp | 29 ++++++----- 4 files changed, 48 insertions(+), 64 deletions(-) diff --git a/include/boost/python/converter/class.hpp b/include/boost/python/converter/class.hpp index c6fef86a..458ecee4 100644 --- a/include/boost/python/converter/class.hpp +++ b/include/boost/python/converter/class.hpp @@ -32,31 +32,31 @@ struct class_unwrapper template void* class_unwrapper::can_convert(PyObject* p) const { - return objects::find_holder(p); + return objects::find_instance(p); } template -T& class_unwrapper::convert(PyObject*, void* holder_, boost::type) const +T& class_unwrapper::convert(PyObject*, void* found, boost::type) const { - return *static_cast*>(holder_)->target(); + return *static_cast(found); } template -T const& class_unwrapper::convert(PyObject*, void* holder_, boost::type) const +T const& class_unwrapper::convert(PyObject*, void* found, boost::type) const { - return *static_cast*>(holder_)->target(); + return *static_cast(found); } template -T* class_unwrapper::convert(PyObject*, void* holder_, boost::type) const +T* class_unwrapper::convert(PyObject*, void* found, boost::type) const { - return static_cast*>(holder_)->target(); + return static_cast(found); } template -T const* class_unwrapper::convert(PyObject*, void* holder_, boost::type) const +T const* class_unwrapper::convert(PyObject*, void* found, boost::type) const { - return static_cast*>(holder_)->target(); + return static_cast(found); } }}} // namespace boost::python::converter diff --git a/include/boost/python/object/class.hpp b/include/boost/python/object/class.hpp index b272d5fe..bc8f40d1 100644 --- a/include/boost/python/object/class.hpp +++ b/include/boost/python/object/class.hpp @@ -17,15 +17,16 @@ namespace boost { namespace python { namespace objects { template struct holder; // Base class for all holders -struct BOOST_PYTHON_DECL holder_base : noncopyable +struct BOOST_PYTHON_DECL instance_holder : noncopyable { public: - holder_base(converter::type_id_t id); - virtual ~holder_base(); - virtual bool held_by_value() const = 0; + instance_holder(); + virtual ~instance_holder(); - holder_base* next() const; - converter::type_id_t type() const; + // return the next holder in a chain + instance_holder* next() const; + + virtual void* holds(converter::type_id_t) = 0; void install(PyObject* inst); @@ -39,41 +40,30 @@ struct BOOST_PYTHON_DECL holder_base : noncopyable }; typedef iterator_adaptor< - holder_base* + instance_holder* , iterator_policies , value_type_is - , reference_is - , pointer_is + , reference_is + , pointer_is , iterator_category_is > iterator; private: - converter::type_id_t m_type; - holder_base* m_next; -}; - -// Abstract base class which holds a Held, somehow. Provides a uniform -// way to get a pointer to the held object -template -struct holder : holder_base -{ - typedef Held held_type; - holder(); - virtual Held* target() = 0; + instance_holder* m_next; }; // Each extension instance will be one of these struct instance { PyObject_HEAD - holder_base* objects; + instance_holder* objects; }; -BOOST_PYTHON_DECL holder_base* find_holder_impl(PyObject*, converter::type_id_t); +BOOST_PYTHON_DECL void* find_instance_impl(PyObject*, converter::type_id_t); template -holder* find_holder(PyObject* p, T* = 0) +T* find_instance(PyObject* p, T* = 0) { - return static_cast*>(find_holder_impl(p, converter::type_id())); + return static_cast(find_instance_impl(p, converter::type_id())); } BOOST_PYTHON_DECL PyTypeObject* class_metatype(); @@ -82,22 +72,11 @@ BOOST_PYTHON_DECL PyTypeObject* class_type(); // // implementation // -inline holder_base* holder_base::next() const +inline instance_holder* instance_holder::next() const { return m_next; } -inline converter::type_id_t holder_base::type() const -{ - return m_type; -} - -template -holder::holder() - : holder_base(converter::type_id()) -{ -} - }}} // namespace boost::python::objects #endif // CLASS_DWA20011214_HPP diff --git a/include/boost/python/object/value_holder.hpp b/include/boost/python/object/value_holder.hpp index a06afe84..be7247da 100644 --- a/include/boost/python/object/value_holder.hpp +++ b/include/boost/python/object/value_holder.hpp @@ -7,11 +7,12 @@ # define VALUE_HOLDER_DWA20011215_HPP # include +# include namespace boost { namespace python { namespace objects { template -struct value_holder : holder +struct value_holder : instance_holder { // Forward construction to the held object value_holder(PyObject*) @@ -58,8 +59,7 @@ struct value_holder : holder : m_held(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {} private: // required holder implementation - Held* target() { return &m_held; } - bool held_by_value() const { return true; } + void* holds(converter::type_id_t); private: // data members Held m_held; @@ -75,6 +75,12 @@ struct value_holder_generator }; }; +template +void* value_holder::holds(converter::type_id_t x) +{ + return x == converter::type_id() ? &m_held : 0; +} + }}} // namespace boost::python::objects #endif // VALUE_HOLDER_DWA20011215_HPP diff --git a/src/object/class.cpp b/src/object/class.cpp index 1b855120..8e85f38b 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -11,13 +11,12 @@ namespace boost { namespace python { namespace objects { -holder_base::holder_base(converter::type_id_t id) - : m_type(id) - , m_next(0) +instance_holder::instance_holder() + : m_next(0) { } -holder_base::~holder_base() +instance_holder::~instance_holder() { } @@ -134,28 +133,28 @@ BOOST_PYTHON_DECL PyTypeObject* class_type() return &class_type_object; } -void holder_base::install(PyObject* self) +void instance_holder::install(PyObject* self) { assert(self->ob_type->ob_type == &class_metatype_object); m_next = ((instance*)self)->objects; ((instance*)self)->objects = this; } -BOOST_PYTHON_DECL holder_base* -find_holder_impl(PyObject* inst, converter::type_id_t type) +BOOST_PYTHON_DECL void* +find_instance_impl(PyObject* inst, converter::type_id_t type) { if (inst->ob_type->ob_type != &class_metatype_object) return 0; + instance* self = reinterpret_cast(inst); - holder_base::iterator match = std::find_if( - holder_base::iterator(self->objects), holder_base::iterator(0) - , bind(std::equal_to() - , bind(mem_fn(&holder_base::type), _1) - , type)); - - return match != holder_base::iterator(0) - ? match.base() : 0; + for (instance_holder::iterator match(self->objects), end(0); match != end; ++match) + { + void* const found = (*match).holds(type); + if (found) + return found; + } + return 0; } }}} // namespace boost::python::objects From 10a04acf418f39cca5f046d5456699c7200f8045 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 9 Jan 2002 21:20:51 +0000 Subject: [PATCH 209/369] Missing this-> inserted (due to EDG 245 diagnostics) [SVN r12261] --- include/boost/python/converter/unwrap.hpp | 2 +- include/boost/python/converter/wrap.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/python/converter/unwrap.hpp b/include/boost/python/converter/unwrap.hpp index ffd0f081..525f1bb0 100644 --- a/include/boost/python/converter/unwrap.hpp +++ b/include/boost/python/converter/unwrap.hpp @@ -162,7 +162,7 @@ T unwrap_more_::operator*() template unwrap_::~unwrap_() { - destroy(); + this->destroy(); } }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/wrap.hpp b/include/boost/python/converter/wrap.hpp index ec87f73d..97d7b8de 100644 --- a/include/boost/python/converter/wrap.hpp +++ b/include/boost/python/converter/wrap.hpp @@ -158,7 +158,7 @@ wrap_::wrap_() template wrap_::~wrap_() { - destroy(); + this->destroy(); } }}} // namespace boost::python::converter From 8cff66e8c62dd88f5fcdc3cceb4bcccca23cf6e0 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 9 Jan 2002 23:23:44 +0000 Subject: [PATCH 210/369] initial checkin [SVN r12264] --- src/module.cpp | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/module.cpp diff --git a/src/module.cpp b/src/module.cpp new file mode 100644 index 00000000..9faaca06 --- /dev/null +++ b/src/module.cpp @@ -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. + +#include +#include + +namespace boost { namespace python { + +namespace { + ref name_holder; +} + +bool module_base::initializing() +{ + return name_holder.get() != 0; +} + +string module_base::name() +{ + // If this fails, you haven't created a module object + assert(initializing()); + return string(name_holder); +} + +module_base::module_base(const char* name) + : m_module(Py_InitModule(const_cast(name), initial_methods)) +{ + // If this fails, you've created more than 1 module object in your module + assert(name_holder.get() == 0); + name_holder = ref(PyObject_GetAttrString(m_module, const_cast("__name__"))); +} + +module_base::~module_base() +{ + name_holder.reset(); +} + +void module_base::add(PyObject* x, const char* name) +{ + add(ref(x), name); +} + +void module_base::add(ref x, const char* name) +{ + ref f(x); // First take possession of the object. + if (PyObject_SetAttrString(m_module, const_cast(name), x.get()) < 0) + throw error_already_set(); +} + +void module_base::add(PyTypeObject* x, const char* name /*= 0*/) +{ + this->add((PyObject*)x, name ? name : x->tp_name); +} + +void module_base::add_overload(objects::function* x, const char* name) +{ + PyObject* existing = PyObject_HasAttrString(m_module, const_cast(name)) + ? PyObject_GetAttrString(m_module, const_cast(name)) + : 0; + + if (existing != 0 && existing->ob_type == &objects::function_type) + { + static_cast(existing)->add_overload(x); + } + else + { + add(x, name); + } +} + +PyMethodDef module_base::initial_methods[] = { { 0, 0, 0, 0 } }; + +}} // namespace boost::python From aeef66ce3504ddeaaa60b677739132f9287a6fcf Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 10 Jan 2002 02:32:47 +0000 Subject: [PATCH 211/369] Handle cv-qualified member functions [SVN r12265] --- .../boost/python/detail/arg_tuple_size.hpp | 116 ++++++++++++++++++ src/gen_arg_tuple_size.py | 19 ++- 2 files changed, 133 insertions(+), 2 deletions(-) diff --git a/include/boost/python/detail/arg_tuple_size.hpp b/include/boost/python/detail/arg_tuple_size.hpp index e6b6ccc1..a330a939 100644 --- a/include/boost/python/detail/arg_tuple_size.hpp +++ b/include/boost/python/detail/arg_tuple_size.hpp @@ -99,6 +99,122 @@ struct arg_tuple_size BOOST_STATIC_CONSTANT(std::size_t, value = 6); }; + +// Metrowerks thinks this creates ambiguities +# if !defined(__MWERKS__) || __MWERKS__ > 0x2406 + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 1); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 2); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 3); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 4); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 5); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 6); +}; + + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 1); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 2); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 3); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 4); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 5); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 6); +}; + + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 1); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 2); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 3); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 4); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 5); +}; + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = 6); +}; + + +# endif // __MWERKS__ # else // We will use the "sizeof() trick" to work around the lack of diff --git a/src/gen_arg_tuple_size.py b/src/gen_arg_tuple_size.py index 68e379cb..5edd3286 100644 --- a/src/gen_arg_tuple_size.py +++ b/src/gen_arg_tuple_size.py @@ -21,6 +21,15 @@ header = '''// (C) Copyright David Abrahams 2001. Permission to copy, use, modi _cv_qualifiers = ('', ' const', ' volatile', ' const volatile') +_suffix = { + '': ''' +// Metrowerks thinks this creates ambiguities +# if !defined(__MWERKS__) || __MWERKS__ > 0x2406 +''', ' const volatile': ''' +# endif // __MWERKS__ +''' + }; + def gen_arg_tuple_size(member_function_args, free_function_args = None): if free_function_args is None: free_function_args = member_function_args + 1 @@ -53,14 +62,20 @@ struct arg_tuple_size ''', free_function_args) + '\n' - + gen_functions( + + + reduce(lambda x,y: x+'\n'+y + , map( + lambda cv: gen_functions( '''template struct arg_tuple_size { BOOST_STATIC_CONSTANT(std::size_t, value = %+); }; -''', member_function_args, '') +''' + , member_function_args, cv) + _suffix.get(cv, '') + , _cv_qualifiers)) + + '''# else From 98c9e67625052c9c3ee3dea2c3a338da96230e70 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 10 Jan 2002 13:59:14 +0000 Subject: [PATCH 212/369] Fixed mistaken "C" linkage [SVN r12268] --- test/m2.cpp | 67 +++++++++++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 36 deletions(-) diff --git a/test/m2.cpp b/test/m2.cpp index 3c5267d0..7ea1f9ac 100644 --- a/test/m2.cpp +++ b/test/m2.cpp @@ -14,48 +14,43 @@ using boost::python::wrap; using boost::python::unwrap; -extern "C" +// Get a simple (by value) from the argument, and return the +// string it holds. +PyObject* unwrap_simple(simple x) { - // Get a simple (by value) from the argument, and return the - // string it holds. - PyObject* unwrap_simple(simple x) - { - return PyString_FromString(x.s); - } + return PyString_FromString(x.s); +} - // Likewise, but demands that its possible to get a non-const - // reference to the simple. - PyObject* unwrap_simple_ref(simple& x) - { - return PyString_FromString(x.s); - } +// Likewise, but demands that its possible to get a non-const +// reference to the simple. +PyObject* unwrap_simple_ref(simple& x) +{ + return PyString_FromString(x.s); +} - // Likewise, with a const reference to the simple object. - PyObject* unwrap_simple_const_ref(simple const& x) - { - return PyString_FromString(x.s); - } +// Likewise, with a const reference to the simple object. +PyObject* unwrap_simple_const_ref(simple const& x) +{ + return PyString_FromString(x.s); +} - // Get an int (by value) from the argument, and convert it to a - // Python Int. - PyObject* unwrap_int(int x) - { - return PyInt_FromLong(x); - } +// Get an int (by value) from the argument, and convert it to a +// Python Int. +PyObject* unwrap_int(int x) +{ + return PyInt_FromLong(x); +} - // Get a non-const reference to an int from the argument - PyObject* unwrap_int_ref(int& x) - { - return PyInt_FromLong(x); - } +// Get a non-const reference to an int from the argument +PyObject* unwrap_int_ref(int& x) +{ + return PyInt_FromLong(x); +} - // Get a const reference to an int from the argument. - PyObject* unwrap_int_const_ref(int const& x) - { - return PyInt_FromLong(x); - } - - // ------------------- +// Get a const reference to an int from the argument. +PyObject* unwrap_int_const_ref(int const& x) +{ + return PyInt_FromLong(x); } // MSVC6 bug workaround From 7d1cbcb0c12955e990576384c94f3199c42ef848 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 10 Jan 2002 19:07:18 +0000 Subject: [PATCH 213/369] Possible workaround for cxx 6.2 [SVN r12270] --- include/boost/python/object/forward.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/boost/python/object/forward.hpp b/include/boost/python/object/forward.hpp index 88eefe6b..149b7330 100644 --- a/include/boost/python/object/forward.hpp +++ b/include/boost/python/object/forward.hpp @@ -19,8 +19,12 @@ namespace boost { namespace python { namespace objects { template struct forward { + BOOST_STATIC_CONSTANT( + bool, by_value = (is_scalar::value | is_reference::value) + ); + typedef typename mpl::select_type< - is_scalar::value | is_reference::value + by_value , T , reference_wrapper< typename add_const::type From dd1ac7952b961d9c9c77d1c9d0c251984115c260 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 10 Jan 2002 19:28:16 +0000 Subject: [PATCH 214/369] Modified Files: boost/graph/breadth_first_search.hpp MSVC workaround boost/python/reference.hpp boost/python/converter/type_id.hpp boost/python/converter/unwrap.hpp boost/python/converter/wrap.hpp boost/python/converter/wrapper.hpp boost/python/detail/config.hpp libs/python/Jamfile libs/python/src/converter/registry.cpp libs/python/src/converter/type_id.cpp libs/python/src/converter/unwrap.cpp libs/python/test/m1.cpp Added Files: boost/python/converter/wrapper_base.hpp CXX 6.x fixes [SVN r12271] --- Jamfile | 2 + include/boost/python/converter/type_id.hpp | 102 +++++++++++------- include/boost/python/converter/unwrap.hpp | 2 +- include/boost/python/converter/wrap.hpp | 2 +- include/boost/python/converter/wrapper.hpp | 16 +-- .../boost/python/converter/wrapper_base.hpp | 28 +++++ include/boost/python/reference.hpp | 11 +- src/converter/registry.cpp | 2 +- src/converter/type_id.cpp | 36 ++----- src/converter/unwrap.cpp | 5 +- 10 files changed, 116 insertions(+), 90 deletions(-) create mode 100644 include/boost/python/converter/wrapper_base.hpp diff --git a/Jamfile b/Jamfile index 13cb04d7..deb8c690 100644 --- a/Jamfile +++ b/Jamfile @@ -8,6 +8,7 @@ PYTHON_PROPERTIES += <*>"-inline deferred" <*>$(BOOST_ROOT)/boost/compatibility/cpp_c_headers BOOST_PYTHON_DYNAMIC_LIB + BOOST_PYTHON_V2 ; @@ -22,6 +23,7 @@ dll bpl src/converter/type_id.cpp src/object/class.cpp src/object/function.cpp + # src/object/inheritance.cpp src/errors.cpp src/module.cpp src/objects.cpp diff --git a/include/boost/python/converter/type_id.hpp b/include/boost/python/converter/type_id.hpp index c383c352..cf3e4a0d 100644 --- a/include/boost/python/converter/type_id.hpp +++ b/include/boost/python/converter/type_id.hpp @@ -32,24 +32,43 @@ namespace detail # define BOOST_PYTHON_TYPE_ID_NAME # endif -# if 1 +// type ids which represent the same information as std::type_info +// (i.e. the top-level reference and cv-qualifiers are stripped), but +// which works across shared libraries. +struct undecorated_type_id_t : totally_ordered +{ +# ifdef BOOST_PYTHON_TYPE_ID_NAME + typedef char const* base_id_t; +# else + typedef std::type_info const* base_id_t; +# endif + + undecorated_type_id_t(base_id_t); + + bool operator<(undecorated_type_id_t const& rhs) const; + bool operator==(undecorated_type_id_t const& rhs) const; + + friend BOOST_PYTHON_DECL std::ostream& operator<<( + std::ostream&, undecorated_type_id_t const&); + + private: // data members + base_id_t m_base_type; +}; + struct type_id_t : totally_ordered { enum decoration { const_ = 0x1, volatile_ = 0x2, reference = 0x4 }; -# ifdef BOOST_PYTHON_TYPE_ID_NAME -typedef char const* base_id_t; -# else -typedef std::type_info const* base_id_t; -# endif - - type_id_t(base_id_t, decoration decoration); + type_id_t(undecorated_type_id_t, decoration decoration); bool operator<(type_id_t const& rhs) const; bool operator==(type_id_t const& rhs) const; friend BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, type_id_t const&); - private: + private: // type + typedef undecorated_type_id_t base_id_t; + + private: // data members decoration m_decoration; base_id_t m_base_type; }; @@ -129,14 +148,22 @@ struct is_reference_to_volatile # endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template -inline type_id_t type_id(detail::dummy* = 0) +inline undecorated_type_id_t undecorated_type_id(detail::dummy* = 0) { - return type_id_t( + return undecorated_type_id_t( # ifdef BOOST_PYTHON_TYPE_ID_NAME typeid(T).name() # else &typeid(T) -# endif +# endif + ); +} + +template +inline type_id_t type_id(detail::dummy* = 0) +{ + return type_id_t( + undecorated_type_id() , type_id_t::decoration( (is_const::value || is_reference_to_const::value ? type_id_t::const_ : 0) @@ -147,51 +174,48 @@ inline type_id_t type_id(detail::dummy* = 0) ); } -inline type_id_t::type_id_t(base_id_t base_t, decoration decoration) +inline undecorated_type_id_t::undecorated_type_id_t(base_id_t base_t) + : m_base_type(base_t) +{ +} + +inline type_id_t::type_id_t(undecorated_type_id_t base_t, decoration decoration) : m_decoration(decoration) , m_base_type(base_t) { } +inline bool undecorated_type_id_t::operator<(undecorated_type_id_t const& rhs) const +{ +# ifdef BOOST_PYTHON_TYPE_ID_NAME + return std::strcmp(m_base_type, rhs.m_base_type) < 0; +# else + return m_base_type->before(*rhs.m_base_type); +# endif +} + inline bool type_id_t::operator<(type_id_t const& rhs) const { return m_decoration < rhs.m_decoration || m_decoration == rhs.m_decoration + && m_base_type < rhs.m_base_type; +} + +inline bool undecorated_type_id_t::operator==(undecorated_type_id_t const& rhs) const +{ # ifdef BOOST_PYTHON_TYPE_ID_NAME - && std::strcmp(m_base_type, rhs.m_base_type) < 0; + return !std::strcmp(m_base_type, rhs.m_base_type); # else - && m_base_type->before(*rhs.m_base_type); + return *m_base_type == *rhs.m_base_type; # endif } inline bool type_id_t::operator==(type_id_t const& rhs) const { - return m_decoration == rhs.m_decoration -# ifdef BOOST_PYTHON_TYPE_ID_NAME - && !std::strcmp(m_base_type, rhs.m_base_type); -# else - && *m_base_type == *rhs.m_base_type; -# endif + return m_decoration == rhs.m_decoration && m_base_type == rhs.m_base_type; } -# else -// This is the type which is used to identify a type -typedef char const* type_id_t; - -// This is a workaround for a silly MSVC bug -// Converts a compile-time type to its corresponding runtime identifier. -template -type_id_t type_id(detail::dummy* = 0) -{ - return typeid(T).name(); -} -# endif - -struct BOOST_PYTHON_DECL type_id_before -{ - bool operator()(type_id_t const& x, type_id_t const& y) const; -}; - +BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, undecorated_type_id_t const&); BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, type_id_t const&); }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/unwrap.hpp b/include/boost/python/converter/unwrap.hpp index 525f1bb0..3380d49d 100644 --- a/include/boost/python/converter/unwrap.hpp +++ b/include/boost/python/converter/unwrap.hpp @@ -89,7 +89,7 @@ struct unwrap_more_ { } private: - static BOOST_PYTHON_DECL std::pair m_unwrapper; + static BOOST_PYTHON_DECL std::pair& m_unwrapper; }; template diff --git a/include/boost/python/converter/wrap.hpp b/include/boost/python/converter/wrap.hpp index 97d7b8de..eb23c6d3 100644 --- a/include/boost/python/converter/wrap.hpp +++ b/include/boost/python/converter/wrap.hpp @@ -11,11 +11,11 @@ # include # include # include +# include # include namespace boost { namespace python { namespace converter { -struct BOOST_PYTHON_DECL wrapper_base; extern BOOST_PYTHON_DECL body& identity_wrapper; template struct wrapper; diff --git a/include/boost/python/converter/wrapper.hpp b/include/boost/python/converter/wrapper.hpp index 80afae46..5d4874d2 100644 --- a/include/boost/python/converter/wrapper.hpp +++ b/include/boost/python/converter/wrapper.hpp @@ -5,28 +5,14 @@ // to its suitability for any purpose. #ifndef WRAPPER_DWA2001127_HPP # define WRAPPER_DWA2001127_HPP -# include +# include # include -# include # include # include # include namespace boost { namespace python { namespace converter { -struct source_holder_base; -struct wrap_base; -template struct wrap_more_; - -struct BOOST_PYTHON_DECL wrapper_base : body -{ - public: - wrapper_base(type_id_t); // registers - ~wrapper_base(); // unregisters - - virtual PyObject* do_conversion(wrap_base const&, source_holder_base const&) const = 0; -}; - extern BOOST_PYTHON_DECL body& identity_wrapper; template diff --git a/include/boost/python/converter/wrapper_base.hpp b/include/boost/python/converter/wrapper_base.hpp new file mode 100644 index 00000000..585959ae --- /dev/null +++ b/include/boost/python/converter/wrapper_base.hpp @@ -0,0 +1,28 @@ +// Copyright David Abrahams 2002. 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 WRAPPER_BASE_DWA2002110_HPP +# define WRAPPER_BASE_DWA2002110_HPP +# include +# include + +namespace boost { namespace python { namespace converter { + +struct source_holder_base; +struct wrap_base; +template struct wrap_more_; + +struct BOOST_PYTHON_DECL wrapper_base : body +{ + public: + wrapper_base(type_id_t); // registers + ~wrapper_base(); // unregisters + + virtual PyObject* do_conversion(wrap_base const&, source_holder_base const&) const = 0; +}; + +}}} // namespace boost::python::converter + +#endif // WRAPPER_BASE_DWA2002110_HPP diff --git a/include/boost/python/reference.hpp b/include/boost/python/reference.hpp index 4eb9ad51..b950f01b 100644 --- a/include/boost/python/reference.hpp +++ b/include/boost/python/reference.hpp @@ -16,7 +16,9 @@ # include # include # include -# include + +# ifndef BOOST_PYTHON_V2 +# include BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE @@ -35,14 +37,19 @@ struct py_ptr_conversions : Base }; BOOST_PYTHON_END_CONVERSION_NAMESPACE +# endif namespace boost { namespace python { +# ifndef BOOST_PYTHON_V2 BOOST_PYTHON_IMPORT_CONVERSION(py_ptr_conversions); +# endif template class reference +# ifndef BOOST_PYTHON_V2 : public py_ptr_conversions, T> +# endif { public: typedef T value_type; @@ -165,11 +172,13 @@ private: typedef reference ref; +#ifndef BOOST_PYTHON_V2 template ref make_ref(const T& x) { return ref(to_python(x)); } +#endif }} // namespace boost::python diff --git a/src/converter/registry.cpp b/src/converter/registry.cpp index d247353c..4ce9e709 100644 --- a/src/converter/registry.cpp +++ b/src/converter/registry.cpp @@ -18,7 +18,7 @@ namespace boost { namespace python { namespace converter { namespace // { - typedef std::map registry_t; + typedef std::map registry_t; registry_t& entries() { diff --git a/src/converter/type_id.cpp b/src/converter/type_id.cpp index fc2db66a..421cc5cf 100644 --- a/src/converter/type_id.cpp +++ b/src/converter/type_id.cpp @@ -13,19 +13,18 @@ namespace boost { namespace python { namespace converter { -#if 1 -bool type_id_before::operator()(type_id_t const& x, type_id_t const& y) const +BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream& os, undecorated_type_id_t const& x) { - return x < y; +# ifdef BOOST_PYTHON_TYPE_ID_NAME + return os << x.m_base_type; +# else + return os << x.m_base_type->name(); +# endif } BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream& os, type_id_t const& x) { -# ifdef BOOST_PYTHON_TYPE_ID_NAME os << x.m_base_type; -# else - os << x.m_base_type->name(); -# endif // VC6 mistakenly distinguishes typeid(X) from typeid(X const) // from typeid(X&)... so the name is already correct. I have it // from Jason Shirk that VC7.0 has the same bug but it will be @@ -41,27 +40,4 @@ BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream& os, type_id_t const& x) return os; } -#else -bool type_id_before::operator()(type_id_t const& x, type_id_t const& y) const -{ - for (;;) - { - if (*y == 0) - { - return 0; - } - else if (*x == 0) - { - return 1; - } - else if (*x != *y) - { - return *x < *y; - } - ++x; - ++y; - } -} -#endif - }}} // namespace boost::python::converter diff --git a/src/converter/unwrap.cpp b/src/converter/unwrap.cpp index 33a7d7ae..6a72ab77 100644 --- a/src/converter/unwrap.cpp +++ b/src/converter/unwrap.cpp @@ -17,6 +17,7 @@ namespace }; pyobject_unwrapper static_unwrapper; + std::pair unwrapper_pair(&static_unwrapper,&static_unwrapper); pyobject_unwrapper::pyobject_unwrapper() : unwrapper_base(type_id()) @@ -29,7 +30,7 @@ namespace } } -BOOST_PYTHON_DECL std::pair -unwrap_more_::m_unwrapper(&static_unwrapper,&static_unwrapper); +BOOST_PYTHON_DECL std::pair& +unwrap_more_::m_unwrapper = unwrapper_pair; }}} // namespace boost::python::converter From 0964ecac8c88b9fd9464b08ad651909ff7b8c52c Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 10 Jan 2002 20:10:32 +0000 Subject: [PATCH 215/369] cxx fixes [SVN r12272] --- include/boost/python/detail/cast.hpp | 7 +++++-- include/boost/python/reference.hpp | 11 ++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/include/boost/python/detail/cast.hpp b/include/boost/python/detail/cast.hpp index 67fe7b34..367f1f14 100644 --- a/include/boost/python/detail/cast.hpp +++ b/include/boost/python/detail/cast.hpp @@ -9,8 +9,9 @@ #ifndef CAST_DWA052500_H_ # define CAST_DWA052500_H_ -# include -# include +# ifndef BOOST_PYTHON_V2 +# include +# include namespace boost { namespace python { @@ -75,4 +76,6 @@ struct downcast }} // namespace boost::python +# endif // BOOST_PYTHON_V2 + #endif // CAST_DWA052500_H_ diff --git a/include/boost/python/reference.hpp b/include/boost/python/reference.hpp index b950f01b..e081e07c 100644 --- a/include/boost/python/reference.hpp +++ b/include/boost/python/reference.hpp @@ -14,8 +14,10 @@ # include # include # include +# include # include # include +# include # ifndef BOOST_PYTHON_V2 # include @@ -165,7 +167,14 @@ private: #endif inline PyObject* object() const - { return as_object(m_p); } + { +#ifdef BOOST_PYTHON_V2 + return (PyObject*)( + (char*)&m_p->ob_type - offsetof(PyObject,ob_type)); +#else + return as_object(m_p); +#endif + } T* m_p; }; From b796db648ae317ea008ffe4ee5b4421ccf156035 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 14 Jan 2002 21:28:49 +0000 Subject: [PATCH 216/369] added default constructor for use with BGL [SVN r12318] --- include/boost/python/converter/type_id.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/boost/python/converter/type_id.hpp b/include/boost/python/converter/type_id.hpp index cf3e4a0d..2c0c1a26 100644 --- a/include/boost/python/converter/type_id.hpp +++ b/include/boost/python/converter/type_id.hpp @@ -44,6 +44,9 @@ struct undecorated_type_id_t : totally_ordered # endif undecorated_type_id_t(base_id_t); + + // default constructor for use in BGL graph internal properties + undecorated_type_id_t() {} bool operator<(undecorated_type_id_t const& rhs) const; bool operator==(undecorated_type_id_t const& rhs) const; From 7926e1bc3cfd28fe4a121926835c4343e09b207d Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 20 Jan 2002 03:08:08 +0000 Subject: [PATCH 217/369] Fixes for reference parameters to constructors [SVN r12364] --- .../boost/python/detail/extension_class.hpp | 77 +++++++++-- include/boost/python/detail/init_function.hpp | 52 +++++++- include/boost/python/reference.hpp | 117 ++++++++++++----- src/gen_extclass.py | 122 ++++++++++++------ src/gen_init_function.py | 52 +++++++- 5 files changed, 328 insertions(+), 92 deletions(-) diff --git a/include/boost/python/detail/extension_class.hpp b/include/boost/python/detail/extension_class.hpp index 05ebe229..638217d1 100644 --- a/include/boost/python/detail/extension_class.hpp +++ b/include/boost/python/detail/extension_class.hpp @@ -1,4 +1,4 @@ -// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and +// (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. @@ -727,25 +727,80 @@ class held_instance : public Held public: held_instance(PyObject*) : Held() {} template - held_instance(PyObject*, A1 a1) : Held(a1) {} + held_instance(PyObject*, A1 a1) : Held( + typename unwrap_parameter::type(a1)) {} template - held_instance(PyObject*, A1 a1, A2 a2) : Held(a1, a2) {} + held_instance(PyObject*, A1 a1, A2 a2) : Held( + typename unwrap_parameter::type(a1) + , typename unwrap_parameter::type(a2)) {} template - held_instance(PyObject*, A1 a1, A2 a2, A3 a3) : Held(a1, a2, a3) {} + held_instance(PyObject*, A1 a1, A2 a2, A3 a3) : Held( + typename unwrap_parameter::type(a1) + , typename unwrap_parameter::type(a2) + , typename unwrap_parameter::type(a3)) {} template - held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) : Held(a1, a2, a3, a4) {} + held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) : Held( + typename unwrap_parameter::type(a1) + , typename unwrap_parameter::type(a2) + , typename unwrap_parameter::type(a3) + , typename unwrap_parameter::type(a4)) {} template - held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : Held(a1, a2, a3, a4, a5) {} + held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : Held( + typename unwrap_parameter::type(a1) + , typename unwrap_parameter::type(a2) + , typename unwrap_parameter::type(a3) + , typename unwrap_parameter::type(a4) + , typename unwrap_parameter::type(a5)) {} template - held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) : Held(a1, a2, a3, a4, a5, a6) {} + held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) : Held( + typename unwrap_parameter::type(a1) + , typename unwrap_parameter::type(a2) + , typename unwrap_parameter::type(a3) + , typename unwrap_parameter::type(a4) + , typename unwrap_parameter::type(a5) + , typename unwrap_parameter::type(a6)) {} template - 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) {} + held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) : Held( + typename unwrap_parameter::type(a1) + , typename unwrap_parameter::type(a2) + , typename unwrap_parameter::type(a3) + , typename unwrap_parameter::type(a4) + , typename unwrap_parameter::type(a5) + , typename unwrap_parameter::type(a6) + , typename unwrap_parameter::type(a7)) {} template - 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) {} + held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) : Held( + typename unwrap_parameter::type(a1) + , typename unwrap_parameter::type(a2) + , typename unwrap_parameter::type(a3) + , typename unwrap_parameter::type(a4) + , typename unwrap_parameter::type(a5) + , typename unwrap_parameter::type(a6) + , typename unwrap_parameter::type(a7) + , typename unwrap_parameter::type(a8)) {} template - 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) {} + held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) : Held( + typename unwrap_parameter::type(a1) + , typename unwrap_parameter::type(a2) + , typename unwrap_parameter::type(a3) + , typename unwrap_parameter::type(a4) + , typename unwrap_parameter::type(a5) + , typename unwrap_parameter::type(a6) + , typename unwrap_parameter::type(a7) + , typename unwrap_parameter::type(a8) + , typename unwrap_parameter::type(a9)) {} template - 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) {} + held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) : Held( + typename unwrap_parameter::type(a1) + , typename unwrap_parameter::type(a2) + , typename unwrap_parameter::type(a3) + , typename unwrap_parameter::type(a4) + , typename unwrap_parameter::type(a5) + , typename unwrap_parameter::type(a6) + , typename unwrap_parameter::type(a7) + , typename unwrap_parameter::type(a8) + , typename unwrap_parameter::type(a9) + , typename unwrap_parameter::type(a10)) {} }; // Abstract base class for all obj holders. Base for template class diff --git a/include/boost/python/detail/init_function.hpp b/include/boost/python/detail/init_function.hpp index 69df703d..ed34f9be 100644 --- a/include/boost/python/detail/init_function.hpp +++ b/include/boost/python/detail/init_function.hpp @@ -1,4 +1,4 @@ -// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and +// (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. @@ -89,11 +89,14 @@ namespace detail { typedef void const_reference; }; + struct reference_parameter_base {}; + template class reference_parameter + : public reference_parameter_base { - typedef typename parameter_traits::const_reference const_reference; public: + typedef typename parameter_traits::const_reference const_reference; reference_parameter(const_reference value) : value(value) {} operator const_reference() { return value; } @@ -101,6 +104,51 @@ namespace detail { const_reference value; }; +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct unwrap_parameter + { + typedef typename boost::add_reference::type type; + }; + + template + struct unwrap_parameter > + { + typedef typename reference_parameter::const_reference type; + }; +# else + template + struct unwrap_parameter_helper + { + template + struct apply + { + typedef typename T::const_reference type; + }; + }; + + template <> + struct unwrap_parameter_helper + { + template + struct apply + { + typedef typename add_reference::type type; + }; + }; + + template + struct unwrap_parameter + { + BOOST_STATIC_CONSTANT( + bool, is_wrapped = (is_base_and_derived::value)); + + typedef typename unwrap_parameter_helper< + is_wrapped + >::template apply::type type; + }; +# endif + class extension_instance; class instance_holder_base; diff --git a/include/boost/python/reference.hpp b/include/boost/python/reference.hpp index e081e07c..f0cdab55 100644 --- a/include/boost/python/reference.hpp +++ b/include/boost/python/reference.hpp @@ -59,18 +59,10 @@ public: reference(const reference& rhs) : m_p(rhs.m_p) { - Py_XINCREF(object()); + assert(m_p == 0 || m_p->ob_refcnt > 0); + Py_XINCREF(m_p); } -#if !defined(BOOST_MSVC6_OR_EARLIER) - template - reference(const reference& rhs) - : m_p(rhs.object()) - { - Py_XINCREF(object()); - } -#endif - reference() : m_p(0) {} // These are two ways of spelling the same thing, that we need to increment @@ -81,85 +73,140 @@ public: template explicit reference(T2* x) - : m_p(expect_non_null(x)) {} + : m_p(expect_non_null(x)) + { + assert(m_p->ob_refcnt > 0); + } template reference(T2* x, increment_count_t) - : m_p(expect_non_null(x)) { Py_INCREF(object()); } + : m_p(expect_non_null(x)) + { + assert(m_p->ob_refcnt > 0); + Py_INCREF(m_p); + } template reference(T2* x, allow_null) - : m_p(x) {} + : m_p(x) + { + assert(m_p == 0 || m_p->ob_refcnt > 0); + } template reference(T2* x, allow_null, increment_count_t) - : m_p(x) { Py_XINCREF(object()); } + : m_p(x) + { + assert(m_p == 0 || m_p->ob_refcnt > 0); + Py_XINCREF(m_p); + } template reference(T2* x, increment_count_t, allow_null) - : m_p(x) { Py_XINCREF(object()); } - -#if !defined(BOOST_MSVC6_OR_EARLIER) - template - reference& operator=(const reference& rhs) + : m_p(x) { - Py_XDECREF(object()); - m_p = rhs.m_p; - Py_XINCREF(object()); - return *this; + assert(m_p == 0 || m_p->ob_refcnt > 0); + Py_XINCREF(m_p); } -#endif - + reference& operator=(const reference& rhs) { + assert(rhs.m_p == 0 || rhs.m_p->ob_refcnt > 0); Py_XINCREF(static_cast(rhs.m_p)); - Py_XDECREF(object()); + assert(m_p == 0 || m_p->ob_refcnt > 0); + Py_XDECREF(m_p); m_p = rhs.m_p; return *this; } ~reference() { + assert(m_p == 0 || m_p->ob_refcnt > 0); Py_XDECREF(m_p); } - T& operator*() const { return *m_p; } + T& operator*() const + { + assert(m_p == 0 || m_p->ob_refcnt > 0); + 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* operator->() const + { + assert(m_p == 0 || m_p->ob_refcnt > 0); + return &**this; + } - T* get() const { return m_p; } + T* get() const + { + assert(m_p == 0 || m_p->ob_refcnt > 0); + return m_p; + } T* release() { + assert(m_p == 0 || m_p->ob_refcnt > 0); T* p = m_p; m_p = 0; return p; } void reset() - { Py_XDECREF(m_p); m_p = 0; } + { + assert(m_p == 0 || m_p->ob_refcnt > 0); + Py_XDECREF(m_p); + m_p = 0; + } template void reset(T2* x) - { Py_XDECREF(m_p); m_p = expect_non_null(x);} + { + assert(m_p == 0 || m_p->ob_refcnt > 0); + Py_XDECREF(m_p); + m_p = expect_non_null(x); + assert(m_p == 0 || m_p->ob_refcnt > 0); + } template void reset(T2* x, increment_count_t) - { Py_XDECREF(m_p); m_p = expect_non_null(x); Py_INCREF(object()); } + { + assert(m_p == 0 || m_p->ob_refcnt > 0); + Py_XDECREF(m_p); + m_p = expect_non_null(x); + assert(m_p->ob_refcnt > 0); + Py_INCREF(m_p); + } template void reset(T2* x, allow_null) - { Py_XDECREF(m_p); m_p = x;} + { + assert(m_p == 0 || m_p->ob_refcnt > 0); + Py_XDECREF(m_p); + m_p = x; + assert(m_p == 0 || m_p->ob_refcnt > 0); + } template void reset(T2* x, allow_null, increment_count_t) - { Py_XDECREF(m_p); m_p = x; Py_XINCREF(object()); } + { + assert(m_p == 0 || m_p->ob_refcnt > 0); + Py_XDECREF(m_p); + m_p = x; + assert(m_p == 0 || m_p->ob_refcnt > 0); + Py_XINCREF(m_p); + } template void reset(T2* x, increment_count_t, allow_null) - { Py_XDECREF(m_p); m_p = x; Py_XINCREF(object()); } + { + assert(m_p == 0 || m_p->ob_refcnt > 0); + Py_XDECREF(m_p); + m_p = x; + assert(m_p == 0 || m_p->ob_refcnt > 0); + Py_XINCREF(m_p); + } #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) private: diff --git a/src/gen_extclass.py b/src/gen_extclass.py index b794dc2c..6316bab9 100644 --- a/src/gen_extclass.py +++ b/src/gen_extclass.py @@ -3,7 +3,7 @@ import string def gen_extclass(args): return ( -"""// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and +"""// (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. @@ -43,26 +43,51 @@ template struct right_operand; enum without_downcast_t { without_downcast }; -namespace detail { +namespace detail +{ // forward declarations -class extension_instance; -class extension_class_base; -template class instance_holder; -template class instance_value_holder; -template class instance_ptr_holder; -template struct operand_select; + class extension_instance; + class extension_class_base; + template class instance_holder; + template class instance_value_holder; + template class instance_ptr_holder; + template struct operand_select; template struct choose_op; template struct choose_rop; template struct choose_unary_op; template struct define_operator; -meta_class* extension_meta_class(); -extension_instance* get_extension_instance(PyObject* p); -void report_missing_instance_data(extension_instance*, class_t*, const std::type_info&); -void report_missing_ptr_data(extension_instance*, class_t*, const std::type_info&); -void report_missing_class_object(const std::type_info&); -void report_released_smart_pointer(const std::type_info&); + class BOOST_PYTHON_DECL extension_instance : public instance + { + public: + extension_instance(PyTypeObject* class_); + ~extension_instance(); + + void add_implementation(std::auto_ptr holder); + + typedef std::vector held_objects; + const held_objects& wrapped_objects() const + { return m_wrapped_objects; } + private: + held_objects m_wrapped_objects; + }; + +} // namespace detail + +# ifndef BOOST_PYTHON_NO_TEMPLATE_EXPORT +BOOST_PYTHON_EXPORT_TEMPLATE_CLASS class_t; +BOOST_PYTHON_EXPORT_TEMPLATE_CLASS meta_class; +# endif + +namespace detail { + +BOOST_PYTHON_DECL meta_class* extension_meta_class(); +BOOST_PYTHON_DECL extension_instance* get_extension_instance(PyObject* p); +BOOST_PYTHON_DECL void report_missing_instance_data(extension_instance*, class_t*, const std::type_info&); +BOOST_PYTHON_DECL void report_missing_ptr_data(extension_instance*, class_t*, const std::type_info&); +BOOST_PYTHON_DECL void report_missing_class_object(const std::type_info&); +BOOST_PYTHON_DECL void report_released_smart_pointer(const std::type_info&); template T* check_non_null(T* p) @@ -76,7 +101,7 @@ template class held_instance; typedef void* (*conversion_function_ptr)(void*); -struct base_class_info +struct BOOST_PYTHON_DECL base_class_info { base_class_info(extension_class_base* t, conversion_function_ptr f) :class_object(t), convert(f) @@ -90,7 +115,7 @@ typedef base_class_info derived_class_info; struct add_operator_base; -class extension_class_base : public class_t +class BOOST_PYTHON_DECL extension_class_base : public class_t { public: extension_class_base(const char* name); @@ -270,8 +295,7 @@ class python_extension_class_converters boost::python::detail::report_missing_ptr_data(self, boost::python::detail::class_registry::class_object(), typeid(T)); throw boost::python::argument_error(); #if defined(__MWERKS__) && __MWERKS__ <= 0x2406 - PtrType x; - return x; + return *(PtrType*)0; #endif } @@ -384,7 +408,7 @@ namespace detail { template class instance_holder; -class read_only_setattr_function : public function +class BOOST_PYTHON_DECL read_only_setattr_function : public function { public: read_only_setattr_function(const char* name); @@ -703,13 +727,15 @@ class held_instance : public Held public:""" + gen_functions("""%{ template <%(class A%n%:, %)>%} - held_instance(PyObject*%(, A%n% a%n%)) : Held(%(a%n%:, %)) {}""", args) + held_instance(PyObject*%(, A%n% a%n%)) : Held( + %(typename unwrap_parameter::type(a%n)%: + , %)) {}""", args) + """ }; // Abstract base class for all obj holders. Base for template class // instance_holder<>, below. -class instance_holder_base +class BOOST_PYTHON_DECL instance_holder_base { public: virtual ~instance_holder_base() {} @@ -738,12 +764,39 @@ class instance_value_holder : public instance_holder public: Held* target() { return &m_held; } Wrapper* value_target() { return &m_held; } -""" - + gen_functions("""%{ - template <%(class A%n%:, %)>%} - instance_value_holder(extension_instance* p%(, A%n a%n%)) : - m_held(p%(, a%n%)) {}""", args) - + """ + + instance_value_holder(extension_instance* p) : + m_held(p) {} + template + instance_value_holder(extension_instance* p, A1 a1) : + m_held(p, a1) {} + template + instance_value_holder(extension_instance* p, A1 a1, A2 a2) : + m_held(p, a1, a2) {} + template + instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3) : + m_held(p, a1, a2, a3) {} + template + instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4) : + m_held(p, a1, a2, a3, a4) {} + template + 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 + 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 + 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 + 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 + 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 + 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; } @@ -770,21 +823,6 @@ class instance_ptr_holder : public instance_holder PtrType m_ptr; }; -class extension_instance : public instance -{ - public: - extension_instance(PyTypeObject* class_); - ~extension_instance(); - - void add_implementation(std::auto_ptr holder); - - typedef std::vector held_objects; - const held_objects& wrapped_objects() const - { return m_wrapped_objects; } - private: - held_objects m_wrapped_objects; -}; - // // Template function implementations // diff --git a/src/gen_init_function.py b/src/gen_init_function.py index 80a9c199..ff294dbb 100644 --- a/src/gen_init_function.py +++ b/src/gen_init_function.py @@ -4,7 +4,7 @@ import string def gen_init_function(args): return ( -"""// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and +"""// (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. @@ -95,11 +95,14 @@ namespace detail { typedef void const_reference; }; + struct reference_parameter_base {}; + template class reference_parameter + : public reference_parameter_base { - typedef typename parameter_traits::const_reference const_reference; public: + typedef typename parameter_traits::const_reference const_reference; reference_parameter(const_reference value) : value(value) {} operator const_reference() { return value; } @@ -107,6 +110,51 @@ namespace detail { const_reference value; }; +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct unwrap_parameter + { + typedef typename boost::add_reference::type type; + }; + + template + struct unwrap_parameter > + { + typedef typename reference_parameter::const_reference type; + }; +# else + template + struct unwrap_parameter_helper + { + template + struct apply + { + typedef typename T::const_reference type; + }; + }; + + template <> + struct unwrap_parameter_helper + { + template + struct apply + { + typedef typename add_reference::type type; + }; + }; + + template + struct unwrap_parameter + { + BOOST_STATIC_CONSTANT( + bool, is_wrapped = (is_base_and_derived::value)); + + typedef typename unwrap_parameter_helper< + is_wrapped + >::template apply::type type; + }; +# endif + class extension_instance; class instance_holder_base; From c3a311ab85a7f6612885459cf8eadbeebc561372 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 20 Jan 2002 23:07:05 +0000 Subject: [PATCH 218/369] Explicit qualifications help MSVC6 [SVN r12380] --- include/boost/python/make_function.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/boost/python/make_function.hpp b/include/boost/python/make_function.hpp index fddc640b..f9ffd5c3 100644 --- a/include/boost/python/make_function.hpp +++ b/include/boost/python/make_function.hpp @@ -6,13 +6,13 @@ #ifndef MAKE_FUNCTION_DWA20011221_HPP # define MAKE_FUNCTION_DWA20011221_HPP -# include -# include -# include # include # include # include # include +# include +# include +# include namespace boost { namespace python { @@ -21,7 +21,7 @@ objects::function* make_function(F f) { return new objects::function( objects::py_function( - bind(detail::caller(), f, _1, _2)) + ::boost::bind(detail::caller(), f, _1, _2)) , detail::arg_tuple_size::value); } @@ -31,7 +31,7 @@ objects::function* make_constructor(T* = 0, ArgList* = 0, Generator* = 0) enum { nargs = mpl::size::value }; return new objects::function( objects::py_function( - bind(detail::caller(), + ::boost::bind(detail::caller(), objects::make_holder ::template apply::execute , _1, _2)) From a48f252cfaa9d2d15881ee3de7c199616093965e Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 20 Jan 2002 23:41:56 +0000 Subject: [PATCH 219/369] Moved add_overload functionality to function::add_to_namespace [SVN r12381] --- include/boost/python/module.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/python/module.hpp b/include/boost/python/module.hpp index b257b9ff..317cc5e4 100644 --- a/include/boost/python/module.hpp +++ b/include/boost/python/module.hpp @@ -11,6 +11,7 @@ # include # include # include +# include namespace boost { namespace python { @@ -25,7 +26,6 @@ class BOOST_PYTHON_DECL module_base void add(PyObject* x, const char* name); void add(PyTypeObject* x, const char* name = 0); void add(ref x, const char*name); - void add_overload(objects::function* x, const char* name); // Return true iff a module is currently being built. static bool initializing(); @@ -58,7 +58,7 @@ class module : public module_base template void def(Fn fn, const char* name) { - add_overload(make_function(fn), name); + this->add(boost::python::make_function(fn), name); } }; From 386992c3b8ad845a0790348a987f6c8321560d3d Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 20 Jan 2002 23:43:36 +0000 Subject: [PATCH 220/369] suppress gcc warning [SVN r12382] --- include/boost/python/converter/class.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/python/converter/class.hpp b/include/boost/python/converter/class.hpp index 458ecee4..f437a73a 100644 --- a/include/boost/python/converter/class.hpp +++ b/include/boost/python/converter/class.hpp @@ -18,6 +18,10 @@ struct class_unwrapper , private unwrapper , private unwrapper { + protected: +# ifdef __GNUC__ // suppress warning that "all member functions are private" (duh) + void uncallable(); +# endif private: void* can_convert(PyObject*) const; T& convert(PyObject*, void*, boost::type) const; From 3d03ca3d10268ddf08b87a49770b712de2bb7e91 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 20 Jan 2002 23:50:52 +0000 Subject: [PATCH 221/369] made it possible to initialize from type_info [SVN r12383] --- include/boost/python/converter/type_id.hpp | 67 +++++++++++++++------- src/converter/type_id.cpp | 6 +- 2 files changed, 46 insertions(+), 27 deletions(-) diff --git a/include/boost/python/converter/type_id.hpp b/include/boost/python/converter/type_id.hpp index 2c0c1a26..fd731f83 100644 --- a/include/boost/python/converter/type_id.hpp +++ b/include/boost/python/converter/type_id.hpp @@ -37,24 +37,25 @@ namespace detail // which works across shared libraries. struct undecorated_type_id_t : totally_ordered { + undecorated_type_id_t(std::type_info const&); + + // default constructor needed to build arrays, etc. + undecorated_type_id_t(); + + bool operator<(undecorated_type_id_t const& rhs) const; + bool operator==(undecorated_type_id_t const& rhs) const; + + char const* name() const; + friend BOOST_PYTHON_DECL std::ostream& operator<<( + std::ostream&, undecorated_type_id_t const&); + + private: // data members # ifdef BOOST_PYTHON_TYPE_ID_NAME typedef char const* base_id_t; # else typedef std::type_info const* base_id_t; # endif - undecorated_type_id_t(base_id_t); - - // default constructor for use in BGL graph internal properties - undecorated_type_id_t() {} - - bool operator<(undecorated_type_id_t const& rhs) const; - bool operator==(undecorated_type_id_t const& rhs) const; - - friend BOOST_PYTHON_DECL std::ostream& operator<<( - std::ostream&, undecorated_type_id_t const&); - - private: // data members base_id_t m_base_type; }; @@ -66,8 +67,10 @@ struct type_id_t : totally_ordered bool operator<(type_id_t const& rhs) const; bool operator==(type_id_t const& rhs) const; + friend BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, type_id_t const&); - + + operator undecorated_type_id_t const&() const; private: // type typedef undecorated_type_id_t base_id_t; @@ -153,13 +156,7 @@ struct is_reference_to_volatile template inline undecorated_type_id_t undecorated_type_id(detail::dummy* = 0) { - return undecorated_type_id_t( -# ifdef BOOST_PYTHON_TYPE_ID_NAME - typeid(T).name() -# else - &typeid(T) -# endif - ); + return undecorated_type_id_t(typeid(T)); } template @@ -177,8 +174,19 @@ inline type_id_t type_id(detail::dummy* = 0) ); } -inline undecorated_type_id_t::undecorated_type_id_t(base_id_t base_t) - : m_base_type(base_t) +inline undecorated_type_id_t::undecorated_type_id_t(std::type_info const& id) + : m_base_type( +# ifdef BOOST_PYTHON_TYPE_ID_NAME + id.name() +# else + &id +# endif + ) +{ +} + +inline undecorated_type_id_t::undecorated_type_id_t() + : m_base_type() { } @@ -218,6 +226,21 @@ inline bool type_id_t::operator==(type_id_t const& rhs) const return m_decoration == rhs.m_decoration && m_base_type == rhs.m_base_type; } +inline type_id_t::operator undecorated_type_id_t const&() const +{ + return m_base_type; +} + +inline char const* undecorated_type_id_t::name() const +{ +# ifdef BOOST_PYTHON_TYPE_ID_NAME + return m_base_type; +# else + return m_base_type->name(); +# endif +} + + BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, undecorated_type_id_t const&); BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, type_id_t const&); diff --git a/src/converter/type_id.cpp b/src/converter/type_id.cpp index 421cc5cf..688dd2bc 100644 --- a/src/converter/type_id.cpp +++ b/src/converter/type_id.cpp @@ -15,11 +15,7 @@ namespace boost { namespace python { namespace converter { BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream& os, undecorated_type_id_t const& x) { -# ifdef BOOST_PYTHON_TYPE_ID_NAME - return os << x.m_base_type; -# else - return os << x.m_base_type->name(); -# endif + return os << x.name(); } BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream& os, type_id_t const& x) From dabb22bb6aaa636bc245c747447eaccf4249feaf Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 20 Jan 2002 23:52:36 +0000 Subject: [PATCH 222/369] added class wrapping [SVN r12384] --- include/boost/python/object/class.hpp | 38 +++++- .../boost/python/object/class_unwrapper.hpp | 8 +- include/boost/python/object/function.hpp | 8 +- include/boost/python/object/value_holder.hpp | 8 +- src/object/class.cpp | 118 +++++++++++++++--- 5 files changed, 150 insertions(+), 30 deletions(-) diff --git a/include/boost/python/object/class.hpp b/include/boost/python/object/class.hpp index bc8f40d1..808e3669 100644 --- a/include/boost/python/object/class.hpp +++ b/include/boost/python/object/class.hpp @@ -6,16 +6,44 @@ #ifndef CLASS_DWA20011214_HPP # define CLASS_DWA20011214_HPP +# include # include # include # include # include +# include # include +# include -namespace boost { namespace python { namespace objects { +namespace boost { namespace python { + +class module; + +namespace objects { template struct holder; +// To identify a class, we don't need cv/reference decorations +typedef converter::undecorated_type_id_t class_id; + +struct BOOST_PYTHON_DECL class_base : noncopyable +{ + // constructor + class_base( + module& name_space // Which name space the class will live in + , char const* name // The name of the class + + , std::size_t num_types // A list of class_ids. The first is the type + , class_id const*const types // this is wrapping. The rest are the types of + // any bases. + ); + + // Retrieve a pointer to the underlying object + PyObject* object() const { return m_object.get(); } + private: + ref m_object; +}; + // Base class for all holders struct BOOST_PYTHON_DECL instance_holder : noncopyable { @@ -28,7 +56,7 @@ struct BOOST_PYTHON_DECL instance_holder : noncopyable virtual void* holds(converter::type_id_t) = 0; - void install(PyObject* inst); + void install(PyObject* inst) throw(); struct iterator_policies : default_iterator_policies { @@ -58,6 +86,8 @@ struct instance instance_holder* objects; }; +// Given a type_id, find the instance data which corresponds to it, or +// return 0 in case no such type is held. BOOST_PYTHON_DECL void* find_instance_impl(PyObject*, converter::type_id_t); template @@ -66,8 +96,8 @@ T* find_instance(PyObject* p, T* = 0) return static_cast(find_instance_impl(p, converter::type_id())); } -BOOST_PYTHON_DECL PyTypeObject* class_metatype(); -BOOST_PYTHON_DECL PyTypeObject* class_type(); +BOOST_PYTHON_DECL ref class_metatype(); +BOOST_PYTHON_DECL ref class_type(); // // implementation diff --git a/include/boost/python/object/class_unwrapper.hpp b/include/boost/python/object/class_unwrapper.hpp index 666c6e93..0877ff24 100644 --- a/include/boost/python/object/class_unwrapper.hpp +++ b/include/boost/python/object/class_unwrapper.hpp @@ -18,14 +18,14 @@ struct class_unwrapper template struct reference_unwrapper : converter::unwrapper { - bool convertible(PyObject* p) const + void* can_convert(PyObject* p) const { - return find_holder(p) != 0; + return find_instance(p); } - Target convert(PyObject* p, void*&) const + Target convert(PyObject* p, void* data, ) const { - return *find_holder(p)->target(); + return *find_instance(p)->target(); } }; diff --git a/include/boost/python/object/function.hpp b/include/boost/python/object/function.hpp index ed7dd319..cc2695d8 100644 --- a/include/boost/python/object/function.hpp +++ b/include/boost/python/object/function.hpp @@ -22,10 +22,16 @@ struct BOOST_PYTHON_DECL function : PyObject ~function(); PyObject* call(PyObject*, PyObject*) const; - void add_overload(function* overload); + + // Add an attributeto the name_space with the given name. If it is + // a function object (this class), and an existing function is + // already there, add it as an overload. + static void add_to_namespace( + PyObject* name_space, char const* name, PyObject* attribute); private: // helper functions void argument_error(PyObject* args, PyObject* keywords) const; + void add_overload(function* overload); private: // data members py_function m_fn; diff --git a/include/boost/python/object/value_holder.hpp b/include/boost/python/object/value_holder.hpp index be7247da..d6e38a79 100644 --- a/include/boost/python/object/value_holder.hpp +++ b/include/boost/python/object/value_holder.hpp @@ -8,6 +8,8 @@ # include # include +# include +# include namespace boost { namespace python { namespace objects { @@ -76,9 +78,11 @@ struct value_holder_generator }; template -void* value_holder::holds(converter::type_id_t x) +void* value_holder::holds(converter::type_id_t dst_t) { - return x == converter::type_id() ? &m_held : 0; + converter::type_id_t src_t = converter::type_id(); + return src_t == dst_t ? &m_held + : find_static_type(&m_held, src_t, dst_t); } }}} // namespace boost::python::objects diff --git a/src/object/class.cpp b/src/object/class.cpp index 8e85f38b..5ebabba1 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -6,8 +6,14 @@ #include #include #include +#include +#include +#include +#include #include +#include #include +#include namespace boost { namespace python { namespace objects { @@ -64,6 +70,20 @@ PyTypeObject class_metatype_object = { // PyType_GenericNew /* tp_new */ }; +// Get the metatype object for all extension classes. +BOOST_PYTHON_DECL ref class_metatype() +{ + if (class_metatype_object.tp_dict == 0) + { + class_metatype_object.ob_type = &PyType_Type; + class_metatype_object.tp_base = &PyType_Type; + if (PyType_Ready(&class_metatype_object)) + return ref(); + } + return ref((PyObject*)&class_metatype_object, ref::increment_count); +} + +// Do we really need this? I'm beginning to think we don't! PyTypeObject class_type_object = { PyObject_HEAD_INIT(0) //&class_metatype_object) 0, @@ -107,33 +127,21 @@ PyTypeObject class_type_object = { PyType_GenericNew }; -BOOST_PYTHON_DECL PyTypeObject* class_metatype() -{ - if (class_metatype_object.tp_dict == 0) - { - class_metatype_object.ob_type = &PyType_Type; - class_metatype_object.tp_base = &PyType_Type; - if (PyType_Ready(&class_metatype_object)) - return 0; - } - Py_INCREF(&class_metatype_object); - return &class_metatype_object; -} - -BOOST_PYTHON_DECL PyTypeObject* class_type() +BOOST_PYTHON_DECL ref class_type() { if (class_type_object.tp_dict == 0) { - class_type_object.ob_type = class_metatype(); + class_type_object.ob_type = (PyTypeObject*)class_metatype().release(); class_type_object.tp_base = &PyBaseObject_Type; if (PyType_Ready(&class_type_object)) - return 0; + return ref(); } - Py_INCREF(&class_type_object); - return &class_type_object; + return ref((PyObject*)&class_type_object, ref::increment_count); } -void instance_holder::install(PyObject* self) +// Install the instance data for a C++ object into a Python instance +// object. +void instance_holder::install(PyObject* self) throw() { assert(self->ob_type->ob_type == &class_metatype_object); m_next = ((instance*)self)->objects; @@ -157,4 +165,76 @@ find_instance_impl(PyObject* inst, converter::type_id_t type) return 0; } +namespace +{ + struct class_registry + { + public: + ref get(class_id id) const; + void set(class_id, ref class_object); + private: + typedef detail::map_entry entry; + std::vector m_impl; + }; + + class_registry& registry() + { + static class_registry x; + return x; + } + + ref class_registry::get(class_id id) const + { + std::vector::const_iterator start = m_impl.begin(); + std::vector::const_iterator finish = m_impl.end(); + + std::vector::const_iterator p + = boost::detail::lower_bound(start, finish, id); + + if (p == finish && p->key != id) + { + string report("extension class wrapper for base class "); + (report += id.name()) += "has not been created yet"; + PyErr_SetObject(PyExc_RuntimeError, report.get()); + throw error_already_set(); + } + return p->value; + } + + void class_registry::set(class_id id, ref object) + { + std::vector::iterator start = m_impl.begin(); + std::vector::iterator finish = m_impl.end(); + m_impl.insert( + boost::detail::lower_bound(start, finish, id) + , entry(id, object)); + } +} + +class_base::class_base( + module& m, char const* name, std::size_t num_types, class_id const* const types) +{ + class_registry& r = registry(); + assert(num_types >= 1); + tuple bases(std::max(num_types - 1, static_cast(1))); + if (num_types > 1) + { + for (std::size_t i = 1; i < num_types; ++i) + bases.set_item(i - 1, r.get(types[i])); + } + else + { + bases.set_item(0, class_type()); + } + + tuple args(3); + args.set_item(0, string(name).reference()); + args.set_item(1, bases.reference()); + args.set_item(2, dictionary().reference()); + + m_object = ref(PyObject_CallObject(class_metatype().get(), args.get())); + r.set(types[0], m_object); + m.add(m_object, name); +} + }}} // namespace boost::python::objects From f7a5e6deb81ce98b71fb99280b4cbf55244c10bb Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 20 Jan 2002 23:52:52 +0000 Subject: [PATCH 223/369] Moved add_overload functionality to function::add_to_namespace [SVN r12385] --- src/module.cpp | 23 +++------------------- src/object/function.cpp | 42 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/module.cpp b/src/module.cpp index 9faaca06..0851805f 100644 --- a/src/module.cpp +++ b/src/module.cpp @@ -7,7 +7,6 @@ // producing this work. #include -#include namespace boost { namespace python { @@ -47,9 +46,9 @@ void module_base::add(PyObject* x, const char* name) void module_base::add(ref x, const char* name) { - ref f(x); // First take possession of the object. - if (PyObject_SetAttrString(m_module, const_cast(name), x.get()) < 0) - throw error_already_set(); + // Use function::add_to_namespace to achieve overloading if + // appropriate. + objects::function::add_to_namespace(m_module, name, x.get()); } void module_base::add(PyTypeObject* x, const char* name /*= 0*/) @@ -57,22 +56,6 @@ void module_base::add(PyTypeObject* x, const char* name /*= 0*/) this->add((PyObject*)x, name ? name : x->tp_name); } -void module_base::add_overload(objects::function* x, const char* name) -{ - PyObject* existing = PyObject_HasAttrString(m_module, const_cast(name)) - ? PyObject_GetAttrString(m_module, const_cast(name)) - : 0; - - if (existing != 0 && existing->ob_type == &objects::function_type) - { - static_cast(existing)->add_overload(x); - } - else - { - add(x, name); - } -} - PyMethodDef module_base::initial_methods[] = { { 0, 0, 0, 0 } }; }} // namespace boost::python diff --git a/src/object/function.cpp b/src/object/function.cpp index 52a0456c..3755dfb1 100644 --- a/src/object/function.cpp +++ b/src/object/function.cpp @@ -6,6 +6,8 @@ #include #include +#include +#include namespace boost { namespace python { namespace objects { @@ -28,7 +30,7 @@ function::~function() PyObject* function::call(PyObject* args, PyObject* keywords) const { - int nargs = PyTuple_GET_SIZE(args); + std::size_t nargs = PyTuple_GET_SIZE(args); function const* f = this; do { @@ -63,6 +65,8 @@ void function::argument_error(PyObject* args, PyObject* keywords) const void function::add_overload(function* overload) { + Py_XINCREF(overload); + function* parent = this; while (parent->m_overloads != 0) @@ -72,6 +76,42 @@ void function::add_overload(function* overload) parent->m_overloads = overload; } +void function::add_to_namespace( + PyObject* name_space, char const* name_, PyObject* attribute_) +{ + ref attribute(attribute_, ref::increment_count); + string name(name_); + + if (attribute_->ob_type == &function_type) + { + PyObject* dict = 0; + + if (PyClass_Check(name_space)) + dict = ((PyClassObject*)name_space)->cl_dict; + else if (PyType_Check(name_space)) + dict = ((PyTypeObject*)name_space)->tp_dict; + else + dict = PyObject_GetAttrString(name_space, "__dict__"); + + if (dict == 0) + throw error_already_set(); + + ref existing(PyObject_GetItem(dict, name.get()), ref::null_ok); + + if (existing.get() && existing->ob_type == &function_type) + { + static_cast(existing.get())->add_overload( + static_cast(attribute_)); + return; + } + } + + // The PyObject_GetAttrString() call above left an active error + PyErr_Clear(); + if (PyObject_SetAttr(name_space, name.get(), attribute_) < 0) + throw error_already_set(); +} + extern "C" { // Stolen from Python's funcobject.c From 4a1d077238fecb53f5010b7c197e9c52fb70e544 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 20 Jan 2002 23:54:26 +0000 Subject: [PATCH 224/369] Added implicit conversion tests [SVN r12386] --- test/newtest.py | 74 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/test/newtest.py b/test/newtest.py index d29ac129..0636641b 100644 --- a/test/newtest.py +++ b/test/newtest.py @@ -60,14 +60,82 @@ try: wrap_int_ref(n) Create an extension class which wraps "complicated" (init1 and get_n) are a complicated constructor and member function, respectively. ->>> C = xclass('C', (xinst,), {'__init__': init1, 'get_n': get_n}) ->>> c1 = C(s, 99) +>>> c1 = complicated(s, 99) >>> c1.get_n() 99 ->>> c2 = C(s) +>>> c2 = complicated(s) >>> c2.get_n() 0 +>>> a = A() +>>> b = B() +>>> c = C() +>>> d = D() + +------ +>>> take_a(a) +0 + +>>> try: +... take_b(a) +... except: pass +... else: print 'no exception' + +>>> try: +... take_c(a) +... except: pass +... else: print 'no exception' + +>>> try: +... take_d(a) +... except: pass +... else: print 'no exception' + +------ +>>> take_a(b) +0 + +>>> take_b(b) +1 + +>>> try: +... take_c(b) +... except: pass +... else: print 'no exception' + +>>> try: +... take_d(b) +... except: pass +... else: print 'no exception' + +------- +>>> take_a(c) +0 + +>>> try: +... take_b(c) +... except: pass +... else: print 'no exception' + +>>> take_c(c) +2 + +>>> try: +... take_d(c) +... except: pass +... else: print 'no exception' + +------- +>>> take_a(d) +0 +>>> take_b(d) +1 +>>> take_c(d) +2 +>>> take_d(d) +3 + + """ def run(args = None): From 03e9e4c1d9fff14e25f62f0aecca289ab9630dd1 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 21 Jan 2002 00:47:05 +0000 Subject: [PATCH 225/369] Added class wrapping [SVN r12387] --- Jamfile | 2 +- include/boost/python/class.hpp | 166 ++++++ include/boost/python/detail/map_entry.hpp | 44 ++ include/boost/python/detail/wrap_function.hpp | 56 ++ .../boost/python/object/class_converters.hpp | 101 ++++ include/boost/python/object/class_wrapper.hpp | 62 +++ include/boost/python/object/inheritance.hpp | 165 ++++++ src/object/inheritance.cpp | 493 ++++++++++++++++++ test/m1.cpp | 99 +++- 9 files changed, 1164 insertions(+), 24 deletions(-) create mode 100644 include/boost/python/class.hpp create mode 100644 include/boost/python/detail/map_entry.hpp create mode 100644 include/boost/python/detail/wrap_function.hpp create mode 100644 include/boost/python/object/class_converters.hpp create mode 100644 include/boost/python/object/class_wrapper.hpp create mode 100644 include/boost/python/object/inheritance.hpp create mode 100644 src/object/inheritance.cpp diff --git a/Jamfile b/Jamfile index deb8c690..71e0c5b7 100644 --- a/Jamfile +++ b/Jamfile @@ -23,7 +23,7 @@ dll bpl src/converter/type_id.cpp src/object/class.cpp src/object/function.cpp - # src/object/inheritance.cpp + src/object/inheritance.cpp src/errors.cpp src/module.cpp src/objects.cpp diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp new file mode 100644 index 00000000..d61a8fc0 --- /dev/null +++ b/include/boost/python/class.hpp @@ -0,0 +1,166 @@ +// Copyright David Abrahams 2002. 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 CLASS_DWA200216_HPP +# define CLASS_DWA200216_HPP + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +namespace // put some convenience classes into the unnamed namespace for the user +{ + // A type list for specifying bases + template < BOOST_MPL_LIST_DEFAULT_PARAMETERS(typename B, ::boost::mpl::null_argument) > + struct bases : ::boost::mpl::type_list< BOOST_MPL_LIST_PARAMETERS(B) >::type + {}; + + // A type list for specifying arguments + template < BOOST_MPL_LIST_DEFAULT_PARAMETERS(typename A, ::boost::mpl::null_argument) > + struct args : ::boost::mpl::type_list< BOOST_MPL_LIST_PARAMETERS(A) >::type + {}; +} + +namespace boost { namespace python { + +// Forward declarations +namespace objects +{ + struct value_holder_generator; +} + +namespace detail +{ + // This is an mpl BinaryMetaFunction object with a runtime behavior, + // which is to write the id of the type which is passed as its 2nd + // compile-time argument into the iterator pointed to by its runtime + // argument + struct write_type_id + { + // The first argument is Ignored because mpl::for_each is still + // currently an accumulate (reduce) implementation. + template struct apply + { + // also an artifact of accumulate-based for_each + typedef void type; + + // Here's the runtime behavior + static void execute(converter::undecorated_type_id_t** p) + { + *(*p)++ = converter::undecorated_type_id(); + } + }; + }; +} + +// +// class_ +// +// This is the primary mechanism through which users will expose +// C++ classes to Python. The three template arguments are: +// +// T - The class being exposed to Python +// +// Bases - An MPL sequence of base classes +// +// HolderGenerator - +// An optional type generator for the "holder" which +// maintains the C++ object inside the Python instance. The +// default just holds the object "by-value", but other +// holders can be substituted which will hold the C++ object +// by smart pointer, for example. +// +template < + class T // class being wrapped + , class Bases = mpl::type_list<>::type + , class HolderGenerator = objects::value_holder_generator + > +class class_ : objects::class_base +{ + typedef class_ self; + public: + + // Construct with the module and class name + class_(module&, char const* name); + + // Wrap a member function or a non-member function which can take + // a T, T cv&, or T cv* as its first parameter, or a callable + // python object. + template + self& def(F f, char const* name) + { + // Use function::add_to_namespace to achieve overloading if + // appropriate. + objects::function::add_to_namespace(this->object(), name, detail::wrap_function(f)); + return *this; + } + + // Define the constructor with the given Args, which should be an + // MPL sequence of types. + template + self& def_init(Args const& = Args()) + { + def(make_constructor(), "__init__"); + return *this; + } + + // Define the default constructor. + self& def_init() + { + this->def_init(mpl::type_list<>::type()); + return *this; + } + + private: // types + typedef objects::class_id class_id; + + // A helper class which will contain an array of id objects to be + // passed to the base class constructor + struct id_vector + { + id_vector() + { + // Stick the derived class id into the first element of the array + ids[0] = converter::undecorated_type_id(); + + // Write the rest of the elements into succeeding positions. + class_id* p = ids + 1; + mpl::for_each::execute(&p); + } + + BOOST_STATIC_CONSTANT( + std::size_t, size = mpl::size::value + 1); + class_id ids[size]; + }; + + private: // helper functions + void initialize_converters(); +}; + + +// +// implementations +// +template +inline class_::class_( + module& m, char const* name = typeid(T).name()) + : class_base(m, name, id_vector::size, id_vector().ids) +{ + // Bring the class converters into existence. This static object + // will survive until the shared library this module lives in is + // unloaded (that doesn't happen until Python terminates). + static objects::class_converters converters(object()); +} + +}} // namespace boost::python + +#endif // CLASS_DWA200216_HPP diff --git a/include/boost/python/detail/map_entry.hpp b/include/boost/python/detail/map_entry.hpp new file mode 100644 index 00000000..9249523a --- /dev/null +++ b/include/boost/python/detail/map_entry.hpp @@ -0,0 +1,44 @@ +// Copyright David Abrahams 2002. 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 MAP_ENTRY_DWA2002118_HPP +# define MAP_ENTRY_DWA2002118_HPP + +namespace boost { namespace python { namespace detail { + +// A trivial type that works well as the value_type of associative +// vector maps +template +struct map_entry +{ + map_entry() {} + map_entry(Key k) : key(k), value() {} + map_entry(Key k, Value v) : key(k), value(v) {} + + bool operator<(map_entry const& rhs) const + { + return this->key < rhs.key; + } + + Key key; + Value value; +}; + +template +bool operator<(map_entry const& e, Key const& k) +{ + return e.key < k; +} + +template +bool operator<(Key const& k, map_entry const& e) +{ + return k < e.key; +} + + +}}} // namespace boost::python::detail + +#endif // MAP_ENTRY_DWA2002118_HPP diff --git a/include/boost/python/detail/wrap_function.hpp b/include/boost/python/detail/wrap_function.hpp new file mode 100644 index 00000000..0424183d --- /dev/null +++ b/include/boost/python/detail/wrap_function.hpp @@ -0,0 +1,56 @@ +// Copyright David Abrahams 2002. 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 WRAP_FUNCTION_DWA2002118_HPP +# define WRAP_FUNCTION_DWA2002118_HPP + +# include +# include +# include +# include + +namespace boost { namespace python { namespace detail { + +// A function which converts its argument into a Python callable +// object. Not very general yet! + +// This should eventually be replaced with a mechanism for specialized +// wrap/unwrap objects. In other words, to_python(f), where f is a +// function pointer or function type, should produce a callable Python +// object. + +template +struct wrap_function_select +{ + template + static objects::function* execute(F f) + { + return make_function(f); + } +}; + +template<> +struct wrap_function_select +{ + template + static F execute(F f) + { + return f; + } +}; + +template +PyObject* wrap_function(F f) +{ + return wrap_function_select< + type_traits::ice_or< + is_function::value + , is_member_function_pointer::value + >::value >::execute(f); +} + +}}} // namespace boost::python::detail + +#endif // WRAP_FUNCTION_DWA2002118_HPP diff --git a/include/boost/python/object/class_converters.hpp b/include/boost/python/object/class_converters.hpp new file mode 100644 index 00000000..c14103b6 --- /dev/null +++ b/include/boost/python/object/class_converters.hpp @@ -0,0 +1,101 @@ +// Copyright David Abrahams 2002. 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 CLASS_CONVERTERS_DWA2002119_HPP +# define CLASS_CONVERTERS_DWA2002119_HPP + +# include +# include +# include + +namespace boost { namespace python { namespace objects { + +// Instantiating this class brings into existence all converters +// associated with a class Bases is expected to be an mpl sequence of +// base types. +template +struct class_converters +{ + public: // member functions + // Constructor takes the python class object associated with T + class_converters(PyObject* python_class); + + private: // data members + converter::class_unwrapper m_unwrapper; + class_wrapper m_wrapper; +}; + +// +// Implementation details +// + +////////////////////////////////////////////////////////////////////// +// +// register_base_of - +// A BinaryMetaFunction object which registers a single base +// class of T, and the corresponding cast(s) +// + + +// register_downcast/do_nothing - +// Helpers for register_base_of<> which take care of registering +// down-casts +template +struct register_downcast +{ + static void execute() + { + register_conversion(true); + } +}; + +struct do_nothing +{ + static void execute() { } +}; + +// Here's where the real work gets done: +template +struct register_base_of +{ + // Ignored is needed because mpl::for_each is still actually + // accumulate. We're not using any state so it just sits there. + template + struct apply + { + typedef void type; // 'type' needs to be defined for the same reasons + + // Here's the runtime part: + static void execute() + { + // Register the Base class + register_dynamic_id(); + // Register the up-cast + register_conversion(false); + + // Register the down-cast, if appropriate. + mpl::select_type< + is_polymorphic::value + , register_downcast + , do_nothing + >::type::execute(); + } + }; +}; + +template +class_converters::class_converters(PyObject* type_object) + : m_wrapper(type_object) +{ + // register all up/downcasts here + register_dynamic_id(); + + // register each base in the sequence + mpl::for_each >::execute(); +} + +}}} // namespace boost::python::object + +#endif // CLASS_CONVERTERS_DWA2002119_HPP diff --git a/include/boost/python/object/class_wrapper.hpp b/include/boost/python/object/class_wrapper.hpp new file mode 100644 index 00000000..0e49ce84 --- /dev/null +++ b/include/boost/python/object/class_wrapper.hpp @@ -0,0 +1,62 @@ +// 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 CLASS_WRAPPER_DWA20011221_HPP +# define CLASS_WRAPPER_DWA20011221_HPP + +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace objects { + +template +struct class_wrapper + : converter::wrapper +{ + class_wrapper(PyObject* type_) + : m_class_object(type_) + { +# ifndef NDEBUG + assert(type_->ob_type == (PyTypeObject*)class_metatype().get()); +# endif NDEBUG + } + + PyObject* convert(T const& x) const + { + // Don't call the type to do the construction, since that + // would require the registration of an __init__ copy + // constructor. Instead, just construct the object in place. + PyObject* raw_result = (PyObject*)PyObject_New( + instance, (PyTypeObject*)m_class_object.get()); + + if (raw_result == 0) + return 0; + + // Everything's OK; Bypass NULL checks but guard against + // exceptions. + ref result(raw_result, ref::allow_null()); + + // Build a value_holder to contain the object using the copy + // constructor + value_holder* p = new value_holder(raw_result, cref(x)); + + // Install it in the instance + p->install(raw_result); + + // Return the new result + return result.release(); + } + + private: + ref m_class_object; +}; + + +}}} // namespace boost::python::objects + +#endif // CLASS_WRAPPER_DWA20011221_HPP diff --git a/include/boost/python/object/inheritance.hpp b/include/boost/python/object/inheritance.hpp new file mode 100644 index 00000000..60aeda58 --- /dev/null +++ b/include/boost/python/object/inheritance.hpp @@ -0,0 +1,165 @@ +// Copyright David Abrahams 2002. 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 INHERITANCE_DWA200216_HPP +# define INHERITANCE_DWA200216_HPP + +# include +# include + +namespace boost { namespace python { namespace objects { + +typedef converter::undecorated_type_id_t class_id; +using converter::undecorated_type_id; + +// Types used to get address and id of most derived type +typedef std::pair dynamic_id_t; +typedef dynamic_id_t (*dynamic_id_function)(void*); + +BOOST_PYTHON_DECL void register_dynamic_id_aux( + class_id static_id, dynamic_id_function get_dynamic_id); + +BOOST_PYTHON_DECL void add_cast( + class_id src_t, class_id dst_t, void* (*cast)(void*), bool polymorphic); + +BOOST_PYTHON_DECL void* find_static_type(void* p, class_id src, class_id dst); + +BOOST_PYTHON_DECL void* find_dynamic_type(void* p, class_id src, class_id dst); + +// is_polymorphic test from John Maddock +template +struct is_polymorphic +{ + struct d1 : public T + { + d1(); + char padding[256]; + }; + struct d2 : public T + { + d2(); + virtual ~d2(); + virtual void foo(); + char padding[256]; + }; + BOOST_STATIC_CONSTANT(bool, value = (sizeof(d2) == sizeof(d1))); +}; + +// +// a generator with an execute() function which, given a source type +// and a pointer to an object of that type, returns its most-derived +// /reachable/ type identifier and object pointer. +// + +// first, the case where T has virtual functions +template +struct polymorphic_id_generator +{ + static dynamic_id_t execute(void* p_) + { + T* p = static_cast(p_); + return std::make_pair(dynamic_cast(p), class_id(typeid(*p))); + } +}; + +// now, the non-polymorphic case. +template +struct non_polymorphic_id_generator +{ + static dynamic_id_t execute(void* p_) + { + return std::make_pair(p_, converter::undecorated_type_id()); + } +}; + +// Now the generalized selector +template +struct dynamic_id_generator +{ + typedef typename mpl::select_type< + is_polymorphic::value + , polymorphic_id_generator + , non_polymorphic_id_generator >::type type; +}; + +// Register the dynamic id function for T with the type-conversion +// system. +template +void register_dynamic_id(T* = 0) +{ + typedef typename dynamic_id_generator::type generator; + register_dynamic_id_aux( + converter::undecorated_type_id(), &generator::execute); +} + +// +// a generator with an execute() function which, given a void* +// pointing to an object of type Source will attempt to convert it to +// an object of type Target. +// + +template +struct dynamic_cast_generator +{ + static void* execute(void* source) + { + return dynamic_cast( + static_cast(source)); + } + +}; + +template +struct implicit_cast_generator +{ + static void* execute(void* source) + { + Target* result = static_cast(source); + return result; + } +}; + +template +struct cast_generator +{ + // CWPro7 will return false sometimes, but that's OK since we can + // always cast up with dynamic_cast<> + BOOST_STATIC_CONSTANT( + bool, is_upcast = ( + is_base_and_derived::value + )); + + typedef typename mpl::select_type< + is_upcast +# if defined(__MWERKS__) && __MWERKS__ <= 0x2406 + // grab a few more implicit_cast cases for CodeWarrior + || !is_polymorphic::value + || !is_polymorphic::value +# endif + , implicit_cast_generator + , dynamic_cast_generator + >::type type; +}; + +template +inline void register_conversion( + // We need this parameter because CWPro7 can't determine + // which is the base reliably. + bool is_downcast = !cast_generator::is_upcast + + // These parameters shouldn't be used, they're an MSVC bug workaround + , Source* = 0, Target* = 0) +{ + typedef typename cast_generator::type generator; + + add_cast(converter::undecorated_type_id() + , converter::undecorated_type_id() + , &generator::execute + , is_downcast); +} + +}}} // namespace boost::python::object + +#endif // INHERITANCE_DWA200216_HPP diff --git a/src/object/inheritance.cpp b/src/object/inheritance.cpp new file mode 100644 index 00000000..5b95e478 --- /dev/null +++ b/src/object/inheritance.cpp @@ -0,0 +1,493 @@ +// Copyright David Abrahams 2002. 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. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Procedure: +// +// The search is a BFS over the space of (type,address) pairs +// guided by the edges of the casting graph whose nodes +// correspond to classes, and whose edges are traversed by +// applying associated cast functions to an address. We use +// vertex distance to the goal node in the cast_graph to rate the +// paths. The vertex distance to any goal node is calculated on +// demand and outdated by the addition of edges to the graph. + +namespace boost { +namespace +{ + enum edge_cast_t { edge_cast = 8010 }; +} + +// Install properties +BOOST_INSTALL_PROPERTY(edge, cast); + +namespace +{ + typedef void*(*cast_function)(void*); + + // + // Here we put together the low-level data structures of the + // casting graph representation. + // + typedef python::converter::undecorated_type_id_t class_id; + + // represents a graph of available casts + +#if 0 + struct cast_graph + : +#else + typedef +#endif + adjacency_list > > +#if 0 + {}; +#else + cast_graph; +#endif + + typedef cast_graph::vertex_descriptor vertex_t; + typedef cast_graph::edge_descriptor edge_t; + + struct smart_graph + { + typedef std::vector::const_iterator node_distance_map; + + typedef std::pair out_edges_t; + + // Return a map of the distances from any node to the given + // target node + node_distance_map distances_to(vertex_t target) const + { + std::size_t n = num_vertices(m_topology); + if (m_distances.size() != n * n) + { + m_distances.clear(); + m_distances.resize(n * n, std::numeric_limits::max()); + m_known_vertices = n; + } + + std::vector::iterator to_target = m_distances.begin() + n * target; + + // this node hasn't been used as a target yet + if (to_target[target] != 0) + { + typedef reverse_graph reverse_cast_graph; + reverse_cast_graph reverse_topology(m_topology); + + to_target[target] = 0; + + breadth_first_search( + reverse_topology, target + , visitor( + make_bfs_visitor( + record_distances( + make_iterator_property_map( + to_target + , get(vertex_index, reverse_topology) +# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + , *to_target +# endif + ) + , on_tree_edge() + )))); + } + + return to_target; + } + + cast_graph& topology() { return m_topology; } + cast_graph const& topology() const { return m_topology; } + + std::size_t known_vertices() const { return m_known_vertices; } + + smart_graph() + : m_known_vertices(0) + {} + + private: + cast_graph m_topology; + mutable std::vector m_distances; + mutable std::size_t m_known_vertices; + }; + + smart_graph& full_graph() + { + static smart_graph x; + return x; + } + + smart_graph& up_graph() + { + static smart_graph x; + return x; + } + + // + // Our index of class types + // + using boost::python::objects::dynamic_id_function; + typedef tuples::tuple< + class_id // static type + , vertex_t // corresponding vertex + , dynamic_id_function // dynamic_id if polymorphic, or 0 + > + index_entry_interface; + typedef index_entry_interface::inherited index_entry; + enum { ksrc_static_t, kvertex, kdynamic_id }; + + typedef std::vector type_index_t; + + + type_index_t& type_index() + { + static type_index_t x; + return x; + } + + template + struct select1st + { + typedef typename tuples::element<0, Tuple>::type result_type; + + result_type const& operator()(Tuple const& x) const + { + return tuples::get<0>(x); + } + }; + + // map a type to a position in the index + inline type_index_t::iterator type_position(class_id type) + { + typedef index_entry entry; + + return std::lower_bound( + type_index().begin(), type_index().end() + , make_tuple(type, vertex_t(), dynamic_id_function(0)) + , boost::bind(std::less() + , boost::bind(select1st(), _1) + , boost::bind(select1st(), _2))); + } + + inline index_entry* seek_type(class_id type) + { + type_index_t::iterator p = type_position(type); + if (p == type_index().end() || tuples::get(*p) != type) + return 0; + else + return &*p; + } + + // Get the entry for a type, inserting if neccessary + inline type_index_t::iterator demand_type(class_id type) + { + type_index_t::iterator p = type_position(type); + + if (p != type_index().end() && tuples::get(*p) == type) + return p; + + vertex_t v = add_vertex(full_graph().topology()); + vertex_t v2 = add_vertex(up_graph().topology()); + assert(v == v2); + return type_index().insert(p, make_tuple(type, v, dynamic_id_function(0))); + } + + // Map a two types to a vertex in the graph, inserting if neccessary + typedef std::pair + type_index_iterator_pair; + + inline type_index_iterator_pair + demand_types(class_id t1, class_id t2) + { + // be sure there will be no reallocation + type_index().reserve(type_index().size() + 2); + type_index_t::iterator first = demand_type(t1); + type_index_t::iterator second = demand_type(t2); + if (first == second) + ++first; + return std::make_pair(first, second); + } + + struct q_elt + { + q_elt(std::size_t distance + , void* src_address + , vertex_t target + , cast_function cast + ) + : distance(distance) + , src_address(src_address) + , target(target) + , cast(cast) + {} + + std::size_t distance; + void* src_address; + vertex_t target; + cast_function cast; + + bool operator<(q_elt const& rhs) const + { + return distance < rhs.distance; + } + }; + + // Optimization: + // + // Given p, src_t, dst_t + // + // Get a pointer pd to the most-derived object + // if it's polymorphic, dynamic_cast to void* + // otherwise pd = p + // + // Get the most-derived typeid src_td + // + // ptrdiff_t offset = p - pd + // + // Now we can keep a cache, for [src_t, offset, src_td, dst_t] of + // the cast transformation function to use on p and the next src_t + // in the chain. src_td, dst_t don't change throughout this + // process. In order to represent unreachability, when a pair is + // found to be unreachable, we stick a 0-returning "dead-cast" + // function in the cache. + + // This is needed in a few places below + inline void* identity_cast(void* p) + { + return p; + } + + void* search(smart_graph const& g, void* p, vertex_t src, vertex_t dst) + { + // I think this test was thoroughly bogus -- dwa + // If we know there's no path; bail now. + // if (src > g.known_vertices() || dst > g.known_vertices()) + // return 0; + + smart_graph::node_distance_map d(g.distances_to(dst)); + + if (d[src] == std::numeric_limits::max()) + return 0; + + typedef property_map::const_type cast_map; + cast_map casts = get(edge_cast, g.topology()); + + typedef std::pair search_state; + typedef std::vector visited_t; + visited_t visited; + std::priority_queue q; + + q.push(q_elt(d[src], p, src, identity_cast)); + while (!q.empty()) + { + q_elt top = q.top(); + q.pop(); + + // Check to see if we have a real state + void* dst_address = top.cast(top.src_address); + if (dst_address == 0) + continue; + + if (top.target == dst) + return dst_address; + + search_state s(top.target,dst_address); + + visited_t::iterator pos = std::lower_bound( + visited.begin(), visited.end(), s); + + // If already visited, continue + if (pos != visited.end() && *pos == s) + continue; + + visited.insert(pos, s); // mark it + + // expand it: + smart_graph::out_edges_t edges = out_edges(s.first, g.topology()); + for (cast_graph::out_edge_iterator p = edges.first + , finish = edges.second + ; p != finish + ; ++p + ) + { + edge_t e = *p; + q.push(q_elt( + d[target(e, g.topology())] + , dst_address + , target(e, g.topology()) + , boost::get(casts, e))); + } + } + return 0; + } + + struct cache_element + { + typedef tuples::tuple< + class_id // source static type + , class_id // target type + , std::ptrdiff_t // offset within source object + , class_id // source dynamic type + >::inherited key_type; + + cache_element(key_type const& k) + : key(k) + , offset(0) + {} + + key_type key; + std::ptrdiff_t offset; + + BOOST_STATIC_CONSTANT( + std::ptrdiff_t, not_found = integer_traits::const_min); + + bool operator<(cache_element const& rhs) const + { + return this->key < rhs.key; + } + + bool unreachable() const + { + return offset == not_found; + } + }; + + enum { kdst_t = ksrc_static_t + 1, koffset, ksrc_dynamic_t }; + typedef std::vector cache_t; + + cache_t& cache() + { + static cache_t x; + return x; + } + + inline void* convert_type(void* const p, class_id src_t, class_id dst_t, bool polymorphic) + { + // Quickly rule out unregistered types + index_entry* src_p = seek_type(src_t); + if (src_p == 0) + return 0; + + index_entry* dst_p = seek_type(dst_t); + if (dst_p == 0) + return 0; + + // Look up the dynamic_id function and call it to get the dynamic + // info + boost::python::objects::dynamic_id_t dynamic_id = polymorphic + ? tuples::get(*src_p)(p) + : std::make_pair(p, src_t); + + // Look in the cache first for a quickie address translation + std::ptrdiff_t offset = (char*)p - (char*)dynamic_id.first; + + cache_element seek(make_tuple(src_t, dst_t, offset, dynamic_id.second)); + cache_t& c = cache(); + cache_t::iterator const cache_pos + = std::lower_bound(c.begin(), c.end(), seek); + + + // if found in the cache, we're done + if (cache_pos != c.end() && cache_pos->key == seek.key) + { + return cache_pos->offset == cache_element::not_found + ? 0 : (char*)p + cache_pos->offset; + } + + // If we are starting at the most-derived type, only look in the up graph + smart_graph const& g = polymorphic && dynamic_id.second != src_t + ? full_graph() : up_graph(); + + void* result = search( + g, p, tuples::get(*src_p) + , tuples::get(*dst_p)); + + // update the cache + c.insert(cache_pos, seek)->offset + = (result == 0) ? cache_element::not_found : (char*)result - (char*)p; + + return result; + } +} + +namespace python { namespace objects { + +BOOST_PYTHON_DECL void* find_dynamic_type(void* p, class_id src_t, class_id dst_t) +{ + return convert_type(p, src_t, dst_t, true); +} + +BOOST_PYTHON_DECL void* find_static_type(void* p, class_id src_t, class_id dst_t) +{ + return convert_type(p, src_t, dst_t, false); +} + +BOOST_PYTHON_DECL void add_cast( + class_id src_t, class_id dst_t, cast_function cast, bool is_downcast) +{ + // adding an edge will invalidate any record of unreachability in + // the cache. + static std::size_t expected_cache_len = 0; + cache_t& c = cache(); + if (c.size() > expected_cache_len) + { + c.erase(std::remove_if( + c.begin(), c.end(), + mem_fn(&cache_element::unreachable)) + , c.end()); + + // If any new cache entries get added, we'll have to do this + // again when the next edge is added + expected_cache_len = c.size(); + } + + type_index_iterator_pair types = demand_types(src_t, dst_t); + vertex_t src = tuples::get(*types.first); + vertex_t dst = tuples::get(*types.second); + + cast_graph* const g[2] = { &up_graph().topology(), &full_graph().topology() }; + + for (cast_graph*const* p = g + (is_downcast ? 1 : 0); p < g + 2; ++p) + { + edge_t e; + bool added; + + tie(e, added) = add_edge(src, dst, **p); + assert(added); + + put(get(edge_cast, **p), e, cast); + put(get(edge_index, **p), e, num_edges(full_graph().topology()) - 1); + } +} + +BOOST_PYTHON_DECL void register_dynamic_id_aux( + class_id static_id, dynamic_id_function get_dynamic_id) +{ + tuples::get(*demand_type(static_id)) = get_dynamic_id; +} + +}}} // namespace boost::python::objects diff --git a/test/m1.cpp b/test/m1.cpp index 78471bfc..da3ca5d5 100644 --- a/test/m1.cpp +++ b/test/m1.cpp @@ -11,8 +11,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -227,10 +229,47 @@ simple const& g(simple const& x) return x; } +struct A +{ + A() : x(0) {} + char const* name() { return "A"; } + int x; +}; + +struct B : A +{ + B() : x(1) {} + char const* name() { return "B"; } + int x; +}; + + +struct C : A +{ + C() : x(2) {} + char const* name() { return "C"; } + virtual ~C() {} + int x; +}; + +struct D : B, C +{ + D() : x(3) {} + char const* name() { return "D"; } + int x; +}; + +int take_a(A const& a) { return a.x; } +int take_b(B const& b) { return b.x; } +int take_c(C const& c) { return c.x; } +int take_d(D const& d) { return d.x; } + BOOST_PYTHON_MODULE_INIT(m1) { - boost::python::module m1("m1"); - + using boost::python::module; + using boost::python::class_; + + module m1("m1"); // Create the converters; they are self-registering/unregistering. static int_wrapper wrap_int; static simple_wrapper wrap_simple; @@ -242,13 +281,16 @@ BOOST_PYTHON_MODULE_INIT(m1) static simple_ref_wrapper wrap_simple_ref; // This unwrapper extracts pointers and references to the "complicated" class. - static boost::python::converter::class_unwrapper unwrap_complicated; + // static boost::python::converter::class_unwrapper unwrap_complicated; // Insert the extension metaclass object - m1.add(boost::python::objects::class_metatype(), "xclass"); + m1.add( + boost::python::objects::class_metatype() + , "xclass"); // Insert the base class for all extension classes - m1.add(boost::python::objects::class_type(), "xinst"); + m1.add(boost::python::objects::class_type() + , "xinst"); m1.def(new_noddy, "new_noddy"); m1.def(new_simple, "new_simple"); @@ -259,25 +301,36 @@ BOOST_PYTHON_MODULE_INIT(m1) // Expose g() m1.def(g, "g"); - // Expose complicated's get_n() member function. See newtest.py - // for how it's used to build an extension class. - m1.def(&complicated::get_n, "get_n"); + m1.def(take_a, "take_a"); + m1.def(take_b, "take_b"); + m1.def(take_c, "take_c"); + m1.def(take_d, "take_d"); - // Expose complicated::complicated(simple const&, int) as init1 - boost::python::objects::function* init = boost::python::make_constructor< - complicated - , boost::mpl::type_list - , boost::python::objects::value_holder_generator>(); - - boost::python::ref manager(init); - - init->add_overload( - boost::python::make_constructor< - complicated - , boost::mpl::type_list - , boost::python::objects::value_holder_generator>()); - - m1.add(manager, "init1"); + class_(m1, "A") + .def_init() + .def(&A::name, "name") + ; + + class_ >(m1, "B") + .def_init() + .def(&B::name, "name") + ; + + class_ >(m1, "C") + .def_init() + .def(&C::name, "name") + ; + + class_ >(m1, "D") + .def_init() + .def(&D::name, "name") + ; + + class_(m1, "complicated") + .def_init(args()) + .def_init(args()) + .def(&complicated::get_n, "get_n") + ; } #include "module_tail.cpp" From 078585db28da772b7cb1d8f31f7198f83463483e Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 21 Jan 2002 06:20:15 +0000 Subject: [PATCH 226/369] fixed transfer-of-ownership counting to avoid problems [SVN r12392] --- include/boost/python/reference.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/python/reference.hpp b/include/boost/python/reference.hpp index f0cdab55..97edef99 100644 --- a/include/boost/python/reference.hpp +++ b/include/boost/python/reference.hpp @@ -173,10 +173,10 @@ public: void reset(T2* x, increment_count_t) { assert(m_p == 0 || m_p->ob_refcnt > 0); + Py_XINCREF(x); Py_XDECREF(m_p); m_p = expect_non_null(x); assert(m_p->ob_refcnt > 0); - Py_INCREF(m_p); } template @@ -192,20 +192,20 @@ public: void reset(T2* x, allow_null, increment_count_t) { assert(m_p == 0 || m_p->ob_refcnt > 0); + Py_XINCREF(x); Py_XDECREF(m_p); m_p = x; assert(m_p == 0 || m_p->ob_refcnt > 0); - Py_XINCREF(m_p); } template void reset(T2* x, increment_count_t, allow_null) { assert(m_p == 0 || m_p->ob_refcnt > 0); + Py_XINCREF(x); Py_XDECREF(m_p); m_p = x; assert(m_p == 0 || m_p->ob_refcnt > 0); - Py_XINCREF(m_p); } #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) From 93501af04601590e46feede4a11e03fae700d2d6 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 21 Jan 2002 06:23:33 +0000 Subject: [PATCH 227/369] always use ref (counting) for safety [SVN r12393] --- include/boost/python/object/class.hpp | 4 ++-- include/boost/python/object/class_converters.hpp | 5 +++-- include/boost/python/object/class_wrapper.hpp | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/boost/python/object/class.hpp b/include/boost/python/object/class.hpp index 808e3669..4817e15d 100644 --- a/include/boost/python/object/class.hpp +++ b/include/boost/python/object/class.hpp @@ -38,8 +38,8 @@ struct BOOST_PYTHON_DECL class_base : noncopyable // any bases. ); - // Retrieve a pointer to the underlying object - PyObject* object() const { return m_object.get(); } + // Retrieve the underlying object + ref object() const { return m_object; } private: ref m_object; }; diff --git a/include/boost/python/object/class_converters.hpp b/include/boost/python/object/class_converters.hpp index c14103b6..d4ba4b6d 100644 --- a/include/boost/python/object/class_converters.hpp +++ b/include/boost/python/object/class_converters.hpp @@ -9,6 +9,7 @@ # include # include # include +# include namespace boost { namespace python { namespace objects { @@ -20,7 +21,7 @@ struct class_converters { public: // member functions // Constructor takes the python class object associated with T - class_converters(PyObject* python_class); + class_converters(ref const& python_class); private: // data members converter::class_unwrapper m_unwrapper; @@ -86,7 +87,7 @@ struct register_base_of }; template -class_converters::class_converters(PyObject* type_object) +class_converters::class_converters(ref const& type_object) : m_wrapper(type_object) { // register all up/downcasts here diff --git a/include/boost/python/object/class_wrapper.hpp b/include/boost/python/object/class_wrapper.hpp index 0e49ce84..cbfb2ae6 100644 --- a/include/boost/python/object/class_wrapper.hpp +++ b/include/boost/python/object/class_wrapper.hpp @@ -18,7 +18,7 @@ template struct class_wrapper : converter::wrapper { - class_wrapper(PyObject* type_) + class_wrapper(ref const& type_) : m_class_object(type_) { # ifndef NDEBUG From 41634f9998844058678b169b42e2eedccdb6a9c4 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 21 Jan 2002 06:56:27 +0000 Subject: [PATCH 228/369] Use ref everywhere for reliability [SVN r12394] --- include/boost/python/class.hpp | 2 +- include/boost/python/module.hpp | 8 ++++---- include/boost/python/object/function.hpp | 2 +- src/module.cpp | 11 +++++++---- src/object/function.cpp | 22 +++++++++++----------- 5 files changed, 24 insertions(+), 21 deletions(-) diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index d61a8fc0..76a74df2 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -100,7 +100,7 @@ class class_ : objects::class_base { // Use function::add_to_namespace to achieve overloading if // appropriate. - objects::function::add_to_namespace(this->object(), name, detail::wrap_function(f)); + objects::function::add_to_namespace(this->object(), name, ref(detail::wrap_function(f))); return *this; } diff --git a/include/boost/python/module.hpp b/include/boost/python/module.hpp index 317cc5e4..318f4a64 100644 --- a/include/boost/python/module.hpp +++ b/include/boost/python/module.hpp @@ -25,7 +25,7 @@ class BOOST_PYTHON_DECL module_base // Add elements to the module void add(PyObject* x, const char* name); void add(PyTypeObject* x, const char* name = 0); - void add(ref x, const char*name); + void add(ref const& x, const char*name); // Return true iff a module is currently being built. static bool initializing(); @@ -35,10 +35,10 @@ class BOOST_PYTHON_DECL module_base static string name(); // Return a pointer to the Python module object being built - PyObject* module() const; + ref module() const; private: - PyObject* m_module; + ref m_module; static PyMethodDef initial_methods[1]; }; @@ -65,7 +65,7 @@ class module : public module_base // // inline implementations // -inline PyObject* module_base::module() const +inline ref module_base::module() const { return m_module; } diff --git a/include/boost/python/object/function.hpp b/include/boost/python/object/function.hpp index cc2695d8..c239b6e6 100644 --- a/include/boost/python/object/function.hpp +++ b/include/boost/python/object/function.hpp @@ -27,7 +27,7 @@ struct BOOST_PYTHON_DECL function : PyObject // a function object (this class), and an existing function is // already there, add it as an overload. static void add_to_namespace( - PyObject* name_space, char const* name, PyObject* attribute); + ref const& name_space, char const* name, ref const& attribute); private: // helper functions void argument_error(PyObject* args, PyObject* keywords) const; diff --git a/src/module.cpp b/src/module.cpp index 0851805f..917f8d3a 100644 --- a/src/module.cpp +++ b/src/module.cpp @@ -27,11 +27,14 @@ string module_base::name() } module_base::module_base(const char* name) - : m_module(Py_InitModule(const_cast(name), initial_methods)) + : m_module( + Py_InitModule(const_cast(name), initial_methods) + , ref::increment_count) { // If this fails, you've created more than 1 module object in your module assert(name_holder.get() == 0); - name_holder = ref(PyObject_GetAttrString(m_module, const_cast("__name__"))); + name_holder = ref(PyObject_GetAttrString( + m_module.get() , const_cast("__name__"))); } module_base::~module_base() @@ -44,11 +47,11 @@ void module_base::add(PyObject* x, const char* name) add(ref(x), name); } -void module_base::add(ref x, const char* name) +void module_base::add(ref const& x, const char* name) { // Use function::add_to_namespace to achieve overloading if // appropriate. - objects::function::add_to_namespace(m_module, name, x.get()); + objects::function::add_to_namespace(m_module, name, x); } void module_base::add(PyTypeObject* x, const char* name /*= 0*/) diff --git a/src/object/function.cpp b/src/object/function.cpp index 3755dfb1..7878fa47 100644 --- a/src/object/function.cpp +++ b/src/object/function.cpp @@ -77,21 +77,21 @@ void function::add_overload(function* overload) } void function::add_to_namespace( - PyObject* name_space, char const* name_, PyObject* attribute_) + ref const& name_space, char const* name_, ref const& attribute) { - ref attribute(attribute_, ref::increment_count); - string name(name_); + string const name(name_); + PyObject* const ns = name_space.get(); - if (attribute_->ob_type == &function_type) + if (attribute->ob_type == &function_type) { PyObject* dict = 0; - if (PyClass_Check(name_space)) - dict = ((PyClassObject*)name_space)->cl_dict; - else if (PyType_Check(name_space)) - dict = ((PyTypeObject*)name_space)->tp_dict; + if (PyClass_Check(ns)) + dict = ((PyClassObject*)ns)->cl_dict; + else if (PyType_Check(ns)) + dict = ((PyTypeObject*)ns)->tp_dict; else - dict = PyObject_GetAttrString(name_space, "__dict__"); + dict = PyObject_GetAttrString(ns, "__dict__"); if (dict == 0) throw error_already_set(); @@ -101,14 +101,14 @@ void function::add_to_namespace( if (existing.get() && existing->ob_type == &function_type) { static_cast(existing.get())->add_overload( - static_cast(attribute_)); + static_cast(attribute.get())); return; } } // The PyObject_GetAttrString() call above left an active error PyErr_Clear(); - if (PyObject_SetAttr(name_space, name.get(), attribute_) < 0) + if (PyObject_SetAttr(ns, name.get(), attribute.get()) < 0) throw error_already_set(); } From ed2ebc7d3d506ab8874cf0ba1f479748d1513534 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 21 Jan 2002 21:18:47 +0000 Subject: [PATCH 229/369] added: missing // after #endif [SVN r12405] --- include/boost/python/object/class_wrapper.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/python/object/class_wrapper.hpp b/include/boost/python/object/class_wrapper.hpp index cbfb2ae6..f199a99f 100644 --- a/include/boost/python/object/class_wrapper.hpp +++ b/include/boost/python/object/class_wrapper.hpp @@ -23,7 +23,7 @@ struct class_wrapper { # ifndef NDEBUG assert(type_->ob_type == (PyTypeObject*)class_metatype().get()); -# endif NDEBUG +# endif // NDEBUG } PyObject* convert(T const& x) const From 98a1329dd72525920c3edfc19f06b5ea2db418e3 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 22 Jan 2002 01:43:40 +0000 Subject: [PATCH 230/369] default argument moved to declaration. [SVN r12414] --- include/boost/python/class.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index 76a74df2..abd38d82 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -90,7 +90,7 @@ class class_ : objects::class_base public: // Construct with the module and class name - class_(module&, char const* name); + class_(module&, char const* name = typeid(T).name()); // Wrap a member function or a non-member function which can take // a T, T cv&, or T cv* as its first parameter, or a callable @@ -152,7 +152,7 @@ class class_ : objects::class_base // template inline class_::class_( - module& m, char const* name = typeid(T).name()) + module& m, char const* name) : class_base(m, name, id_vector::size, id_vector().ids) { // Bring the class converters into existence. This static object From 996d83eae0638804dc51158a3ec315507e7aee61 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 22 Jan 2002 02:32:48 +0000 Subject: [PATCH 231/369] fix for EDG [SVN r12415] --- include/boost/python/class.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index abd38d82..25815acc 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -127,6 +127,7 @@ class class_ : objects::class_base // passed to the base class constructor struct id_vector { + typedef objects::class_id class_id; id_vector() { // Stick the derived class id into the first element of the array From 248985e51a080ba328e48b8ce0fa30bba5c27bfe Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 22 Jan 2002 13:12:41 +0000 Subject: [PATCH 232/369] ICL compatibility [SVN r12435] --- src/object/inheritance.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/object/inheritance.cpp b/src/object/inheritance.cpp index 5b95e478..7efc980c 100644 --- a/src/object/inheritance.cpp +++ b/src/object/inheritance.cpp @@ -109,7 +109,7 @@ namespace make_iterator_property_map( to_target , get(vertex_index, reverse_topology) -# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +# ifdef BOOST_MSVC_STD_ITERATOR , *to_target # endif ) From 51a66a32028d68c04d91470305a666120405013c Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 22 Jan 2002 13:52:05 +0000 Subject: [PATCH 233/369] Fixes for gcc-2.95.3 [SVN r12442] --- include/boost/python/class.hpp | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index 25815acc..3b20406e 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -89,8 +89,15 @@ class class_ : objects::class_base typedef class_ self; public: - // Construct with the module and class name - class_(module&, char const* name = typeid(T).name()); + // Construct with the module and automatically derive the class + // name + class_(module&); + + // Construct with the module and class name. [ Would have used a + // default argument but gcc-2.95.2 choked on typeid(T).name() as a + // default parameter value] + class_(module&, char const* name); + // Wrap a member function or a non-member function which can take // a T, T cv&, or T cv* as its first parameter, or a callable @@ -100,7 +107,8 @@ class class_ : objects::class_base { // Use function::add_to_namespace to achieve overloading if // appropriate. - objects::function::add_to_namespace(this->object(), name, ref(detail::wrap_function(f))); + objects::function::add_to_namespace( + this->object(), name, ref(detail::wrap_function(f))); return *this; } @@ -151,6 +159,17 @@ class class_ : objects::class_base // // implementations // +template +inline class_::class_( + module& m) + : class_base(m, typeid(T).name(), id_vector::size, id_vector().ids) +{ + // Bring the class converters into existence. This static object + // will survive until the shared library this module lives in is + // unloaded (that doesn't happen until Python terminates). + static objects::class_converters converters(object()); +} + template inline class_::class_( module& m, char const* name) From 0389aab0a33211c99fac0986930ab0a037fb74e5 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 22 Jan 2002 19:51:04 +0000 Subject: [PATCH 234/369] Nicer syntactic sugar [SVN r12447] --- include/boost/python/class.hpp | 40 +++++++++------- include/boost/python/module.hpp | 67 +++++++++++++++++++++------ include/boost/python/object/class.hpp | 3 +- src/module.cpp | 37 +++++---------- src/object/class.cpp | 8 ++-- 5 files changed, 90 insertions(+), 65 deletions(-) diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index 3b20406e..0f8d2a69 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -6,7 +6,6 @@ #ifndef CLASS_DWA200216_HPP # define CLASS_DWA200216_HPP -# include # include # include # include @@ -84,26 +83,26 @@ template < , class Bases = mpl::type_list<>::type , class HolderGenerator = objects::value_holder_generator > -class class_ : objects::class_base +class class_ : private objects::class_base { typedef class_ self; public: - // Construct with the module and automatically derive the class - // name - class_(module&); + // Automatically derive the class name - only works on some + // compilers because type_info::name is sometimes mangled (gcc) + class_(); - // Construct with the module and class name. [ Would have used a - // default argument but gcc-2.95.2 choked on typeid(T).name() as a - // default parameter value] - class_(module&, char const* name); + // Construct with the class name. [ Would have used a default + // argument but gcc-2.95.2 choked on typeid(T).name() as a default + // parameter value] + class_(char const* name); // Wrap a member function or a non-member function which can take // a T, T cv&, or T cv* as its first parameter, or a callable // python object. template - self& def(F f, char const* name) + self& def(char const* name, F f) { // Use function::add_to_namespace to achieve overloading if // appropriate. @@ -117,7 +116,7 @@ class class_ : objects::class_base template self& def_init(Args const& = Args()) { - def(make_constructor(), "__init__"); + def("__init__", make_constructor()); return *this; } @@ -128,6 +127,9 @@ class class_ : objects::class_base return *this; } + // return the underlying object + ref object() const; + private: // types typedef objects::class_id class_id; @@ -160,9 +162,8 @@ class class_ : objects::class_base // implementations // template -inline class_::class_( - module& m) - : class_base(m, typeid(T).name(), id_vector::size, id_vector().ids) +inline class_::class_() + : class_base(typeid(T).name(), id_vector::size, id_vector().ids) { // Bring the class converters into existence. This static object // will survive until the shared library this module lives in is @@ -171,9 +172,8 @@ inline class_::class_( } template -inline class_::class_( - module& m, char const* name) - : class_base(m, name, id_vector::size, id_vector().ids) +inline class_::class_(char const* name) + : class_base(name, id_vector::size, id_vector().ids) { // Bring the class converters into existence. This static object // will survive until the shared library this module lives in is @@ -181,6 +181,12 @@ inline class_::class_( static objects::class_converters converters(object()); } +template +inline ref class_::object() const +{ + return this->class_base::object(); +} + }} // namespace boost::python #endif // CLASS_DWA200216_HPP diff --git a/include/boost/python/module.hpp b/include/boost/python/module.hpp index 318f4a64..a6a3a8e7 100644 --- a/include/boost/python/module.hpp +++ b/include/boost/python/module.hpp @@ -15,6 +15,8 @@ namespace boost { namespace python { +template class class_; + class BOOST_PYTHON_DECL module_base { public: @@ -23,18 +25,12 @@ class BOOST_PYTHON_DECL module_base ~module_base(); // Add elements to the module - void add(PyObject* x, const char* name); - void add(PyTypeObject* x, const char* name = 0); - void add(ref const& x, const char*name); - - // Return true iff a module is currently being built. - static bool initializing(); + void setattr(const char* name, PyObject*); + void setattr(const char* name, ref const&); + void add(PyTypeObject* x); // just use the type's name + void add_type(ref); - // Return the name of the module currently being built. - // REQUIRES: initializing() == true - static string name(); - - // Return a pointer to the Python module object being built + // Return a reference to the Python module object being built ref module() const; private: @@ -48,17 +44,34 @@ class module : public module_base module(const char* name) : module_base(name) {} + // Add elements to the module + module& setattr(const char* name, PyObject*); + module& setattr(const char* name, PyTypeObject*); + module& setattr(const char* name, ref const&); + module& add(PyTypeObject* x); // just use the type's name + + template + module& add(class_ const& c) + { + std::cout << "adding " << typeid(T).name() << " to module" << std::endl << std::flush; + Py_INCREF(c.object()); + this->add_type(c.object()); + return *this; + } + # if 0 template - void def_raw(Fn fn, const char* name) + void def_raw(char const* name, Fn fn) { add(detail::new_raw_arguments_function(fn), name); } -# endif +# endif + template - void def(Fn fn, const char* name) + module& def(char const* name, Fn fn) { - this->add(boost::python::make_function(fn), name); + this->setattr(name, boost::python::make_function(fn)); + return *this; } }; @@ -70,6 +83,30 @@ inline ref module_base::module() const return m_module; } +inline module& module::setattr(const char* name, PyObject* x) +{ + this->module_base::setattr(name, x); + return *this; +} + +inline module& module::setattr(const char* name, PyTypeObject* x) +{ + this->module_base::setattr(name, (PyObject*)x); + return *this; +} + +inline module& module::setattr(const char* name, ref const& x) +{ + this->module_base::setattr(name, x); + return *this; +} + +inline module& module::add(PyTypeObject* x) +{ + this->module_base::add(x); + return *this; +} + }} // namespace boost::python #endif // MODULE_DWA20011221_HPP diff --git a/include/boost/python/object/class.hpp b/include/boost/python/object/class.hpp index 4817e15d..53d886fa 100644 --- a/include/boost/python/object/class.hpp +++ b/include/boost/python/object/class.hpp @@ -30,8 +30,7 @@ struct BOOST_PYTHON_DECL class_base : noncopyable { // constructor class_base( - module& name_space // Which name space the class will live in - , char const* name // The name of the class + char const* name // The name of the class , std::size_t num_types // A list of class_ids. The first is the type , class_id const*const types // this is wrapping. The rest are the types of diff --git a/src/module.cpp b/src/module.cpp index 917f8d3a..dbc81729 100644 --- a/src/module.cpp +++ b/src/module.cpp @@ -10,53 +10,38 @@ namespace boost { namespace python { -namespace { - ref name_holder; -} - -bool module_base::initializing() -{ - return name_holder.get() != 0; -} - -string module_base::name() -{ - // If this fails, you haven't created a module object - assert(initializing()); - return string(name_holder); -} - module_base::module_base(const char* name) : m_module( Py_InitModule(const_cast(name), initial_methods) , ref::increment_count) { - // If this fails, you've created more than 1 module object in your module - assert(name_holder.get() == 0); - name_holder = ref(PyObject_GetAttrString( - m_module.get() , const_cast("__name__"))); } module_base::~module_base() { - name_holder.reset(); } -void module_base::add(PyObject* x, const char* name) +void module_base::setattr(const char* name, PyObject* x) { - add(ref(x), name); + setattr(name, ref(x)); } -void module_base::add(ref const& x, const char* name) +void module_base::setattr(char const* name, ref const& x) { // Use function::add_to_namespace to achieve overloading if // appropriate. objects::function::add_to_namespace(m_module, name, x); } -void module_base::add(PyTypeObject* x, const char* name /*= 0*/) +void module_base::add(PyTypeObject* x) { - this->add((PyObject*)x, name ? name : x->tp_name); + this->setattr(x->tp_name, (PyObject*)x); +} + +void module_base::add_type(ref x) +{ + assert(PyObject_TypeCheck(x.get(), &PyType_Type)); + add((PyTypeObject*)x.release()); } PyMethodDef module_base::initial_methods[] = { { 0, 0, 0, 0 } }; diff --git a/src/object/class.cpp b/src/object/class.cpp index 5ebabba1..b928ba66 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include @@ -190,11 +189,11 @@ namespace std::vector::const_iterator p = boost::detail::lower_bound(start, finish, id); - + if (p == finish && p->key != id) { string report("extension class wrapper for base class "); - (report += id.name()) += "has not been created yet"; + (report += id.name()) += " has not been created yet"; PyErr_SetObject(PyExc_RuntimeError, report.get()); throw error_already_set(); } @@ -212,7 +211,7 @@ namespace } class_base::class_base( - module& m, char const* name, std::size_t num_types, class_id const* const types) + char const* name, std::size_t num_types, class_id const* const types) { class_registry& r = registry(); assert(num_types >= 1); @@ -234,7 +233,6 @@ class_base::class_base( m_object = ref(PyObject_CallObject(class_metatype().get(), args.get())); r.set(types[0], m_object); - m.add(m_object, name); } }}} // namespace boost::python::objects From f2785302392eaf4e1b26c5fed8e3d52f9d48e052 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 22 Jan 2002 19:56:36 +0000 Subject: [PATCH 235/369] Nicer syntactic sugar [SVN r12448] --- test/m1.cpp | 93 +++++++++++++++++++++++++++++------------------------ test/m2.cpp | 28 ++++++++-------- 2 files changed, 65 insertions(+), 56 deletions(-) diff --git a/test/m1.cpp b/test/m1.cpp index da3ca5d5..7f88af2b 100644 --- a/test/m1.cpp +++ b/test/m1.cpp @@ -269,7 +269,6 @@ BOOST_PYTHON_MODULE_INIT(m1) using boost::python::module; using boost::python::class_; - module m1("m1"); // Create the converters; they are self-registering/unregistering. static int_wrapper wrap_int; static simple_wrapper wrap_simple; @@ -280,56 +279,66 @@ BOOST_PYTHON_MODULE_INIT(m1) static simple_const_ref_unwrapper unwrap_simple_const_ref; static simple_ref_wrapper wrap_simple_ref; - // This unwrapper extracts pointers and references to the "complicated" class. - // static boost::python::converter::class_unwrapper unwrap_complicated; + module m1("m1"); + + m1 + // Insert the metaclass for all extension classes + .setattr("xclass", boost::python::objects::class_metatype()) - // Insert the extension metaclass object - m1.add( - boost::python::objects::class_metatype() - , "xclass"); - - // Insert the base class for all extension classes - m1.add(boost::python::objects::class_type() - , "xinst"); + // Insert the base class for all extension classes + .setattr("xinst", boost::python::objects::class_type()) - m1.def(new_noddy, "new_noddy"); - m1.def(new_simple, "new_simple"); - - // Expose f() - m1.def(f, "f"); + .def("new_noddy", new_noddy) + .def("new_simple", new_simple) - // Expose g() - m1.def(g, "g"); + // Expose f() + .def("f", f) - m1.def(take_a, "take_a"); - m1.def(take_b, "take_b"); - m1.def(take_c, "take_c"); - m1.def(take_d, "take_d"); + // Expose g() + .def("g", g) - class_(m1, "A") - .def_init() - .def(&A::name, "name") - ; - - class_ >(m1, "B") - .def_init() - .def(&B::name, "name") - ; - - class_ >(m1, "C") - .def_init() - .def(&C::name, "name") + .def("take_a", take_a) + .def("take_b", take_b) + .def("take_c", take_c) + .def("take_d", take_d) + + .add( + class_("A") + .def_init() + .def("name", &A::name) + ) + ; - class_ >(m1, "D") - .def_init() - .def(&D::name, "name") + // sequence points don't ensure that "A" is constructed before "B" + // or "C" below if we make them part of the same chain + m1 + .add( + class_ >("B") + .def_init() + .def("name", &B::name) + ) + + .add( + class_ >("C") + .def_init() + .def("name", &C::name) + ) ; - class_(m1, "complicated") - .def_init(args()) - .def_init(args()) - .def(&complicated::get_n, "get_n") + m1 + .add( + class_ >("D") + .def_init() + .def("name", &D::name) + ) + + .add( + class_("complicated") + .def_init(args()) + .def_init(args()) + .def("get_n", &complicated::get_n) + ) ; } diff --git a/test/m2.cpp b/test/m2.cpp index 7ea1f9ac..d70b0c13 100644 --- a/test/m2.cpp +++ b/test/m2.cpp @@ -66,21 +66,21 @@ struct rewrap BOOST_PYTHON_MODULE_INIT(m2) { - boost::python::module m2("m2"); - - m2.def(unwrap_int, "unwrap_int"); - m2.def(unwrap_int_ref, "unwrap_int_ref"); - m2.def(unwrap_int_const_ref, "unwrap_int_const_ref"); - m2.def(unwrap_simple, "unwrap_simple"); - m2.def(unwrap_simple_ref, "unwrap_simple_ref"); - m2.def(unwrap_simple_const_ref, "unwrap_simple_const_ref"); + boost::python::module("m2") + .def("unwrap_int", unwrap_int) + .def("unwrap_int_ref", unwrap_int_ref) + .def("unwrap_int_const_ref", unwrap_int_const_ref) + .def("unwrap_simple", unwrap_simple) + .def("unwrap_simple_ref", unwrap_simple_ref) + .def("unwrap_simple_const_ref", unwrap_simple_const_ref) - m2.def(&rewrap::f, "wrap_int"); - m2.def(&rewrap::f, "wrap_int_ref"); - m2.def(&rewrap::f, "wrap_int_const_ref"); - m2.def(&rewrap::f, "wrap_simple"); - m2.def(&rewrap::f, "wrap_simple_ref"); - m2.def(&rewrap::f, "wrap_simple_const_ref"); + .def("wrap_int", &rewrap::f) + .def("wrap_int_ref", &rewrap::f) + .def("wrap_int_const_ref", &rewrap::f) + .def("wrap_simple", &rewrap::f) + .def("wrap_simple_ref", &rewrap::f) + .def("wrap_simple_const_ref", &rewrap::f) + ; } #include "module_tail.cpp" From f40a534bfb1b6aabc21b4f5075c49d31a2529c48 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 22 Jan 2002 21:55:08 +0000 Subject: [PATCH 236/369] cleanup [SVN r12449] --- include/boost/python/module.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/boost/python/module.hpp b/include/boost/python/module.hpp index a6a3a8e7..5661e106 100644 --- a/include/boost/python/module.hpp +++ b/include/boost/python/module.hpp @@ -53,7 +53,6 @@ class module : public module_base template module& add(class_ const& c) { - std::cout << "adding " << typeid(T).name() << " to module" << std::endl << std::flush; Py_INCREF(c.object()); this->add_type(c.object()); return *this; From 088b1cab833fea1852fc72ed688d14708ef84df5 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 23 Jan 2002 06:08:46 +0000 Subject: [PATCH 237/369] workarounds for KCC's reservation of 'overload' as a keyword [SVN r12451] --- include/boost/python/object/function.hpp | 2 +- src/object/function.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/python/object/function.hpp b/include/boost/python/object/function.hpp index c239b6e6..2a05a946 100644 --- a/include/boost/python/object/function.hpp +++ b/include/boost/python/object/function.hpp @@ -31,7 +31,7 @@ struct BOOST_PYTHON_DECL function : PyObject private: // helper functions void argument_error(PyObject* args, PyObject* keywords) const; - void add_overload(function* overload); + void add_overload(function*); private: // data members py_function m_fn; diff --git a/src/object/function.cpp b/src/object/function.cpp index 7878fa47..a30e9f15 100644 --- a/src/object/function.cpp +++ b/src/object/function.cpp @@ -63,9 +63,9 @@ void function::argument_error(PyObject* args, PyObject* keywords) const PyErr_BadArgument(); } -void function::add_overload(function* overload) +void function::add_overload(function* overload_) { - Py_XINCREF(overload); + Py_XINCREF(overload_); function* parent = this; @@ -73,7 +73,7 @@ void function::add_overload(function* overload) { parent = parent->m_overloads; } - parent->m_overloads = overload; + parent->m_overloads = overload_; } void function::add_to_namespace( From 71032f6c4c0887834d4657b3405729b149810911 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 30 Jan 2002 20:18:39 +0000 Subject: [PATCH 238/369] New conversion mechanism, builtin converters [SVN r12590] --- Jamfile | 65 +- include/boost/python/converter/class.hpp | 89 +- .../boost/python/converter/registration.hpp | 94 +- include/boost/python/converter/registry.hpp | 43 +- include/boost/python/converter/source.hpp | 10 +- include/boost/python/converter/unwrap.hpp | 6 +- include/boost/python/converter/unwrapper.hpp | 3 +- include/boost/python/converter/wrap.hpp | 1 + include/boost/python/converter/wrapper.hpp | 1 + .../boost/python/detail/arg_tuple_size.hpp | 12 +- include/boost/python/detail/char_array.hpp | 23 + include/boost/python/detail/eval.hpp | 38 + include/boost/python/detail/returning.hpp | 876 ++++++++++-------- include/boost/python/detail/signature.hpp | 217 +++++ include/boost/python/make_function.hpp | 7 + .../boost/python/object/class_converters.hpp | 2 +- include/boost/python/object/class_wrapper.hpp | 19 +- include/boost/python/object/make_holder.hpp | 36 +- include/boost/python/object/value_holder.hpp | 93 +- include/boost/python/objects.hpp | 4 +- src/converter/registry.cpp | 111 ++- src/gen_arg_tuple_size.py | 12 +- src/gen_signature.py | 90 ++ src/gen_value_holder.py | 35 + src/object/class.cpp | 2 +- test/m1.cpp | 180 ++-- test/m2.cpp | 4 - 27 files changed, 1352 insertions(+), 721 deletions(-) create mode 100644 include/boost/python/detail/char_array.hpp create mode 100644 include/boost/python/detail/eval.hpp create mode 100644 include/boost/python/detail/signature.hpp create mode 100644 src/gen_signature.py create mode 100644 src/gen_value_holder.py diff --git a/Jamfile b/Jamfile index 71e0c5b7..684c21d5 100644 --- a/Jamfile +++ b/Jamfile @@ -8,36 +8,47 @@ PYTHON_PROPERTIES += <*>"-inline deferred" <*>$(BOOST_ROOT)/boost/compatibility/cpp_c_headers BOOST_PYTHON_DYNAMIC_LIB - BOOST_PYTHON_V2 - ; + BOOST_PYTHON_V2 + ; +{ + dll bpl + : + src/converter/from_python.cpp + src/converter/to_python.cpp + src/converter/registry.cpp + src/converter/type_id.cpp + src/object/class.cpp + src/object/function.cpp + src/object/inheritance.cpp + src/errors.cpp + src/module.cpp + src/objects.cpp + src/converter/builtin_converters.cpp + : + $(PYTHON_PROPERTIES) + BOOST_PYTHON_SOURCE + ; -dll bpl - : - src/converter/body.cpp - src/converter/handle.cpp - src/converter/registry.cpp - src/converter/wrapper.cpp - src/converter/unwrap.cpp - src/converter/unwrapper.cpp - src/converter/type_id.cpp - src/object/class.cpp - src/object/function.cpp - src/object/inheritance.cpp - src/errors.cpp - src/module.cpp - src/objects.cpp - : - $(PYTHON_PROPERTIES) - BOOST_PYTHON_SOURCE - ; + extension m1 : test/m1.cpp bpl # BOOST_PYTHON_TRACE + : + : debug-python + ; -extension m1 : test/m1.cpp bpl # BOOST_PYTHON_TRACE - : - : debug-python ; - -extension m2 : test/m2.cpp bpl # BOOST_PYTHON_TRACE + extension m2 : test/m2.cpp bpl # BOOST_PYTHON_TRACE : : debug-python ; -boost-python-runtest try : test/newtest.py m1 m2 : : debug-python ; \ No newline at end of file + boost-python-runtest try : test/newtest.py m1 m2 : : debug-python ; + + extension builtin_converters_ext : test/test_builtin_converters.cpp bpl + : + : debug-python + ; + + boost-python-runtest test_builtin_converters : test/test_builtin_converters.py + builtin_converters_ext + : + : debug-python + ; +} diff --git a/include/boost/python/converter/class.hpp b/include/boost/python/converter/class.hpp index f437a73a..67de6fad 100644 --- a/include/boost/python/converter/class.hpp +++ b/include/boost/python/converter/class.hpp @@ -7,62 +7,69 @@ # define CLASS_DWA20011215_HPP # include -# include +# include namespace boost { namespace python { namespace converter { template -struct class_unwrapper - : private unwrapper - , private unwrapper - , private unwrapper - , private unwrapper +struct class_from_python_converter { - protected: -# ifdef __GNUC__ // suppress warning that "all member functions are private" (duh) - void uncallable(); -# endif - private: - void* can_convert(PyObject*) const; - T& convert(PyObject*, void*, boost::type) const; - T const& convert(PyObject*, void*, boost::type) const; - T* convert(PyObject*, void*, boost::type) const; - T const* convert(PyObject*, void*, boost::type) const; + class_from_python_converter(); + + static void* convertible(PyObject*); + static T& convert_ref(PyObject*, from_python_data&); + static T const& convert_cref(PyObject*, from_python_data&); + static T* convert_ptr(PyObject*, from_python_data&); + static T const* convert_cptr(PyObject*, from_python_data&); + + from_python_converter to_ref; + from_python_converter to_cref; + from_python_converter to_ptr; + from_python_converter to_cptr; }; // // implementations // template -void* class_unwrapper::can_convert(PyObject* p) const +class_from_python_converter::class_from_python_converter() + : to_ref(convertible, convert_ref) + , to_cref(convertible, convert_cref) + , to_ptr(convertible, convert_ptr) + , to_cptr(convertible, convert_cptr) +{} + +template +T& class_from_python_converter::convert_ref(PyObject*, from_python_data& x) +{ + return *static_cast(x.stage1); +} + +template +T const& class_from_python_converter::convert_cref(PyObject*, from_python_data& x) +{ + return *static_cast(x.stage1); +} + + +template +T* class_from_python_converter::convert_ptr(PyObject*, from_python_data& x) +{ + return static_cast(x.stage1); +} + +template +T const* class_from_python_converter::convert_cptr(PyObject*, from_python_data& x) +{ + return static_cast(x.stage1); +} + +template +void* class_from_python_converter::convertible(PyObject* p) { return objects::find_instance(p); } -template -T& class_unwrapper::convert(PyObject*, void* found, boost::type) const -{ - return *static_cast(found); -} - -template -T const& class_unwrapper::convert(PyObject*, void* found, boost::type) const -{ - return *static_cast(found); -} - -template -T* class_unwrapper::convert(PyObject*, void* found, boost::type) const -{ - return static_cast(found); -} - -template -T const* class_unwrapper::convert(PyObject*, void* found, boost::type) const -{ - return static_cast(found); -} - }}} // namespace boost::python::converter #endif // CLASS_DWA20011215_HPP diff --git a/include/boost/python/converter/registration.hpp b/include/boost/python/converter/registration.hpp index b8a6326b..39223d8a 100644 --- a/include/boost/python/converter/registration.hpp +++ b/include/boost/python/converter/registration.hpp @@ -9,6 +9,9 @@ # include # include # include +# include +# include +# include # include # ifdef BOOST_PYTHON_TRACE # include @@ -16,8 +19,9 @@ namespace boost { namespace python { namespace converter { -struct BOOST_PYTHON_DECL wrapper_base; -struct BOOST_PYTHON_DECL unwrapper_base; +template struct from_python_converter; +template struct target; +template struct source; // This class is really sort of a "templated namespace". It manages a // static data member which refers to the registry entry for T. This @@ -28,21 +32,74 @@ struct registration { public: // member functions // Return a converter which can convert the given Python object to - // T, or 0 if no such converter exists - static std::pair unwrapper(PyObject*); + // T, or 0 if no such converter exists. Fill in data with + // the result of the converter's check function + static from_python_converter const* get_from_python(PyObject*, void*& data); // Return a converter which can convert T to a Python object, or 0 // if no such converter exists - static wrapper_base* wrapper(); + static to_python_function::type get_to_python(); + static registry::entry* find_entry(); private: // helper functions static registry::entry* entry(); - static registry::entry* find_entry(); + static registry::entry* known_entry(); private: // data members static registry::entry* m_registry_entry; }; +namespace detail +{ + // An MPL BinaryMetaFunction class which initializes the + // registration entry for the target type of its 2nd argument. + struct setup_target_registration + { + template struct apply + { + typedef T type; + static void execute() + { + typedef typename target::type target_t; + registration::find_entry(); + } + }; + }; + + template + struct find_return_value_entry + { + static void execute() { registration::find_entry(); } + }; + + template <> + struct find_return_value_entry + { + static void execute() {} + }; + +# if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 + template <> + struct find_return_value_entry + { + static void execute() {} + }; +# endif +} + +template +void acquire_registrations(Sequence signature) +{ + typedef typename mpl::pop_front::sequence args; + typedef typename mpl::front::type return_type; + + mpl::for_each::execute(); + + typedef typename source::type return_source_type; + detail::find_return_value_entry::execute(); +} + + // because this is static POD data it will be initialized to zero template registry::entry* registration::m_registry_entry; @@ -50,33 +107,40 @@ registry::entry* registration::m_registry_entry; template registry::entry* registration::find_entry() { - return registry::find(type_id()); + return m_registry_entry = registry::find(type_id()); } template inline registry::entry* registration::entry() { if (!m_registry_entry) - m_registry_entry = find_entry(); + find_entry(); return m_registry_entry; } template -std::pair registration::unwrapper(PyObject* p) +inline registry::entry* registration::known_entry() { -# ifdef BOOST_PYTHON_TRACE - std::cout << "retrieving unwrapper for " << type_id() << std::endl; -# endif - return entry()->unwrapper(p); + assert(m_registry_entry != 0); + return m_registry_entry; } template -wrapper_base* registration::wrapper() +from_python_converter const* registration::get_from_python(PyObject* p, void*& data) +{ + return static_cast const*>( + known_entry()->get_from_python(p, data) + ); +} + +template +typename to_python_function::type registration::get_to_python() { # ifdef BOOST_PYTHON_TRACE std::cout << "retrieving wrapper for " << type_id() << std::endl; # endif - return entry()->wrapper(); + return reinterpret_cast::type>( + known_entry()->get_to_python()); } }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/registry.hpp b/include/boost/python/converter/registry.hpp index 2023a732..21f31692 100644 --- a/include/boost/python/converter/registry.hpp +++ b/include/boost/python/converter/registry.hpp @@ -8,14 +8,15 @@ # include # include # include -# include +# include +# include # include # include namespace boost { namespace python { namespace converter { -struct BOOST_PYTHON_DECL wrapper_base; -struct BOOST_PYTHON_DECL unwrapper_base; +struct BOOST_PYTHON_DECL from_python_converter_base; +struct BOOST_PYTHON_DECL to_python_converter_base; // This namespace acts as a sort of singleton namespace registry @@ -31,43 +32,45 @@ namespace registry // Python object from_python to the C++ type with which this // converter is associated in the registry, or 0 if no such // converter exists. - std::pair unwrapper(PyObject*) const; + from_python_converter_base const* get_from_python(PyObject*, void*& data) const; - // Return a converter appropriate for converting a C++ object - // whose type this entry is associated with in the registry to a - // Python object, or 0 if no such converter exists. - wrapper_base* wrapper() const; + // Return a conversion function appropriate for converting a C++ + // object whose type this entry is associated with in the + // registry to a Python object, or 0 if no such converter + // exists. This function must be reinterpret_cast to the + // appropriate to_python_function type. + to_python_function_base get_to_python() const; // Conversion classes use these functions to register // themselves. - void insert(wrapper_base&); - void remove(wrapper_base&); + void insert(from_python_converter_base&); + void remove(from_python_converter_base&); - void insert(unwrapper_base&); - void remove(unwrapper_base&); + void insert(to_python_converter_base&); + void remove(to_python_converter_base&); private: // types - typedef std::list unwrappers; + typedef std::vector from_python_converters; private: // helper functions - unwrappers::iterator find(unwrapper_base const&); + from_python_converters::iterator find(from_python_converter_base const&); private: // data members // The collection of from_python converters for the associated // C++ type. - unwrappers m_unwrappers; + from_python_converters m_from_python_converters; // The unique to_python converter for the associated C++ type. - converter::wrapper_base* m_wrapper; + to_python_converter_base* m_to_python_converter; }; BOOST_PYTHON_DECL entry* find(type_id_t); - BOOST_PYTHON_DECL void insert(wrapper_base& x); - BOOST_PYTHON_DECL void insert(unwrapper_base& x); - BOOST_PYTHON_DECL void remove(wrapper_base& x); - BOOST_PYTHON_DECL void remove(unwrapper_base& x); + BOOST_PYTHON_DECL void insert(to_python_converter_base& x); + BOOST_PYTHON_DECL void insert(from_python_converter_base& x); + BOOST_PYTHON_DECL void remove(to_python_converter_base& x); + BOOST_PYTHON_DECL void remove(from_python_converter_base& x); } }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/source.hpp b/include/boost/python/converter/source.hpp index 94fdc5b8..9abf245f 100644 --- a/include/boost/python/converter/source.hpp +++ b/include/boost/python/converter/source.hpp @@ -20,15 +20,11 @@ namespace boost { namespace python { namespace converter { template struct source { - BOOST_STATIC_CONSTANT(bool, use_identity = (::boost::is_pointer::value)); - - typedef typename mpl::select_type< - use_identity - , T - , typename add_reference< + typedef + typename add_reference< typename add_const::type >::type - >::type type; + type; }; }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/unwrap.hpp b/include/boost/python/converter/unwrap.hpp index 3380d49d..eccb0992 100644 --- a/include/boost/python/converter/unwrap.hpp +++ b/include/boost/python/converter/unwrap.hpp @@ -1,3 +1,4 @@ +#error obsolete // 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 @@ -27,9 +28,10 @@ struct BOOST_PYTHON_DECL unwrap_base : handle inline unwrap_base(PyObject* source, std::pair); inline PyObject* source() const; + inline void*& data(); + protected: inline PyObject*& source(); - inline void* data() const; private: // data members PyObject* m_source; @@ -117,7 +119,7 @@ inline unwrap_base::unwrap_base(PyObject* source, std::pair) const = 0; + virtual T convert(PyObject*, void*& data, boost::type) const = 0; }; // diff --git a/include/boost/python/converter/wrap.hpp b/include/boost/python/converter/wrap.hpp index eb23c6d3..b61fff19 100644 --- a/include/boost/python/converter/wrap.hpp +++ b/include/boost/python/converter/wrap.hpp @@ -1,3 +1,4 @@ +#error obsolete // 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 diff --git a/include/boost/python/converter/wrapper.hpp b/include/boost/python/converter/wrapper.hpp index 5d4874d2..e20ed404 100644 --- a/include/boost/python/converter/wrapper.hpp +++ b/include/boost/python/converter/wrapper.hpp @@ -1,3 +1,4 @@ +#error obsolete // 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 diff --git a/include/boost/python/detail/arg_tuple_size.hpp b/include/boost/python/detail/arg_tuple_size.hpp index a330a939..04bca0af 100644 --- a/include/boost/python/detail/arg_tuple_size.hpp +++ b/include/boost/python/detail/arg_tuple_size.hpp @@ -11,6 +11,8 @@ #ifndef ARG_TUPLE_SIZE_DWA20011201_HPP # define ARG_TUPLE_SIZE_DWA20011201_HPP +# include + namespace boost { namespace python { namespace detail { // Computes (at compile-time) the number of elements that a Python @@ -223,16 +225,6 @@ struct arg_tuple_size // 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 -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 diff --git a/include/boost/python/detail/char_array.hpp b/include/boost/python/detail/char_array.hpp new file mode 100644 index 00000000..d68aea47 --- /dev/null +++ b/include/boost/python/detail/char_array.hpp @@ -0,0 +1,23 @@ +// Copyright David Abrahams 2002. 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 CHAR_ARRAY_DWA2002129_HPP +# define CHAR_ARRAY_DWA2002129_HPP + +namespace boost { namespace python { namespace detail { + +// 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 +struct char_array +{ + char elements[n+1]; +}; + +}}} // namespace boost::python::detail + +#endif // CHAR_ARRAY_DWA2002129_HPP diff --git a/include/boost/python/detail/eval.hpp b/include/boost/python/detail/eval.hpp new file mode 100644 index 00000000..3e799507 --- /dev/null +++ b/include/boost/python/detail/eval.hpp @@ -0,0 +1,38 @@ +// Copyright David Abrahams 2002. 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 EVAL_DWA2002124_HPP +# define EVAL_DWA2002124_HPP + +namespace boost { namespace python { namespace detail { + +template struct undefined; +template +struct eval +{ +# if defined(BOOST_MSVC) && BOOST_MSVC <= 1200 + // based on the (non-conforming) MSVC trick from MPL + template + struct unarymetafunction_vc : UnaryMetaFunction {}; + + // illegal C++ which causes VC to admit that unarymetafunction_vc + // can have a nested template: + template<> + struct unarymetafunction_vc + { + template struct apply; + }; + + typedef typename unarymetafunction_vc< + ::boost::mpl::detail::msvc_never_true::value + >::template apply::type type; +# else + typedef typename UnaryMetaFunction::template apply::type type; +# endif +}; + +}}} // namespace boost::python::detail + +#endif // EVAL_DWA2002124_HPP diff --git a/include/boost/python/detail/returning.hpp b/include/boost/python/detail/returning.hpp index 87aecac5..4aa228b5 100644 --- a/include/boost/python/detail/returning.hpp +++ b/include/boost/python/detail/returning.hpp @@ -14,8 +14,9 @@ //# include # include # include -# include # include +# include +# include namespace boost { namespace python { namespace detail { @@ -27,246 +28,291 @@ struct returning static PyObject* call(R (A0::*pmf)(), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; // find the result converter - wrap_more r(c0); - if (!c0) return 0; - return r( ((*c0).*pmf)() ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)() ); } template static PyObject* call(R (A0::*pmf)(A1), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; // find the result converter - wrap_more r(c1); - if (!c0) return 0; - return r( ((*c0).*pmf)(*c1) ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))) ); } template static PyObject* call(R (A0::*pmf)(A1, A2), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; // find the result converter - wrap_more r(c2); - if (!c0) return 0; - return r( ((*c0).*pmf)(*c1, *c2) ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))) ); } template static PyObject* call(R (A0::*pmf)(A1, A2, A3), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; // find the result converter - wrap_more r(c3); - if (!c0) return 0; - return r( ((*c0).*pmf)(*c1, *c2, *c3) ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))) ); } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); - unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; + from_python c4(PyTuple_GET_ITEM(args, 4)); + if (!c4.convertible()) return 0; // find the result converter - wrap_more r(c4); - if (!c0) return 0; - return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))) ); } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); - unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); - unwrap_more c5(PyTuple_GET_ITEM(args, 5), c4); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; + from_python c4(PyTuple_GET_ITEM(args, 4)); + if (!c4.convertible()) return 0; + from_python c5(PyTuple_GET_ITEM(args, 5)); + if (!c5.convertible()) return 0; // find the result converter - wrap_more r(c5); - if (!c0) return 0; - return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5) ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))) ); } template static PyObject* call(R (A0::*pmf)() const, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; // find the result converter - wrap_more r(c0); - if (!c0) return 0; - return r( ((*c0).*pmf)() ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)() ); } template static PyObject* call(R (A0::*pmf)(A1) const, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; // find the result converter - wrap_more r(c1); - if (!c0) return 0; - return r( ((*c0).*pmf)(*c1) ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))) ); } template static PyObject* call(R (A0::*pmf)(A1, A2) const, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; // find the result converter - wrap_more r(c2); - if (!c0) return 0; - return r( ((*c0).*pmf)(*c1, *c2) ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))) ); } template static PyObject* call(R (A0::*pmf)(A1, A2, A3) const, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; // find the result converter - wrap_more r(c3); - if (!c0) return 0; - return r( ((*c0).*pmf)(*c1, *c2, *c3) ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))) ); } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); - unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; + from_python c4(PyTuple_GET_ITEM(args, 4)); + if (!c4.convertible()) return 0; // find the result converter - wrap_more r(c4); - if (!c0) return 0; - return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))) ); } template 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 c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); - unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); - unwrap_more c5(PyTuple_GET_ITEM(args, 5), c4); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; + from_python c4(PyTuple_GET_ITEM(args, 4)); + if (!c4.convertible()) return 0; + from_python c5(PyTuple_GET_ITEM(args, 5)); + if (!c5.convertible()) return 0; // find the result converter - wrap_more r(c5); - if (!c0) return 0; - return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5) ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))) ); } template static PyObject* call(R (A0::*pmf)() volatile, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; // find the result converter - wrap_more r(c0); - if (!c0) return 0; - return r( ((*c0).*pmf)() ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)() ); } template static PyObject* call(R (A0::*pmf)(A1) volatile, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; // find the result converter - wrap_more r(c1); - if (!c0) return 0; - return r( ((*c0).*pmf)(*c1) ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))) ); } template static PyObject* call(R (A0::*pmf)(A1, A2) volatile, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; // find the result converter - wrap_more r(c2); - if (!c0) return 0; - return r( ((*c0).*pmf)(*c1, *c2) ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))) ); } template static PyObject* call(R (A0::*pmf)(A1, A2, A3) volatile, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; // find the result converter - wrap_more r(c3); - if (!c0) return 0; - return r( ((*c0).*pmf)(*c1, *c2, *c3) ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))) ); } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) volatile, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); - unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; + from_python c4(PyTuple_GET_ITEM(args, 4)); + if (!c4.convertible()) return 0; // find the result converter - wrap_more r(c4); - if (!c0) return 0; - return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))) ); } template 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 c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); - unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); - unwrap_more c5(PyTuple_GET_ITEM(args, 5), c4); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; + from_python c4(PyTuple_GET_ITEM(args, 4)); + if (!c4.convertible()) return 0; + from_python c5(PyTuple_GET_ITEM(args, 5)); + if (!c5.convertible()) return 0; // find the result converter - wrap_more r(c5); - if (!c0) return 0; - return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5) ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))) ); } @@ -276,82 +322,97 @@ struct returning static PyObject* call(R (A0::*pmf)() const volatile, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; // find the result converter - wrap_more r(c0); - if (!c0) return 0; - return r( ((*c0).*pmf)() ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)() ); } template static PyObject* call(R (A0::*pmf)(A1) const volatile, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; // find the result converter - wrap_more r(c1); - if (!c0) return 0; - return r( ((*c0).*pmf)(*c1) ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))) ); } template static PyObject* call(R (A0::*pmf)(A1, A2) const volatile, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; // find the result converter - wrap_more r(c2); - if (!c0) return 0; - return r( ((*c0).*pmf)(*c1, *c2) ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))) ); } template static PyObject* call(R (A0::*pmf)(A1, A2, A3) const volatile, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; // find the result converter - wrap_more r(c3); - if (!c0) return 0; - return r( ((*c0).*pmf)(*c1, *c2, *c3) ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))) ); } template 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 c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); - unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; + from_python c4(PyTuple_GET_ITEM(args, 4)); + if (!c4.convertible()) return 0; // find the result converter - wrap_more r(c4); - if (!c0) return 0; - return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))) ); } template 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 c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); - unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); - unwrap_more c5(PyTuple_GET_ITEM(args, 5), c4); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; + from_python c4(PyTuple_GET_ITEM(args, 4)); + if (!c4.convertible()) return 0; + from_python c5(PyTuple_GET_ITEM(args, 5)); + if (!c5.convertible()) return 0; // find the result converter - wrap_more r(c5); - if (!c0) return 0; - return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5) ); + to_python r; + return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))) ); } # endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION @@ -359,90 +420,104 @@ struct returning static PyObject* call(R (*pf)(), PyObject*, PyObject* /* keywords */ ) { // find the result converter - wrap c0; - if (!c0) return 0; + to_python c0; return c0( (*pf)() ); } template static PyObject* call(R (*pf)(A0), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; // find the result converter - wrap_more c1(c0); - if (!c0) return 0; - return c1( (*pf)(*c0) ); + to_python c1; + return c1( (*pf)(c0(PyTuple_GET_ITEM(args, 0))) ); } template static PyObject* call(R (*pf)(A0, A1), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; // find the result converter - wrap_more c2(c1); - if (!c0) return 0; - return c2( (*pf)(*c0, *c1) ); + to_python c2; + return c2( (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1))) ); } template static PyObject* call(R (*pf)(A0, A1, A2), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; // find the result converter - wrap_more c3(c2); - if (!c0) return 0; - return c3( (*pf)(*c0, *c1, *c2) ); + to_python c3; + return c3( (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))) ); } template static PyObject* call(R (*pf)(A0, A1, A2, A3), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; // find the result converter - wrap_more c4(c3); - if (!c0) return 0; - return c4( (*pf)(*c0, *c1, *c2, *c3) ); + to_python c4; + return c4( (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))) ); } template static PyObject* call(R (*pf)(A0, A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); - unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; + from_python c4(PyTuple_GET_ITEM(args, 4)); + if (!c4.convertible()) return 0; // find the result converter - wrap_more c5(c4); - if (!c0) return 0; - return c5( (*pf)(*c0, *c1, *c2, *c3, *c4) ); + to_python c5; + return c5( (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))) ); } template static PyObject* call(R (*pf)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); - unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); - unwrap_more c5(PyTuple_GET_ITEM(args, 5), c4); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; + from_python c4(PyTuple_GET_ITEM(args, 4)); + if (!c4.convertible()) return 0; + from_python c5(PyTuple_GET_ITEM(args, 5)); + if (!c5.convertible()) return 0; // find the result converter - wrap_more c6(c5); - if (!c0) return 0; - return c6( (*pf)(*c0, *c1, *c2, *c3, *c4, *c5) ); + to_python c6; + return c6( (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))) ); } }; @@ -454,75 +529,90 @@ struct returning static PyObject* call(R (A0::*pmf)(), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(); return detail::none(); } template static PyObject* call(R (A0::*pmf)(A1), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(*c1); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))); return detail::none(); } template static PyObject* call(R (A0::*pmf)(A1, A2), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(*c1, *c2); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))); return detail::none(); } template static PyObject* call(R (A0::*pmf)(A1, A2, A3), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(*c1, *c2, *c3); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))); return detail::none(); } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); - unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; + from_python c4(PyTuple_GET_ITEM(args, 4)); + if (!c4.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(*c1, *c2, *c3, *c4); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))); return detail::none(); } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); - unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); - unwrap_more c5(PyTuple_GET_ITEM(args, 5), c4); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; + from_python c4(PyTuple_GET_ITEM(args, 4)); + if (!c4.convertible()) return 0; + from_python c5(PyTuple_GET_ITEM(args, 5)); + if (!c5.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))); return detail::none(); } @@ -530,75 +620,90 @@ struct returning static PyObject* call(R (A0::*pmf)() const, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(); return detail::none(); } template static PyObject* call(R (A0::*pmf)(A1) const, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(*c1); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))); return detail::none(); } template static PyObject* call(R (A0::*pmf)(A1, A2) const, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(*c1, *c2); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))); return detail::none(); } template static PyObject* call(R (A0::*pmf)(A1, A2, A3) const, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(*c1, *c2, *c3); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))); return detail::none(); } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); - unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; + from_python c4(PyTuple_GET_ITEM(args, 4)); + if (!c4.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(*c1, *c2, *c3, *c4); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))); return detail::none(); } template 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 c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); - unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); - unwrap_more c5(PyTuple_GET_ITEM(args, 5), c4); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; + from_python c4(PyTuple_GET_ITEM(args, 4)); + if (!c4.convertible()) return 0; + from_python c5(PyTuple_GET_ITEM(args, 5)); + if (!c5.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))); return detail::none(); } @@ -606,75 +711,90 @@ struct returning static PyObject* call(R (A0::*pmf)() volatile, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(); return detail::none(); } template static PyObject* call(R (A0::*pmf)(A1) volatile, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(*c1); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))); return detail::none(); } template static PyObject* call(R (A0::*pmf)(A1, A2) volatile, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(*c1, *c2); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))); return detail::none(); } template static PyObject* call(R (A0::*pmf)(A1, A2, A3) volatile, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(*c1, *c2, *c3); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))); return detail::none(); } template static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) volatile, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); - unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; + from_python c4(PyTuple_GET_ITEM(args, 4)); + if (!c4.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(*c1, *c2, *c3, *c4); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))); return detail::none(); } template 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 c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); - unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); - unwrap_more c5(PyTuple_GET_ITEM(args, 5), c4); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; + from_python c4(PyTuple_GET_ITEM(args, 4)); + if (!c4.convertible()) return 0; + from_python c5(PyTuple_GET_ITEM(args, 5)); + if (!c5.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))); return detail::none(); } @@ -685,75 +805,90 @@ struct returning static PyObject* call(R (A0::*pmf)() const volatile, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(); return detail::none(); } template static PyObject* call(R (A0::*pmf)(A1) const volatile, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(*c1); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))); return detail::none(); } template static PyObject* call(R (A0::*pmf)(A1, A2) const volatile, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(*c1, *c2); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))); return detail::none(); } template static PyObject* call(R (A0::*pmf)(A1, A2, A3) const volatile, PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(*c1, *c2, *c3); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))); return detail::none(); } template 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 c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); - unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; + from_python c4(PyTuple_GET_ITEM(args, 4)); + if (!c4.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(*c1, *c2, *c3, *c4); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))); return detail::none(); } template 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 c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); - unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); - unwrap_more c5(PyTuple_GET_ITEM(args, 5), c4); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; + from_python c4(PyTuple_GET_ITEM(args, 4)); + if (!c4.convertible()) return 0; + from_python c5(PyTuple_GET_ITEM(args, 5)); + if (!c5.convertible()) return 0; - if (!c0) return 0; - ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5); + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))); return detail::none(); } @@ -768,75 +903,90 @@ struct returning static PyObject* call(R (*pf)(A0), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; - if (!c0) return 0; - (*pf)(*c0); + (*pf)(c0(PyTuple_GET_ITEM(args, 0))); return detail::none(); } template static PyObject* call(R (*pf)(A0, A1), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; - if (!c0) return 0; - (*pf)(*c0, *c1); + (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1))); return detail::none(); } template static PyObject* call(R (*pf)(A0, A1, A2), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; - if (!c0) return 0; - (*pf)(*c0, *c1, *c2); + (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))); return detail::none(); } template static PyObject* call(R (*pf)(A0, A1, A2, A3), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; - if (!c0) return 0; - (*pf)(*c0, *c1, *c2, *c3); + (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))); return detail::none(); } template static PyObject* call(R (*pf)(A0, A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); - unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; + from_python c4(PyTuple_GET_ITEM(args, 4)); + if (!c4.convertible()) return 0; - if (!c0) return 0; - (*pf)(*c0, *c1, *c2, *c3, *c4); + (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))); return detail::none(); } template static PyObject* call(R (*pf)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ ) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); - unwrap_more c1(PyTuple_GET_ITEM(args, 1), c0); - unwrap_more c2(PyTuple_GET_ITEM(args, 2), c1); - unwrap_more c3(PyTuple_GET_ITEM(args, 3), c2); - unwrap_more c4(PyTuple_GET_ITEM(args, 4), c3); - unwrap_more c5(PyTuple_GET_ITEM(args, 5), c4); + from_python c0(PyTuple_GET_ITEM(args, 0)); + if (!c0.convertible()) return 0; + from_python c1(PyTuple_GET_ITEM(args, 1)); + if (!c1.convertible()) return 0; + from_python c2(PyTuple_GET_ITEM(args, 2)); + if (!c2.convertible()) return 0; + from_python c3(PyTuple_GET_ITEM(args, 3)); + if (!c3.convertible()) return 0; + from_python c4(PyTuple_GET_ITEM(args, 4)); + if (!c4.convertible()) return 0; + from_python c5(PyTuple_GET_ITEM(args, 5)); + if (!c5.convertible()) return 0; - if (!c0) return 0; - (*pf)(*c0, *c1, *c2, *c3, *c4, *c5); + (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))); return detail::none(); } }; diff --git a/include/boost/python/detail/signature.hpp b/include/boost/python/detail/signature.hpp new file mode 100644 index 00000000..db8b39a4 --- /dev/null +++ b/include/boost/python/detail/signature.hpp @@ -0,0 +1,217 @@ +// (C) Copyright David Abrahams 2002. 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 and Lawrence +// Livermore National Labs +// +// This file generated for 5-argument member functions and 6-argument free +// functions by gen_signature.py + +#ifndef SIGNATURE_DWA2002128_HPP +# define SIGNATURE_DWA2002128_HPP + +# include + +namespace boost { namespace python { namespace detail { + +template +mpl::type_list +signature(R (*)()) +{ + return mpl::type_list(); +} + +template +mpl::type_list +signature(R (*)(A0)) +{ + return mpl::type_list(); +} + +template +mpl::type_list +signature(R (*)(A0, A1)) +{ + return mpl::type_list(); +} + +template +mpl::type_list +signature(R (*)(A0, A1, A2)) +{ + return mpl::type_list(); +} + +template +mpl::type_list +signature(R (*)(A0, A1, A2, A3)) +{ + return mpl::type_list(); +} + +template +mpl::type_list +signature(R (*)(A0, A1, A2, A3, A4)) +{ + return mpl::type_list(); +} + +template +mpl::type_list +signature(R (*)(A0, A1, A2, A3, A4, A5)) +{ + return mpl::type_list(); +} +template +mpl::type_list signature(R (A0::*)()) +{ + return mpl::type_list(); +} + +template +mpl::type_list signature(R (A0::*)(A1)) +{ + return mpl::type_list(); +} + +template +mpl::type_list signature(R (A0::*)(A1, A2)) +{ + return mpl::type_list(); +} + +template +mpl::type_list signature(R (A0::*)(A1, A2, A3)) +{ + return mpl::type_list(); +} + +template +mpl::type_list signature(R (A0::*)(A1, A2, A3, A4)) +{ + return mpl::type_list(); +} + +template +mpl::type_list signature(R (A0::*)(A1, A2, A3, A4, A5)) +{ + return mpl::type_list(); +} + + +template +mpl::type_list signature(R (A0::*)() const) +{ + return mpl::type_list(); +} + +template +mpl::type_list signature(R (A0::*)(A1) const) +{ + return mpl::type_list(); +} + +template +mpl::type_list signature(R (A0::*)(A1, A2) const) +{ + return mpl::type_list(); +} + +template +mpl::type_list signature(R (A0::*)(A1, A2, A3) const) +{ + return mpl::type_list(); +} + +template +mpl::type_list signature(R (A0::*)(A1, A2, A3, A4) const) +{ + return mpl::type_list(); +} + +template +mpl::type_list signature(R (A0::*)(A1, A2, A3, A4, A5) const) +{ + return mpl::type_list(); +} + + +template +mpl::type_list signature(R (A0::*)() volatile) +{ + return mpl::type_list(); +} + +template +mpl::type_list signature(R (A0::*)(A1) volatile) +{ + return mpl::type_list(); +} + +template +mpl::type_list signature(R (A0::*)(A1, A2) volatile) +{ + return mpl::type_list(); +} + +template +mpl::type_list signature(R (A0::*)(A1, A2, A3) volatile) +{ + return mpl::type_list(); +} + +template +mpl::type_list signature(R (A0::*)(A1, A2, A3, A4) volatile) +{ + return mpl::type_list(); +} + +template +mpl::type_list signature(R (A0::*)(A1, A2, A3, A4, A5) volatile) +{ + return mpl::type_list(); +} + + +template +mpl::type_list signature(R (A0::*)() const volatile) +{ + return mpl::type_list(); +} + +template +mpl::type_list signature(R (A0::*)(A1) const volatile) +{ + return mpl::type_list(); +} + +template +mpl::type_list signature(R (A0::*)(A1, A2) const volatile) +{ + return mpl::type_list(); +} + +template +mpl::type_list signature(R (A0::*)(A1, A2, A3) const volatile) +{ + return mpl::type_list(); +} + +template +mpl::type_list signature(R (A0::*)(A1, A2, A3, A4) const volatile) +{ + return mpl::type_list(); +} + +template +mpl::type_list signature(R (A0::*)(A1, A2, A3, A4, A5) const volatile) +{ + return mpl::type_list(); +} + +}}} // namespace boost::python::detail + +#endif // SIGNATURE_DWA2002128_HPP + diff --git a/include/boost/python/make_function.hpp b/include/boost/python/make_function.hpp index f9ffd5c3..dfd11865 100644 --- a/include/boost/python/make_function.hpp +++ b/include/boost/python/make_function.hpp @@ -8,8 +8,10 @@ # include # include +# include # include # include +# include # include # include # include @@ -19,6 +21,7 @@ namespace boost { namespace python { template objects::function* make_function(F f) { + converter::acquire_registrations(detail::signature(f)); return new objects::function( objects::py_function( ::boost::bind(detail::caller(), f, _1, _2)) @@ -29,6 +32,10 @@ template objects::function* make_constructor(T* = 0, ArgList* = 0, Generator* = 0) { enum { nargs = mpl::size::value }; + + typedef typename mpl::push_front::sequence signature; + converter::acquire_registrations(signature()); + return new objects::function( objects::py_function( ::boost::bind(detail::caller(), diff --git a/include/boost/python/object/class_converters.hpp b/include/boost/python/object/class_converters.hpp index d4ba4b6d..d5978af7 100644 --- a/include/boost/python/object/class_converters.hpp +++ b/include/boost/python/object/class_converters.hpp @@ -24,7 +24,7 @@ struct class_converters class_converters(ref const& python_class); private: // data members - converter::class_unwrapper m_unwrapper; + converter::class_from_python_converter m_unwrapper; class_wrapper m_wrapper; }; diff --git a/include/boost/python/object/class_wrapper.hpp b/include/boost/python/object/class_wrapper.hpp index f199a99f..26334bc7 100644 --- a/include/boost/python/object/class_wrapper.hpp +++ b/include/boost/python/object/class_wrapper.hpp @@ -8,31 +8,31 @@ # include # include -# include # include +# include # include namespace boost { namespace python { namespace objects { template struct class_wrapper - : converter::wrapper + : converter::to_python_converter { class_wrapper(ref const& type_) - : m_class_object(type_) + : converter::to_python_converter(convert) + , m_class_object_keeper(type_) { -# ifndef NDEBUG assert(type_->ob_type == (PyTypeObject*)class_metatype().get()); -# endif // NDEBUG + m_class_object = (PyTypeObject*)type_.get(); } - PyObject* convert(T const& x) const + static PyObject* convert(T const& x) { // Don't call the type to do the construction, since that // would require the registration of an __init__ copy // constructor. Instead, just construct the object in place. PyObject* raw_result = (PyObject*)PyObject_New( - instance, (PyTypeObject*)m_class_object.get()); + instance, m_class_object); if (raw_result == 0) return 0; @@ -53,9 +53,12 @@ struct class_wrapper } private: - ref m_class_object; + ref m_class_object_keeper; + static PyTypeObject* m_class_object; }; +template +PyTypeObject* class_wrapper::m_class_object; }}} // namespace boost::python::objects diff --git a/include/boost/python/object/make_holder.hpp b/include/boost/python/object/make_holder.hpp index 76b3a5f4..8a72a880 100644 --- a/include/boost/python/object/make_holder.hpp +++ b/include/boost/python/object/make_holder.hpp @@ -10,36 +10,10 @@ # include # include # include +# include namespace boost { namespace python { namespace objects { - -template struct undefined; -template -struct eval -{ -# if defined(BOOST_MSVC) && BOOST_MSVC <= 1200 - // based on the (non-conforming) MSVC trick from MPL - template - struct unarymetafunction_vc : UnaryMetaFunction {}; - - // illegal C++ which causes VC to admit that unarymetafunction_vc - // can have a nested template: - template<> - struct unarymetafunction_vc - { - template struct apply; - }; - - typedef typename unarymetafunction_vc< - ::boost::mpl::detail::msvc_never_true::value - >::template apply::type type; -# else - typedef typename UnaryMetaFunction::template apply::type type; -# endif -}; - - template struct make_holder; template <> @@ -48,7 +22,7 @@ struct make_holder<0> template struct apply { - typedef typename eval::type holder; + typedef typename detail::eval::type holder; static void execute( PyObject* p) { @@ -64,7 +38,7 @@ struct make_holder<1> template struct apply { - typedef typename eval::type holder; + typedef typename detail::eval::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; @@ -83,7 +57,7 @@ struct make_holder<2> template struct apply { - typedef typename eval::type holder; + typedef typename detail::eval::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; typedef typename mpl::at<1,ArgList>::type t1; @@ -103,7 +77,7 @@ struct make_holder<3> template struct apply { - typedef typename eval::type holder; + typedef typename detail::eval::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; typedef typename mpl::at<1,ArgList>::type t1; diff --git a/include/boost/python/object/value_holder.hpp b/include/boost/python/object/value_holder.hpp index d6e38a79..85e3797f 100644 --- a/include/boost/python/object/value_holder.hpp +++ b/include/boost/python/object/value_holder.hpp @@ -22,43 +22,116 @@ struct value_holder : instance_holder template value_holder(PyObject*, A1 a1) - : m_held(a1) {} + : m_held( + (unwrap_reference::type&)(a1) + ) + {} template value_holder(PyObject*, A1 a1, A2 a2) - : m_held(a1, a2) {} + : m_held( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + ) + {} template value_holder(PyObject*, A1 a1, A2 a2, A3 a3) - : m_held(a1, a2, a3) {} + : m_held( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + ) + {} template value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) - : m_held(a1, a2, a3, a4) {} + : m_held( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + , (unwrap_reference::type&)(a4) + ) + {} template value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) - : m_held(a1, a2, a3, a4, a5) {} + : m_held( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + , (unwrap_reference::type&)(a4) + , (unwrap_reference::type&)(a5) + ) {} template value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) - : m_held(a1, a2, a3, a4, a5, a6) {} + : m_held( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + , (unwrap_reference::type&)(a4) + , (unwrap_reference::type&)(a5) + , (unwrap_reference::type&)(a6) + ) {} template value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) - : m_held(a1, a2, a3, a4, a5, a6, a7) {} + : m_held( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + , (unwrap_reference::type&)(a4) + , (unwrap_reference::type&)(a5) + , (unwrap_reference::type&)(a6) + , (unwrap_reference::type&)(a7) + ) + {} template value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) - : m_held(a1, a2, a3, a4, a5, a6, a7, a8) {} + : m_held( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + , (unwrap_reference::type&)(a4) + , (unwrap_reference::type&)(a5) + , (unwrap_reference::type&)(a6) + , (unwrap_reference::type&)(a7) + , (unwrap_reference::type&)(a8) + ) + {} template value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) - : m_held(a1, a2, a3, a4, a5, a6, a7, a8, a9) {} + : m_held( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + , (unwrap_reference::type&)(a4) + , (unwrap_reference::type&)(a5) + , (unwrap_reference::type&)(a6) + , (unwrap_reference::type&)(a7) + , (unwrap_reference::type&)(a8) + , (unwrap_reference::type&)(a9) + ) + {} template value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) - : m_held(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {} + : m_held( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + , (unwrap_reference::type&)(a4) + , (unwrap_reference::type&)(a5) + , (unwrap_reference::type&)(a6) + , (unwrap_reference::type&)(a7) + , (unwrap_reference::type&)(a8) + , (unwrap_reference::type&)(a9) + , (unwrap_reference::type&)(a10) + ) + {} private: // required holder implementation void* holds(converter::type_id_t); diff --git a/include/boost/python/objects.hpp b/include/boost/python/objects.hpp index 93173462..8b230478 100644 --- a/include/boost/python/objects.hpp +++ b/include/boost/python/objects.hpp @@ -354,6 +354,8 @@ struct BOOST_PYTHON_DECL list_slice_proxy }} // namespace boost::python +# ifndef BOOST_PYTHON_V2 + BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE BOOST_PYTHON_DECL PyObject* to_python(const boost::python::tuple&); @@ -389,5 +391,5 @@ inline boost::python::dictionary from_python(PyObject* p, boost::python::type -# include +# include +# include +# include +# include # include -# include # include # include # ifdef BOOST_PYTHON_TRACE @@ -23,6 +24,15 @@ namespace // registry_t& entries() { static registry_t registry; + static bool builtin_converters_initialized = false; + if (!builtin_converters_initialized) + { + // Make this true early because registering the builtin + // converters will cause recursion. + builtin_converters_initialized = true; + + initialize_builtin_converters(); + } return registry; } } // namespace @@ -35,124 +45,127 @@ namespace registry } entry::entry() - : m_wrapper(0) + : m_to_python_converter(0) { } entry::~entry() { - if (m_wrapper != 0) - m_wrapper->m_can_unregister = false; + if (m_to_python_converter != 0) + m_to_python_converter->m_can_unregister = false; - for (unwrappers::iterator p = m_unwrappers.begin(); p != m_unwrappers.end(); ++p) + for (from_python_converters::iterator p = m_from_python_converters.begin() + ; p != m_from_python_converters.end() + ; ++p) { (*p)->m_can_unregister = false; } } - std::pair - entry::unwrapper(PyObject* p) const - { - unwrapper_base* body = 0; - void* data = 0; - - for (unwrappers::const_iterator q = m_unwrappers.begin(), - finish = m_unwrappers.end(); + from_python_converter_base const* + entry::get_from_python(PyObject* p, void*& data_out) const + { + for (from_python_converters::const_iterator q = m_from_python_converters.begin(), + finish = m_from_python_converters.end(); q != finish; ++q) { - data = (*q)->can_convert(p); + void* const data = (*q)->convertible(p); if (data != 0) { - body = *q; + data_out = data; + return *q; break; } } - return std::make_pair(body,data); + return 0; } - wrapper_base* entry::wrapper() const + to_python_function_base entry::get_to_python() const { - return m_wrapper; + return m_to_python_converter + ? m_to_python_converter->converter() + : 0; } - entry::unwrappers::iterator entry::find(unwrapper_base const& x) + entry::from_python_converters::iterator entry::find(from_python_converter_base const& x) { - return std::find(m_unwrappers.begin(), m_unwrappers.end(), &x); + return std::find(m_from_python_converters.begin(), m_from_python_converters.end(), &x); } - void entry::insert(unwrapper_base& x) + void entry::insert(from_python_converter_base& x) { - unwrappers::iterator p = this->find(x); + from_python_converters::iterator p = this->find(x); - assert(p == m_unwrappers.end()); - if (p != m_unwrappers.end()) + if (p != m_from_python_converters.end()) { + assert(!"converter already registered"); throw std::runtime_error( "trying to register unrapper which is already registered"); } - m_unwrappers.push_back(&x); + + m_from_python_converters.push_back(&x); } - void entry::remove(unwrapper_base& x) + void entry::remove(from_python_converter_base& x) { - unwrappers::iterator p = find(x); + from_python_converters::iterator p = find(x); // Be sure we're not removing a converter which hasn't been // registered. - assert(p != m_unwrappers.end()); - if (p == m_unwrappers.end()) + if (p == m_from_python_converters.end()) { + assert(!"trying to unregister from_python_converter which is not registered"); throw std::runtime_error( - "trying to unregister unwrapper which is not registered"); + "trying to unregister from_python_converter which is not registered"); } - m_unwrappers.erase(p); + m_from_python_converters.erase(p); } - void entry::insert(wrapper_base& x) + void entry::insert(to_python_converter_base& x) { - assert(m_wrapper == 0); // we have a problem otherwise - if (m_wrapper != 0) + assert(m_to_python_converter == 0); // we have a problem otherwise + if (m_to_python_converter != 0) { throw std::runtime_error( - "trying to register wrapper for a type which already has a registered wrapper"); + "trying to register to_python_converter for a type which already has a registered to_python_converter"); } - m_wrapper = &x; + m_to_python_converter = &x; } - void entry::remove(wrapper_base& x) + void entry::remove(to_python_converter_base& x) { - assert(m_wrapper == &x); - if (m_wrapper != &x) + assert(m_to_python_converter == &x); + if (m_to_python_converter != &x) { throw std::runtime_error( - "trying to unregister a wrapper which is not registered"); + "trying to unregister a to_python_converter which is not registered"); } - m_wrapper = 0; + m_to_python_converter = 0; } - void insert(wrapper_base& w) + void insert(to_python_converter_base& w) { # ifdef BOOST_PYTHON_TRACE - std::cout << "inserting wrapper for " << w.key() << std::endl; + std::cout << "inserting to_python_converter for " << w.key() << std::endl; # endif find(w.key())->insert(w); } - void insert(unwrapper_base& u) + void insert(from_python_converter_base& u) { # ifdef BOOST_PYTHON_TRACE - std::cout << "inserting unwrapper for " << u.key() << std::endl; + std::cout << "inserting from_python_converter for " << u.key() << std::endl; # endif find(u.key())->insert(u); } - void remove(wrapper_base& w) + void remove(to_python_converter_base& w) { find(w.key())->remove(w); } - void remove(unwrapper_base& u) + void remove(from_python_converter_base& u) { find(u.key())->remove(u); } diff --git a/src/gen_arg_tuple_size.py b/src/gen_arg_tuple_size.py index 5edd3286..9de332ab 100644 --- a/src/gen_arg_tuple_size.py +++ b/src/gen_arg_tuple_size.py @@ -42,6 +42,8 @@ def gen_arg_tuple_size(member_function_args, free_function_args = None): #ifndef ARG_TUPLE_SIZE_DWA20011201_HPP # define ARG_TUPLE_SIZE_DWA20011201_HPP +# include + namespace boost { namespace python { namespace detail { // Computes (at compile-time) the number of elements that a Python @@ -85,16 +87,6 @@ struct arg_tuple_size // 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 -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 diff --git a/src/gen_signature.py b/src/gen_signature.py new file mode 100644 index 00000000..1af3437d --- /dev/null +++ b/src/gen_signature.py @@ -0,0 +1,90 @@ +# (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 + +from gen_function import * +import string + +header = '''// (C) Copyright David Abrahams 2002. 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 and Lawrence +// Livermore National Labs +// +// This file generated for %d-argument member functions and %d-argument free +// functions by gen_signature.py +''' + +_cv_qualifiers = ('', ' const', ' volatile', ' const volatile') + +_suffix = { + '': ''' +// Metrowerks thinks this creates ambiguities +# if !defined(__MWERKS__) || __MWERKS__ > 0x2406 +''', ' const volatile': ''' +# endif // __MWERKS__ +''' + }; + +def gen_arg_tuple_size(member_function_args, free_function_args = None): + if free_function_args is None: + free_function_args = member_function_args + 1 + + return_none = '''; + return detail::none();''' + + return (header % (member_function_args, free_function_args) + + ''' +#ifndef SIGNATURE_DWA2002128_HPP +# define SIGNATURE_DWA2002128_HPP + +# include + +namespace boost { namespace python { namespace detail { +''' + + + gen_functions(''' +template +mpl::type_list +signature(R (*)(%(A%n%:, %))) +{ + return mpl::type_list() +} +''', free_function_args) + + + reduce(lambda x,y: x+'\n'+y + , map( + lambda cv: gen_functions( +'''template +mpl::type_list signature(R (A0::*)(%(A%+%:, %))%1) +{ + return mpl::type_list(); +} + +''', member_function_args, cv) + , _cv_qualifiers)) + '''}}} // namespace boost::python::detail + +#endif // SIGNATURE_DWA2002128_HPP +''') + +if __name__ == '__main__': + import sys + + if len(sys.argv) == 1: + member_function_args = 5 + free_function_args = 6 + else: + member_function_args = int(sys.argv[1]) + if len(sys.argv) > 2: + free_function_args = int(sys.argv[2]) + else: + free_function_args = member_function_args + + print gen_arg_tuple_size(member_function_args, free_function_args) + + diff --git a/src/gen_value_holder.py b/src/gen_value_holder.py new file mode 100644 index 00000000..b01e2c0e --- /dev/null +++ b/src/gen_value_holder.py @@ -0,0 +1,35 @@ +# Copyright David Abrahams 2002. 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 Livermore National Labs + +from gen_function import * +import string + +def _generate(member_function_args, free_function_args = None): + return ('''// 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 VALUE_HOLDER_DWA20011215_HPP +# define VALUE_HOLDER_DWA20011215_HPP + +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace objects { + +template +struct value_holder : instance_holder +{ + // Forward construction to the held object +''' + + + gen_functions( diff --git a/src/object/class.cpp b/src/object/class.cpp index b928ba66..de3e32f5 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -46,7 +46,7 @@ PyTypeObject class_metatype_object = { 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | // Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ diff --git a/test/m1.cpp b/test/m1.cpp index 7f88af2b..6b4c55e1 100644 --- a/test/m1.cpp +++ b/test/m1.cpp @@ -4,19 +4,18 @@ // "as is" without express or implied warranty, and with no claim as // to its suitability for any purpose. + #include "simple_type.hpp" #include "complicated.hpp" -#include -#include -#include -#include #include #include #include +#include #include -#include +//#include #include -#include +#include +#include #include #include #include @@ -61,9 +60,12 @@ PyObject* new_noddy() } // Simple is a wrapper around a struct simple, which just contains a char* -struct SimpleObject : PyObject +struct SimpleObject { + PyObject_HEAD simple x; + + static simple& extract(SimpleObject& o) { return o.x; } }; PyTypeObject SimpleType = { @@ -72,7 +74,7 @@ PyTypeObject SimpleType = { "Simple", sizeof(SimpleObject), 0, - dealloc, /*tp_dealloc*/ + dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ @@ -98,120 +100,38 @@ PyObject* new_simple() // description of how the type parameters to wrapper<> and unwrapper<> // are selected. // - -// Wrap an int by converting it to a Python Int -struct int_wrapper - : boost::python::converter::wrapper -{ - PyObject* convert(int const& x) const - { - return PyInt_FromLong(x); - } -}; +using boost::python::converter::from_python_data; // Wrap a simple by converting it to a Simple -struct simple_wrapper - : boost::python::converter::wrapper +PyObject* simple_to_python(simple const& x) { - PyObject* convert(simple const& x) const - { - SimpleObject* p = PyObject_New(SimpleObject, &SimpleType); - p->x = x; - return p; - } -}; + SimpleObject* p = PyObject_New(SimpleObject, &SimpleType); + p->x = x; + return (PyObject*)p; +} + // wrap a mutable reference to a simple by converting it to a // Simple. Normally we wouldn't do it this way, since modifications to // the result clearly don't change the original object, but here we're // just proving that the mechanism works. -struct simple_ref_wrapper - : boost::python::converter::wrapper +PyObject* simple_ref_to_python(simple& x) { - PyObject* convert(simple& x) const - { - SimpleObject* p = PyObject_New(SimpleObject, &SimpleType); - p->x = x; - return p; - } -}; + SimpleObject* p = PyObject_New(SimpleObject, &SimpleType); + p->x = x; + return (PyObject*)p; +} -// extract an int from a Python Int by converting it to an int. Since -// int is a scalar type, we convert by-value. Since Python Ints are -// immutable, there's no non-const reference converter. -struct native_int_unwrapper - : boost::python::converter::unwrapper +int noddy_to_int(PyObject* p, from_python_data&) { - void* can_convert(PyObject* p) const - { - return PyInt_Check(p) ? non_null : 0; - } - - int convert(PyObject* p, void*, boost::type) const - { - return PyInt_AsLong(p); - } -}; - -// Extract an int from a Noddy -struct noddy_int_unwrapper - : boost::python::converter::unwrapper -{ - void* can_convert(PyObject* p) const - { - return p->ob_type == &NoddyType ? non_null : 0; - } - - int convert(PyObject* p, void*, boost::type) const - { - return static_cast(p)->x; - } -}; + return static_cast(p)->x; +} // Extract a mutable reference to an int from a Noddy. -struct noddy_int_ref_unwrapper - : boost::python::converter::unwrapper +int& noddy_to_int_ref(PyObject* p, from_python_data&) { - void* can_convert(PyObject* p) const - { - return p->ob_type == &NoddyType ? non_null : 0; - } - - int& convert(PyObject* p, void*, boost::type) const - { - return static_cast(p)->x; - } -}; - -// Extract a mutable reference to a simple from a Simple -struct simple_ref_unwrapper - : boost::python::converter::unwrapper -{ - void* can_convert(PyObject* p) const - { - return p->ob_type == &SimpleType ? non_null : 0; - } - - simple& convert(PyObject* p, void*, boost::type) const - { - return static_cast(p)->x; - } -}; - -// Extract a const reference to a simple from a Simple -struct simple_const_ref_unwrapper - : boost::python::converter::unwrapper -{ - void* can_convert(PyObject* p) const - { - return p->ob_type == &SimpleType ? non_null : 0; - } - - simple const& convert(PyObject* p, void*, boost::type) const - { - return static_cast(p)->x; - } -}; + return static_cast(p)->x; +} // // Some C++ functions to expose to Python @@ -232,6 +152,7 @@ simple const& g(simple const& x) struct A { A() : x(0) {} + virtual ~A() {} char const* name() { return "A"; } int x; }; @@ -268,19 +189,38 @@ BOOST_PYTHON_MODULE_INIT(m1) { using boost::python::module; using boost::python::class_; + using boost::python::converter::to_python_converter; + using boost::python::converter::from_python_converter; + using boost::python::reference_from_python; + using boost::python::value_from_python; + using boost::python::type_from_python; + using boost::python::get_member; // Create the converters; they are self-registering/unregistering. - static int_wrapper wrap_int; - static simple_wrapper wrap_simple; - static native_int_unwrapper unwrap_int1; - static noddy_int_unwrapper unwrap_int2; - static noddy_int_ref_unwrapper unwrap_int3; - static simple_ref_unwrapper unwrap_simple; - static simple_const_ref_unwrapper unwrap_simple_const_ref; - static simple_ref_wrapper wrap_simple_ref; + static to_python_converter c1(simple_to_python); + + static from_python_converter c2( + &(boost::python::type_from_python<&NoddyType>::convertible), noddy_to_int); + + static from_python_converter c3( + &(boost::python::type_from_python<&NoddyType>::convertible), noddy_to_int_ref); + + static boost::python::reference_from_python< + &SimpleType + , simple + , SimpleObject + , &SimpleObject::extract + > + unwrap_simple; + + static to_python_converter simple_ref_wrapper(simple_ref_to_python); module m1("m1"); + typedef boost::python::objects::pointer_holder_generator< + boost::python::objects::shared_ptr_generator + > use_shared_ptr; + m1 // Insert the metaclass for all extension classes .setattr("xclass", boost::python::objects::class_metatype()) @@ -303,7 +243,7 @@ BOOST_PYTHON_MODULE_INIT(m1) .def("take_d", take_d) .add( - class_("A") + class_, use_shared_ptr>("A") .def_init() .def("name", &A::name) ) @@ -314,13 +254,13 @@ BOOST_PYTHON_MODULE_INIT(m1) // or "C" below if we make them part of the same chain m1 .add( - class_ >("B") + class_, use_shared_ptr>("B") .def_init() .def("name", &B::name) ) .add( - class_ >("C") + class_, use_shared_ptr>("C") .def_init() .def("name", &C::name) ) @@ -328,7 +268,7 @@ BOOST_PYTHON_MODULE_INIT(m1) m1 .add( - class_ >("D") + class_, use_shared_ptr>("D") .def_init() .def("name", &D::name) ) diff --git a/test/m2.cpp b/test/m2.cpp index d70b0c13..be2934e0 100644 --- a/test/m2.cpp +++ b/test/m2.cpp @@ -7,13 +7,9 @@ // This module exercises the converters exposed in m1 at a low level // by exposing raw Python extension functions that use wrap<> and // unwrap<> objects. -#include #include #include "simple_type.hpp" -using boost::python::wrap; -using boost::python::unwrap; - // Get a simple (by value) from the argument, and return the // string it holds. PyObject* unwrap_simple(simple x) From 1f128575514a887278e0b5ceaffbb43e1d327529 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 30 Jan 2002 22:12:07 +0000 Subject: [PATCH 239/369] initial checkin [SVN r12591] --- .../boost/python/reference_from_python.hpp | 57 ++++++++++++++++++ include/boost/python/value_from_python.hpp | 60 +++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 include/boost/python/reference_from_python.hpp create mode 100644 include/boost/python/value_from_python.hpp diff --git a/include/boost/python/reference_from_python.hpp b/include/boost/python/reference_from_python.hpp new file mode 100644 index 00000000..8e7b9b6c --- /dev/null +++ b/include/boost/python/reference_from_python.hpp @@ -0,0 +1,57 @@ +// Copyright David Abrahams 2002. 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 REFERENCE_FROM_PYTHON_DWA2002130_HPP +# define REFERENCE_FROM_PYTHON_DWA2002130_HPP + +# include +# include + +namespace boost { namespace python { + +// Utility which produces a member extractor function on platforms +// other than VC6. +template +struct get_member +{ + static Member& execute(Class* c) + { + return c->*mp; + } +}; + +template < + PyTypeObject const* python_type + , class Value + , class PythonObject + , Value& (*extract)(PythonObject&) + > +struct reference_from_python : type_from_python +{ + reference_from_python() + : m_mutable_converter(convertible, convert_mutable) + , m_const_converter(convertible, convert_const) + {} + + static Value& convert_mutable(PyObject* op, converter::from_python_data&) + { + return extract(*(PythonObject*)op); + } + + static Value const& convert_const(PyObject* op, converter::from_python_data&) + { + return extract(*(PythonObject*)op); + } + + private: + typedef converter::from_python_converter mutable_converter; + typedef converter::from_python_converter const_converter; + mutable_converter m_mutable_converter; + const_converter m_const_converter; +}; + +}} // namespace boost::python + +#endif // REFERENCE_FROM_PYTHON_DWA2002130_HPP diff --git a/include/boost/python/value_from_python.hpp b/include/boost/python/value_from_python.hpp new file mode 100644 index 00000000..bb4ecf87 --- /dev/null +++ b/include/boost/python/value_from_python.hpp @@ -0,0 +1,60 @@ +// Copyright David Abrahams 2002. 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 VALUE_FROM_PYTHON_DWA2002130_HPP +# define VALUE_FROM_PYTHON_DWA2002130_HPP + +# include +# include +# include + +namespace boost { namespace python { + +template +struct value_from_python +{ + value_from_python() + : m_converter( + &Derived::convertible + , &Derived::convert + + // Change this to a compile-time check later to avoid + // generating destroy function + , has_trivial_destructor::value ? 0 : &Derived::destroy + ) + { + // Scalar types are really converted by-value; the formulation + // is much simpler. + BOOST_STATIC_ASSERT(!(is_scalar::value)); + } + + static void* get_storage(converter::from_python_data& data) + { + return converter::get_storage(data); + } + + // Mark successful construction + static void constructed(converter::from_python_data& data) + { + data.stage1 = get_storage(data); + } + + inline static void destroy(converter::from_python_data& data) + { + // Get the location of the storage for + void* storage = get_storage(data); + + // Check for successful construction + if (data.stage1 == storage) + static_cast(storage)->~T(); + } + + private: + converter::from_python_converter m_converter; +}; + +}} // namespace boost::python + +#endif // VALUE_FROM_PYTHON_DWA2002130_HPP From 88a8721b89ba445bf83cd2f3272c036f34820302 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 30 Jan 2002 22:18:50 +0000 Subject: [PATCH 240/369] initial checkin [SVN r12592] --- src/converter/builtin_converters.cpp | 153 +++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 src/converter/builtin_converters.cpp diff --git a/src/converter/builtin_converters.cpp b/src/converter/builtin_converters.cpp new file mode 100644 index 00000000..07a00259 --- /dev/null +++ b/src/converter/builtin_converters.cpp @@ -0,0 +1,153 @@ +// Copyright David Abrahams 2002. 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. + +#include +#include +#include +#include +#include +#include +#include +//#include +#include + +namespace boost { namespace python { namespace converter { + +namespace +{ + struct int_value_functions_base + { + static void* convertible(PyObject* obj) + { + PyNumberMethods* number_methods = obj->ob_type->tp_as_number; + + return number_methods && number_methods->nb_int + ? &number_methods->nb_int : 0; + } + }; + + template + struct int_value_functions : int_value_functions_base + { + static T convert(PyObject* obj, from_python_data& data) + { + unaryfunc f = *static_cast(data.stage1); + ref int_object(f(obj)); + return numeric_cast(PyInt_AsLong(int_object.get())); + } + }; + + struct cstring_value_functions + { + static void* convertible(PyObject* obj) + { + return PyString_Check(obj) ? obj : 0; + } + + static char const* convert(PyObject* obj, from_python_data&) + { + return PyString_AsString(obj); + } + }; + + char constructed; + + struct string_cref_functions + { + typedef std::string const& result_type; + + static void* convertible(PyObject* obj) + { + return obj->ob_type->tp_str ? &obj->ob_type->tp_str : 0; + } + + static std::string const& convert( + PyObject* obj, from_python_data& data) + { + ref string_object((**static_cast(data.stage1))(obj)); + void* storage = get_storage(data); + std::string* p = new (storage) std::string(PyString_AsString(string_object.get())); + + // note that construction is successful. + data.stage1 = &constructed; + return *p; + } + + static void destroy(from_python_data& data) + { + if (data.stage1 == &constructed) + { + typedef std::string string_t; + void* storage = get_storage(data); + ((string_t*)storage)->~string_t(); + } + } + }; + + template + struct rvalue_const_ref_functions : Base + { + static T const& convert(PyObject* obj, from_python_data& data) + { + void* storage = get_storage(data); + T* p = new (storage) T(Base::convert(obj,data)); + + // note that construction is successful. + data.stage1 = &constructed; + return *p; + } + }; + + struct register_int_converters + { + template + struct apply + { + typedef void type; + + static void execute() + { + typedef int_value_functions value_functions; + typedef rvalue_const_ref_functions cref_functions; + + static from_python_converter value_from_python( + value_functions::convertible + , value_functions::convert); + static from_python_converter cref_from_python( + cref_functions::convertible + , cref_functions::convert); + }; + }; + }; +} + +#define REGISTER_INT_CONVERTERS(U) register_int_converters::apply::execute() +#define REGISTER_INT_CONVERTERS2(U) REGISTER_INT_CONVERTERS(signed U); REGISTER_INT_CONVERTERS(unsigned U) + + +void initialize_builtin_converters() +{ + REGISTER_INT_CONVERTERS2(char); + REGISTER_INT_CONVERTERS2(short); + REGISTER_INT_CONVERTERS2(int); + REGISTER_INT_CONVERTERS2(long); +// mpl::for_each::execute(); + + static from_python_converter cstring_from_python( + &cstring_value_functions::convertible + , &cstring_value_functions::convert); + + static from_python_converter cstring_cref_from_python( + &rvalue_const_ref_functions::convertible + , &rvalue_const_ref_functions::convert); + + static from_python_converter string_cref_from_python( + &string_cref_functions::convertible + , &string_cref_functions::convert + , &string_cref_functions::destroy); +} + +}}} // namespace boost::python::converter From 6a75fa83b5b6fab78dbe915563fffc5bb298cf1d Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 31 Jan 2002 05:53:54 +0000 Subject: [PATCH 241/369] New conversion methods, builtin converters ---------------------------------------------------------------------- Committing in . Modified Files: boost/python/reference_from_python.hpp boost/python/value_from_python.hpp boost/python/converter/body.hpp boost/python/converter/handle.hpp libs/python/src/converter/builtin_converters.cpp libs/python/test/m1.cpp libs/python/test/m2.cpp Added Files: boost/python/converter/builtin_converters.hpp boost/python/converter/builtin_to_python_converters.hpp boost/python/converter/from_python.hpp boost/python/converter/from_python_data.hpp boost/python/converter/from_python_function.hpp boost/python/converter/to_python.hpp boost/python/converter/to_python_function.hpp boost/python/object/auto_ptr_generator.hpp boost/python/object/pointer_holder.hpp libs/python/src/converter/from_python.cpp libs/python/src/converter/to_python.cpp libs/python/test/test_builtin_converters.cpp libs/python/test/test_builtin_converters.py Removed Files: boost/python/convert.hpp boost/python/converter/unwrap.hpp boost/python/converter/unwrapper.hpp boost/python/converter/wrap.hpp boost/python/converter/wrapper.hpp boost/python/object/class_unwrapper.hpp ---------------------------------------------------------------------- [SVN r12596] --- include/boost/python/convert.hpp | 84 ------- include/boost/python/converter/body.hpp | 5 - .../python/converter/builtin_converters.hpp | 15 ++ .../builtin_to_python_converters.hpp | 75 ++++++ .../boost/python/converter/from_python.hpp | 169 +++++++++++++ .../python/converter/from_python_data.hpp | 206 +++++++++++++++ .../python/converter/from_python_function.hpp | 23 ++ include/boost/python/converter/handle.hpp | 18 ++ include/boost/python/converter/to_python.hpp | 116 +++++++++ .../python/converter/to_python_function.hpp | 23 ++ include/boost/python/converter/unwrap.hpp | 172 ------------- include/boost/python/converter/unwrapper.hpp | 40 --- include/boost/python/converter/wrap.hpp | 167 ------------ include/boost/python/converter/wrapper.hpp | 57 ----- .../python/object/auto_ptr_generator.hpp | 23 ++ .../boost/python/object/class_unwrapper.hpp | 40 --- .../boost/python/object/pointer_holder.hpp | 201 +++++++++++++++ .../boost/python/reference_from_python.hpp | 17 +- include/boost/python/value_from_python.hpp | 18 +- src/converter/builtin_converters.cpp | 238 ++++++++++++------ src/converter/from_python.cpp | 27 ++ src/converter/to_python.cpp | 24 ++ test/m1.cpp | 8 +- test/m2.cpp | 3 - test/test_builtin_converters.cpp | 65 +++++ test/test_builtin_converters.py | 86 +++++++ 26 files changed, 1259 insertions(+), 661 deletions(-) delete mode 100644 include/boost/python/convert.hpp create mode 100644 include/boost/python/converter/builtin_converters.hpp create mode 100644 include/boost/python/converter/builtin_to_python_converters.hpp create mode 100644 include/boost/python/converter/from_python.hpp create mode 100644 include/boost/python/converter/from_python_data.hpp create mode 100644 include/boost/python/converter/from_python_function.hpp create mode 100644 include/boost/python/converter/to_python.hpp create mode 100644 include/boost/python/converter/to_python_function.hpp delete mode 100644 include/boost/python/converter/unwrap.hpp delete mode 100644 include/boost/python/converter/unwrapper.hpp delete mode 100644 include/boost/python/converter/wrap.hpp delete mode 100644 include/boost/python/converter/wrapper.hpp create mode 100644 include/boost/python/object/auto_ptr_generator.hpp delete mode 100644 include/boost/python/object/class_unwrapper.hpp create mode 100644 include/boost/python/object/pointer_holder.hpp create mode 100644 src/converter/from_python.cpp create mode 100644 src/converter/to_python.cpp create mode 100644 test/test_builtin_converters.cpp create mode 100644 test/test_builtin_converters.py diff --git a/include/boost/python/convert.hpp b/include/boost/python/convert.hpp deleted file mode 100644 index 5614bd3b..00000000 --- a/include/boost/python/convert.hpp +++ /dev/null @@ -1,84 +0,0 @@ -// 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 CONVERT_DWA20011129_HPP -# define CONVERT_DWA20011129_HPP - -# include -# include -# include -# include - -namespace boost { namespace python { - -namespace detail -{ - template - struct converter_gen - { - typedef T value_type; - typedef typename converter::source::type source_t; - typedef converter::wrap_ wrap_t; - typedef converter::wrap_more_ wrap_more_t; - - typedef typename converter::target::type target_t; - typedef converter::unwrap_ unwrap_t; - typedef converter::unwrap_more_ unwrap_more_t; - }; -} - -template -struct wrap : detail::converter_gen::wrap_t -{ - typedef typename detail::converter_gen::wrap_t base_t; - typedef typename detail::converter_gen::source_t source_t; -}; - -template -struct wrap_more : detail::converter_gen::wrap_more_t -{ - typedef typename detail::converter_gen::wrap_more_t base_t; - typedef typename detail::converter_gen::source_t source_t; - wrap_more(converter::handle& prev); -}; - -template -struct unwrap : detail::converter_gen::unwrap_t -{ - typedef typename detail::converter_gen::unwrap_t base_t; - unwrap(PyObject*); -}; - -template -struct unwrap_more : detail::converter_gen::unwrap_more_t -{ - typedef typename detail::converter_gen::unwrap_more_t base_t; - unwrap_more(PyObject*, converter::handle& prev); -}; - -// -// implementations -// -template -inline wrap_more::wrap_more(converter::handle& prev) - : base_t(prev) -{ -} - -template -inline unwrap::unwrap(PyObject* source) - : base_t(source) -{ -} - -template -inline unwrap_more::unwrap_more(PyObject* source, converter::handle& prev) - : base_t(source, prev) -{ -} - -}} // namespace boost::python - -#endif // CONVERT_DWA20011129_HPP diff --git a/include/boost/python/converter/body.hpp b/include/boost/python/converter/body.hpp index 72653ee0..d9170839 100644 --- a/include/boost/python/converter/body.hpp +++ b/include/boost/python/converter/body.hpp @@ -10,8 +10,6 @@ namespace boost { namespace python { namespace converter { -struct BOOST_PYTHON_DECL handle; - namespace registry { class entry; @@ -23,9 +21,6 @@ struct BOOST_PYTHON_DECL body body(type_id_t key); virtual ~body() {} - // default implementation is a no-op - virtual void destroy_handle(handle*) const; - type_id_t key() const; protected: diff --git a/include/boost/python/converter/builtin_converters.hpp b/include/boost/python/converter/builtin_converters.hpp new file mode 100644 index 00000000..9c19cbc5 --- /dev/null +++ b/include/boost/python/converter/builtin_converters.hpp @@ -0,0 +1,15 @@ +// Copyright David Abrahams 2002. 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 BUILTIN_CONVERTERS_DWA2002124_HPP +# define BUILTIN_CONVERTERS_DWA2002124_HPP + +namespace boost { namespace python { namespace converter { + +void initialize_builtin_converters(); + +}}} // namespace boost::python::converter + +#endif // BUILTIN_CONVERTERS_DWA2002124_HPP diff --git a/include/boost/python/converter/builtin_to_python_converters.hpp b/include/boost/python/converter/builtin_to_python_converters.hpp new file mode 100644 index 00000000..4e9f89e3 --- /dev/null +++ b/include/boost/python/converter/builtin_to_python_converters.hpp @@ -0,0 +1,75 @@ +// Copyright David Abrahams 2002. 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 BUILTIN_TO_PYTHON_CONVERTERS_DWA2002129_HPP +# define BUILTIN_TO_PYTHON_CONVERTERS_DWA2002129_HPP +# include +# include + +namespace boost { namespace python { namespace converter { + +template struct to_python_lookup; + +template +struct to_python_int +{ + bool convertible() const { return true; } + PyObject* operator()(T x) const { return PyInt_FromLong(long(x)); } +}; + +# define BOOST_PYTHON_TO_INT(T) \ + template <> struct to_python_lookup : to_python_int {}; \ + template <> struct to_python_lookup : to_python_int {}; + +BOOST_PYTHON_TO_INT(char) +BOOST_PYTHON_TO_INT(short) +BOOST_PYTHON_TO_INT(int) +BOOST_PYTHON_TO_INT(long) +# undef BOOST_TO_PYTHON_INT + +template <> +struct to_python_lookup +{ + bool convertible() const { return true; } + PyObject* operator()(char const* x) const { return PyString_FromString(x); } +}; + +template <> +struct to_python_lookup +{ + bool convertible() const { return true; } + PyObject* operator()(std::string const& x) const + { + return PyString_FromString(x.c_str()); + } +}; + +template <> +struct to_python_lookup +{ + bool convertible() const { return true; } + PyObject* operator()(float x) const { return PyFloat_FromDouble(x); } +}; + +template <> +struct to_python_lookup +{ + bool convertible() const { return true; } + PyObject* operator()(double x) const { return PyFloat_FromDouble(x); } +}; + +template <> +struct to_python_lookup +{ + bool convertible() const { return true; } + PyObject* operator()(long double x) const + { + return PyFloat_FromDouble(x); + } +}; + +}}} // namespace boost::python::converter + +#endif // BUILTIN_TO_PYTHON_CONVERTERS_DWA2002129_HPP diff --git a/include/boost/python/converter/from_python.hpp b/include/boost/python/converter/from_python.hpp new file mode 100644 index 00000000..234f61d1 --- /dev/null +++ b/include/boost/python/converter/from_python.hpp @@ -0,0 +1,169 @@ +// Copyright David Abrahams 2002. 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 FROM_PYTHON_DWA2002127_HPP +# define FROM_PYTHON_DWA2002127_HPP + +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +// The type of convertibility checking functions +typedef void* (*from_python_check)(PyObject*); +typedef void (*from_python_destructor)(from_python_data&); + +// forward declaration +template struct from_python_lookup; + +// from_python -- +// A body class representing a conversion from python to C++. + +struct BOOST_PYTHON_DECL from_python_converter_base : body +{ + from_python_converter_base(type_id_t, from_python_check); // registers + ~from_python_converter_base(); // unregisters + + // Must return non-null iff the conversion will be successful. Any + // non-null pointer is acceptable, and will be passed on to the + // convert() function, so useful data can be stored there. + inline void* convertible(PyObject*) const; +// inline type_id_t key() const; + private: +// type_id_t m_key; + from_python_check m_convertible; +}; + + +template +struct from_python_converter : from_python_converter_base +{ + public: // types + typedef typename from_python_function::type conversion_function; + + public: // member functions + from_python_converter(from_python_check, conversion_function, from_python_destructor = 0); + T convert(PyObject*, from_python_data&) const; + void destroy(from_python_data&) const; + + private: // data members + conversion_function m_convert; + from_python_destructor m_destroy; +}; + +// ------------------------------------------------------------------------- + +//struct from_python_base +//{ +//}; + +// A class which implements from_python with a registry lookup. +template +struct from_python_lookup // : from_python_base +{ + public: // types + + public: // member functions + from_python_lookup(PyObject* source); + ~from_python_lookup(); + + bool convertible() const; + T operator()(PyObject*); + + public: // functions for use by conversion implementations + // Get the converter object + from_python_converter const* converter() const; + + private: // data members + typedef typename from_python_intermediate_data::type intermediate_t; + mutable intermediate_t m_intermediate_data; + from_python_converter const* m_converter; +}; + +// +// implementations +// +inline void* from_python_converter_base::convertible(PyObject* o) const +{ + return m_convertible(o); +} + +# if 0 +inline type_id_t from_python_converter_base::key() const +{ + return m_key; +} +# endif + +template +inline from_python_converter::from_python_converter( + from_python_check checker + , conversion_function converter + , from_python_destructor destructor // = 0 + ) + : from_python_converter_base(type_id(), checker) + , m_convert(converter) + , m_destroy(destructor) +{ + +} + +template +inline T from_python_converter::convert(PyObject* src, from_python_data& data) const +{ + return this->m_convert(src, data); +} + +template +inline void from_python_converter::destroy(from_python_data& data) const +{ + if (this->m_destroy) + { + this->m_destroy(data); + } +} + +template +inline from_python_lookup::from_python_lookup(PyObject* src) + : m_converter( + registration::get_from_python( + src, m_intermediate_data.stage1)) +{ +} + +template +inline from_python_lookup::~from_python_lookup() +{ + if (m_converter != 0) + m_converter->destroy(m_intermediate_data); +} + +template +inline bool from_python_lookup::convertible() const +{ + return this->m_converter != 0; +} + +template +inline T from_python_lookup::operator()(PyObject* obj) +{ + return this->m_converter->convert(obj, m_intermediate_data); +} + +template +inline from_python_converter const* +from_python_lookup::converter() const +{ + return this->m_converter; +} + +}}} // namespace boost::python::converter + +#endif // FROM_PYTHON_DWA2002127_HPP diff --git a/include/boost/python/converter/from_python_data.hpp b/include/boost/python/converter/from_python_data.hpp new file mode 100644 index 00000000..3edcbad7 --- /dev/null +++ b/include/boost/python/converter/from_python_data.hpp @@ -0,0 +1,206 @@ +// Copyright David Abrahams 2002. 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 FROM_PYTHON_AUX_DATA_DWA2002128_HPP +# define FROM_PYTHON_AUX_DATA_DWA2002128_HPP + +# include +# include +# include +# include + +// Keep these for the metaprogram which EDG is choking on. +# if !defined(__EDG__) || (__EDG_VERSION__ > 245) +# include +# include +# include +# include +# endif + +namespace boost { namespace python { namespace converter { + +// A POD which is layout-compatible with the real intermediate data +// for all from_python conversions. There may be additional storage if +// we are converting a reference type. +struct from_python_data +{ + void* stage1; +}; + +namespace detail +{ + template struct referent_alignment; + template struct referent_size; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + template + struct referent_alignment + { + BOOST_STATIC_CONSTANT( + std::size_t, value = alignment_of::value); + }; + + template + struct referent_size + { + BOOST_STATIC_CONSTANT( + std::size_t, value = sizeof(T)); + }; + +# else + + template + struct alignment_chars + { + BOOST_STATIC_CONSTANT( + std::size_T, n = alignment_of::value); + char elements[n + 1]; + }; + + template struct referent_alignment + { + template + static alignment_chars helper(U&); + + static T t; + + BOOST_STATIC_CONSTANT( + std::size_t, value = sizeof(helper(t).elements) - 1); + }; + + + template struct referent_size + { + static T t; + BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(t)); + }; + +# endif + + struct unknown_alignment + { + void* p; + }; + +// EDG is too slow to handle this metaprogram :( +#if !defined(__EDG__) || (__EDG_VERSION__ > 245) + struct alignment_dummy; + + template + struct best_alignment_type + { + template + struct apply + { + BOOST_STATIC_CONSTANT( + std::size_t, align1 = alignment_of::value); + + BOOST_STATIC_CONSTANT( + std::size_t, align2 = alignment_of::value); + + BOOST_STATIC_CONSTANT( + bool, aligned2 = ( + (align2 >= target_alignment) + & (align2 % target_alignment == 0)) + ); + + BOOST_STATIC_CONSTANT( + bool, choose_t2 = ( + aligned2 && ( + is_same::value + | (align2 < alignment_of::value) + | (sizeof(T2) < sizeof(T1))) + )); + + typedef mpl::select_type::type type; + }; + }; + + typedef mpl::type_list< + char,short,int,long,float,double,long double + ,void* + ,void(*)() + ,void (alignment_dummy::*)() + , char (alignment_dummy::*) + > + align_types; +#endif // EDG is too slow + + template + struct aligned_storage + { + typedef Align align_t; + union + { + Align align; + char bytes[size + // this is just a STATIC_ASSERT. For some reason + // MSVC was barfing on the boost one. + - (is_same::value ? size : 0)]; + }; + }; + + template + struct referent_storage + { +// EDG is too slow to handle this metaprogram :( +#if !defined(__EDG__) || (__EDG_VERSION__ > 245) + typedef mpl::for_each< + align_types + , unknown_alignment + , best_alignment_type::value> + > loop; + typedef typename loop::state align_t; +#else + // The Python source makes the assumption that double has + // maximal alignment anyway + typedef double align_t; +#endif + + typedef aligned_storage::value> type; + }; + + template + struct intermediate_data : from_python_data + { + typename referent_storage::type stage2; + }; + + template <> + struct intermediate_data : from_python_data + { + }; + +} + +// ------------------------------------------------------------------------- +// Auxiliary POD storage where the convertible and/or convert functions of a +// from_python object may place arbitrary data. +// +// Always starts with a void* +// +// For references, we produce additional aligned storage sufficient to +// store the referent + +template +struct from_python_intermediate_data +{ + typedef typename mpl::select_type< + is_reference::value, T, void>::type just_reference_t; + + typedef detail::intermediate_data type; +}; + +template +void* get_storage(from_python_data& x, boost::type* = 0) +{ + typedef typename from_python_intermediate_data::type layout; + return static_cast(&x)->stage2.bytes; +} + +}}} // namespace boost::python::converter + +#endif // FROM_PYTHON_AUX_DATA_DWA2002128_HPP diff --git a/include/boost/python/converter/from_python_function.hpp b/include/boost/python/converter/from_python_function.hpp new file mode 100644 index 00000000..0cf90459 --- /dev/null +++ b/include/boost/python/converter/from_python_function.hpp @@ -0,0 +1,23 @@ +// Copyright David Abrahams 2002. 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 FROM_PYTHON_FUNCTION_DWA2002128_HPP +# define FROM_PYTHON_FUNCTION_DWA2002128_HPP + +# include + +namespace boost { namespace python { namespace converter { + +struct from_python_data; + +template +struct from_python_function +{ + typedef T (*type)(PyObject*, from_python_data&); +}; + +}}} // namespace boost::python::converter + +#endif // FROM_PYTHON_FUNCTION_DWA2002128_HPP diff --git a/include/boost/python/converter/handle.hpp b/include/boost/python/converter/handle.hpp index 03671634..bc06be38 100644 --- a/include/boost/python/converter/handle.hpp +++ b/include/boost/python/converter/handle.hpp @@ -24,6 +24,7 @@ struct BOOST_PYTHON_DECL handle : boost::noncopyable // // Constructors taking a handle links this into a chain of // handles, for more efficient management in function wrappers + handle(); handle(body* body); handle(body* body, handle& prev); @@ -43,6 +44,9 @@ struct BOOST_PYTHON_DECL handle : boost::noncopyable protected: // member functions for derived classes // Get the body we hold inline body* get_body() const; + + inline void set_body(body*); + inline void set_prev(handle&); // Release all bodies in the chain, in reverse order of // initialization. Only actually called for the head of the chain. @@ -59,6 +63,10 @@ struct BOOST_PYTHON_DECL handle : boost::noncopyable // // implementations // +inline handle::handle() + : m_next(0) +{} + inline handle::handle(body* body, handle& prev) : m_body(body), m_next(0) { @@ -85,6 +93,16 @@ inline body* handle::get_body() const return m_body; } +inline void handle::set_body(body* body) +{ + m_body = body; +} + +inline void handle::set_prev(handle& prev) +{ + prev.m_next = this; +} + }}} // namespace boost::python::converter #endif // HANDLE_DWA20011130_HPP diff --git a/include/boost/python/converter/to_python.hpp b/include/boost/python/converter/to_python.hpp new file mode 100644 index 00000000..61dc7dad --- /dev/null +++ b/include/boost/python/converter/to_python.hpp @@ -0,0 +1,116 @@ +// Copyright David Abrahams 2002. 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 TO_PYTHON_DWA2002127_HPP +# define TO_PYTHON_DWA2002127_HPP + +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +template struct to_python_lookup; + +struct BOOST_PYTHON_DECL to_python_converter_base : body +{ + to_python_converter_base(type_id_t, to_python_function_base); // registers + ~to_python_converter_base(); // unregisters + +// inline type_id_t key() const; + inline to_python_function_base converter() const; + private: +// type_id_t m_key; + to_python_function_base m_convert; +}; + +template +struct to_python_converter : to_python_converter_base +{ + public: // types + typedef typename to_python_function::type converter_t; + + public: // member functions + to_python_converter(converter_t); + converter_t converter() const; + + private: // data members + converter_t m_convert; +}; + +// ------------------------------------------------------------------------- + +//struct to_python_base {}; + +template +struct to_python_lookup //: to_python_base +{ + public: // member functions + to_python_lookup(); + bool convertible() const; + PyObject* operator()(T) const; + private: + typename to_python_function::type m_convert; +}; + +// +// implementations +// +# if 0 +inline type_id_t +to_python_converter_base::key() const +{ + return m_key; +} +# endif + +inline to_python_function_base +to_python_converter_base::converter() const +{ + return m_convert; +} + +template +to_python_converter::to_python_converter(converter_t convert) + : to_python_converter_base( + type_id(), reinterpret_cast(convert)) +{ +} + +template +inline typename to_python_function::type +to_python_converter::converter() const +{ + return reinterpret_cast( + this->to_python_converter_base::converter()); +} + +template +inline to_python_lookup::to_python_lookup() + : m_convert( + registration::get_to_python()) +{ +} + +template +inline bool +to_python_lookup::convertible() const +{ + return m_converter != 0; +} + +template +inline PyObject* +to_python_lookup::operator()(T x) const +{ + return m_convert ? m_convert(x) : 0; +} + +}}} // namespace boost::python::converter + +#endif // TO_PYTHON_DWA2002127_HPP diff --git a/include/boost/python/converter/to_python_function.hpp b/include/boost/python/converter/to_python_function.hpp new file mode 100644 index 00000000..9d408749 --- /dev/null +++ b/include/boost/python/converter/to_python_function.hpp @@ -0,0 +1,23 @@ +// Copyright David Abrahams 2002. 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 TO_PYTHON_FUNCTION_DWA2002128_HPP +# define TO_PYTHON_FUNCTION_DWA2002128_HPP + +# include + +namespace boost { namespace python { namespace converter { + +typedef PyObject* (*to_python_function_base)(void); + +template +struct to_python_function +{ + typedef PyObject*(*type)(T); +}; + +}}} // namespace boost::python::converter + +#endif // TO_PYTHON_FUNCTION_DWA2002128_HPP diff --git a/include/boost/python/converter/unwrap.hpp b/include/boost/python/converter/unwrap.hpp deleted file mode 100644 index eccb0992..00000000 --- a/include/boost/python/converter/unwrap.hpp +++ /dev/null @@ -1,172 +0,0 @@ -#error obsolete -// 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 UNWRAP_BASE_DWA20011130_HPP -# define UNWRAP_BASE_DWA20011130_HPP - -# include -# include -# include -# include -# include -# include -# include -# include - -namespace boost { namespace python { namespace converter { - -template struct unwrapper; -struct BOOST_PYTHON_DECL body; - -struct BOOST_PYTHON_DECL unwrap_base : handle -{ - public: // member functions - inline unwrap_base(PyObject* source, std::pair, handle& prev); - inline unwrap_base(PyObject* source, std::pair); - inline PyObject* source() const; - - inline void*& data(); - - protected: - inline PyObject*& source(); - - private: // data members - PyObject* m_source; - void* m_data; -}; - -// These converters will be used by the function wrappers. They don't -// manage any resources, but are instead linked into a chain which is -// managed by an instance of unwrap_ or wrap_. -template -struct unwrap_more_ : unwrap_base -{ - public: // member functions - // Construction - unwrap_more_(PyObject* source, handle& prev); - - // invoke the conversion or throw an exception if unsuccessful - T operator*(); - - protected: // constructor - // this constructor is only for the use of unwrap_ - unwrap_more_(PyObject* source); - - private: - typedef typename unwrapper_select::type unwrapper_t; -}; - -// specialization for PyObject* -template <> -struct unwrap_more_ - : unwrap_base -{ - public: // member functions - // Construction - unwrap_more_(PyObject* source, handle& prev) - : unwrap_base(source, m_unwrapper, prev) - { - } - - - // invoke the conversion or throw an exception if unsuccessful - PyObject* operator*() - { - return source(); - } - - void* can_convert(PyObject*) const - { - return &m_unwrapper; - } - - protected: // constructor - // this constructor is only for the use of unwrap_ - unwrap_more_(PyObject* source) - : unwrap_base(source, m_unwrapper) - - { - } - private: - static BOOST_PYTHON_DECL std::pair& m_unwrapper; -}; - -template -struct unwrap_ : unwrap_more_ -{ - unwrap_(PyObject* source); - ~unwrap_(); -}; - -// -// implementations -// -inline unwrap_base::unwrap_base( - PyObject* source, std::pair unwrapper, handle& prev) - : handle(unwrapper.first, prev) - , m_source(source) - , m_data(unwrapper.second) -{ -} - -inline unwrap_base::unwrap_base(PyObject* source, std::pair unwrapper) - : handle(unwrapper.first) - , m_source(source) - , m_data(unwrapper.second) -{ -} - -inline void*& unwrap_base::data() -{ - return m_data; -} - -inline PyObject* unwrap_base::source() const -{ - return m_source; -} - -inline PyObject*& unwrap_base::source() -{ - return m_source; -} - -template -unwrap_more_::unwrap_more_(PyObject* source, handle& prev) - : unwrap_base(source, - registration::unwrapper(source), - prev) -{ -} - -template -unwrap_more_::unwrap_more_(PyObject* source) - : unwrap_base(source, registration::unwrapper(source)) -{ -} - -template -inline unwrap_::unwrap_(PyObject* source) - : unwrap_more_(source) -{ -} - -template -T unwrap_more_::operator*() -{ - return static_cast*>( - get_body())->convert(this->source(), this->data(), boost::type()); -} - -template -unwrap_::~unwrap_() -{ - this->destroy(); -} - -}}} // namespace boost::python::converter - -#endif // UNWRAP_BASE_DWA20011130_HPP diff --git a/include/boost/python/converter/unwrapper.hpp b/include/boost/python/converter/unwrapper.hpp deleted file mode 100644 index 8a16e957..00000000 --- a/include/boost/python/converter/unwrapper.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#error obsolete -// 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 UNWRAPPER_DWA2001127_HPP -# define UNWRAPPER_DWA2001127_HPP - -# include -# include -# include -# include - -namespace boost { namespace python { namespace converter { - -template struct unwrap_more_; - -// Abstract base for all unwrappers of Ts -template -struct unwrapper : unwrapper_base -{ - public: - unwrapper(); - - virtual T convert(PyObject*, void*& data, boost::type) const = 0; -}; - -// -// implementations -// -template -unwrapper::unwrapper() - : unwrapper_base(type_id()) -{ -} - -}}} // namespace boost::python::converter - -#endif // UNWRAPPER_DWA2001127_HPP diff --git a/include/boost/python/converter/wrap.hpp b/include/boost/python/converter/wrap.hpp deleted file mode 100644 index b61fff19..00000000 --- a/include/boost/python/converter/wrap.hpp +++ /dev/null @@ -1,167 +0,0 @@ -#error obsolete -// 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 WRAP_DWA2001127_HPP -# define WRAP_DWA2001127_HPP -# include -# include -# include -# include -# include -# include -# include -# include - -namespace boost { namespace python { namespace converter { - -extern BOOST_PYTHON_DECL body& identity_wrapper; - -template struct wrapper; - -struct wrap_base : handle -{ - public: // member functions - wrap_base(body*, handle& prev); - wrap_base(body*); - PyObject* release(); - - public: // accessor, really only for wrappers - PyObject*& target() const; - - protected: - void hold_result(PyObject*) const; - - private: - mutable PyObject* m_target; -}; - -template -struct wrap_more_ : wrap_base -{ - protected: - typedef T source_t; - - public: // member functions - wrap_more_(handle& prev); - - PyObject* operator()(source_t) const; - - protected: // constructor for wrap_, below - wrap_more_(); - - private: // helper functions - static wrapper_base* lookup(); - - private: - friend class wrapper; -}; - -template -struct wrap_ : wrap_more_ -{ - typedef typename wrap_more_::source_t source_t; - public: // member functions - wrap_(); - ~wrap_(); -}; - - -// Specialization for PyObject* -template <> -struct wrap_more_ : wrap_base -{ - protected: - typedef PyObject* source_t; - - public: // member functions - wrap_more_(handle& prev) - : wrap_base(&identity_wrapper, prev) {} - - PyObject* operator()(source_t x) const { return x; } - - protected: // constructor for wrap_, below - wrap_more_() - : wrap_base(&identity_wrapper) {} - private: - friend class wrapper; -}; - -// -// implementations -// -inline wrap_base::wrap_base(body* body, handle& prev) - : handle(body, prev) - , m_target(0) -{ -} - -inline wrap_base::wrap_base(body* body) - : handle(body), - m_target(0) -{ -} - -inline PyObject*& wrap_base::target() const -{ - return m_target; -} - -inline void wrap_base::hold_result(PyObject* p) const -{ - assert(m_target == 0); - m_target = p; -} - -inline PyObject* wrap_base::release() -{ - PyObject* result = m_target; - m_target = 0; - return result; -} - -template -inline wrapper_base* wrap_more_::lookup() -{ - // Find the converters registered for T and get a wrapper - // appropriate for the source object - return registration::wrapper(); -} - -template -inline wrap_more_::wrap_more_(handle& prev) - : wrap_base(lookup(), prev) -{ - -} - -template -PyObject* wrap_more_::operator()(source_t x) const -{ - return static_cast*>( - this->get_body())->do_conversion(*this, source_holder(x)); -} - -template -wrap_more_::wrap_more_() - : wrap_base(lookup()) -{ -} - -template -wrap_::wrap_() - : wrap_more_() -{ -} - -template -wrap_::~wrap_() -{ - this->destroy(); -} - -}}} // namespace boost::python::converter - -#endif // WRAP_DWA2001127_HPP diff --git a/include/boost/python/converter/wrapper.hpp b/include/boost/python/converter/wrapper.hpp deleted file mode 100644 index e20ed404..00000000 --- a/include/boost/python/converter/wrapper.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#error obsolete -// 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 WRAPPER_DWA2001127_HPP -# define WRAPPER_DWA2001127_HPP -# include -# include -# include -# include -# include - -namespace boost { namespace python { namespace converter { - -extern BOOST_PYTHON_DECL body& identity_wrapper; - -template -struct wrapper : wrapper_base -{ - public: - wrapper(); - - PyObject* do_conversion(wrap_base const&, source_holder_base const&) const; - - // This does the actual conversion - virtual PyObject* convert(T source) const = 0; -}; - -// -// implementations -// - -template -wrapper::wrapper() - : wrapper_base(type_id()) -{ -} - - -template -PyObject* wrapper::do_conversion(wrap_base const& handle_, source_holder_base const& data_) const -{ - // Casting pointers instead of references suppresses a CWPro7 bug. - wrap_more_ const& handle = *static_cast const*>(&handle_); - source_holder const& data = *static_cast const*>(&data_); - if (handle.target() == 0) - { - handle.hold_result(convert(data.value)); - } - return handle.target(); -} - -}}} // namespace boost::python::converter - -#endif // WRAPPER_DWA2001127_HPP diff --git a/include/boost/python/object/auto_ptr_generator.hpp b/include/boost/python/object/auto_ptr_generator.hpp new file mode 100644 index 00000000..9c13e436 --- /dev/null +++ b/include/boost/python/object/auto_ptr_generator.hpp @@ -0,0 +1,23 @@ +// Copyright David Abrahams 2002. 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 AUTO_PTR_GENERATOR_DWA2002123_HPP +# define AUTO_PTR_GENERATOR_DWA2002123_HPP +# include + +namespace boost { namespace python { namespace object { + +struct auto_ptr_generator +{ + template + struct apply + { + typedef std::auto_ptr type; + }; +}; + +}}} // namespace boost::python::object + +#endif // AUTO_PTR_GENERATOR_DWA2002123_HPP diff --git a/include/boost/python/object/class_unwrapper.hpp b/include/boost/python/object/class_unwrapper.hpp deleted file mode 100644 index 0877ff24..00000000 --- a/include/boost/python/object/class_unwrapper.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// 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 CLASS_UNWRAPPER_DWA20011221_HPP -# define CLASS_UNWRAPPER_DWA20011221_HPP - -# include -# include - -namespace boost { namespace python { namespace objects { - -template -struct class_unwrapper -{ - private: - template - struct reference_unwrapper : converter::unwrapper - { - void* can_convert(PyObject* p) const - { - return find_instance(p); - } - - Target convert(PyObject* p, void* data, ) const - { - return *find_instance(p)->target(); - } - }; - - reference_unwrapper m_reference; -# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - reference_unwrapper m_const_reference; -# endif -}; - -}}} // namespace boost::python::objects - -#endif // CLASS_UNWRAPPER_DWA20011221_HPP diff --git a/include/boost/python/object/pointer_holder.hpp b/include/boost/python/object/pointer_holder.hpp new file mode 100644 index 00000000..81fcac0c --- /dev/null +++ b/include/boost/python/object/pointer_holder.hpp @@ -0,0 +1,201 @@ +// 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 POINTER_HOLDER_DWA20011215_HPP +# define POINTER_HOLDER_DWA20011215_HPP + +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace objects { + +template +struct pointer_holder : instance_holder +{ + pointer_holder(Pointer); + + // Forward construction to the held object + pointer_holder(PyObject*) + : m_p(new Value) {} + + + template + pointer_holder(PyObject*, A1 a1) + : m_p(new Value( + (unwrap_reference::type&)(a1) + )) + {} + + template + pointer_holder(PyObject*, A1 a1, A2 a2) + : m_p(new Value( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + )) + {} + + template + pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3) + : m_p(new Value( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + )) + {} + + template + pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) + : m_p(new Value( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + , (unwrap_reference::type&)(a4) + )) + {} + + template + pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) + : m_p(new Value( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + , (unwrap_reference::type&)(a4) + , (unwrap_reference::type&)(a5) + )) {} + + template + pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) + : m_p(new Value( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + , (unwrap_reference::type&)(a4) + , (unwrap_reference::type&)(a5) + , (unwrap_reference::type&)(a6) + )) {} + + template + pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) + : m_p(new Value( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + , (unwrap_reference::type&)(a4) + , (unwrap_reference::type&)(a5) + , (unwrap_reference::type&)(a6) + , (unwrap_reference::type&)(a7) + )) + {} + + template + pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) + : m_p(new Value( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + , (unwrap_reference::type&)(a4) + , (unwrap_reference::type&)(a5) + , (unwrap_reference::type&)(a6) + , (unwrap_reference::type&)(a7) + , (unwrap_reference::type&)(a8) + )) + {} + + template + pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) + : m_p(new Value( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + , (unwrap_reference::type&)(a4) + , (unwrap_reference::type&)(a5) + , (unwrap_reference::type&)(a6) + , (unwrap_reference::type&)(a7) + , (unwrap_reference::type&)(a8) + , (unwrap_reference::type&)(a9) + )) + {} + + template + pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) + : m_p(new Value( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + , (unwrap_reference::type&)(a4) + , (unwrap_reference::type&)(a5) + , (unwrap_reference::type&)(a6) + , (unwrap_reference::type&)(a7) + , (unwrap_reference::type&)(a8) + , (unwrap_reference::type&)(a9) + , (unwrap_reference::type&)(a10) + )) + {} + + private: // required holder implementation + void* holds(converter::type_id_t); + + private: // data members + Pointer m_p; +}; + +}}} + +// back to namespace boost for this forward declaration +namespace boost +{ + template class shared_ptr; +} + +namespace boost { namespace python { namespace objects { + +struct shared_ptr_generator +{ + template + struct apply + { + typedef boost::shared_ptr type; + }; +}; + +// A generator metafunction which can be passed to make_holder +// PointerGenerator should be another generator metafunction which +// makes the appropriate (smart) pointer type to hold the argument to +// pointer_holder_generator. +template +struct pointer_holder_generator +{ + template + struct apply + { + typedef typename detail::eval::type pointer; + typedef pointer_holder type; + }; +}; + +template +pointer_holder::pointer_holder(Pointer p) + : m_p(p) +{ +} + +template +void* pointer_holder::holds(converter::type_id_t dst_t) +{ + if (dst_t == converter::type_id()) + return &this->m_p; + + converter::type_id_t src_t = converter::type_id(); + return src_t == dst_t ? &*this->m_p + : find_dynamic_type(&*this->m_p, src_t, dst_t); +} + +}}} // namespace boost::python::objects + +#endif // POINTER_HOLDER_DWA20011215_HPP diff --git a/include/boost/python/reference_from_python.hpp b/include/boost/python/reference_from_python.hpp index 8e7b9b6c..a9631dc5 100644 --- a/include/boost/python/reference_from_python.hpp +++ b/include/boost/python/reference_from_python.hpp @@ -26,23 +26,28 @@ template < PyTypeObject const* python_type , class Value , class PythonObject - , Value& (*extract)(PythonObject&) + , class Extract > -struct reference_from_python : type_from_python +struct reference_from_python { + typedef type_from_python convertible_t; + reference_from_python() - : m_mutable_converter(convertible, convert_mutable) - , m_const_converter(convertible, convert_const) + : m_mutable_converter( + &convertible_t::convertible, convert_mutable) + + , m_const_converter( + &convertible_t::convertible, convert_const) {} static Value& convert_mutable(PyObject* op, converter::from_python_data&) { - return extract(*(PythonObject*)op); + return Extract::execute(*(PythonObject*)op); } static Value const& convert_const(PyObject* op, converter::from_python_data&) { - return extract(*(PythonObject*)op); + return Extract::execute(*(PythonObject*)op); } private: diff --git a/include/boost/python/value_from_python.hpp b/include/boost/python/value_from_python.hpp index bb4ecf87..0ff80323 100644 --- a/include/boost/python/value_from_python.hpp +++ b/include/boost/python/value_from_python.hpp @@ -9,12 +9,27 @@ # include # include # include +# include namespace boost { namespace python { template struct value_from_python { + typedef converter::from_python_check from_python_check; + + value_from_python(from_python_check convertible) + : m_converter( + convertible + , &Derived::convert + + // Change this to a compile-time check later to avoid + // generating destroy function + , has_trivial_destructor::value ? 0 : &Derived::destroy + ) + { + } + value_from_python() : m_converter( &Derived::convertible @@ -25,9 +40,6 @@ struct value_from_python , has_trivial_destructor::value ? 0 : &Derived::destroy ) { - // Scalar types are really converted by-value; the formulation - // is much simpler. - BOOST_STATIC_ASSERT(!(is_scalar::value)); } static void* get_storage(converter::from_python_data& data) diff --git a/src/converter/builtin_converters.cpp b/src/converter/builtin_converters.cpp index 07a00259..c2ce3dae 100644 --- a/src/converter/builtin_converters.cpp +++ b/src/converter/builtin_converters.cpp @@ -8,7 +8,8 @@ #include #include #include -#include +#include +#include #include #include //#include @@ -18,113 +19,185 @@ namespace boost { namespace python { namespace converter { namespace { - struct int_value_functions_base + // Only an object which we know is holding a char const* can be + // converted to one + struct convertible_to_cstring { - static void* convertible(PyObject* obj) + static unaryfunc* execute(PyObject* obj) { - PyNumberMethods* number_methods = obj->ob_type->tp_as_number; - - return number_methods && number_methods->nb_int - ? &number_methods->nb_int : 0; - } - }; - - template - struct int_value_functions : int_value_functions_base - { - static T convert(PyObject* obj, from_python_data& data) - { - unaryfunc f = *static_cast(data.stage1); - ref int_object(f(obj)); - return numeric_cast(PyInt_AsLong(int_object.get())); + return PyString_Check(obj) ? &obj->ob_type->tp_str : 0; } }; - struct cstring_value_functions + struct extract_cstring { - static void* convertible(PyObject* obj) - { - return PyString_Check(obj) ? obj : 0; - } - - static char const* convert(PyObject* obj, from_python_data&) + static char const* execute(PyObject* obj) { return PyString_AsString(obj); } }; - char constructed; - - struct string_cref_functions + // Any object which can be converted to a Python string can also be + // converted to a C++ string, since the latter owns its bytes. + struct convertible_to_string { - typedef std::string const& result_type; - - static void* convertible(PyObject* obj) + static unaryfunc* execute(PyObject* obj) { return obj->ob_type->tp_str ? &obj->ob_type->tp_str : 0; } + }; + + // Transform a function returning a unaryfunc* into one that returns a void* + template + struct return_void_ptr + { + static void* execute(PyObject* p) { return F::execute(p); } + }; + + template < + class T // The target type + , class Convertible // returns a pointer to a unaryfunc producing an object + , class TExtract // ...from which TExtract extracts T's constructor argument + > + struct tp_scalar_from_python + : from_python_converter + { + private: + typedef return_void_ptr convertible_fn; - static std::string const& convert( - PyObject* obj, from_python_data& data) + public: + tp_scalar_from_python() + : from_python_converter( + &convertible_fn::execute + , convert) + {} + + static T convert(PyObject* obj, from_python_data& data) { - ref string_object((**static_cast(data.stage1))(obj)); - void* storage = get_storage(data); - std::string* p = new (storage) std::string(PyString_AsString(string_object.get())); + unaryfunc converter = *(unaryfunc*)data.stage1; + ref converted(converter(obj)); + return TExtract::execute(converted.get()); + } + }; + + // Extract a reference to T using the functions in the source + // object's type slots + template < + class T // The target type + , class Convertible // returns a pointer to a unaryfunc producing an object + , class TExtract // ...from which TExtract extracts T's constructor argument + > + struct tp_cref_from_python + : value_from_python > + { + private: + typedef value_from_python > base; + + public: + tp_cref_from_python() + : base(&return_void_ptr::execute) + {} + + static T const& convert(PyObject* obj, from_python_data& data) + { + unaryfunc converter = *(unaryfunc*)data.stage1; + + void* storage = get_storage(data); + + ref converted(converter(obj)); + + T* const p = new (storage) T(TExtract::execute(converted.get())); // note that construction is successful. - data.stage1 = &constructed; + data.stage1 = p; + return *p; } + }; - static void destroy(from_python_data& data) + struct convertible_to_int + { + static unaryfunc* execute(PyObject* obj) { - if (data.stage1 == &constructed) + PyNumberMethods* number_methods = obj->ob_type->tp_as_number; + if (number_methods == 0) + return 0; + + // For floating types, return the float conversion slot to avoid + // creating a new object. We'll handle that in + // py_int_or_float_as_long, below + if (PyObject_TypeCheck(obj, &PyFloat_Type) && number_methods->nb_float) + return &number_methods->nb_float; + + return number_methods && number_methods->nb_int + ? &number_methods->nb_int : 0; + } + }; + + struct py_int_or_float_as_long + { + static long execute(PyObject* obj) + { + if (PyObject_TypeCheck(obj, &PyFloat_Type)) { - typedef std::string string_t; - void* storage = get_storage(data); - ((string_t*)storage)->~string_t(); + return numeric_cast(PyFloat_AS_DOUBLE(obj)); + } + else + { + return PyInt_AS_LONG(obj); } } }; - template - struct rvalue_const_ref_functions : Base + struct convertible_to_double { - static T const& convert(PyObject* obj, from_python_data& data) + static unaryfunc* execute(PyObject* obj) { - void* storage = get_storage(data); - T* p = new (storage) T(Base::convert(obj,data)); - - // note that construction is successful. - data.stage1 = &constructed; - return *p; + PyNumberMethods* number_methods = obj->ob_type->tp_as_number; + if (number_methods == 0) + return 0; + + // For integer types, return the tp_int conversion slot to avoid + // creating a new object. We'll handle that in + // py_float_or_int_as_double, below + if (PyObject_TypeCheck(obj, &PyInt_Type) && number_methods->nb_int) + return &number_methods->nb_int; + + return number_methods && number_methods->nb_float + ? &number_methods->nb_float : 0; } }; - struct register_int_converters + struct py_float_or_int_as_double { - template - struct apply + static double execute(PyObject* obj) { - typedef void type; - - static void execute() + if (PyObject_TypeCheck(obj, &PyInt_Type)) { - typedef int_value_functions value_functions; - typedef rvalue_const_ref_functions cref_functions; - - static from_python_converter value_from_python( - value_functions::convertible - , value_functions::convert); - static from_python_converter cref_from_python( - cref_functions::convertible - , cref_functions::convert); - }; - }; + return PyInt_AS_LONG(obj); + } + else + { + return PyFloat_AS_DOUBLE(obj); + } + } }; -} -#define REGISTER_INT_CONVERTERS(U) register_int_converters::apply::execute() + template + struct scalar_from_python + { + tp_cref_from_python cref_converter; + tp_scalar_from_python value_converter; + }; + + template + void register_int_converters(T* = 0) + { + static scalar_from_python x; + }; +} + +#define REGISTER_INT_CONVERTERS(U) register_int_converters() #define REGISTER_INT_CONVERTERS2(U) REGISTER_INT_CONVERTERS(signed U); REGISTER_INT_CONVERTERS(unsigned U) @@ -134,20 +207,21 @@ void initialize_builtin_converters() REGISTER_INT_CONVERTERS2(short); REGISTER_INT_CONVERTERS2(int); REGISTER_INT_CONVERTERS2(long); -// mpl::for_each::execute(); - static from_python_converter cstring_from_python( - &cstring_value_functions::convertible - , &cstring_value_functions::convert); + static scalar_from_python< + float,convertible_to_double,py_float_or_int_as_double> float_from_python; + + static scalar_from_python< + double,convertible_to_double,py_float_or_int_as_double> double_from_python; + + static scalar_from_python< + long double,convertible_to_double,py_float_or_int_as_double> long_double_from_python; + + static scalar_from_python< + char const*, convertible_to_cstring, extract_cstring> cstring_from_python; - static from_python_converter cstring_cref_from_python( - &rvalue_const_ref_functions::convertible - , &rvalue_const_ref_functions::convert); - - static from_python_converter string_cref_from_python( - &string_cref_functions::convertible - , &string_cref_functions::convert - , &string_cref_functions::destroy); + static tp_cref_from_python< + std::string, convertible_to_string, extract_cstring> string_from_python; } }}} // namespace boost::python::converter diff --git a/src/converter/from_python.cpp b/src/converter/from_python.cpp new file mode 100644 index 00000000..979ad935 --- /dev/null +++ b/src/converter/from_python.cpp @@ -0,0 +1,27 @@ +// Copyright David Abrahams 2002. 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. + +#include + +namespace boost { namespace python { namespace converter { + +from_python_converter_base::from_python_converter_base( + type_id_t type + , from_python_check checker + ) + : body(type) + , m_convertible(checker) +{ + registry::insert(*this); +} + +from_python_converter_base::~from_python_converter_base() +{ + if (can_unregister()) + registry::remove(*this); +} + +}}} // namespace boost::python::converter diff --git a/src/converter/to_python.cpp b/src/converter/to_python.cpp new file mode 100644 index 00000000..9cede51d --- /dev/null +++ b/src/converter/to_python.cpp @@ -0,0 +1,24 @@ +// Copyright David Abrahams 2002. 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. + +#include +#include + +namespace boost { namespace python { namespace converter { + +to_python_converter_base::to_python_converter_base(type_id_t key, to_python_function_base convert) + : body(key) + , m_convert(convert) +{ + registry::insert(*this); +} + +to_python_converter_base::~to_python_converter_base() +{ + registry::remove(*this); +} + +}}} // namespace boost::python::converter diff --git a/test/m1.cpp b/test/m1.cpp index 6b4c55e1..d422b426 100644 --- a/test/m1.cpp +++ b/test/m1.cpp @@ -64,8 +64,11 @@ struct SimpleObject { PyObject_HEAD simple x; +}; - static simple& extract(SimpleObject& o) { return o.x; } +struct extract_simple_object +{ + static simple& execute(SimpleObject& o) { return o.x; } }; PyTypeObject SimpleType = { @@ -209,12 +212,13 @@ BOOST_PYTHON_MODULE_INIT(m1) &SimpleType , simple , SimpleObject - , &SimpleObject::extract + , extract_simple_object > unwrap_simple; static to_python_converter simple_ref_wrapper(simple_ref_to_python); + module m1("m1"); typedef boost::python::objects::pointer_holder_generator< diff --git a/test/m2.cpp b/test/m2.cpp index be2934e0..0a5df161 100644 --- a/test/m2.cpp +++ b/test/m2.cpp @@ -49,9 +49,6 @@ PyObject* unwrap_int_const_ref(int const& x) return PyInt_FromLong(x); } -// MSVC6 bug workaround -template struct xxxx; - // rewrap extracts a T from the argument, then converts the T back // to a PyObject* and returns it. template diff --git a/test/test_builtin_converters.cpp b/test/test_builtin_converters.cpp new file mode 100644 index 00000000..6ffccdf9 --- /dev/null +++ b/test/test_builtin_converters.cpp @@ -0,0 +1,65 @@ +// Copyright David Abrahams 2002. 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. +#include +#include +#include +#include + + +template +struct by_value +{ + static T rewrap(T x) + { + return x; + } +}; + +template +struct by_const_reference +{ + static T rewrap(T const& x) + { + return x; + } +}; + +BOOST_PYTHON_MODULE_INIT(builtin_converters_ext) +{ + boost::python::module("builtin_converters_ext") + + .def("rewrap_value_signed_char", by_value::rewrap) + .def("rewrap_value_unsigned_char", by_value::rewrap) + .def("rewrap_value_int", by_value::rewrap) + .def("rewrap_value_unsigned_int", by_value::rewrap) + .def("rewrap_value_short", by_value::rewrap) + .def("rewrap_value_unsigned_short", by_value::rewrap) + .def("rewrap_value_long", by_value::rewrap) + .def("rewrap_value_unsigned_long", by_value::rewrap) + .def("rewrap_value_float", by_value::rewrap) + .def("rewrap_value_double", by_value::rewrap) + .def("rewrap_value_long_double", by_value::rewrap) + .def("rewrap_value_string", by_value::rewrap) + .def("rewrap_value_cstring", by_value::rewrap) + + + .def("rewrap_const_reference_signed_char", by_const_reference::rewrap) + .def("rewrap_const_reference_unsigned_char", by_const_reference::rewrap) + .def("rewrap_const_reference_int", by_const_reference::rewrap) + .def("rewrap_const_reference_unsigned_int", by_const_reference::rewrap) + .def("rewrap_const_reference_short", by_const_reference::rewrap) + .def("rewrap_const_reference_unsigned_short", by_const_reference::rewrap) + .def("rewrap_const_reference_long", by_const_reference::rewrap) + .def("rewrap_const_reference_unsigned_long", by_const_reference::rewrap) + .def("rewrap_const_reference_float", by_const_reference::rewrap) + .def("rewrap_const_reference_double", by_const_reference::rewrap) + .def("rewrap_const_reference_long_double", by_const_reference::rewrap) + .def("rewrap_const_reference_string", by_const_reference::rewrap) + .def("rewrap_const_reference_cstring", by_const_reference::rewrap) + + ; +} + diff --git a/test/test_builtin_converters.py b/test/test_builtin_converters.py new file mode 100644 index 00000000..3941a29c --- /dev/null +++ b/test/test_builtin_converters.py @@ -0,0 +1,86 @@ +""" +>>> from builtin_converters_ext import * +>>> rewrap_value_signed_char(42) +42 +>>> rewrap_value_unsigned_char(42) +42 +>>> rewrap_value_int(42) +42 +>>> rewrap_value_unsigned_int(42) +42 +>>> rewrap_value_short(42) +42 +>>> rewrap_value_unsigned_short(42) +42 +>>> rewrap_value_long(42) +42 +>>> rewrap_value_unsigned_long(42) +42 + +>>> abs(rewrap_value_float(4.2) - 4.2) < .000001 +1 +>>> rewrap_value_double(4.2) - 4.2 +0.0 +>>> rewrap_value_long_double(4.2) - 4.2 +0.0 + +>>> rewrap_value_cstring('hello, world') +'hello, world' +>>> rewrap_value_string('yo, wassup?') +'yo, wassup?' + +>>> rewrap_const_reference_signed_char(42) +42 +>>> rewrap_const_reference_unsigned_char(42) +42 +>>> rewrap_const_reference_int(42) +42 +>>> rewrap_const_reference_unsigned_int(42) +42 +>>> rewrap_const_reference_short(42) +42 +>>> rewrap_const_reference_unsigned_short(42) +42 +>>> rewrap_const_reference_long(42) +42 +>>> rewrap_const_reference_unsigned_long(42) +42 +>>> abs(rewrap_const_reference_float(4.2) - 4.2) < .000001 +1 +>>> rewrap_const_reference_double(4.2) - 4.2 +0.0 +>>> rewrap_const_reference_long_double(4.2) - 4.2 +0.0 + +>>> rewrap_const_reference_cstring('hello, world') +'hello, world' +>>> rewrap_const_reference_string('yo, wassup?') +'yo, wassup?' + +Now check implicit conversions between floating/integer types + +>>> rewrap_const_reference_float(42) +42.0 + +>>> rewrap_const_reference_int(42.0) +42 + +>>> rewrap_value_float(42) +42.0 + +>>> rewrap_value_int(42.0) +42 + +""" +def run(args = None): + import sys + import doctest + + if args is not None: + sys.argv = args + return doctest.testmod(sys.modules.get(__name__)) + +if __name__ == '__main__': + print "running..." + import sys + sys.exit(run()[0]) From b3117c2b02b9793325de5cc231e41327cac74903 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 1 Feb 2002 04:36:46 +0000 Subject: [PATCH 242/369] Use call policies [SVN r12618] --- include/boost/python/converter/smart_ptr.hpp | 70 ++ include/boost/python/converter/to_python.hpp | 2 +- include/boost/python/converter/type_id.hpp | 82 +- include/boost/python/copy_const_reference.hpp | 42 + .../boost/python/copy_non_const_reference.hpp | 42 + .../boost/python/default_call_policies.hpp | 72 ++ include/boost/python/detail/caller.hpp | 220 ++++- .../boost/python/detail/indirect_traits.hpp | 116 +++ include/boost/python/detail/returning.hpp | 842 +++++++++++++----- include/boost/python/from_python.hpp | 42 + include/boost/python/make_function.hpp | 15 +- include/boost/python/module.hpp | 16 +- .../python/return_internal_reference.hpp | 45 + include/boost/python/return_value_policy.hpp | 20 + include/boost/python/to_python.hpp | 37 + include/boost/python/type_from_python.hpp | 23 + src/objects.cpp | 4 +- test/m1.cpp | 13 +- test/m2.cpp | 28 +- 19 files changed, 1380 insertions(+), 351 deletions(-) create mode 100644 include/boost/python/converter/smart_ptr.hpp create mode 100644 include/boost/python/copy_const_reference.hpp create mode 100644 include/boost/python/copy_non_const_reference.hpp create mode 100644 include/boost/python/default_call_policies.hpp create mode 100644 include/boost/python/detail/indirect_traits.hpp create mode 100644 include/boost/python/from_python.hpp create mode 100644 include/boost/python/return_internal_reference.hpp create mode 100644 include/boost/python/return_value_policy.hpp create mode 100644 include/boost/python/to_python.hpp create mode 100644 include/boost/python/type_from_python.hpp diff --git a/include/boost/python/converter/smart_ptr.hpp b/include/boost/python/converter/smart_ptr.hpp new file mode 100644 index 00000000..bae4c2b8 --- /dev/null +++ b/include/boost/python/converter/smart_ptr.hpp @@ -0,0 +1,70 @@ +// Copyright David Abrahams 2002. 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 SMART_PTR_DWA2002123_HPP +# define SMART_PTR_DWA2002123_HPP + +# include +# include +namespace boost { namespace python { namespace converter { + +template +class smart_ptr_wrapper + : wrapper +{ + smart_ptr_wrapper(ref const& type_) + : m_class_object(type_) + { + assert(type_->ob_type == (PyTypeObject*)class_metatype().get()); + } + + PyObject* convert(Pointer x) const; + + private: + ref m_class_object; + + smart_ptr_converters(); +} + + +// +// implementations +// + +template +PyObject* smart_ptr_wrapper::convert(Pointer x) const +{ + if (x.operator->() == 0) + return detail::none(); + + // Don't call the type to do the construction, since that + // would require the registration of an __init__ copy + // constructor. Instead, just construct the object in place. + PyObject* raw_result = (PyObject*)PyObject_New( + instance, (PyTypeObject*)m_class_object.get()); + + if (raw_result == 0) + return 0; + + // Everything's OK; Bypass NULL checks but guard against + // exceptions. + ref result(raw_result, ref::allow_null()); + + // Build a value_holder to contain the object using the copy + // constructor + objects::pointer_holder* + p = new objects::pointer_holder(x); + + // Install it in the instance + p->install(raw_result); + + // Return the new result + return result.release(); +} + + +}}} // namespace boost::python::converter + +#endif // SMART_PTR_DWA2002123_HPP diff --git a/include/boost/python/converter/to_python.hpp b/include/boost/python/converter/to_python.hpp index 61dc7dad..a1d6c28b 100644 --- a/include/boost/python/converter/to_python.hpp +++ b/include/boost/python/converter/to_python.hpp @@ -101,7 +101,7 @@ template inline bool to_python_lookup::convertible() const { - return m_converter != 0; + return m_convert != 0; } template diff --git a/include/boost/python/converter/type_id.hpp b/include/boost/python/converter/type_id.hpp index fd731f83..e5068604 100644 --- a/include/boost/python/converter/type_id.hpp +++ b/include/boost/python/converter/type_id.hpp @@ -6,10 +6,8 @@ #ifndef TYPE_ID_DWA20011127_HPP # define TYPE_ID_DWA20011127_HPP # include -# include +# include # include -# include -# include # include # include # include @@ -79,80 +77,6 @@ struct type_id_t : totally_ordered base_id_t m_base_type; }; -# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -template -struct is_reference_to_const -{ - BOOST_STATIC_CONSTANT(bool, value = false); -}; - -template -struct is_reference_to_const -{ - BOOST_STATIC_CONSTANT(bool, value = true); -}; - -template -struct is_reference_to_volatile -{ - BOOST_STATIC_CONSTANT(bool, value = false); -}; - -template -struct is_reference_to_volatile -{ - BOOST_STATIC_CONSTANT(bool, value = true); -}; -# else -template -struct is_const_help -{ - typedef typename mpl::select_type< - is_const::value - , type_traits::yes_type - , type_traits::no_type - >::type type; -}; - -template -struct is_volatile_help -{ - typedef typename mpl::select_type< - is_volatile::value - , type_traits::yes_type - , type_traits::no_type - >::type type; -}; - -template -typename is_const_help::type reference_to_const_helper(V&); - -type_traits::no_type -reference_to_const_helper(...); - -template -struct is_reference_to_const -{ - static T t; - BOOST_STATIC_CONSTANT( - bool, value - = sizeof(reference_to_const_helper(t)) == sizeof(type_traits::yes_type)); -}; - -template -typename is_volatile_help::type reference_to_volatile_helper(V&); -type_traits::no_type reference_to_volatile_helper(...); - -template -struct is_reference_to_volatile -{ - static T t; - BOOST_STATIC_CONSTANT( - bool, value - = sizeof(reference_to_volatile_helper(t)) == sizeof(type_traits::yes_type)); -}; -# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template inline undecorated_type_id_t undecorated_type_id(detail::dummy* = 0) { @@ -165,9 +89,9 @@ inline type_id_t type_id(detail::dummy* = 0) return type_id_t( undecorated_type_id() , type_id_t::decoration( - (is_const::value || is_reference_to_const::value + (is_const::value || python::detail::is_reference_to_const::value ? type_id_t::const_ : 0) - | (is_volatile::value || is_reference_to_volatile::value + | (is_volatile::value || python::detail::is_reference_to_volatile::value ? type_id_t::volatile_ : 0) | (is_reference::value ? type_id_t::reference : 0) ) diff --git a/include/boost/python/copy_const_reference.hpp b/include/boost/python/copy_const_reference.hpp new file mode 100644 index 00000000..55e8f87f --- /dev/null +++ b/include/boost/python/copy_const_reference.hpp @@ -0,0 +1,42 @@ +// Copyright David Abrahams 2002. 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 COPY_CONST_REFERENCE_DWA2002131_HPP +# define COPY_CONST_REFERENCE_DWA2002131_HPP +# include +# include +# include + +namespace boost { namespace python { + +namespace detail +{ + template + struct copy_const_reference_expects_a_const_reference_return_type +# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__) + {} +# endif + ; +} + +template struct to_python; + +struct copy_const_reference +{ + template + struct apply + { + typedef typename mpl::select_type< + detail::is_reference_to_const::value + , to_python + , detail::copy_const_reference_expects_a_const_reference_return_type + >::type type; + }; +}; + + +}} // namespace boost::python + +#endif // COPY_CONST_REFERENCE_DWA2002131_HPP diff --git a/include/boost/python/copy_non_const_reference.hpp b/include/boost/python/copy_non_const_reference.hpp new file mode 100644 index 00000000..4afdc369 --- /dev/null +++ b/include/boost/python/copy_non_const_reference.hpp @@ -0,0 +1,42 @@ +// Copyright David Abrahams 2002. 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 COPY_NON_CONST_REFERENCE_DWA2002131_HPP +# define COPY_NON_CONST_REFERENCE_DWA2002131_HPP +# include +# include +# include + +namespace boost { namespace python { + +namespace detail +{ + template + struct copy_non_const_reference_expects_a_non_const_reference_return_type +# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__) + {} +# endif + ; +} + +template struct to_python; + +struct copy_non_const_reference +{ + template + struct apply + { + typedef typename mpl::select_type< + boost::python::detail::is_reference_to_non_const::value + , to_python + , detail::copy_non_const_reference_expects_a_non_const_reference_return_type + >::type type; + }; +}; + + +}} // namespace boost::python + +#endif // COPY_NON_CONST_REFERENCE_DWA2002131_HPP diff --git a/include/boost/python/default_call_policies.hpp b/include/boost/python/default_call_policies.hpp new file mode 100644 index 00000000..3dc3d4d4 --- /dev/null +++ b/include/boost/python/default_call_policies.hpp @@ -0,0 +1,72 @@ +// Copyright David Abrahams 2002. 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 DEFAULT_CALL_POLICIES_DWA2002131_HPP +# define DEFAULT_CALL_POLICIES_DWA2002131_HPP +# include +# include + +namespace boost { namespace python { + +template struct to_python; + +namespace detail +{ +// for "readable" error messages + template struct specify_a_result_policy_to_wrap_functions_returning +# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__) + {} +# endif + ; +} + +struct default_result_converter; + +struct default_call_policies +{ + // Nothing to do + static bool precall(PyObject*) + { + return true; + } + + // Pass the result through + static PyObject* postcall(PyObject*, PyObject* result) + { + return result; + } + + typedef default_result_converter result_converter; +}; + +struct default_result_converter +{ + template + struct apply + { + typedef typename mpl::select_type< + is_reference::value | is_pointer::value + , detail::specify_a_result_policy_to_wrap_functions_returning + , to_python + >::type type; + }; +}; + +// Exceptions for c strings an PyObject*s +template <> +struct default_result_converter::apply +{ + typedef boost::python::to_python type; +}; + +template <> +struct default_result_converter::apply +{ + typedef boost::python::to_python type; +}; + +}} // namespace boost::python + +#endif // DEFAULT_CALL_POLICIES_DWA2002131_HPP diff --git a/include/boost/python/detail/caller.hpp b/include/boost/python/detail/caller.hpp index 95c6dc7a..fe022961 100644 --- a/include/boost/python/detail/caller.hpp +++ b/include/boost/python/detail/caller.hpp @@ -6,19 +6,229 @@ #ifndef CALLER_DWA20011214_HPP # define CALLER_DWA20011214_HPP -# include # include +# include +# include +# include +# include +# include -namespace boost { namespace python { namespace detail { +namespace boost { namespace python +{ + template struct to_python; +}} + +namespace boost { namespace python { namespace detail { + +// for "readable" error messages +template struct must_use_a_result_handler_to_wrap_functions_returning +# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__) +{} +# endif +; + +struct to_python_generator +{ + template + struct apply + { + typedef typename mpl::select_type< + is_reference::value | is_pointer::value + , must_use_a_result_handler_to_wrap_functions_returning + , to_python + >::type type; + }; +}; struct caller { typedef PyObject* result_type; - template - PyObject* operator()(F f, PyObject* args, PyObject* keywords) + template + PyObject* operator()(R (*f)(), PyObject* args, PyObject* keywords, P const& policies) const { - return call(f, args, keywords); + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (*f)(A0), PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (*f)(A0, A1), PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (*f)(A0, A1, A2), PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (*f)(A0, A1, A2, A3), PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (*f)(A0, A1, A2, A3, A4), PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (*f)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + +// Member functions + template + PyObject* operator()(R (A0::*f)(), PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (A0::*f)(A1), PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (A0::*f)(A1, A2), PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (A0::*f)(A1, A2, A3), PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (A0::*f)(A1, A2, A3, A4), PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (A0::*f)(A1, A2, A3, A4, A5), PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (A0::*f)() const, PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (A0::*f)(A1) const, PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (A0::*f)(A1, A2) const, PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (A0::*f)(A1, A2, A3) const, PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (A0::*f)(A1, A2, A3, A4) const, PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (A0::*f)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (A0::*f)() volatile, PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (A0::*f)(A1) volatile, PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (A0::*f)(A1, A2) volatile, PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (A0::*f)(A1, A2, A3) volatile, PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (A0::*f)(A1, A2, A3, A4) volatile, PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (A0::*f)(A1, A2, A3, A4, A5) volatile, PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (A0::*f)() const volatile, PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (A0::*f)(A1) const volatile, PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (A0::*f)(A1, A2) const volatile, PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (A0::*f)(A1, A2, A3) const volatile, PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (A0::*f)(A1, A2, A3, A4) const volatile, PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); + } + + template + PyObject* operator()(R (A0::*f)(A1, A2, A3, A4, A5) const volatile, PyObject* args, PyObject* keywords, P const& policies) const + { + return returning::call(f, args, keywords, policies); } }; diff --git a/include/boost/python/detail/indirect_traits.hpp b/include/boost/python/detail/indirect_traits.hpp new file mode 100644 index 00000000..c76ffbc0 --- /dev/null +++ b/include/boost/python/detail/indirect_traits.hpp @@ -0,0 +1,116 @@ +// Copyright David Abrahams 2002. 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 INDIRECT_TRAITS_DWA2002131_HPP +# define INDIRECT_TRAITS_DWA2002131_HPP +# include +# include +# include + +namespace boost { namespace python { namespace detail { + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct is_reference_to_const +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +template +struct is_reference_to_const +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +template +struct is_reference_to_non_const +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +template +struct is_reference_to_non_const +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +template +struct is_reference_to_volatile +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +template +struct is_reference_to_volatile +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; +# else + +typedef char (&inner_yes_type)[3]; +typedef char (&inner_no_type)[2]; +typedef char (&outer_no_type)[1]; + +template +struct is_const_help +{ + typedef typename mpl::select_type< + is_const::value + , inner_yes_type + , inner_no_type + >::type type; +}; + +template +struct is_volatile_help +{ + typedef typename mpl::select_type< + is_volatile::value + , inner_yes_type + , inner_no_type + >::type type; +}; + +template +typename is_const_help::type reference_to_const_helper(V&); + +outer_no_type +reference_to_const_helper(...); + +template +struct is_reference_to_const +{ + static T t; + BOOST_STATIC_CONSTANT( + bool, value + = sizeof(reference_to_const_helper(t)) == sizeof(inner_yes_type)); +}; + +template +struct is_reference_to_non_const +{ + static T t; + BOOST_STATIC_CONSTANT( + bool, value + = sizeof(reference_to_const_helper(t)) == sizeof(inner_no_type)); +}; + +template +typename is_volatile_help::type reference_to_volatile_helper(V&); +outer_no_type reference_to_volatile_helper(...); + +template +struct is_reference_to_volatile +{ + static T t; + BOOST_STATIC_CONSTANT( + bool, value + = sizeof(reference_to_volatile_helper(t)) == sizeof(inner_yes_type)); +}; +# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +}}} // namespace boost::python::detail + +#endif // INDIRECT_TRAITS_DWA2002131_HPP diff --git a/include/boost/python/detail/returning.hpp b/include/boost/python/detail/returning.hpp index 4aa228b5..c8533f9e 100644 --- a/include/boost/python/detail/returning.hpp +++ b/include/boost/python/detail/returning.hpp @@ -18,25 +18,38 @@ # include # include +namespace boost { namespace python +{ + template struct to_python; +}} // namespace boost::python + namespace boost { namespace python { namespace detail { // Calling C++ from Python template struct returning { - template - static PyObject* call(R (A0::*pmf)(), PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); if (!c0.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)() ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)() ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (A0::*pmf)(A1), PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -45,11 +58,19 @@ struct returning if (!c1.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))) ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))) ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (A0::*pmf)(A1, A2), PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -60,11 +81,19 @@ struct returning if (!c2.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))) ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))) ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3), PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -77,11 +106,19 @@ struct returning if (!c3.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))) ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))) ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -96,11 +133,19 @@ struct returning if (!c4.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))) ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))) ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -117,23 +162,39 @@ struct returning if (!c5.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))) ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))) ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (A0::*pmf)() const, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)() const, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); if (!c0.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)() ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)() ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (A0::*pmf)(A1) const, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1) const, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -142,11 +203,19 @@ struct returning if (!c1.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))) ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))) ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (A0::*pmf)(A1, A2) const, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2) const, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -157,11 +226,19 @@ struct returning if (!c2.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))) ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))) ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3) const, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3) const, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -174,11 +251,19 @@ struct returning if (!c3.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))) ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))) ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -193,11 +278,19 @@ struct returning if (!c4.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))) ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))) ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -214,23 +307,39 @@ struct returning if (!c5.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))) ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))) ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (A0::*pmf)() volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)() volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); if (!c0.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)() ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)() ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (A0::*pmf)(A1) volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1) volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -239,11 +348,19 @@ struct returning if (!c1.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))) ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))) ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (A0::*pmf)(A1, A2) volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2) volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -254,11 +371,19 @@ struct returning if (!c2.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))) ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))) ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3) volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3) volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -271,11 +396,19 @@ struct returning if (!c3.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))) ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))) ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -290,11 +423,19 @@ struct returning if (!c4.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))) ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))) ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -311,26 +452,42 @@ struct returning if (!c5.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))) ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))) ); + + if (!result) return 0; + return policies.postcall(args, result); } // missing const volatile type traits # ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template - static PyObject* call(R (A0::*pmf)() const volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)() const volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); if (!c0.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)() ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)() ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (A0::*pmf)(A1) const volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1) const volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -339,11 +496,19 @@ struct returning if (!c1.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))) ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))) ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (A0::*pmf)(A1, A2) const volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2) const volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -354,11 +519,19 @@ struct returning if (!c2.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))) ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))) ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3) const volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3) const volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -371,11 +544,19 @@ struct returning if (!c3.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))) ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))) ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -390,11 +571,19 @@ struct returning if (!c4.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))) ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))) ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -411,31 +600,58 @@ struct returning if (!c5.convertible()) return 0; // find the result converter - to_python r; - return r( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))) ); + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))) ); + + if (!result) return 0; + return policies.postcall(args, result); } # endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - - static PyObject* call(R (*pf)(), PyObject*, PyObject* /* keywords */ ) + + + template + static PyObject* call(R (*pf)(), PyObject* args, PyObject*, P const& policies) { // find the result converter - to_python c0; - return c0( (*pf)() ); + typedef typename P::result_converter result_converter; + typename eval::type c0; + if (!c0.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = c0( (*pf)() ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (*pf)(A0), PyObject* args, PyObject* /* keywords */ ) + + template + static PyObject* call(R (*pf)(A0), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); if (!c0.convertible()) return 0; // find the result converter - to_python c1; - return c1( (*pf)(c0(PyTuple_GET_ITEM(args, 0))) ); + typedef typename P::result_converter result_converter; + typename eval::type c1; + if (!c1.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = c1( (*pf)(c0(PyTuple_GET_ITEM(args, 0))) ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (*pf)(A0, A1), PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (*pf)(A0, A1), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -444,11 +660,19 @@ struct returning if (!c1.convertible()) return 0; // find the result converter - to_python c2; - return c2( (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1))) ); + typedef typename P::result_converter result_converter; + typename eval::type c2; + if (!c2.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = c2( (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1))) ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (*pf)(A0, A1, A2), PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (*pf)(A0, A1, A2), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -459,11 +683,19 @@ struct returning if (!c2.convertible()) return 0; // find the result converter - to_python c3; - return c3( (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))) ); + typedef typename P::result_converter result_converter; + typename eval::type c3; + if (!c3.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = c3( (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))) ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (*pf)(A0, A1, A2, A3), PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (*pf)(A0, A1, A2, A3), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -476,11 +708,19 @@ struct returning if (!c3.convertible()) return 0; // find the result converter - to_python c4; - return c4( (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))) ); + typedef typename P::result_converter result_converter; + typename eval::type c4; + if (!c4.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = c4( (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))) ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (*pf)(A0, A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (*pf)(A0, A1, A2, A3, A4), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -495,11 +735,19 @@ struct returning if (!c4.convertible()) return 0; // find the result converter - to_python c5; - return c5( (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))) ); + typedef typename P::result_converter result_converter; + typename eval::type c5; + if (!c5.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = c5( (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))) ); + + if (!result) return 0; + return policies.postcall(args, result); } - template - static PyObject* call(R (*pf)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (*pf)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -516,8 +764,16 @@ struct returning if (!c5.convertible()) return 0; // find the result converter - to_python c6; - return c6( (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))) ); + typedef typename P::result_converter result_converter; + typename eval::type c6; + if (!c6.convertible()) return 0; + + if (!policies.precall(args)) return 0; + + PyObject* result = c6( (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))) ); + + if (!result) return 0; + return policies.postcall(args, result); } }; @@ -525,30 +781,36 @@ template <> struct returning { typedef void R; - template - static PyObject* call(R (A0::*pmf)(), PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); if (!c0.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (A0::*pmf)(A1), PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); if (!c0.convertible()) return 0; from_python c1(PyTuple_GET_ITEM(args, 1)); if (!c1.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (A0::*pmf)(A1, A2), PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -557,12 +819,15 @@ struct returning if (!c1.convertible()) return 0; from_python c2(PyTuple_GET_ITEM(args, 2)); if (!c2.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3), PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -573,12 +838,15 @@ struct returning if (!c2.convertible()) return 0; from_python c3(PyTuple_GET_ITEM(args, 3)); if (!c3.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -591,12 +859,15 @@ struct returning if (!c3.convertible()) return 0; from_python c4(PyTuple_GET_ITEM(args, 4)); if (!c4.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -611,35 +882,44 @@ struct returning if (!c4.convertible()) return 0; from_python c5(PyTuple_GET_ITEM(args, 5)); if (!c5.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (A0::*pmf)() const, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)() const, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); if (!c0.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (A0::*pmf)(A1) const, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1) const, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); if (!c0.convertible()) return 0; from_python c1(PyTuple_GET_ITEM(args, 1)); if (!c1.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (A0::*pmf)(A1, A2) const, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2) const, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -648,12 +928,15 @@ struct returning if (!c1.convertible()) return 0; from_python c2(PyTuple_GET_ITEM(args, 2)); if (!c2.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3) const, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3) const, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -664,12 +947,15 @@ struct returning if (!c2.convertible()) return 0; from_python c3(PyTuple_GET_ITEM(args, 3)); if (!c3.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -682,12 +968,15 @@ struct returning if (!c3.convertible()) return 0; from_python c4(PyTuple_GET_ITEM(args, 4)); if (!c4.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -702,35 +991,44 @@ struct returning if (!c4.convertible()) return 0; from_python c5(PyTuple_GET_ITEM(args, 5)); if (!c5.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (A0::*pmf)() volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)() volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); if (!c0.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (A0::*pmf)(A1) volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1) volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); if (!c0.convertible()) return 0; from_python c1(PyTuple_GET_ITEM(args, 1)); if (!c1.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (A0::*pmf)(A1, A2) volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2) volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -739,12 +1037,15 @@ struct returning if (!c1.convertible()) return 0; from_python c2(PyTuple_GET_ITEM(args, 2)); if (!c2.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3) volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3) volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -755,12 +1056,15 @@ struct returning if (!c2.convertible()) return 0; from_python c3(PyTuple_GET_ITEM(args, 3)); if (!c3.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -773,12 +1077,15 @@ struct returning if (!c3.convertible()) return 0; from_python c4(PyTuple_GET_ITEM(args, 4)); if (!c4.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -793,38 +1100,47 @@ struct returning if (!c4.convertible()) return 0; from_python c5(PyTuple_GET_ITEM(args, 5)); if (!c5.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))); - return detail::none(); + + return policies.postcall(args, detail::none()); } // missing const volatile type traits # ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template - static PyObject* call(R (A0::*pmf)() const volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)() const volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); if (!c0.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (A0::*pmf)(A1) const volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1) const volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); if (!c0.convertible()) return 0; from_python c1(PyTuple_GET_ITEM(args, 1)); if (!c1.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (A0::*pmf)(A1, A2) const volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2) const volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -833,12 +1149,15 @@ struct returning if (!c1.convertible()) return 0; from_python c2(PyTuple_GET_ITEM(args, 2)); if (!c2.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3) const volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3) const volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -849,12 +1168,15 @@ struct returning if (!c2.convertible()) return 0; from_python c3(PyTuple_GET_ITEM(args, 3)); if (!c3.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -867,12 +1189,15 @@ struct returning if (!c3.convertible()) return 0; from_python c4(PyTuple_GET_ITEM(args, 4)); if (!c4.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const volatile, PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const volatile, PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -887,42 +1212,53 @@ struct returning if (!c4.convertible()) return 0; from_python c5(PyTuple_GET_ITEM(args, 5)); if (!c5.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))); - return detail::none(); + + return policies.postcall(args, detail::none()); } # endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - - static PyObject* call(R (*pf)(), PyObject*, PyObject* /* keywords */ ) + + template + static PyObject* call(R (*pf)(), PyObject*, PyObject*, P const& policies) { (*pf)(); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (*pf)(A0), PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (*pf)(A0), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); if (!c0.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + (*pf)(c0(PyTuple_GET_ITEM(args, 0))); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (*pf)(A0, A1), PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (*pf)(A0, A1), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); if (!c0.convertible()) return 0; from_python c1(PyTuple_GET_ITEM(args, 1)); if (!c1.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1))); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (*pf)(A0, A1, A2), PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (*pf)(A0, A1, A2), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -931,12 +1267,15 @@ struct returning if (!c1.convertible()) return 0; from_python c2(PyTuple_GET_ITEM(args, 2)); if (!c2.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (*pf)(A0, A1, A2, A3), PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (*pf)(A0, A1, A2, A3), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -947,12 +1286,15 @@ struct returning if (!c2.convertible()) return 0; from_python c3(PyTuple_GET_ITEM(args, 3)); if (!c3.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (*pf)(A0, A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (*pf)(A0, A1, A2, A3, A4), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -965,12 +1307,15 @@ struct returning if (!c3.convertible()) return 0; from_python c4(PyTuple_GET_ITEM(args, 4)); if (!c4.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))); - return detail::none(); + + return policies.postcall(args, detail::none()); } - template - static PyObject* call(R (*pf)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ ) + template + static PyObject* call(R (*pf)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject*, P const& policies) { // check that each of the arguments is convertible from_python c0(PyTuple_GET_ITEM(args, 0)); @@ -985,9 +1330,12 @@ struct returning if (!c4.convertible()) return 0; from_python c5(PyTuple_GET_ITEM(args, 5)); if (!c5.convertible()) return 0; - + + if (!policies.precall(args)) return 0; + (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))); - return detail::none(); + + return policies.postcall(args, detail::none()); } }; diff --git a/include/boost/python/from_python.hpp b/include/boost/python/from_python.hpp new file mode 100644 index 00000000..995f7877 --- /dev/null +++ b/include/boost/python/from_python.hpp @@ -0,0 +1,42 @@ +// Copyright David Abrahams 2002. 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 FROM_PYTHON_DWA2002128_HPP +# define FROM_PYTHON_DWA2002128_HPP + +# include +# include + +namespace boost { namespace python { + +template +struct from_python + : converter::from_python_lookup::type> +{ + typedef converter::from_python_lookup::type> base; + from_python(PyObject*); +}; + +// specialization for PyObject* +template <> +struct from_python +{ + from_python(PyObject*) {} + bool convertible() const { return true; } + PyObject* operator()(PyObject* source) const { return source; } +}; + +// +// implementations +// +template +from_python::from_python(PyObject* source) + : base(source) +{ +} + +}} // namespace boost::python + +#endif // FROM_PYTHON_DWA2002128_HPP diff --git a/include/boost/python/make_function.hpp b/include/boost/python/make_function.hpp index dfd11865..6f989256 100644 --- a/include/boost/python/make_function.hpp +++ b/include/boost/python/make_function.hpp @@ -15,6 +15,7 @@ # include # include # include +# include namespace boost { namespace python { @@ -24,7 +25,17 @@ objects::function* make_function(F f) converter::acquire_registrations(detail::signature(f)); return new objects::function( objects::py_function( - ::boost::bind(detail::caller(), f, _1, _2)) + ::boost::bind(detail::caller(), f, _1, _2, default_call_policies())) + , detail::arg_tuple_size::value); +} + +template +objects::function* make_function(F f, Policies const& policies) +{ + converter::acquire_registrations(detail::signature(f)); + return new objects::function( + objects::py_function( + ::boost::bind(detail::caller(), f, _1, _2, policies)) , detail::arg_tuple_size::value); } @@ -41,7 +52,7 @@ objects::function* make_constructor(T* = 0, ArgList* = 0, Generator* = 0) ::boost::bind(detail::caller(), objects::make_holder ::template apply::execute - , _1, _2)) + , _1, _2, default_call_policies())) , nargs + 1); } diff --git a/include/boost/python/module.hpp b/include/boost/python/module.hpp index 5661e106..3a243b06 100644 --- a/include/boost/python/module.hpp +++ b/include/boost/python/module.hpp @@ -58,20 +58,20 @@ class module : public module_base return *this; } -# if 0 - template - void def_raw(char const* name, Fn fn) - { - add(detail::new_raw_arguments_function(fn), name); - } -# endif - template module& def(char const* name, Fn fn) { this->setattr(name, boost::python::make_function(fn)); return *this; } + + + template + module& def(char const* name, Fn fn, ResultHandler handler) + { + this->setattr(name, boost::python::make_function(fn, handler)); + return *this; + } }; // diff --git a/include/boost/python/return_internal_reference.hpp b/include/boost/python/return_internal_reference.hpp new file mode 100644 index 00000000..ac7f3fbf --- /dev/null +++ b/include/boost/python/return_internal_reference.hpp @@ -0,0 +1,45 @@ +// Copyright David Abrahams 2002. 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 RETURN_INTERNAL_REFERENCE_DWA2002131_HPP +# define RETURN_INTERNAL_REFERENCE_DWA2002131_HPP + +# include +# include + +namespace boost { namespace python { + +namespace detail +{ + template + struct return_internal_reference_requires_a_pointer_or_reference_return_type +# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__) + {} +# endif + ; +}; + +struct internal_reference_to_python_generator +{ + template + struct apply + { + typedef typename mpl::select_type< + !is_object::value + , internal_reference_to_python + , detail::return_internal_reference_requires_a_pointer_or_reference_return_type + >::type type; + }; +}; + +template +struct return_internal_reference : Base +{ + typedef wrap_internal_reference result_converter; +}; + +}} // namespace boost::python + +#endif // RETURN_INTERNAL_REFERENCE_DWA2002131_HPP diff --git a/include/boost/python/return_value_policy.hpp b/include/boost/python/return_value_policy.hpp new file mode 100644 index 00000000..0beec47b --- /dev/null +++ b/include/boost/python/return_value_policy.hpp @@ -0,0 +1,20 @@ +// Copyright David Abrahams 2002. 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 RETURN_VALUE_POLICY_DWA2002131_HPP +# define RETURN_VALUE_POLICY_DWA2002131_HPP +# include + +namespace boost { namespace python { + +template +struct return_value_policy : Base +{ + typedef Handler result_converter; +}; + +}} // namespace boost::python + +#endif // RETURN_VALUE_POLICY_DWA2002131_HPP diff --git a/include/boost/python/to_python.hpp b/include/boost/python/to_python.hpp new file mode 100644 index 00000000..e00346bb --- /dev/null +++ b/include/boost/python/to_python.hpp @@ -0,0 +1,37 @@ +// Copyright David Abrahams 2002. 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 TO_PYTHON_DWA2002128_HPP +# define TO_PYTHON_DWA2002128_HPP + +# include +# include + +namespace boost { namespace python { + +template +struct to_python + : converter::to_python_lookup::type> +{ +}; + +// specialization for PyObject* +template <> +struct to_python +{ + bool convertible() const { return true; } + PyObject* operator()(PyObject* source) const { return source; } +}; + +template <> +struct to_python +{ + bool convertible() const { return true; } + PyObject* operator()(PyObject* source) const { return source; } +}; + +}} // namespace boost::python + +#endif // TO_PYTHON_DWA2002128_HPP diff --git a/include/boost/python/type_from_python.hpp b/include/boost/python/type_from_python.hpp new file mode 100644 index 00000000..46d59d13 --- /dev/null +++ b/include/boost/python/type_from_python.hpp @@ -0,0 +1,23 @@ +// Copyright David Abrahams 2002. 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 TYPE_FROM_PYTHON_DWA2002130_HPP +# define TYPE_FROM_PYTHON_DWA2002130_HPP + +namespace boost { namespace python { + +template +struct type_from_python +{ + static void* convertible(PyObject* op) + { + return PyObject_TypeCheck( + op, const_cast(python_type)) ? op : 0; + } +}; + +}} // namespace boost::python + +#endif // TYPE_FROM_PYTHON_DWA2002130_HPP diff --git a/src/objects.cpp b/src/objects.cpp index 90417dac..b447b262 100644 --- a/src/objects.cpp +++ b/src/objects.cpp @@ -8,7 +8,9 @@ // TODO: Move inline implementations from objects.cpp here -#define BOOST_PYTHON_SOURCE +#ifndef BOOST_PYTHON_SOURCE +r# define BOOST_PYTHON_SOURCE +#endif #include #include diff --git a/test/m1.cpp b/test/m1.cpp index d422b426..b807dc43 100644 --- a/test/m1.cpp +++ b/test/m1.cpp @@ -12,7 +12,8 @@ #include #include #include -//#include +#include +#include #include #include #include @@ -198,6 +199,9 @@ BOOST_PYTHON_MODULE_INIT(m1) using boost::python::value_from_python; using boost::python::type_from_python; using boost::python::get_member; + using boost::python::copy_const_reference; + using boost::python::return_value_policy; + using boost::mpl::type_list; // Create the converters; they are self-registering/unregistering. static to_python_converter c1(simple_to_python); @@ -239,7 +243,8 @@ BOOST_PYTHON_MODULE_INIT(m1) .def("f", f) // Expose g() - .def("g", g) + .def("g", g , return_value_policy() + ) .def("take_a", take_a) .def("take_b", take_b) @@ -279,8 +284,8 @@ BOOST_PYTHON_MODULE_INIT(m1) .add( class_("complicated") - .def_init(args()) - .def_init(args()) + .def_init(type_list()) + .def_init(type_list()) .def("get_n", &complicated::get_n) ) ; diff --git a/test/m2.cpp b/test/m2.cpp index 0a5df161..afffb27d 100644 --- a/test/m2.cpp +++ b/test/m2.cpp @@ -8,6 +8,9 @@ // by exposing raw Python extension functions that use wrap<> and // unwrap<> objects. #include +#include +#include +#include #include "simple_type.hpp" // Get a simple (by value) from the argument, and return the @@ -59,6 +62,10 @@ struct rewrap BOOST_PYTHON_MODULE_INIT(m2) { + using boost::python::return_value_policy; + using boost::python::copy_const_reference; + using boost::python::copy_non_const_reference; + boost::python::module("m2") .def("unwrap_int", unwrap_int) .def("unwrap_int_ref", unwrap_int_ref) @@ -68,11 +75,24 @@ BOOST_PYTHON_MODULE_INIT(m2) .def("unwrap_simple_const_ref", unwrap_simple_const_ref) .def("wrap_int", &rewrap::f) - .def("wrap_int_ref", &rewrap::f) - .def("wrap_int_const_ref", &rewrap::f) + + .def("wrap_int_ref", &rewrap::f + , return_value_policy() + ) + + .def("wrap_int_const_ref", &rewrap::f + , return_value_policy() + ) + .def("wrap_simple", &rewrap::f) - .def("wrap_simple_ref", &rewrap::f) - .def("wrap_simple_const_ref", &rewrap::f) + + .def("wrap_simple_ref", &rewrap::f + , return_value_policy() + ) + + .def("wrap_simple_const_ref", &rewrap::f + , return_value_policy() + ) ; } From 7a16cd4c37525ff4ce58cf8f074d80633a019668 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 2 Feb 2002 00:46:38 +0000 Subject: [PATCH 243/369] remove local rule usage for the time being. [SVN r12625] --- build/Jamfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/Jamfile b/build/Jamfile index 7fd8c285..744c8ec2 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -136,7 +136,7 @@ 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 + ) +rule boost-python-multi-example-runtest ( test-name : modules + ) { boost-python-runtest $(test-name) : ../example/tst_$(test-name).py $(modules) libboost_python From 684e391a9a38d4fb2687bc634da7e102e45727ed Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 2 Feb 2002 00:49:24 +0000 Subject: [PATCH 244/369] remove local rule usage for the time being. [SVN r12626] --- build/Jamfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/Jamfile b/build/Jamfile index 744c8ec2..1ea3665d 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -64,7 +64,7 @@ include python.jam ; local PYTHON_PROPERTIES = $(PYTHON_PROPERTIES) BOOST_PYTHON_DYNAMIC_LIB ; ####################### -local rule bpl-test ( test-name : sources + ) +rule bpl-test ( test-name : sources + ) { boost-python-test $(test-name) : $(sources) libboost_python ; } @@ -108,7 +108,7 @@ boost-python-runtest comprehensive ############# simple tests from ../example ############ -local rule boost-python-example-runtest ( name ) +rule boost-python-example-runtest ( name ) { bpl-test $(name) : ../example/$(name).cpp ; From 12988b879e344446decf84bcf6764383bf7e1c50 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 2 Feb 2002 08:31:11 +0000 Subject: [PATCH 245/369] *** empty log message *** [SVN r12627] --- include/boost/python/copy_const_reference.hpp | 4 ++-- include/boost/python/copy_non_const_reference.hpp | 4 ++-- include/boost/python/default_call_policies.hpp | 12 ++++++++---- include/boost/python/make_function.hpp | 6 ------ 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/include/boost/python/copy_const_reference.hpp b/include/boost/python/copy_const_reference.hpp index 55e8f87f..57c45fd4 100644 --- a/include/boost/python/copy_const_reference.hpp +++ b/include/boost/python/copy_const_reference.hpp @@ -21,7 +21,7 @@ namespace detail ; } -template struct to_python; +template struct to_python_value; struct copy_const_reference { @@ -30,7 +30,7 @@ struct copy_const_reference { typedef typename mpl::select_type< detail::is_reference_to_const::value - , to_python + , to_python_value , detail::copy_const_reference_expects_a_const_reference_return_type >::type type; }; diff --git a/include/boost/python/copy_non_const_reference.hpp b/include/boost/python/copy_non_const_reference.hpp index 4afdc369..dead736f 100644 --- a/include/boost/python/copy_non_const_reference.hpp +++ b/include/boost/python/copy_non_const_reference.hpp @@ -21,7 +21,7 @@ namespace detail ; } -template struct to_python; +template struct to_python_value; struct copy_non_const_reference { @@ -30,7 +30,7 @@ struct copy_non_const_reference { typedef typename mpl::select_type< boost::python::detail::is_reference_to_non_const::value - , to_python + , to_python_value , detail::copy_non_const_reference_expects_a_non_const_reference_return_type >::type type; }; diff --git a/include/boost/python/default_call_policies.hpp b/include/boost/python/default_call_policies.hpp index 3dc3d4d4..475278e4 100644 --- a/include/boost/python/default_call_policies.hpp +++ b/include/boost/python/default_call_policies.hpp @@ -7,10 +7,12 @@ # define DEFAULT_CALL_POLICIES_DWA2002131_HPP # include # include +# include +# include namespace boost { namespace python { -template struct to_python; +template struct to_python_value; namespace detail { @@ -49,7 +51,9 @@ struct default_result_converter typedef typename mpl::select_type< is_reference::value | is_pointer::value , detail::specify_a_result_policy_to_wrap_functions_returning - , to_python + , boost::python::to_python_value< + typename add_reference::type>::type + > >::type type; }; }; @@ -58,13 +62,13 @@ struct default_result_converter template <> struct default_result_converter::apply { - typedef boost::python::to_python type; + typedef boost::python::to_python_value type; }; template <> struct default_result_converter::apply { - typedef boost::python::to_python type; + typedef boost::python::to_python_value type; }; }} // namespace boost::python diff --git a/include/boost/python/make_function.hpp b/include/boost/python/make_function.hpp index 6f989256..90a5c12b 100644 --- a/include/boost/python/make_function.hpp +++ b/include/boost/python/make_function.hpp @@ -11,7 +11,6 @@ # include # include # include -# include # include # include # include @@ -22,7 +21,6 @@ namespace boost { namespace python { template objects::function* make_function(F f) { - converter::acquire_registrations(detail::signature(f)); return new objects::function( objects::py_function( ::boost::bind(detail::caller(), f, _1, _2, default_call_policies())) @@ -32,7 +30,6 @@ objects::function* make_function(F f) template objects::function* make_function(F f, Policies const& policies) { - converter::acquire_registrations(detail::signature(f)); return new objects::function( objects::py_function( ::boost::bind(detail::caller(), f, _1, _2, policies)) @@ -44,9 +41,6 @@ objects::function* make_constructor(T* = 0, ArgList* = 0, Generator* = 0) { enum { nargs = mpl::size::value }; - typedef typename mpl::push_front::sequence signature; - converter::acquire_registrations(signature()); - return new objects::function( objects::py_function( ::boost::bind(detail::caller(), From 25c56164b02dd578677b664191deebb6d6dca52b Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 2 Feb 2002 14:04:48 +0000 Subject: [PATCH 246/369] Last rewrite of the type conversion mechanism, I hope [SVN r12631] --- Jamfile | 1 - example/rwgk2.cpp | 50 ------ example/rwgk3.cpp | 101 ----------- .../builtin_to_python_converters.hpp | 89 ++++------ .../boost/python/converter/from_python.hpp | 55 ++++-- .../boost/python/converter/registration.hpp | 148 ---------------- include/boost/python/converter/registry.hpp | 62 +------ include/boost/python/converter/source.hpp | 32 ---- .../boost/python/converter/source_holder.hpp | 24 --- include/boost/python/converter/to_python.hpp | 116 ------------- .../python/converter/to_python_function.hpp | 17 +- include/boost/python/converter/type_id.hpp | 25 +-- .../boost/python/converter/wrapper_base.hpp | 28 --- include/boost/python/copy_const_reference.hpp | 2 +- .../boost/python/copy_non_const_reference.hpp | 2 +- include/boost/python/detail/caller.hpp | 20 --- include/boost/python/detail/msvc_typeinfo.hpp | 99 +++++++++++ include/boost/python/detail/returning.hpp | 7 - include/boost/python/make_function.hpp | 1 - include/boost/python/object/class_wrapper.hpp | 16 +- include/boost/python/to_python.hpp | 37 ---- src/converter/builtin_converters.cpp | 1 - src/converter/from_python.cpp | 11 +- src/converter/registry.cpp | 164 +++++------------- src/converter/to_python.cpp | 24 --- src/converter/type_id.cpp | 6 - src/object/class.cpp | 3 +- test/m1.cpp | 44 ++--- test/newtest.py | 36 ++-- 29 files changed, 305 insertions(+), 916 deletions(-) delete mode 100644 example/rwgk2.cpp delete mode 100644 example/rwgk3.cpp delete mode 100644 include/boost/python/converter/registration.hpp delete mode 100644 include/boost/python/converter/source.hpp delete mode 100644 include/boost/python/converter/source_holder.hpp delete mode 100644 include/boost/python/converter/to_python.hpp delete mode 100644 include/boost/python/converter/wrapper_base.hpp create mode 100644 include/boost/python/detail/msvc_typeinfo.hpp delete mode 100644 include/boost/python/to_python.hpp delete mode 100644 src/converter/to_python.cpp diff --git a/Jamfile b/Jamfile index 684c21d5..fec34d51 100644 --- a/Jamfile +++ b/Jamfile @@ -15,7 +15,6 @@ PYTHON_PROPERTIES dll bpl : src/converter/from_python.cpp - src/converter/to_python.cpp src/converter/registry.cpp src/converter/type_id.cpp src/object/class.cpp diff --git a/example/rwgk2.cpp b/example/rwgk2.cpp deleted file mode 100644 index 35dce88f..00000000 --- a/example/rwgk2.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include - -namespace { // Avoid cluttering the global namespace. - - // A friendly class. - class world - { - private: - std::string country; - public: - world(const std::string& country) { this->country = country; } - std::string greet() const { return "Hello from " + country + "!"; } - }; - - // A function taking a world object as an argument. - std::string invite(const world& w) { - return w.greet() + " Please come soon!"; - } -} - -#include - -// Python requires an exported function called init in every -// extension module. This is where we build the module contents. -BOOST_PYTHON_MODULE_INIT(example2) -{ - // Create an object representing this extension module. - py::Module this_module("example2"); - - // Create the Python type object for our extension class. - py::ClassWrapper world_class(this_module, "world"); - - // Add the __init__ function. - world_class.def(py::Constructor()); - // Add a regular member function. - world_class.def(&world::greet, "greet"); - - // Add invite() as a regular function to the module. - this_module.def(invite, "invite"); - - // Even better, invite() can also be made a member of world_class!!! - world_class.def(invite, "invite"); -} - -// Win32 DLL boilerplate -#if defined(_WIN32) -#include -extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) { return 1; } -#endif // _WIN32 diff --git a/example/rwgk3.cpp b/example/rwgk3.cpp deleted file mode 100644 index df17b28e..00000000 --- a/example/rwgk3.cpp +++ /dev/null @@ -1,101 +0,0 @@ -#include -#include - -#define rangei(n) for (int i = 0; i < n; i++) - -namespace { // Avoid cluttering the global namespace. - - // A wrapper is used to define additional constructors. - // - struct vector_double_wrapper: std::vector - { - // Tell the compiler how to convert a base class object to - // this wrapper object. - vector_double_wrapper(PyObject*, const std::vector& vd) - : std::vector(vd) {} - - vector_double_wrapper(PyObject* self) - : std::vector() {} - - vector_double_wrapper(PyObject* self, const int n) - : std::vector(n) {} - - vector_double_wrapper(PyObject* self, py::Tuple tuple) - : std::vector(tuple.size()) - { - std::vector::iterator vd = begin(); - rangei(tuple.size()) - vd[i] = from_python(tuple[i].get(), py::Type()); // GCC BUG - } - }; - - double getitem(const std::vector& vd, const std::size_t key) { - return vd[key]; - } - - void setitem(std::vector& vd, const std::size_t key, - const double &d) { - std::vector::iterator vditer = vd.begin(); - vditer[key] = d; - } - - void delitem(std::vector& vd, const std::size_t key) { - std::vector::iterator vditer = vd.begin(); - vd.erase(&vditer[key]); - } - - // Convert vector_double to a regular Python tuple. - // - py::Tuple as_tuple(const std::vector& vd) - { - py::Tuple t(vd.size()); - rangei(vd.size()) t.set_item(i, py::Ptr(py::to_python(vd[i]))); // GCC BUG - return t; - } - - // Function returning a vector_double object to Python. - // - std::vector foo(const int n) - { - std::vector vd(n); - std::vector::iterator vditer = vd.begin(); - rangei(n) vditer[i] = double(i); - return vd; - } - - // Same as foo(), but avoid copying on return. - // - std::auto_ptr > bar(const int n) - { - std::auto_ptr > vdptr(new std::vector(n)); - std::vector::iterator vditer = vdptr->begin(); - rangei(n) vditer[i] = double(10 * i); - return vdptr; - } -} - -BOOST_PYTHON_MODULE_INIT(example3) -{ - py::Module this_module("example3"); - - py::ClassWrapper, vector_double_wrapper> - vector_double(this_module, "vector_double"); - - vector_double.def(py::Constructor<>()); - vector_double.def(py::Constructor()); - vector_double.def(py::Constructor()); - vector_double.def(&std::vector::size, "__len__"); - vector_double.def(getitem, "__getitem__"); - vector_double.def(setitem, "__setitem__"); - vector_double.def(delitem, "__delitem__"); - vector_double.def(as_tuple, "as_tuple"); - - this_module.def(foo, "foo"); - this_module.def(bar, "bar"); -} - -// Win32 DLL boilerplate -#if defined(_WIN32) -#include -extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) { return 1; } -#endif // _WIN32 diff --git a/include/boost/python/converter/builtin_to_python_converters.hpp b/include/boost/python/converter/builtin_to_python_converters.hpp index 4e9f89e3..89ad7b86 100644 --- a/include/boost/python/converter/builtin_to_python_converters.hpp +++ b/include/boost/python/converter/builtin_to_python_converters.hpp @@ -8,20 +8,41 @@ # include # include -namespace boost { namespace python { namespace converter { +namespace boost { namespace python { -template struct to_python_lookup; +// Provide specializations of to_python_value +template struct to_python_value; -template -struct to_python_int +namespace detail { - bool convertible() const { return true; } - PyObject* operator()(T x) const { return PyInt_FromLong(long(x)); } -}; + struct builtin_to_python + { + static bool convertible() { return true; } + }; +} -# define BOOST_PYTHON_TO_INT(T) \ - template <> struct to_python_lookup : to_python_int {}; \ - template <> struct to_python_lookup : to_python_int {}; +# define BOOST_PYTHON_TO_PYTHON_BY_VALUE(T, expr) \ + template <> struct to_python_value \ + : detail::builtin_to_python \ + { \ + PyObject* operator()(T const& x) const \ + { \ + return (expr); \ + } \ + }; \ + template <> struct to_python_value \ + : detail::builtin_to_python \ + { \ + PyObject* operator()(T const& x) const \ + { \ + return (expr); \ + } \ + }; + + +# define BOOST_PYTHON_TO_INT(T) \ + BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, PyInt_FromLong(x)) \ + BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned T, PyInt_FromLong(x)) BOOST_PYTHON_TO_INT(char) BOOST_PYTHON_TO_INT(short) @@ -29,47 +50,13 @@ BOOST_PYTHON_TO_INT(int) BOOST_PYTHON_TO_INT(long) # undef BOOST_TO_PYTHON_INT -template <> -struct to_python_lookup -{ - bool convertible() const { return true; } - PyObject* operator()(char const* x) const { return PyString_FromString(x); } -}; - -template <> -struct to_python_lookup -{ - bool convertible() const { return true; } - PyObject* operator()(std::string const& x) const - { - return PyString_FromString(x.c_str()); - } -}; +BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, PyString_FromString(x)) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, PyString_FromString(x.c_str())) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, PyFloat_FromDouble(x)) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, PyFloat_FromDouble(x)) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, PyFloat_FromDouble(x)) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(PyObject*, x) -template <> -struct to_python_lookup -{ - bool convertible() const { return true; } - PyObject* operator()(float x) const { return PyFloat_FromDouble(x); } -}; - -template <> -struct to_python_lookup -{ - bool convertible() const { return true; } - PyObject* operator()(double x) const { return PyFloat_FromDouble(x); } -}; - -template <> -struct to_python_lookup -{ - bool convertible() const { return true; } - PyObject* operator()(long double x) const - { - return PyFloat_FromDouble(x); - } -}; - -}}} // namespace boost::python::converter +}} // namespace boost::python::converter #endif // BUILTIN_TO_PYTHON_CONVERTERS_DWA2002129_HPP diff --git a/include/boost/python/converter/from_python.hpp b/include/boost/python/converter/from_python.hpp index 234f61d1..ee16a741 100644 --- a/include/boost/python/converter/from_python.hpp +++ b/include/boost/python/converter/from_python.hpp @@ -11,7 +11,7 @@ # include # include # include -# include +# include # include namespace boost { namespace python { namespace converter { @@ -29,16 +29,21 @@ template struct from_python_lookup; struct BOOST_PYTHON_DECL from_python_converter_base : body { from_python_converter_base(type_id_t, from_python_check); // registers - ~from_python_converter_base(); // unregisters // Must return non-null iff the conversion will be successful. Any // non-null pointer is acceptable, and will be passed on to the // convert() function, so useful data can be stored there. inline void* convertible(PyObject*) const; -// inline type_id_t key() const; + + // Given the head of a from_python converter chain, find the + // converter which can convert p, leaving its intermediate data in + // data. + inline static from_python_converter_base const* + find(from_python_converter_base const*chain, PyObject* p, void*& data); + private: -// type_id_t m_key; from_python_check m_convertible; + from_python_converter_base* m_next; }; @@ -52,17 +57,24 @@ struct from_python_converter : from_python_converter_base from_python_converter(from_python_check, conversion_function, from_python_destructor = 0); T convert(PyObject*, from_python_data&) const; void destroy(from_python_data&) const; + + // Find a converter for converting p to a T. + static from_python_converter const* find(PyObject* p, void*& data); private: // data members conversion_function m_convert; from_python_destructor m_destroy; + + // Keeps the chain of converters which convert from PyObject* to T + static from_python_converter_base*const& chain; }; -// ------------------------------------------------------------------------- +// Initialized to refer to a common place in the registry. +template +from_python_converter_base*const& +from_python_converter::chain = registry::from_python_chain(type_id()); -//struct from_python_base -//{ -//}; +// ------------------------------------------------------------------------- // A class which implements from_python with a registry lookup. template @@ -95,12 +107,21 @@ inline void* from_python_converter_base::convertible(PyObject* o) const return m_convertible(o); } -# if 0 -inline type_id_t from_python_converter_base::key() const +inline from_python_converter_base const* +from_python_converter_base::find( + from_python_converter_base const* chain, PyObject* p, void*& data) { - return m_key; + for (from_python_converter_base const* q = chain; q != 0 ; q = q->m_next) + { + void* d = q->convertible(p); + if (d != 0) + { + data = d; + return q; + } + } + return 0; } -# endif template inline from_python_converter::from_python_converter( @@ -115,6 +136,14 @@ inline from_python_converter::from_python_converter( } +template +inline from_python_converter const* +from_python_converter::find(PyObject* p, void*& data) +{ + return static_cast const*>( + from_python_converter_base::find(chain, p, data)); +} + template inline T from_python_converter::convert(PyObject* src, from_python_data& data) const { @@ -133,7 +162,7 @@ inline void from_python_converter::destroy(from_python_data& data) const template inline from_python_lookup::from_python_lookup(PyObject* src) : m_converter( - registration::get_from_python( + from_python_converter::find( src, m_intermediate_data.stage1)) { } diff --git a/include/boost/python/converter/registration.hpp b/include/boost/python/converter/registration.hpp deleted file mode 100644 index 39223d8a..00000000 --- a/include/boost/python/converter/registration.hpp +++ /dev/null @@ -1,148 +0,0 @@ -// 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 REGISTRATION_DWA20011130_HPP -# define REGISTRATION_DWA20011130_HPP -# include -# include -# include -# include -# include -# include -# include -# include -# ifdef BOOST_PYTHON_TRACE -# include -# endif - -namespace boost { namespace python { namespace converter { - -template struct from_python_converter; -template struct target; -template struct source; - -// This class is really sort of a "templated namespace". It manages a -// static data member which refers to the registry entry for T. This -// reference is acquired once to reduce the burden of multiple -// dictionary lookups at runtime. -template -struct registration -{ - public: // member functions - // Return a converter which can convert the given Python object to - // T, or 0 if no such converter exists. Fill in data with - // the result of the converter's check function - static from_python_converter const* get_from_python(PyObject*, void*& data); - - // Return a converter which can convert T to a Python object, or 0 - // if no such converter exists - static to_python_function::type get_to_python(); - - static registry::entry* find_entry(); - private: // helper functions - static registry::entry* entry(); - static registry::entry* known_entry(); - - private: // data members - static registry::entry* m_registry_entry; -}; - -namespace detail -{ - // An MPL BinaryMetaFunction class which initializes the - // registration entry for the target type of its 2nd argument. - struct setup_target_registration - { - template struct apply - { - typedef T type; - static void execute() - { - typedef typename target::type target_t; - registration::find_entry(); - } - }; - }; - - template - struct find_return_value_entry - { - static void execute() { registration::find_entry(); } - }; - - template <> - struct find_return_value_entry - { - static void execute() {} - }; - -# if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 - template <> - struct find_return_value_entry - { - static void execute() {} - }; -# endif -} - -template -void acquire_registrations(Sequence signature) -{ - typedef typename mpl::pop_front::sequence args; - typedef typename mpl::front::type return_type; - - mpl::for_each::execute(); - - typedef typename source::type return_source_type; - detail::find_return_value_entry::execute(); -} - - -// because this is static POD data it will be initialized to zero -template -registry::entry* registration::m_registry_entry; - -template -registry::entry* registration::find_entry() -{ - return m_registry_entry = registry::find(type_id()); -} - -template -inline registry::entry* registration::entry() -{ - if (!m_registry_entry) - find_entry(); - return m_registry_entry; -} - -template -inline registry::entry* registration::known_entry() -{ - assert(m_registry_entry != 0); - return m_registry_entry; -} - -template -from_python_converter const* registration::get_from_python(PyObject* p, void*& data) -{ - return static_cast const*>( - known_entry()->get_from_python(p, data) - ); -} - -template -typename to_python_function::type registration::get_to_python() -{ -# ifdef BOOST_PYTHON_TRACE - std::cout << "retrieving wrapper for " << type_id() << std::endl; -# endif - return reinterpret_cast::type>( - known_entry()->get_to_python()); -} - -}}} // namespace boost::python::converter - -#endif // REGISTRATION_DWA20011130_HPP diff --git a/include/boost/python/converter/registry.hpp b/include/boost/python/converter/registry.hpp index 21f31692..bdb64254 100644 --- a/include/boost/python/converter/registry.hpp +++ b/include/boost/python/converter/registry.hpp @@ -5,72 +5,26 @@ // to its suitability for any purpose. #ifndef REGISTRY_DWA20011127_HPP # define REGISTRY_DWA20011127_HPP -# include # include # include +# include # include -# include -# include -# include namespace boost { namespace python { namespace converter { struct BOOST_PYTHON_DECL from_python_converter_base; -struct BOOST_PYTHON_DECL to_python_converter_base; // This namespace acts as a sort of singleton namespace registry { - // These are the elements stored in the registry - class BOOST_PYTHON_DECL entry - { - public: // member functions - entry(); - ~entry(); - - // Return a converter appropriate for converting the given - // Python object from_python to the C++ type with which this - // converter is associated in the registry, or 0 if no such - // converter exists. - from_python_converter_base const* get_from_python(PyObject*, void*& data) const; - - // Return a conversion function appropriate for converting a C++ - // object whose type this entry is associated with in the - // registry to a Python object, or 0 if no such converter - // exists. This function must be reinterpret_cast to the - // appropriate to_python_function type. - to_python_function_base get_to_python() const; - - // Conversion classes use these functions to register - // themselves. - void insert(from_python_converter_base&); - void remove(from_python_converter_base&); - - void insert(to_python_converter_base&); - void remove(to_python_converter_base&); - - private: // types - typedef std::vector from_python_converters; - - private: // helper functions - from_python_converters::iterator find(from_python_converter_base const&); - - private: // data members - - // The collection of from_python converters for the associated - // C++ type. - from_python_converters m_from_python_converters; - - // The unique to_python converter for the associated C++ type. - to_python_converter_base* m_to_python_converter; - }; - - BOOST_PYTHON_DECL entry* find(type_id_t); + BOOST_PYTHON_DECL to_python_value_function const& + to_python_function(undecorated_type_id_t); - BOOST_PYTHON_DECL void insert(to_python_converter_base& x); - BOOST_PYTHON_DECL void insert(from_python_converter_base& x); - BOOST_PYTHON_DECL void remove(to_python_converter_base& x); - BOOST_PYTHON_DECL void remove(from_python_converter_base& x); + BOOST_PYTHON_DECL void insert(to_python_value_function, undecorated_type_id_t); + + BOOST_PYTHON_DECL from_python_converter_base*& from_python_chain(type_id_t); + + BOOST_PYTHON_DECL PyTypeObject*& class_object(undecorated_type_id_t key); } }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/source.hpp b/include/boost/python/converter/source.hpp deleted file mode 100644 index 9abf245f..00000000 --- a/include/boost/python/converter/source.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// 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 SOURCE_DWA20011119_HPP -# define SOURCE_DWA20011119_HPP -# include -# include -# include - -namespace boost { namespace python { namespace converter { - -// source -- -// -// This type generator (see -// ../../../more/generic_programming.html#type_generator) is used -// to select the argument type to use when converting T to a PyObject* - -template -struct source -{ - typedef - typename add_reference< - typename add_const::type - >::type - type; -}; - -}}} // namespace boost::python::converter - -#endif // SOURCE_DWA20011119_HPP diff --git a/include/boost/python/converter/source_holder.hpp b/include/boost/python/converter/source_holder.hpp deleted file mode 100644 index f2c774f9..00000000 --- a/include/boost/python/converter/source_holder.hpp +++ /dev/null @@ -1,24 +0,0 @@ -// 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 SOURCE_HOLDER_DWA20011215_HPP -# define SOURCE_HOLDER_DWA20011215_HPP - -namespace boost { namespace python { namespace converter { - -struct source_holder_base -{ -}; - -template -struct source_holder : source_holder_base -{ - source_holder(T x) : value(x) {} - T value; -}; - -}}} // namespace boost::python::converter - -#endif // SOURCE_HOLDER_DWA20011215_HPP diff --git a/include/boost/python/converter/to_python.hpp b/include/boost/python/converter/to_python.hpp deleted file mode 100644 index a1d6c28b..00000000 --- a/include/boost/python/converter/to_python.hpp +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright David Abrahams 2002. 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 TO_PYTHON_DWA2002127_HPP -# define TO_PYTHON_DWA2002127_HPP - -# include -# include -# include -# include -# include -# include - -namespace boost { namespace python { namespace converter { - -template struct to_python_lookup; - -struct BOOST_PYTHON_DECL to_python_converter_base : body -{ - to_python_converter_base(type_id_t, to_python_function_base); // registers - ~to_python_converter_base(); // unregisters - -// inline type_id_t key() const; - inline to_python_function_base converter() const; - private: -// type_id_t m_key; - to_python_function_base m_convert; -}; - -template -struct to_python_converter : to_python_converter_base -{ - public: // types - typedef typename to_python_function::type converter_t; - - public: // member functions - to_python_converter(converter_t); - converter_t converter() const; - - private: // data members - converter_t m_convert; -}; - -// ------------------------------------------------------------------------- - -//struct to_python_base {}; - -template -struct to_python_lookup //: to_python_base -{ - public: // member functions - to_python_lookup(); - bool convertible() const; - PyObject* operator()(T) const; - private: - typename to_python_function::type m_convert; -}; - -// -// implementations -// -# if 0 -inline type_id_t -to_python_converter_base::key() const -{ - return m_key; -} -# endif - -inline to_python_function_base -to_python_converter_base::converter() const -{ - return m_convert; -} - -template -to_python_converter::to_python_converter(converter_t convert) - : to_python_converter_base( - type_id(), reinterpret_cast(convert)) -{ -} - -template -inline typename to_python_function::type -to_python_converter::converter() const -{ - return reinterpret_cast( - this->to_python_converter_base::converter()); -} - -template -inline to_python_lookup::to_python_lookup() - : m_convert( - registration::get_to_python()) -{ -} - -template -inline bool -to_python_lookup::convertible() const -{ - return m_convert != 0; -} - -template -inline PyObject* -to_python_lookup::operator()(T x) const -{ - return m_convert ? m_convert(x) : 0; -} - -}}} // namespace boost::python::converter - -#endif // TO_PYTHON_DWA2002127_HPP diff --git a/include/boost/python/converter/to_python_function.hpp b/include/boost/python/converter/to_python_function.hpp index 9d408749..a438ce0c 100644 --- a/include/boost/python/converter/to_python_function.hpp +++ b/include/boost/python/converter/to_python_function.hpp @@ -7,15 +7,24 @@ # define TO_PYTHON_FUNCTION_DWA2002128_HPP # include +# include namespace boost { namespace python { namespace converter { -typedef PyObject* (*to_python_function_base)(void); +// The type of stored function pointers which actually do conversion +// by-value. The void* points to the object to be converted, and +// type-safety is preserved through runtime registration. +typedef PyObject* (*to_python_value_function)(void const*); -template -struct to_python_function +// Given a typesafe to_python conversion function, produces a +// to_python_value_function which can be registered in the usual way. +template +struct as_to_python_value_function { - typedef PyObject*(*type)(T); + static PyObject* convert(void const* x) + { + return ToPython::convert(*(T const*)x); + } }; }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/type_id.hpp b/include/boost/python/converter/type_id.hpp index e5068604..015e55e9 100644 --- a/include/boost/python/converter/type_id.hpp +++ b/include/boost/python/converter/type_id.hpp @@ -7,8 +7,12 @@ # define TYPE_ID_DWA20011127_HPP # include # include +# include +# include +# include # include # include +# include # include # include # include @@ -16,13 +20,6 @@ namespace boost { namespace python { namespace converter { -// a portable mechanism for identifying types at runtime across modules. - -namespace detail -{ - template class dummy; -} - // for this compiler at least, cross-shared-library type_info // comparisons don't work, so use typeid(x).name() instead. It's not // yet clear what the best default strategy is. @@ -61,7 +58,7 @@ struct type_id_t : totally_ordered { enum decoration { const_ = 0x1, volatile_ = 0x2, reference = 0x4 }; - type_id_t(undecorated_type_id_t, decoration decoration); + type_id_t(undecorated_type_id_t, decoration = decoration()); bool operator<(type_id_t const& rhs) const; bool operator==(type_id_t const& rhs) const; @@ -78,13 +75,19 @@ struct type_id_t : totally_ordered }; template -inline undecorated_type_id_t undecorated_type_id(detail::dummy* = 0) +inline undecorated_type_id_t undecorated_type_id(boost::type* = 0) { - return undecorated_type_id_t(typeid(T)); + return undecorated_type_id_t( +# if (!defined(BOOST_MSVC) || BOOST_MSVC > 1300) && (!defined(BOOST_INTEL_CXX_VERSION) || BOOST_INTEL_CXX_VERSION > 600) + typeid(T) +# else // strip the decoration which msvc and Intel mistakenly leave in + python::detail::msvc_typeid() +# endif + ); } template -inline type_id_t type_id(detail::dummy* = 0) +inline type_id_t type_id(boost::type* = 0) { return type_id_t( undecorated_type_id() diff --git a/include/boost/python/converter/wrapper_base.hpp b/include/boost/python/converter/wrapper_base.hpp deleted file mode 100644 index 585959ae..00000000 --- a/include/boost/python/converter/wrapper_base.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright David Abrahams 2002. 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 WRAPPER_BASE_DWA2002110_HPP -# define WRAPPER_BASE_DWA2002110_HPP -# include -# include - -namespace boost { namespace python { namespace converter { - -struct source_holder_base; -struct wrap_base; -template struct wrap_more_; - -struct BOOST_PYTHON_DECL wrapper_base : body -{ - public: - wrapper_base(type_id_t); // registers - ~wrapper_base(); // unregisters - - virtual PyObject* do_conversion(wrap_base const&, source_holder_base const&) const = 0; -}; - -}}} // namespace boost::python::converter - -#endif // WRAPPER_BASE_DWA2002110_HPP diff --git a/include/boost/python/copy_const_reference.hpp b/include/boost/python/copy_const_reference.hpp index 57c45fd4..b2fdd61f 100644 --- a/include/boost/python/copy_const_reference.hpp +++ b/include/boost/python/copy_const_reference.hpp @@ -7,7 +7,7 @@ # define COPY_CONST_REFERENCE_DWA2002131_HPP # include # include -# include +# include namespace boost { namespace python { diff --git a/include/boost/python/copy_non_const_reference.hpp b/include/boost/python/copy_non_const_reference.hpp index dead736f..6f53fbdc 100644 --- a/include/boost/python/copy_non_const_reference.hpp +++ b/include/boost/python/copy_non_const_reference.hpp @@ -7,7 +7,7 @@ # define COPY_NON_CONST_REFERENCE_DWA2002131_HPP # include # include -# include +# include namespace boost { namespace python { diff --git a/include/boost/python/detail/caller.hpp b/include/boost/python/detail/caller.hpp index fe022961..d0b01b6e 100644 --- a/include/boost/python/detail/caller.hpp +++ b/include/boost/python/detail/caller.hpp @@ -20,26 +20,6 @@ namespace boost { namespace python namespace boost { namespace python { namespace detail { -// for "readable" error messages -template struct must_use_a_result_handler_to_wrap_functions_returning -# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__) -{} -# endif -; - -struct to_python_generator -{ - template - struct apply - { - typedef typename mpl::select_type< - is_reference::value | is_pointer::value - , must_use_a_result_handler_to_wrap_functions_returning - , to_python - >::type type; - }; -}; - struct caller { typedef PyObject* result_type; diff --git a/include/boost/python/detail/msvc_typeinfo.hpp b/include/boost/python/detail/msvc_typeinfo.hpp new file mode 100644 index 00000000..2473023a --- /dev/null +++ b/include/boost/python/detail/msvc_typeinfo.hpp @@ -0,0 +1,99 @@ +// Copyright David Abrahams 2002. 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 MSVC_TYPEINFO_DWA200222_HPP +# define MSVC_TYPEINFO_DWA200222_HPP + +#include +#include + +// +// Fix for MSVC's broken typeid() implementation which doesn't strip +// decoration. This fix doesn't handle cv-qualified array types. It +// could probably be done, but I haven't figured it out yet. +// + +# if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(BOOST_INTEL_CXX_VERSION) && BOOST_INTEL_CXX_VERSION <= 600 + +namespace boost { namespace python { namespace detail { + +typedef std::type_info const& typeinfo; + +templatestruct value_id_accessor; + +template<> +struct value_id_accessor<0> +{ + template + static typeinfo get(T*) { return typeid(T); } +}; + +template<> +struct value_id_accessor<1> +{ + template + static typeinfo get(T const*) { return typeid(T); } +}; + +template<> +struct value_id_accessor<2> +{ + template + static typeinfo get(T volatile*) { return typeid(T); } +}; + +template<> +struct value_id_accessor<3> +{ + template + static typeinfo get(T const volatile*) { return typeid(T); } +}; + +template struct bool_t{}; + +template +inline typeinfo typeid_nonref(boost::type* = 0) +{ + BOOST_STATIC_CONSTANT(bool, c = is_const::value); + BOOST_STATIC_CONSTANT(bool, v = is_volatile::value); + return value_id_accessor<(2 * v + c)>::get((T*)0); +} + +template +inline typeinfo typeid_ref(boost::type*, ...) +{ + return typeid_nonref(); +} + +template +inline typeinfo typeid_ref(boost::type*, T& (*)()) +{ + return typeid_nonref(); +} + +template +inline typeinfo typeid_array(bool_t, boost::type* = 0) +{ + typedef T (*x)(); + return typeid_ref((boost::type*)0, x(0)); +} + +template +inline typeinfo typeid_array(bool_t, boost::type* = 0) +{ + return typeid_nonref(); +} + +template +inline typeinfo msvc_typeid(boost::type* = 0) +{ + typedef bool_t::value> tag; + return typeid_array(tag(), (boost::type*)0); +} + +}}} // namespace boost::python::detail + +# endif // BOOST_MSVC +#endif // MSVC_TYPEINFO_DWA200222_HPP diff --git a/include/boost/python/detail/returning.hpp b/include/boost/python/detail/returning.hpp index c8533f9e..99bbc572 100644 --- a/include/boost/python/detail/returning.hpp +++ b/include/boost/python/detail/returning.hpp @@ -11,17 +11,10 @@ #ifndef RETURNING_DWA20011201_HPP # define RETURNING_DWA20011201_HPP -//# include # include # include # include # include -# include - -namespace boost { namespace python -{ - template struct to_python; -}} // namespace boost::python namespace boost { namespace python { namespace detail { diff --git a/include/boost/python/make_function.hpp b/include/boost/python/make_function.hpp index 90a5c12b..2943d96c 100644 --- a/include/boost/python/make_function.hpp +++ b/include/boost/python/make_function.hpp @@ -8,7 +8,6 @@ # include # include -# include # include # include # include diff --git a/include/boost/python/object/class_wrapper.hpp b/include/boost/python/object/class_wrapper.hpp index 26334bc7..4a52f290 100644 --- a/include/boost/python/object/class_wrapper.hpp +++ b/include/boost/python/object/class_wrapper.hpp @@ -6,21 +6,18 @@ #ifndef CLASS_WRAPPER_DWA20011221_HPP # define CLASS_WRAPPER_DWA20011221_HPP -# include # include # include -# include -# include +# include namespace boost { namespace python { namespace objects { template struct class_wrapper - : converter::to_python_converter + : to_python_converter > { class_wrapper(ref const& type_) - : converter::to_python_converter(convert) - , m_class_object_keeper(type_) + : m_class_object_keeper(type_) { assert(type_->ob_type == (PyTypeObject*)class_metatype().get()); m_class_object = (PyTypeObject*)type_.get(); @@ -31,9 +28,8 @@ struct class_wrapper // Don't call the type to do the construction, since that // would require the registration of an __init__ copy // constructor. Instead, just construct the object in place. - PyObject* raw_result = (PyObject*)PyObject_New( - instance, m_class_object); - + PyObject* raw_result = m_class_object->tp_alloc(m_class_object, 0); + if (raw_result == 0) return 0; @@ -41,6 +37,8 @@ struct class_wrapper // exceptions. ref result(raw_result, ref::allow_null()); + ((instance*)raw_result)->objects = 0; + // Build a value_holder to contain the object using the copy // constructor value_holder* p = new value_holder(raw_result, cref(x)); diff --git a/include/boost/python/to_python.hpp b/include/boost/python/to_python.hpp deleted file mode 100644 index e00346bb..00000000 --- a/include/boost/python/to_python.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright David Abrahams 2002. 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 TO_PYTHON_DWA2002128_HPP -# define TO_PYTHON_DWA2002128_HPP - -# include -# include - -namespace boost { namespace python { - -template -struct to_python - : converter::to_python_lookup::type> -{ -}; - -// specialization for PyObject* -template <> -struct to_python -{ - bool convertible() const { return true; } - PyObject* operator()(PyObject* source) const { return source; } -}; - -template <> -struct to_python -{ - bool convertible() const { return true; } - PyObject* operator()(PyObject* source) const { return source; } -}; - -}} // namespace boost::python - -#endif // TO_PYTHON_DWA2002128_HPP diff --git a/src/converter/builtin_converters.cpp b/src/converter/builtin_converters.cpp index c2ce3dae..26834635 100644 --- a/src/converter/builtin_converters.cpp +++ b/src/converter/builtin_converters.cpp @@ -200,7 +200,6 @@ namespace #define REGISTER_INT_CONVERTERS(U) register_int_converters() #define REGISTER_INT_CONVERTERS2(U) REGISTER_INT_CONVERTERS(signed U); REGISTER_INT_CONVERTERS(unsigned U) - void initialize_builtin_converters() { REGISTER_INT_CONVERTERS2(char); diff --git a/src/converter/from_python.cpp b/src/converter/from_python.cpp index 979ad935..2e844acf 100644 --- a/src/converter/from_python.cpp +++ b/src/converter/from_python.cpp @@ -5,6 +5,7 @@ // to its suitability for any purpose. #include +#include namespace boost { namespace python { namespace converter { @@ -14,14 +15,12 @@ from_python_converter_base::from_python_converter_base( ) : body(type) , m_convertible(checker) -{ - registry::insert(*this); -} -from_python_converter_base::~from_python_converter_base() { - if (can_unregister()) - registry::remove(*this); + // Insert this in the converter chain. + from_python_converter_base*& head = registry::from_python_chain(type); + m_next = head; + head = this; } }}} // namespace boost::python::converter diff --git a/src/converter/registry.cpp b/src/converter/registry.cpp index 5b4563a4..c90d709d 100644 --- a/src/converter/registry.cpp +++ b/src/converter/registry.cpp @@ -3,23 +3,32 @@ // 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. - -# include -# include -# include -# include -# include -# include -# include -# ifdef BOOST_PYTHON_TRACE -# include -# endif +#include +#include +#include +#include namespace boost { namespace python { namespace converter { namespace // { - typedef std::map registry_t; + // These are the elements stored in the registry + struct entry + { + entry(); + + // The unique to_python converter for the associated C++ type. + to_python_value_function m_to_python_converter; + + // The collection of from_python converters for the associated + // C++ type. + from_python_converter_base* m_from_python_converters; + + // The class object associated with this type + PyTypeObject* m_class_object; + }; + + typedef std::map registry_t; registry_t& entries() { @@ -35,10 +44,7 @@ namespace // } return registry; } -} // namespace -namespace registry -{ entry* find(type_id_t type) { return &entries()[type]; @@ -46,128 +52,40 @@ namespace registry entry::entry() : m_to_python_converter(0) + , m_from_python_converters(0) + , m_class_object(0) { } +} // namespace - entry::~entry() +namespace registry +{ + to_python_value_function const& to_python_function( + undecorated_type_id_t key) { - if (m_to_python_converter != 0) - m_to_python_converter->m_can_unregister = false; - - for (from_python_converters::iterator p = m_from_python_converters.begin() - ; p != m_from_python_converters.end() - ; ++p) - { - (*p)->m_can_unregister = false; - } - } - - from_python_converter_base const* - entry::get_from_python(PyObject* p, void*& data_out) const - { - for (from_python_converters::const_iterator q = m_from_python_converters.begin(), - finish = m_from_python_converters.end(); - q != finish; - ++q) - { - void* const data = (*q)->convertible(p); - if (data != 0) - { - data_out = data; - return *q; - break; - } - } - return 0; + return find(key)->m_to_python_converter; } - to_python_function_base entry::get_to_python() const + void insert(to_python_value_function f, undecorated_type_id_t source_t) { - return m_to_python_converter - ? m_to_python_converter->converter() - : 0; - } - - entry::from_python_converters::iterator entry::find(from_python_converter_base const& x) - { - return std::find(m_from_python_converters.begin(), m_from_python_converters.end(), &x); - } - - void entry::insert(from_python_converter_base& x) - { - from_python_converters::iterator p = this->find(x); - - if (p != m_from_python_converters.end()) - { - assert(!"converter already registered"); - throw std::runtime_error( - "trying to register unrapper which is already registered"); - } - - m_from_python_converters.push_back(&x); - } - - void entry::remove(from_python_converter_base& x) - { - from_python_converters::iterator p = find(x); - - // Be sure we're not removing a converter which hasn't been - // registered. - if (p == m_from_python_converters.end()) - { - assert(!"trying to unregister from_python_converter which is not registered"); - throw std::runtime_error( - "trying to unregister from_python_converter which is not registered"); - } - m_from_python_converters.erase(p); - } - - void entry::insert(to_python_converter_base& x) - { - assert(m_to_python_converter == 0); // we have a problem otherwise - if (m_to_python_converter != 0) + to_python_value_function& slot = find(source_t)->m_to_python_converter; + assert(slot == 0); // we have a problem otherwise + if (slot != 0) { throw std::runtime_error( "trying to register to_python_converter for a type which already has a registered to_python_converter"); } - m_to_python_converter = &x; + slot = f; + } + + from_python_converter_base*& from_python_chain(type_id_t key) + { + return find(key)->m_from_python_converters; } - void entry::remove(to_python_converter_base& x) + PyTypeObject*& class_object(undecorated_type_id_t key) { - assert(m_to_python_converter == &x); - if (m_to_python_converter != &x) - { - throw std::runtime_error( - "trying to unregister a to_python_converter which is not registered"); - } - m_to_python_converter = 0; - } - - void insert(to_python_converter_base& w) - { -# ifdef BOOST_PYTHON_TRACE - std::cout << "inserting to_python_converter for " << w.key() << std::endl; -# endif - find(w.key())->insert(w); - } - - void insert(from_python_converter_base& u) - { -# ifdef BOOST_PYTHON_TRACE - std::cout << "inserting from_python_converter for " << u.key() << std::endl; -# endif - find(u.key())->insert(u); - } - - void remove(to_python_converter_base& w) - { - find(w.key())->remove(w); - } - - void remove(from_python_converter_base& u) - { - find(u.key())->remove(u); + return find(key)->m_class_object; } } // namespace registry diff --git a/src/converter/to_python.cpp b/src/converter/to_python.cpp deleted file mode 100644 index 9cede51d..00000000 --- a/src/converter/to_python.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright David Abrahams 2002. 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. - -#include -#include - -namespace boost { namespace python { namespace converter { - -to_python_converter_base::to_python_converter_base(type_id_t key, to_python_function_base convert) - : body(key) - , m_convert(convert) -{ - registry::insert(*this); -} - -to_python_converter_base::~to_python_converter_base() -{ - registry::remove(*this); -} - -}}} // namespace boost::python::converter diff --git a/src/converter/type_id.cpp b/src/converter/type_id.cpp index 688dd2bc..904f30d0 100644 --- a/src/converter/type_id.cpp +++ b/src/converter/type_id.cpp @@ -21,18 +21,12 @@ BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream& os, undecorated_type_id BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream& os, type_id_t const& x) { os << x.m_base_type; - // VC6 mistakenly distinguishes typeid(X) from typeid(X const) - // from typeid(X&)... so the name is already correct. I have it - // from Jason Shirk that VC7.0 has the same bug but it will be - // fixed in 7.1 -# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 if (x.m_decoration & type_id_t::const_) os << " const"; if (x.m_decoration & type_id_t::volatile_) os << " volatile"; if (x.m_decoration & type_id_t::reference) os << "&"; -# endif return os; } diff --git a/src/object/class.cpp b/src/object/class.cpp index de3e32f5..5d1ecf01 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -122,7 +121,7 @@ PyTypeObject class_type_object = { 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ - 0, /* tp_alloc */ + PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew }; diff --git a/test/m1.cpp b/test/m1.cpp index b807dc43..b42742ab 100644 --- a/test/m1.cpp +++ b/test/m1.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -105,26 +106,19 @@ PyObject* new_simple() // are selected. // using boost::python::converter::from_python_data; +using boost::python::to_python_converter; -// Wrap a simple by converting it to a Simple -PyObject* simple_to_python(simple const& x) +// Wrap a simple by copying it into a Simple +struct simple_to_python + : to_python_converter { - SimpleObject* p = PyObject_New(SimpleObject, &SimpleType); - p->x = x; - return (PyObject*)p; -} - - -// wrap a mutable reference to a simple by converting it to a -// Simple. Normally we wouldn't do it this way, since modifications to -// the result clearly don't change the original object, but here we're -// just proving that the mechanism works. -PyObject* simple_ref_to_python(simple& x) -{ - SimpleObject* p = PyObject_New(SimpleObject, &SimpleType); - p->x = x; - return (PyObject*)p; -} + static PyObject* convert(simple const& x) + { + SimpleObject* p = PyObject_New(SimpleObject, &SimpleType); + p->x = x; + return (PyObject*)p; + } +}; int noddy_to_int(PyObject* p, from_python_data&) { @@ -184,16 +178,15 @@ struct D : B, C int x; }; -int take_a(A const& a) { return a.x; } -int take_b(B const& b) { return b.x; } -int take_c(C const& c) { return c.x; } -int take_d(D const& d) { return d.x; } +A take_a(A const& a) { return a; } +B take_b(B const& b) { return b; } +C take_c(C const& c) { return c; } +D take_d(D const& d) { return d; } BOOST_PYTHON_MODULE_INIT(m1) { using boost::python::module; using boost::python::class_; - using boost::python::converter::to_python_converter; using boost::python::converter::from_python_converter; using boost::python::reference_from_python; using boost::python::value_from_python; @@ -204,7 +197,7 @@ BOOST_PYTHON_MODULE_INIT(m1) using boost::mpl::type_list; // Create the converters; they are self-registering/unregistering. - static to_python_converter c1(simple_to_python); + static simple_to_python c1; static from_python_converter c2( &(boost::python::type_from_python<&NoddyType>::convertible), noddy_to_int); @@ -219,10 +212,7 @@ BOOST_PYTHON_MODULE_INIT(m1) , extract_simple_object > unwrap_simple; - - static to_python_converter simple_ref_wrapper(simple_ref_to_python); - module m1("m1"); typedef boost::python::objects::pointer_holder_generator< diff --git a/test/newtest.py b/test/newtest.py index 0636641b..4e6de142 100644 --- a/test/newtest.py +++ b/test/newtest.py @@ -73,8 +73,8 @@ are a complicated constructor and member function, respectively. >>> d = D() ------ ->>> take_a(a) -0 +>>> take_a(a).name() +'A' >>> try: ... take_b(a) @@ -92,11 +92,11 @@ are a complicated constructor and member function, respectively. ... else: print 'no exception' ------ ->>> take_a(b) -0 +>>> take_a(b).name() +'A' ->>> take_b(b) -1 +>>> take_b(b).name() +'B' >>> try: ... take_c(b) @@ -109,16 +109,16 @@ are a complicated constructor and member function, respectively. ... else: print 'no exception' ------- ->>> take_a(c) -0 +>>> take_a(c).name() +'A' >>> try: ... take_b(c) ... except: pass ... else: print 'no exception' ->>> take_c(c) -2 +>>> take_c(c).name() +'C' >>> try: ... take_d(c) @@ -126,14 +126,14 @@ are a complicated constructor and member function, respectively. ... else: print 'no exception' ------- ->>> take_a(d) -0 ->>> take_b(d) -1 ->>> take_c(d) -2 ->>> take_d(d) -3 +>>> take_a(d).name() +'A' +>>> take_b(d).name() +'B' +>>> take_c(d).name() +'C' +>>> take_d(d).name() +'D' """ From 14917c9791997288a11bcc3b309ca78efe8f89fd Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 2 Feb 2002 14:31:07 +0000 Subject: [PATCH 247/369] initial checkin [SVN r12633] --- include/boost/python/to_python_converter.hpp | 39 +++++++++++++ include/boost/python/to_python_value.hpp | 58 ++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 include/boost/python/to_python_converter.hpp create mode 100644 include/boost/python/to_python_value.hpp diff --git a/include/boost/python/to_python_converter.hpp b/include/boost/python/to_python_converter.hpp new file mode 100644 index 00000000..6bea9822 --- /dev/null +++ b/include/boost/python/to_python_converter.hpp @@ -0,0 +1,39 @@ +// Copyright David Abrahams 2002. 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 TO_PYTHON_CONVERTER_DWA200221_HPP +# define TO_PYTHON_CONVERTER_DWA200221_HPP + +# include +# include +# include + +namespace boost { namespace python { + +template +struct to_python_converter +{ + to_python_converter(); +}; + +// +// implementation +// + +template +to_python_converter::to_python_converter() +{ + typedef converter::as_to_python_value_function< + T, Derived + > normalized; + + converter::registry::insert( + &normalized::convert + , converter::undecorated_type_id()); +} + +}} // namespace boost::python + +#endif // TO_PYTHON_CONVERTER_DWA200221_HPP diff --git a/include/boost/python/to_python_value.hpp b/include/boost/python/to_python_value.hpp new file mode 100644 index 00000000..a222e9a9 --- /dev/null +++ b/include/boost/python/to_python_value.hpp @@ -0,0 +1,58 @@ +// Copyright David Abrahams 2002. 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 TO_PYTHON_VALUE_DWA200221_HPP +# define TO_PYTHON_VALUE_DWA200221_HPP + +# include +# include +# include +# include +# include + +namespace boost { namespace python { + +template +struct to_python_value +{ + typedef typename add_reference< + typename add_const::type + >::type argument_type; + + static bool convertible(); + PyObject* operator()(argument_type) const; + + private: + // Note that this is a pointer to a function pointer + static converter::to_python_value_function const* fconvert; +}; + + +template +converter::to_python_value_function const* +to_python_value::fconvert + = &converter::registry::to_python_function(converter::undecorated_type_id()); + + +template +bool to_python_value::convertible() +{ + // if this assert fires, our static variable hasn't been set up yet. + assert(fconvert != 0); + return *fconvert != 0; +} + +template +PyObject* to_python_value::operator()(argument_type x) const +{ + // This might be further optimized on platforms which dynamically + // link without specific imports/exports + converter::to_python_value_function f = *fconvert; + return f(&x); +} + +}} // namespace boost::python + +#endif // TO_PYTHON_VALUE_DWA200221_HPP From ecc8abcc50505b86d34693012486ec7c19824254 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 2 Feb 2002 14:34:02 +0000 Subject: [PATCH 248/369] ice_ fixes for KCC [SVN r12634] --- include/boost/python/default_call_policies.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/boost/python/default_call_policies.hpp b/include/boost/python/default_call_policies.hpp index 475278e4..f0b69255 100644 --- a/include/boost/python/default_call_policies.hpp +++ b/include/boost/python/default_call_policies.hpp @@ -48,8 +48,10 @@ struct default_result_converter template struct apply { + BOOST_STATIC_CONSTANT(bool, is_illegal = is_reference::value || is_pointer::value); + typedef typename mpl::select_type< - is_reference::value | is_pointer::value + is_illegal , detail::specify_a_result_policy_to_wrap_functions_returning , boost::python::to_python_value< typename add_reference::type>::type From 7703f91ee26512c7e7c2c8c97b3ac5f971bc64a5 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 2 Feb 2002 15:17:37 +0000 Subject: [PATCH 249/369] fix typo [SVN r12636] --- src/objects.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objects.cpp b/src/objects.cpp index b447b262..8b5ac3dd 100644 --- a/src/objects.cpp +++ b/src/objects.cpp @@ -9,7 +9,7 @@ // TODO: Move inline implementations from objects.cpp here #ifndef BOOST_PYTHON_SOURCE -r# define BOOST_PYTHON_SOURCE +# define BOOST_PYTHON_SOURCE #endif #include From 71de2b5ec52421ed0fd1f717c89b88295e6c0502 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 2 Feb 2002 15:19:59 +0000 Subject: [PATCH 250/369] /Zm upgrade [SVN r12637] --- build/vc60.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/vc60.mak b/build/vc60.mak index 6f303791..1709073c 100644 --- a/build/vc60.mak +++ b/build/vc60.mak @@ -21,7 +21,7 @@ PYEXE="C:\Python21\python.exe" PYINC=/I"C:\Python21\include" PYLIB="C:\Python21\libs\python21.lib" -STDOPTS=/nologo /MD /GR /GX /Zm200 /DBOOST_PYTHON_STATIC_LIB +STDOPTS=/nologo /MD /GR /GX /Zm300 /DBOOST_PYTHON_STATIC_LIB WARNOPTS= OPTOPTS= From 6e5fc91885e622c4d513300e53a05477dd10892c Mon Sep 17 00:00:00 2001 From: Darin Adler Date: Sat, 2 Feb 2002 18:36:12 +0000 Subject: [PATCH 251/369] New smart pointer documentation. Related clean-up of the smart pointer library. Changing includes to include the new individual smart pointer headers. Replacing old smart pointer library with an include of the new smart pointer headers. Simplify ifdefs that involve the member templates macros now that BOOST_MSVC6_MEMBER_TEMPLATES is also guaranteed to bet set for platforms that have full member templates. [SVN r12647] --- include/boost/python/conversions.hpp | 2 +- include/boost/python/detail/extension_class.hpp | 2 +- include/boost/python/object/inheritance.hpp | 2 +- src/types.cpp | 1 - 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/include/boost/python/conversions.hpp b/include/boost/python/conversions.hpp index aa07547f..24ac5614 100644 --- a/include/boost/python/conversions.hpp +++ b/include/boost/python/conversions.hpp @@ -19,7 +19,7 @@ # include # include # include -# include +# include # include # include diff --git a/include/boost/python/detail/extension_class.hpp b/include/boost/python/detail/extension_class.hpp index 638217d1..dd6741d2 100644 --- a/include/boost/python/detail/extension_class.hpp +++ b/include/boost/python/detail/extension_class.hpp @@ -26,7 +26,7 @@ # include # include # include -# include +# include # include namespace boost { namespace python { diff --git a/include/boost/python/object/inheritance.hpp b/include/boost/python/object/inheritance.hpp index 60aeda58..ceeac8f9 100644 --- a/include/boost/python/object/inheritance.hpp +++ b/include/boost/python/object/inheritance.hpp @@ -7,7 +7,7 @@ # define INHERITANCE_DWA200216_HPP # include -# include +# include namespace boost { namespace python { namespace objects { diff --git a/src/types.cpp b/src/types.cpp index e76503d2..eae9adff 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include From 8cc9080d367448edc08d6c8725282d2d5c5d0657 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 2 Feb 2002 20:48:37 +0000 Subject: [PATCH 252/369] Initial pointer adoption tests Have instances actually dispose of their held C++ objects! [SVN r12652] --- Jamfile | 20 +++++++++-- src/object/class.cpp | 19 +++++++++- test/test_builtin_converters.cpp | 2 -- test/test_pointer_adoption.cpp | 61 ++++++++++++++++++++++++++++++++ test/test_pointer_adoption.py | 29 +++++++++++++++ 5 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 test/test_pointer_adoption.cpp create mode 100644 test/test_pointer_adoption.py diff --git a/Jamfile b/Jamfile index fec34d51..e897b19f 100644 --- a/Jamfile +++ b/Jamfile @@ -29,17 +29,20 @@ PYTHON_PROPERTIES BOOST_PYTHON_SOURCE ; - extension m1 : test/m1.cpp bpl # BOOST_PYTHON_TRACE + # -------- general test ------- + extension m1 : test/m1.cpp bpl : : debug-python ; - extension m2 : test/m2.cpp bpl # BOOST_PYTHON_TRACE + extension m2 : test/m2.cpp bpl : : debug-python ; boost-python-runtest try : test/newtest.py m1 m2 : : debug-python ; + # ----------- builtin converters ----------- + extension builtin_converters_ext : test/test_builtin_converters.cpp bpl : : debug-python @@ -50,4 +53,17 @@ PYTHON_PROPERTIES : : debug-python ; + + # ----------- pointer adoption ----------- + + extension test_pointer_adoption_ext : test/test_pointer_adoption.cpp bpl + : + : debug-python + ; + + boost-python-runtest test_pointer_adoption : test/test_pointer_adoption.py + test_pointer_adoption_ext + : + : debug-python + ; } diff --git a/src/object/class.cpp b/src/object/class.cpp index 5d1ecf01..6a839fb2 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -81,6 +81,22 @@ BOOST_PYTHON_DECL ref class_metatype() return ref((PyObject*)&class_metatype_object, ref::increment_count); } +extern "C" +{ + static void instance_dealloc(PyObject* inst) + { + instance* kill_me = (instance*)inst; + + for (instance_holder* p = kill_me->objects, *next; p != 0; p = next) + { + next = p->next(); + delete p; + } + + inst->ob_type->tp_free(inst); + } +} + // Do we really need this? I'm beginning to think we don't! PyTypeObject class_type_object = { PyObject_HEAD_INIT(0) //&class_metatype_object) @@ -88,7 +104,7 @@ PyTypeObject class_type_object = { "Boost.Python.instance", sizeof(instance), 0, - 0, /* tp_dealloc */ + instance_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -206,6 +222,7 @@ namespace m_impl.insert( boost::detail::lower_bound(start, finish, id) , entry(id, object)); + converter::registry::class_object(id) = (PyTypeObject*)object.get(); } } diff --git a/test/test_builtin_converters.cpp b/test/test_builtin_converters.cpp index 6ffccdf9..7e21e046 100644 --- a/test/test_builtin_converters.cpp +++ b/test/test_builtin_converters.cpp @@ -5,8 +5,6 @@ // to its suitability for any purpose. #include #include -#include -#include template diff --git a/test/test_pointer_adoption.cpp b/test/test_pointer_adoption.cpp new file mode 100644 index 00000000..a49be5e8 --- /dev/null +++ b/test/test_pointer_adoption.cpp @@ -0,0 +1,61 @@ +// Copyright David Abrahams 2002. 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. +#include +#include +#include +#include +#include + +using namespace boost::python; +using boost::mpl::type_list; + +int a_instances = 0; + +int num_a_instances() { return a_instances; } + +struct A +{ + A(std::string const& s) + : s(s) + { + ++a_instances; + } + + ~A() + { + --a_instances; + } + + std::string content() const + { + return s; + } + + std::string s; +}; + +A* create(std::string const& s) +{ + return new A(s); +} + +BOOST_PYTHON_MODULE_INIT(test_pointer_adoption_ext) +{ + boost::python::module("test_pointer_adoption_ext") + .def("num_a_instances", num_a_instances) + + // Specify the manage_new_object return policy to take + // ownership of create's result + .def("create", create, return_value_policy()) + + .add( + class_() + .def("content", &A::content) + ) + + ; +} + diff --git a/test/test_pointer_adoption.py b/test/test_pointer_adoption.py new file mode 100644 index 00000000..264d69ce --- /dev/null +++ b/test/test_pointer_adoption.py @@ -0,0 +1,29 @@ +""" +>>> from test_pointer_adoption_ext import * + +>>> num_a_instances() +0 + +>>> a = create('dynamically allocated') +>>> num_a_instances() +1 + +>>> a.content() +'dynamically allocated' + +>>> a = None +>>> num_a_instances() +0 +""" +def run(args = None): + import sys + import doctest + + if args is not None: + sys.argv = args + return doctest.testmod(sys.modules.get(__name__)) + +if __name__ == '__main__': + print "running..." + import sys + sys.exit(run()[0]) From 90647f30f856040c218b3605791c2bd96636ca0c Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 2 Feb 2002 20:54:06 +0000 Subject: [PATCH 253/369] Initial pointer adoption tests Have instances actually dispose of their held C++ objects! [SVN r12653] --- include/boost/python/class.hpp | 7 +- include/boost/python/class_fwd.hpp | 30 ++++++ include/boost/python/detail/cv_category.hpp | 34 +++++++ include/boost/python/detail/type_list.hpp | 16 ++++ include/boost/python/detail/unwind_type.hpp | 51 ++++++++++ include/boost/python/manage_new_object.hpp | 42 +++++++++ include/boost/python/module.hpp | 3 +- include/boost/python/object/class_object.hpp | 26 ++++++ include/boost/python/object/class_wrapper.hpp | 8 +- include/boost/python/to_python_owner.hpp | 93 +++++++++++++++++++ 10 files changed, 300 insertions(+), 10 deletions(-) create mode 100644 include/boost/python/class_fwd.hpp create mode 100644 include/boost/python/detail/cv_category.hpp create mode 100644 include/boost/python/detail/type_list.hpp create mode 100644 include/boost/python/detail/unwind_type.hpp create mode 100644 include/boost/python/manage_new_object.hpp create mode 100644 include/boost/python/object/class_object.hpp create mode 100644 include/boost/python/to_python_owner.hpp diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index 0f8d2a69..b63236c8 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -6,6 +6,7 @@ #ifndef CLASS_DWA200216_HPP # define CLASS_DWA200216_HPP +# include # include # include # include @@ -14,7 +15,7 @@ # include # include # include -# include +# include namespace // put some convenience classes into the unnamed namespace for the user { @@ -80,8 +81,8 @@ namespace detail // template < class T // class being wrapped - , class Bases = mpl::type_list<>::type - , class HolderGenerator = objects::value_holder_generator + , class Bases + , class HolderGenerator > class class_ : private objects::class_base { diff --git a/include/boost/python/class_fwd.hpp b/include/boost/python/class_fwd.hpp new file mode 100644 index 00000000..6faf7aae --- /dev/null +++ b/include/boost/python/class_fwd.hpp @@ -0,0 +1,30 @@ +// Copyright David Abrahams 2002. 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 CLASS_FWD_DWA200222_HPP +# define CLASS_FWD_DWA200222_HPP + +namespace boost { namespace python { + +namespace detail +{ + struct empty_list; +} + +namespace objects +{ + struct value_holder_generator; +} + +template < + class T // class being wrapped + , class Bases = detail::empty_list + , class HolderGenerator = objects::value_holder_generator + > +class class_; + +}} // namespace boost::python + +#endif // CLASS_FWD_DWA200222_HPP diff --git a/include/boost/python/detail/cv_category.hpp b/include/boost/python/detail/cv_category.hpp new file mode 100644 index 00000000..f4ac4b92 --- /dev/null +++ b/include/boost/python/detail/cv_category.hpp @@ -0,0 +1,34 @@ +// Copyright David Abrahams 2002. 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 CV_CATEGORY_DWA200222_HPP +# define CV_CATEGORY_DWA200222_HPP +# include + +namespace boost { namespace python { namespace detail { + +template +struct cv_tag +{ + BOOST_STATIC_CONSTANT(bool, is_const = is_const_); + BOOST_STATIC_CONSTANT(bool, is_volatile = is_const_); +}; + +typedef cv_tag cv_unqualified; +typedef cv_tag const_; +typedef cv_tag volatile_; +typedef cv_tag const_volatile_; + +template +struct cv_category +{ + BOOST_STATIC_CONSTANT(bool, c = is_const::value); + BOOST_STATIC_CONSTANT(bool, v = is_volatile::value); + typedef cv_tag type; +}; + +}}} // namespace boost::python::detail + +#endif // CV_CATEGORY_DWA200222_HPP diff --git a/include/boost/python/detail/type_list.hpp b/include/boost/python/detail/type_list.hpp new file mode 100644 index 00000000..66ac3857 --- /dev/null +++ b/include/boost/python/detail/type_list.hpp @@ -0,0 +1,16 @@ +// Copyright David Abrahams 2002. 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 TYPE_LIST_DWA200222_HPP +# define TYPE_LIST_DWA200222_HPP +# include + +namespace boost { namespace python { namespace detail { + +struct empty_list : boost::mpl::type_list<>::type {}; + +}}} // namespace boost::python::detail + +#endif // TYPE_LIST_DWA200222_HPP diff --git a/include/boost/python/detail/unwind_type.hpp b/include/boost/python/detail/unwind_type.hpp new file mode 100644 index 00000000..eb103be4 --- /dev/null +++ b/include/boost/python/detail/unwind_type.hpp @@ -0,0 +1,51 @@ +// Copyright David Abrahams 2002. 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 UNWIND_TYPE_DWA200222_HPP +# define UNWIND_TYPE_DWA200222_HPP + +# include + +namespace boost { namespace python { namespace detail { + +template +inline typename Generator::result_type +unwind_type_cv(U* p, cv_unqualified, Generator* = 0) +{ + return Generator::execute(p); +} + +template +inline typename Generator::result_type +unwind_type_cv(U const* p, const_, Generator* = 0) +{ + return unwind_type(const_cast(p), (Generator*)0); +} + +template +inline typename Generator::result_type +unwind_type_cv(U volatile* p, volatile_, Generator* = 0) +{ + return unwind_type(const_cast(p), (Generator*)0); +} + +template +inline typename Generator::result_type +unwind_type_cv(U const volatile* p, const_volatile_, Generator* = 0) +{ + return unwind_type(const_cast(p), (Generator*)0); +} + +template +inline typename Generator::result_type +unwind_type(U* p, Generator* = 0) +{ + typedef typename cv_category::type tag; + return unwind_type_cv(p, tag()); +} + +}}} // namespace boost::python::detail + +#endif // UNWIND_TYPE_DWA200222_HPP diff --git a/include/boost/python/manage_new_object.hpp b/include/boost/python/manage_new_object.hpp new file mode 100644 index 00000000..1c41a75d --- /dev/null +++ b/include/boost/python/manage_new_object.hpp @@ -0,0 +1,42 @@ +// Copyright David Abrahams 2002. 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 MANAGE_NEW_OBJECT_DWA200222_HPP +# define MANAGE_NEW_OBJECT_DWA200222_HPP +# include +# include +# include +# include + +namespace boost { namespace python { + +namespace detail +{ + template + struct manage_new_object_requires_a_pointer_return_type +# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__) + {} +# endif + ; +} + +template struct to_python_value; + +struct manage_new_object +{ + template + struct apply + { + typedef typename mpl::select_type< + boost::is_pointer::value + , to_python_owner + , detail::manage_new_object_requires_a_pointer_return_type + >::type type; + }; +}; + +}} // namespace boost::python + +#endif // MANAGE_NEW_OBJECT_DWA200222_HPP diff --git a/include/boost/python/module.hpp b/include/boost/python/module.hpp index 3a243b06..1d4fdd6d 100644 --- a/include/boost/python/module.hpp +++ b/include/boost/python/module.hpp @@ -12,11 +12,10 @@ # include # include # include +# include namespace boost { namespace python { -template class class_; - class BOOST_PYTHON_DECL module_base { public: diff --git a/include/boost/python/object/class_object.hpp b/include/boost/python/object/class_object.hpp new file mode 100644 index 00000000..76960762 --- /dev/null +++ b/include/boost/python/object/class_object.hpp @@ -0,0 +1,26 @@ +// Copyright David Abrahams 2002. 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 CLASS_OBJECT_DWA200222_HPP +# define CLASS_OBJECT_DWA200222_HPP + +# include +# include + +namespace boost { namespace python { namespace objects { + +template +struct class_object +{ + static PyTypeObject*& reference; +}; + +template +PyTypeObject*& class_object::reference = converter::registry::class_object( + converter::undecorated_type_id()); + +}}} // namespace boost::python::objects + +#endif // CLASS_OBJECT_DWA200222_HPP diff --git a/include/boost/python/object/class_wrapper.hpp b/include/boost/python/object/class_wrapper.hpp index 4a52f290..f8702205 100644 --- a/include/boost/python/object/class_wrapper.hpp +++ b/include/boost/python/object/class_wrapper.hpp @@ -25,9 +25,9 @@ struct class_wrapper static PyObject* convert(T const& x) { - // Don't call the type to do the construction, since that - // would require the registration of an __init__ copy - // constructor. Instead, just construct the object in place. + // Don't call the type directly to do the construction, since + // that would require the registration of an appropriate + // __init__ function. PyObject* raw_result = m_class_object->tp_alloc(m_class_object, 0); if (raw_result == 0) @@ -37,8 +37,6 @@ struct class_wrapper // exceptions. ref result(raw_result, ref::allow_null()); - ((instance*)raw_result)->objects = 0; - // Build a value_holder to contain the object using the copy // constructor value_holder* p = new value_holder(raw_result, cref(x)); diff --git a/include/boost/python/to_python_owner.hpp b/include/boost/python/to_python_owner.hpp new file mode 100644 index 00000000..7d3ee5ae --- /dev/null +++ b/include/boost/python/to_python_owner.hpp @@ -0,0 +1,93 @@ +// Copyright David Abrahams 2002. 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 TO_PYTHON_OWNER_DWA200221_HPP +# define TO_PYTHON_OWNER_DWA200221_HPP + +# include +# include +# include +# include +# include + +namespace boost { namespace python { + +template +struct to_python_owner +{ + static bool convertible(); + PyObject* operator()(T ptr) const; + private: + static PyTypeObject* type(); +}; + +// +// implementations +// +namespace detail +{ + struct make_owning_holder + { + typedef objects::instance_holder* result_type; + template + static result_type execute(T* p) + { + return new objects::pointer_holder, T>( + std::auto_ptr(p)); + } + }; + + struct get_pointer_class + { + typedef PyTypeObject* result_type; + template + static result_type execute(T* p) + { + BOOST_STATIC_ASSERT(is_class::value); + return python::objects::class_object::reference; + } + }; +} + +template +inline bool to_python_owner::convertible() +{ + BOOST_STATIC_ASSERT(is_pointer::value); + return type() != 0; +} + +template +inline PyObject* to_python_owner::operator()(T x) const +{ + PyObject* raw_result = type()->tp_alloc(type(), 0); + + if (raw_result == 0) + return 0; + + // Everything's OK; Bypass NULL checks but guard against + // exceptions. + ref result(raw_result, ref::allow_null()); + + // Build a value_holder to contain the object using the copy + // constructor + objects::instance_holder* p = + detail::unwind_type(x); + + // Install it in the instance + p->install(raw_result); + + // Return the new result + return result.release(); +} + +template +inline PyTypeObject* to_python_owner::type() +{ + return detail::unwind_type(T(0)); +} + +}} // namespace boost::python + +#endif // TO_PYTHON_OWNER_DWA200221_HPP From 55a431883925c4acbd22fab58d880c59f68e2e21 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 3 Feb 2002 01:07:10 +0000 Subject: [PATCH 254/369] Handle references too [SVN r12655] --- include/boost/python/detail/unwind_type.hpp | 70 ++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/include/boost/python/detail/unwind_type.hpp b/include/boost/python/detail/unwind_type.hpp index eb103be4..e3caa5fa 100644 --- a/include/boost/python/detail/unwind_type.hpp +++ b/include/boost/python/detail/unwind_type.hpp @@ -40,12 +40,80 @@ unwind_type_cv(U const volatile* p, const_volatile_, Generator* = 0) template inline typename Generator::result_type -unwind_type(U* p, Generator* = 0) +unwind_ptr_type(U* p, Generator* = 0) { typedef typename cv_category::type tag; return unwind_type_cv(p, tag()); } +template +struct unwind_helper +{ + template + static typename Generator::result_type + execute(U p, Generator* = 0) + { + return unwind_ptr_type(p, (Generator*)0); + } + + template + struct apply + { + static typename Generator::result_type + execute() + { + return unwind_ptr_type(U(0),(Generator*)0); + } + }; +}; + +template <> +struct unwind_helper +{ + template + static typename Generator::result_type + execute(U& p, Generator* = 0) + { + return unwind_ptr_type(&p, (Generator*)0); + } + + template + struct apply + { + static typename Generator::result_type + execute() + { + return unwind_ptr_type((U*)0,(Generator*)0); + } + }; +}; + +template +inline typename Generator::result_type +unwind_type(U& p, Generator* = 0) +{ + return unwind_helper::value>::execute(p, (Generator*)0); +} + +template +inline typename Generator::result_type +unwind_type(U const& p, Generator* = 0) +{ + return unwind_helper::value>::execute(p, (Generator*)0); +} + +// Call this one with both template parameters explicitly specified +// and no function arguments: +// +// return unwind_type(); +// +template +inline typename Generator::result_type +unwind_type(type*p = 0, Generator* = 0) +{ + return unwind_helper::value>::template apply::execute(); +} + }}} // namespace boost::python::detail #endif // UNWIND_TYPE_DWA200222_HPP From 021070f0666d9d38335a0f2a716b0f4d4b2d52c7 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 3 Feb 2002 01:07:29 +0000 Subject: [PATCH 255/369] Prepare to generalize [SVN r12656] --- include/boost/python/to_python_owner.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/python/to_python_owner.hpp b/include/boost/python/to_python_owner.hpp index 7d3ee5ae..bf92663b 100644 --- a/include/boost/python/to_python_owner.hpp +++ b/include/boost/python/to_python_owner.hpp @@ -85,7 +85,7 @@ inline PyObject* to_python_owner::operator()(T x) const template inline PyTypeObject* to_python_owner::type() { - return detail::unwind_type(T(0)); + return detail::unwind_type(); } }} // namespace boost::python From 7590d546f1d5d34f51d2479f80a486853c09c4c0 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 3 Feb 2002 03:05:01 +0000 Subject: [PATCH 256/369] initial checkin [SVN r12657] --- .../python/reference_existing_object.hpp | 45 ++++++++ include/boost/python/to_python_indirect.hpp | 102 ++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 include/boost/python/reference_existing_object.hpp create mode 100644 include/boost/python/to_python_indirect.hpp diff --git a/include/boost/python/reference_existing_object.hpp b/include/boost/python/reference_existing_object.hpp new file mode 100644 index 00000000..1f8a43d8 --- /dev/null +++ b/include/boost/python/reference_existing_object.hpp @@ -0,0 +1,45 @@ +// Copyright David Abrahams 2002. 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 REFERENCE_EXISTING_OBJECT_DWA200222_HPP +# define REFERENCE_EXISTING_OBJECT_DWA200222_HPP +# include +# include +# include +# include + +namespace boost { namespace python { + +namespace detail +{ + template + struct reference_existing_object_requires_a_pointer_or_reference_return_type +# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__) + {} +# endif + ; +} + +template struct to_python_value; + +struct reference_existing_object +{ + template + struct apply + { + BOOST_STATIC_CONSTANT( + bool, ok = is_pointer::value || is_reference::value); + + typedef typename mpl::select_type< + ok + , to_python_indirect + , detail::reference_existing_object_requires_a_pointer_or_reference_return_type + >::type type; + }; +}; + +}} // namespace boost::python + +#endif // REFERENCE_EXISTING_OBJECT_DWA200222_HPP diff --git a/include/boost/python/to_python_indirect.hpp b/include/boost/python/to_python_indirect.hpp new file mode 100644 index 00000000..e68eced0 --- /dev/null +++ b/include/boost/python/to_python_indirect.hpp @@ -0,0 +1,102 @@ +// Copyright David Abrahams 2002. 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 TO_PYTHON_INDIRECT_DWA200221_HPP +# define TO_PYTHON_INDIRECT_DWA200221_HPP + +# include +# include +# include +# include +# include + +namespace boost { namespace python { + +template +struct to_python_indirect +{ + static bool convertible(); + PyObject* operator()(T ptr) const; + private: + static PyTypeObject* type(); +}; + +// +// implementations +// +namespace detail +{ + struct make_owning_holder + { + typedef objects::instance_holder* result_type; + template + static result_type execute(T* p) + { + return new objects::pointer_holder, T>( + std::auto_ptr(p)); + } + }; + + struct make_reference_holder + { + typedef objects::instance_holder* result_type; + template + static result_type execute(T* p) + { + return new objects::pointer_holder(p); + } + }; + + struct get_pointer_class + { + typedef PyTypeObject* result_type; + template + static result_type execute(T* p) + { + BOOST_STATIC_ASSERT(is_class::value); + return python::objects::class_object::reference; + } + }; +} + +template +inline bool to_python_indirect::convertible() +{ + return type() != 0; +} + +template +inline PyObject* to_python_indirect::operator()(T x) const +{ + PyObject* raw_result = type()->tp_alloc(type(), 0); + + if (raw_result == 0) + return 0; + + // Everything's OK; Bypass NULL checks but guard against + // exceptions. + ref result(raw_result, ref::allow_null()); + + // Build a value_holder to contain the object using the copy + // constructor + objects::instance_holder* p = + detail::unwind_type(x); + + // Install it in the instance + p->install(raw_result); + + // Return the new result + return result.release(); +} + +template +inline PyTypeObject* to_python_indirect::type() +{ + return detail::unwind_type(); +} + +}} // namespace boost::python + +#endif // TO_PYTHON_INDIRECT_DWA200221_HPP From 64239f1c04be4c18aa608e019c6a3b9ec5f0b1b1 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 3 Feb 2002 03:05:39 +0000 Subject: [PATCH 257/369] Allow indirect reference/pointer returns [SVN r12659] --- include/boost/python/class.hpp | 7 ++ .../boost/python/detail/indirect_traits.hpp | 68 +++++++++++++- include/boost/python/detail/unwind_type.hpp | 76 ++++++++++----- include/boost/python/manage_new_object.hpp | 4 +- include/boost/python/to_python_owner.hpp | 93 ------------------- test/test_pointer_adoption.cpp | 37 +++++++- test/test_pointer_adoption.py | 6 ++ 7 files changed, 165 insertions(+), 126 deletions(-) delete mode 100644 include/boost/python/to_python_owner.hpp diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index b63236c8..4f30dc8d 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -112,6 +112,13 @@ class class_ : private objects::class_base return *this; } + template + self& def(char const* name, Fn fn, CallPolicy policy) + { + this->def(name, boost::python::make_function(fn, policy)); + return *this; + } + // Define the constructor with the given Args, which should be an // MPL sequence of types. template diff --git a/include/boost/python/detail/indirect_traits.hpp b/include/boost/python/detail/indirect_traits.hpp index c76ffbc0..41681719 100644 --- a/include/boost/python/detail/indirect_traits.hpp +++ b/include/boost/python/detail/indirect_traits.hpp @@ -47,6 +47,36 @@ struct is_reference_to_volatile { BOOST_STATIC_CONSTANT(bool, value = true); }; + +template +struct is_reference_to_pointer +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +template +struct is_reference_to_pointer +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +template +struct is_reference_to_pointer +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +template +struct is_reference_to_pointer +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +template +struct is_reference_to_pointer +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; # else typedef char (&inner_yes_type)[3]; @@ -74,8 +104,17 @@ struct is_volatile_help }; template -typename is_const_help::type reference_to_const_helper(V&); - +struct is_pointer_help +{ + typedef typename mpl::select_type< + is_pointer::value + , inner_yes_type + , inner_no_type + >::type type; +}; + +template +typename is_const_help::type reference_to_const_helper(V&); outer_no_type reference_to_const_helper(...); @@ -85,7 +124,8 @@ struct is_reference_to_const static T t; BOOST_STATIC_CONSTANT( bool, value - = sizeof(reference_to_const_helper(t)) == sizeof(inner_yes_type)); + = (is_reference::value + && sizeof(reference_to_const_helper(t)) == sizeof(inner_yes_type))); }; template @@ -94,7 +134,8 @@ struct is_reference_to_non_const static T t; BOOST_STATIC_CONSTANT( bool, value - = sizeof(reference_to_const_helper(t)) == sizeof(inner_no_type)); + = (is_reference::value + && sizeof(reference_to_const_helper(t)) == sizeof(inner_no_type))); }; template @@ -107,7 +148,24 @@ struct is_reference_to_volatile static T t; BOOST_STATIC_CONSTANT( bool, value - = sizeof(reference_to_volatile_helper(t)) == sizeof(inner_yes_type)); + = (is_reference::value + && sizeof(reference_to_volatile_helper(t)) == sizeof(inner_yes_type))); +}; + + +template +typename is_pointer_help::type reference_to_pointer_helper(V&); +outer_no_type reference_to_pointer_helper(...); + +template +struct is_reference_to_pointer +{ + static T t; + BOOST_STATIC_CONSTANT( + bool, value + = (is_reference::value + && sizeof(reference_to_pointer_helper(t)) == sizeof(inner_yes_type)) + ); }; # endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION diff --git a/include/boost/python/detail/unwind_type.hpp b/include/boost/python/detail/unwind_type.hpp index e3caa5fa..add3615a 100644 --- a/include/boost/python/detail/unwind_type.hpp +++ b/include/boost/python/detail/unwind_type.hpp @@ -55,16 +55,6 @@ struct unwind_helper { return unwind_ptr_type(p, (Generator*)0); } - - template - struct apply - { - static typename Generator::result_type - execute() - { - return unwind_ptr_type(U(0),(Generator*)0); - } - }; }; template <> @@ -76,16 +66,6 @@ struct unwind_helper { return unwind_ptr_type(&p, (Generator*)0); } - - template - struct apply - { - static typename Generator::result_type - execute() - { - return unwind_ptr_type((U*)0,(Generator*)0); - } - }; }; template @@ -102,16 +82,70 @@ unwind_type(U const& p, Generator* = 0) return unwind_helper::value>::execute(p, (Generator*)0); } +enum { direct_ = 0, pointer_ = 1, reference_ = 2, reference_to_pointer_ = 3 }; +template struct unwind_helper2; + +template <> +struct unwind_helper2 +{ + template + static typename Generator::result_type + execute(U(*)(), Generator* = 0) + { + return unwind_ptr_type((U*)0, (Generator*)0); + } +}; + +template <> +struct unwind_helper2 +{ + template + static typename Generator::result_type + execute(U*(*)(), Generator* = 0) + { + return unwind_ptr_type((U*)0, (Generator*)0); + } +}; + +template <> +struct unwind_helper2 +{ + template + static typename Generator::result_type + execute(U&(*)(), Generator* = 0) + { + return unwind_ptr_type((U*)0, (Generator*)0); + } +}; + +template <> +struct unwind_helper2 +{ + template + static typename Generator::result_type + execute(U&(*)(), Generator* = 0) + { + return unwind_ptr_type(U(0), (Generator*)0); + } +}; + // Call this one with both template parameters explicitly specified // and no function arguments: // // return unwind_type(); // +// Doesn't work if T is an array type; we could handle that case, but +// why bother? template inline typename Generator::result_type unwind_type(type*p = 0, Generator* = 0) { - return unwind_helper::value>::template apply::execute(); + BOOST_STATIC_CONSTANT(int, indirection + = (pointer_ * is_pointer::value) + | (reference_ * is_reference::value) + | (reference_to_pointer_ * is_reference_to_pointer::value)); + + return unwind_helper2::execute((U(*)())0,(Generator*)0); } }}} // namespace boost::python::detail diff --git a/include/boost/python/manage_new_object.hpp b/include/boost/python/manage_new_object.hpp index 1c41a75d..9c0912ab 100644 --- a/include/boost/python/manage_new_object.hpp +++ b/include/boost/python/manage_new_object.hpp @@ -7,7 +7,7 @@ # define MANAGE_NEW_OBJECT_DWA200222_HPP # include # include -# include +# include # include namespace boost { namespace python { @@ -31,7 +31,7 @@ struct manage_new_object { typedef typename mpl::select_type< boost::is_pointer::value - , to_python_owner + , to_python_indirect , detail::manage_new_object_requires_a_pointer_return_type >::type type; }; diff --git a/include/boost/python/to_python_owner.hpp b/include/boost/python/to_python_owner.hpp deleted file mode 100644 index bf92663b..00000000 --- a/include/boost/python/to_python_owner.hpp +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright David Abrahams 2002. 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 TO_PYTHON_OWNER_DWA200221_HPP -# define TO_PYTHON_OWNER_DWA200221_HPP - -# include -# include -# include -# include -# include - -namespace boost { namespace python { - -template -struct to_python_owner -{ - static bool convertible(); - PyObject* operator()(T ptr) const; - private: - static PyTypeObject* type(); -}; - -// -// implementations -// -namespace detail -{ - struct make_owning_holder - { - typedef objects::instance_holder* result_type; - template - static result_type execute(T* p) - { - return new objects::pointer_holder, T>( - std::auto_ptr(p)); - } - }; - - struct get_pointer_class - { - typedef PyTypeObject* result_type; - template - static result_type execute(T* p) - { - BOOST_STATIC_ASSERT(is_class::value); - return python::objects::class_object::reference; - } - }; -} - -template -inline bool to_python_owner::convertible() -{ - BOOST_STATIC_ASSERT(is_pointer::value); - return type() != 0; -} - -template -inline PyObject* to_python_owner::operator()(T x) const -{ - PyObject* raw_result = type()->tp_alloc(type(), 0); - - if (raw_result == 0) - return 0; - - // Everything's OK; Bypass NULL checks but guard against - // exceptions. - ref result(raw_result, ref::allow_null()); - - // Build a value_holder to contain the object using the copy - // constructor - objects::instance_holder* p = - detail::unwind_type(x); - - // Install it in the instance - p->install(raw_result); - - // Return the new result - return result.release(); -} - -template -inline PyTypeObject* to_python_owner::type() -{ - return detail::unwind_type(); -} - -}} // namespace boost::python - -#endif // TO_PYTHON_OWNER_DWA200221_HPP diff --git a/test/test_pointer_adoption.cpp b/test/test_pointer_adoption.cpp index a49be5e8..be10aebd 100644 --- a/test/test_pointer_adoption.cpp +++ b/test/test_pointer_adoption.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -16,10 +17,24 @@ int a_instances = 0; int num_a_instances() { return a_instances; } +struct inner +{ + inner(std::string const& s) + : s(s) + {} + + void change(std::string const& new_s) + { + this->s = new_s; + } + + std::string s; +}; + struct A { A(std::string const& s) - : s(s) + : x(s) { ++a_instances; } @@ -31,10 +46,15 @@ struct A std::string content() const { - return s; + return x.s; } - - std::string s; + + inner& get_inner() + { + return x; + } + + inner x; }; A* create(std::string const& s) @@ -52,8 +72,15 @@ BOOST_PYTHON_MODULE_INIT(test_pointer_adoption_ext) .def("create", create, return_value_policy()) .add( + class_() - .def("content", &A::content) + .def("content", &A::content) + .def("get_inner", &A::get_inner, return_value_policy()) + ) + + .add( + class_() + .def("change", &inner::change) ) ; diff --git a/test/test_pointer_adoption.py b/test/test_pointer_adoption.py index 264d69ce..197a6df9 100644 --- a/test/test_pointer_adoption.py +++ b/test/test_pointer_adoption.py @@ -11,6 +11,12 @@ >>> a.content() 'dynamically allocated' +>>> innards = a.get_inner() +>>> innards.change('with an exposed reference') +>>> a.content() +'with an exposed reference' + +>>> innards = None >>> a = None >>> num_a_instances() 0 From 0a9d5f680fab9094049392618b10c1ec7734d959 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 3 Feb 2002 05:02:46 +0000 Subject: [PATCH 258/369] initial checkin [SVN r12661] --- include/boost/python/object/life_support.hpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 include/boost/python/object/life_support.hpp diff --git a/include/boost/python/object/life_support.hpp b/include/boost/python/object/life_support.hpp new file mode 100644 index 00000000..c5276c06 --- /dev/null +++ b/include/boost/python/object/life_support.hpp @@ -0,0 +1,17 @@ +// Copyright David Abrahams 2002. 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 LIFE_SUPPORT_DWA200222_HPP +# define LIFE_SUPPORT_DWA200222_HPP +# include +# include + +namespace boost { namespace python { namespace objects { + +BOOST_PYTHON_DECL int make_nurse_and_patient(PyObject* nurse, PyObject* patient); + +}}} // namespace boost::python::object + +#endif // LIFE_SUPPORT_DWA200222_HPP From 262396d48b4183e3490d9478da758c045ebcf92b Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 3 Feb 2002 05:03:05 +0000 Subject: [PATCH 259/369] Object life support [SVN r12662] --- Jamfile | 1 + .../python/return_internal_reference.hpp | 32 +++++- src/object/life_support.cpp | 99 +++++++++++++++++++ test/test_pointer_adoption.cpp | 4 +- test/test_pointer_adoption.py | 8 +- 5 files changed, 137 insertions(+), 7 deletions(-) create mode 100644 src/object/life_support.cpp diff --git a/Jamfile b/Jamfile index e897b19f..ac32456b 100644 --- a/Jamfile +++ b/Jamfile @@ -20,6 +20,7 @@ PYTHON_PROPERTIES src/object/class.cpp src/object/function.cpp src/object/inheritance.cpp + src/object/life_support.cpp src/errors.cpp src/module.cpp src/objects.cpp diff --git a/include/boost/python/return_internal_reference.hpp b/include/boost/python/return_internal_reference.hpp index ac7f3fbf..a1888229 100644 --- a/include/boost/python/return_internal_reference.hpp +++ b/include/boost/python/return_internal_reference.hpp @@ -7,7 +7,10 @@ # define RETURN_INTERNAL_REFERENCE_DWA2002131_HPP # include +# include # include +# include +# include namespace boost { namespace python { @@ -28,18 +31,39 @@ struct internal_reference_to_python_generator { typedef typename mpl::select_type< !is_object::value - , internal_reference_to_python - , detail::return_internal_reference_requires_a_pointer_or_reference_return_type + , to_python_indirect + , detail::return_internal_reference_requires_a_pointer_or_reference_return_type >::type type; }; }; -template +template struct return_internal_reference : Base { - typedef wrap_internal_reference result_converter; + typedef reference_existing_object result_converter; + static PyObject* postcall(PyObject* args, PyObject* result); }; +template +PyObject* return_internal_reference::postcall(PyObject* args_, PyObject* result) +{ + PyObject* patient = PyTuple_GetItem(args_, owner_arg - 1); + if (patient != 0) // Make sure the argument was in range. + { + result = Base::postcall(args_,result); + if (result != 0) + { + if (python::objects::make_nurse_and_patient(result, patient) == 0) + { + return result; + } + } + + } + Py_XDECREF(result); + return 0; +} + }} // namespace boost::python #endif // RETURN_INTERNAL_REFERENCE_DWA2002131_HPP diff --git a/src/object/life_support.cpp b/src/object/life_support.cpp new file mode 100644 index 00000000..f587eb42 --- /dev/null +++ b/src/object/life_support.cpp @@ -0,0 +1,99 @@ +// Copyright David Abrahams 2002. 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. +#include +#include + +namespace boost { namespace python { namespace objects { + +struct life_support +{ + PyObject_HEAD + PyObject* patient; +}; + +extern "C" +{ + static void + life_support_dealloc(PyObject* self) + { + self->ob_type->tp_free(self); + } + + static PyObject * + life_support_call(PyObject *self, PyObject *arg, PyObject *kw) + { + // Let the patient die now + Py_XDECREF(((life_support*)self)->patient); + // Also let the weak reference die. This probably kills us. + Py_XDECREF(PyTuple_GET_ITEM(arg, 0)); + return detail::none(); + } +} + +PyTypeObject life_support_type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + "Boost.Python.life_support", + sizeof(life_support), + 0, + life_support_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, //(reprfunc)func_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + life_support_call, /* tp_call */ + 0, /* tp_str */ + 0, // PyObject_GenericGetAttr, /* tp_getattro */ + 0, // PyObject_GenericSetAttr, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT /* | Py_TPFLAGS_HAVE_GC */,/* tp_flags */ + 0, /* tp_doc */ + 0, // (traverseproc)func_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, //offsetof(PyLife_SupportObject, func_weakreflist), /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, // func_memberlist, /* tp_members */ + 0, //func_getsetlist, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, //offsetof(PyLife_SupportObject, func_dict), /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, + 0 /* tp_new */ +}; + +int make_nurse_and_patient(PyObject* nurse, PyObject* patient) +{ + life_support* system = PyObject_New(life_support, &life_support_type); + if (!system) + return -1; + + // We're going to leak this reference, but don't worry; the + // life_support system decrements it when the nurse dies. + PyObject* weakref = PyWeakref_NewRef(nurse, (PyObject*)system); + if (!weakref) + { + Py_XDECREF(system); + return -1; + } + + system->patient = patient; + Py_XINCREF(patient); // hang on to the patient until death + return 0; +} + +}}} // namespace boost::python::objects diff --git a/test/test_pointer_adoption.cpp b/test/test_pointer_adoption.cpp index be10aebd..61cd49bd 100644 --- a/test/test_pointer_adoption.cpp +++ b/test/test_pointer_adoption.cpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include @@ -75,7 +75,7 @@ BOOST_PYTHON_MODULE_INIT(test_pointer_adoption_ext) class_() .def("content", &A::content) - .def("get_inner", &A::get_inner, return_value_policy()) + .def("get_inner", &A::get_inner, return_internal_reference<>()) ) .add( diff --git a/test/test_pointer_adoption.py b/test/test_pointer_adoption.py index 197a6df9..28e160dc 100644 --- a/test/test_pointer_adoption.py +++ b/test/test_pointer_adoption.py @@ -16,10 +16,16 @@ >>> a.content() 'with an exposed reference' ->>> innards = None +# The a instance should be kept alive... >>> a = None >>> num_a_instances() +1 + +# ...until we're done with its innards +>>> innards = None +>>> num_a_instances() 0 + """ def run(args = None): import sys From bcf4401858ce9b6db3deebb65915ad73eb96b300 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 3 Feb 2002 05:09:31 +0000 Subject: [PATCH 260/369] KCC ice workaround [SVN r12663] --- include/boost/python/return_internal_reference.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/python/return_internal_reference.hpp b/include/boost/python/return_internal_reference.hpp index a1888229..8f60c476 100644 --- a/include/boost/python/return_internal_reference.hpp +++ b/include/boost/python/return_internal_reference.hpp @@ -30,9 +30,9 @@ struct internal_reference_to_python_generator struct apply { typedef typename mpl::select_type< - !is_object::value - , to_python_indirect + is_object::value , detail::return_internal_reference_requires_a_pointer_or_reference_return_type + , to_python_indirect >::type type; }; }; From 21d65ca0bf0f099e68a7d3c5e5a927b81f9a6083 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 3 Feb 2002 06:34:15 +0000 Subject: [PATCH 261/369] arbitrary argument/result adoption [SVN r12664] --- include/boost/python/object/life_support.hpp | 2 +- include/boost/python/object/make_holder.hpp | 78 ++++++++++++++++++ .../python/return_internal_reference.hpp | 26 +----- .../boost/python/with_custodian_and_ward.hpp | 80 +++++++++++++++++++ src/object/life_support.cpp | 12 +-- test/test_pointer_adoption.cpp | 28 +++++++ test/test_pointer_adoption.py | 22 +++++ 7 files changed, 219 insertions(+), 29 deletions(-) create mode 100644 include/boost/python/with_custodian_and_ward.hpp diff --git a/include/boost/python/object/life_support.hpp b/include/boost/python/object/life_support.hpp index c5276c06..5d9587db 100644 --- a/include/boost/python/object/life_support.hpp +++ b/include/boost/python/object/life_support.hpp @@ -10,7 +10,7 @@ namespace boost { namespace python { namespace objects { -BOOST_PYTHON_DECL int make_nurse_and_patient(PyObject* nurse, PyObject* patient); +BOOST_PYTHON_DECL PyObject* make_nurse_and_patient(PyObject* nurse, PyObject* patient); }}} // namespace boost::python::object diff --git a/include/boost/python/object/make_holder.hpp b/include/boost/python/object/make_holder.hpp index 8a72a880..825e02b0 100644 --- a/include/boost/python/object/make_holder.hpp +++ b/include/boost/python/object/make_holder.hpp @@ -93,6 +93,84 @@ struct make_holder<3> }; }; +template <> +struct make_holder<4> +{ + template + struct apply + { + typedef typename detail::eval::type holder; + typedef typename mpl::at<0,ArgList>::type t0; + typedef typename forward::type f0; + typedef typename mpl::at<1,ArgList>::type t1; + typedef typename forward::type f1; + typedef typename mpl::at<2,ArgList>::type t2; + typedef typename forward::type f2; + typedef typename mpl::at<3,ArgList>::type t3; + typedef typename forward::type f3; + + static void execute( + PyObject* p, t0 a0, t1 a1, t2 a2, t3 a3) + { + (new holder(p, f0(a0), f1(a1), f2(a2), f3(a3)))->install(p); + } + }; +}; + +template <> +struct make_holder<5> +{ + template + struct apply + { + typedef typename detail::eval::type holder; + typedef typename mpl::at<0,ArgList>::type t0; + typedef typename forward::type f0; + typedef typename mpl::at<1,ArgList>::type t1; + typedef typename forward::type f1; + typedef typename mpl::at<2,ArgList>::type t2; + typedef typename forward::type f2; + typedef typename mpl::at<3,ArgList>::type t3; + typedef typename forward::type f3; + typedef typename mpl::at<4,ArgList>::type t4; + typedef typename forward::type f4; + + static void execute( + PyObject* p, t0 a0, t1 a1, t2 a2, t3 a3, t4 a4) + { + (new holder(p, f0(a0), f1(a1), f2(a2), f3(a3), f4(a4)))->install(p); + } + }; +}; + +template <> +struct make_holder<6> +{ + template + struct apply + { + typedef typename detail::eval::type holder; + typedef typename mpl::at<0,ArgList>::type t0; + typedef typename forward::type f0; + typedef typename mpl::at<1,ArgList>::type t1; + typedef typename forward::type f1; + typedef typename mpl::at<2,ArgList>::type t2; + typedef typename forward::type f2; + typedef typename mpl::at<3,ArgList>::type t3; + typedef typename forward::type f3; + typedef typename mpl::at<4,ArgList>::type t4; + typedef typename forward::type f4; + typedef typename mpl::at<5,ArgList>::type t5; + typedef typename forward::type f5; + + static void execute( + PyObject* p, t0 a0, t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) + { + (new holder(p, f0(a0), f1(a1), f2(a2), f3(a3), f4(a4), f5(a5)))->install(p); + } + }; +}; + }}} // namespace boost::python::objects #endif // MAKE_HOLDER_DWA20011215_HPP diff --git a/include/boost/python/return_internal_reference.hpp b/include/boost/python/return_internal_reference.hpp index 8f60c476..2066b7a9 100644 --- a/include/boost/python/return_internal_reference.hpp +++ b/include/boost/python/return_internal_reference.hpp @@ -7,10 +7,10 @@ # define RETURN_INTERNAL_REFERENCE_DWA2002131_HPP # include -# include # include # include # include +# include namespace boost { namespace python { @@ -38,32 +38,12 @@ struct internal_reference_to_python_generator }; template -struct return_internal_reference : Base +struct return_internal_reference + : with_custodian_and_ward_postcall<0, owner_arg, Base> { typedef reference_existing_object result_converter; - static PyObject* postcall(PyObject* args, PyObject* result); }; -template -PyObject* return_internal_reference::postcall(PyObject* args_, PyObject* result) -{ - PyObject* patient = PyTuple_GetItem(args_, owner_arg - 1); - if (patient != 0) // Make sure the argument was in range. - { - result = Base::postcall(args_,result); - if (result != 0) - { - if (python::objects::make_nurse_and_patient(result, patient) == 0) - { - return result; - } - } - - } - Py_XDECREF(result); - return 0; -} - }} // namespace boost::python #endif // RETURN_INTERNAL_REFERENCE_DWA2002131_HPP diff --git a/include/boost/python/with_custodian_and_ward.hpp b/include/boost/python/with_custodian_and_ward.hpp new file mode 100644 index 00000000..4ae975af --- /dev/null +++ b/include/boost/python/with_custodian_and_ward.hpp @@ -0,0 +1,80 @@ +// Copyright David Abrahams 2002. 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 WITH_CUSTODIAN_AND_WARD_DWA2002131_HPP +# define WITH_CUSTODIAN_AND_WARD_DWA2002131_HPP + +# include +# include + +namespace boost { namespace python { + +enum custodial_timing { pre_call, post_call }; + +template +struct with_custodian_and_ward : Base +{ + static bool precall(PyObject* args); +}; + +template +struct with_custodian_and_ward_postcall : Base +{ + static PyObject* postcall(PyObject* args, PyObject* result); +}; + +// +// implementations +// +template +bool with_custodian_and_ward::precall(PyObject* args_) +{ + BOOST_STATIC_ASSERT(custodian != ward); + BOOST_STATIC_ASSERT(custodian > 0); + BOOST_STATIC_ASSERT(ward > 0); + + PyObject* patient = PyTuple_GetItem(args_, ward - 1); + if (patient == 0) return false; + PyObject* nurse = PyTuple_GetItem(args_, custodian - 1); + if (nurse == 0) return false; + + PyObject* life_support = python::objects::make_nurse_and_patient(nurse, patient); + if (life_support == 0) + return false; + + bool result = Base::precall(args_); + + if (!result) + Py_XDECREF(life_support); + + return result; +} + +template +PyObject* with_custodian_and_ward_postcall::postcall(PyObject* args_, PyObject* result) +{ + BOOST_STATIC_ASSERT(custodian != ward); + + PyObject* patient = ward > 0 ? PyTuple_GetItem(args_, ward - 1) : result; + if (patient == 0) return 0; + + PyObject* nurse = custodian > 0 ? PyTuple_GetItem(args_, custodian - 1) : result; + if (nurse == 0) return 0; + + result = Base::postcall(args_, result); + if (result == 0) + return 0; + + if (python::objects::make_nurse_and_patient(nurse, patient) == 0) + { + Py_XDECREF(result); + return 0; + } + return result; +} + +}} // namespace boost::python + +#endif // WITH_CUSTODIAN_AND_WARD_DWA2002131_HPP diff --git a/src/object/life_support.cpp b/src/object/life_support.cpp index f587eb42..7507c71c 100644 --- a/src/object/life_support.cpp +++ b/src/object/life_support.cpp @@ -19,6 +19,7 @@ extern "C" static void life_support_dealloc(PyObject* self) { + Py_XDECREF(((life_support*)self)->patient); self->ob_type->tp_free(self); } @@ -27,7 +28,8 @@ extern "C" { // Let the patient die now Py_XDECREF(((life_support*)self)->patient); - // Also let the weak reference die. This probably kills us. + ((life_support*)self)->patient = 0; + // Let the weak reference die. This probably kills us. Py_XDECREF(PyTuple_GET_ITEM(arg, 0)); return detail::none(); } @@ -76,11 +78,11 @@ PyTypeObject life_support_type = { 0 /* tp_new */ }; -int make_nurse_and_patient(PyObject* nurse, PyObject* patient) +PyObject* make_nurse_and_patient(PyObject* nurse, PyObject* patient) { life_support* system = PyObject_New(life_support, &life_support_type); if (!system) - return -1; + return 0; // We're going to leak this reference, but don't worry; the // life_support system decrements it when the nurse dies. @@ -88,12 +90,12 @@ int make_nurse_and_patient(PyObject* nurse, PyObject* patient) if (!weakref) { Py_XDECREF(system); - return -1; + return 0; } system->patient = patient; Py_XINCREF(patient); // hang on to the patient until death - return 0; + return weakref; } }}} // namespace boost::python::objects diff --git a/test/test_pointer_adoption.cpp b/test/test_pointer_adoption.cpp index 61cd49bd..87b3eaab 100644 --- a/test/test_pointer_adoption.cpp +++ b/test/test_pointer_adoption.cpp @@ -57,6 +57,21 @@ struct A inner x; }; +struct B +{ + B() : x(0) {} + + inner const* adopt(A* x) { this->x = x; return &x->get_inner(); } + + std::string a_content() + { + return x ? x->content() : std::string("empty"); + } + + A* x; +}; + + A* create(std::string const& s) { return new A(s); @@ -83,6 +98,19 @@ BOOST_PYTHON_MODULE_INIT(test_pointer_adoption_ext) .def("change", &inner::change) ) + .add( + class_("B") + .def_init() + + .def("adopt", &B::adopt + // Adopt returns a pointer referring to a subobject of its 2nd argument (1st being "self") + , return_internal_reference<2 + // Meanwhile, self holds a reference to the 2nd argument. + , with_custodian_and_ward<1,2> >() + ) + + .def("a_content", &B::a_content) + ) ; } diff --git a/test/test_pointer_adoption.py b/test/test_pointer_adoption.py index 28e160dc..075a640b 100644 --- a/test/test_pointer_adoption.py +++ b/test/test_pointer_adoption.py @@ -26,6 +26,28 @@ >>> num_a_instances() 0 +>>> b = B() +>>> a = create('another') +>>> b.a_content() +'empty' +>>> innards = b.adopt(a); +>>> b.a_content() +'another' +>>> num_a_instances() +1 +>>> del a # innards and b are both holding a reference +>>> num_a_instances() +1 +>>> innards.change('yet another') +>>> b.a_content() +'yet another' + +>>> del innards +>>> num_a_instances() # b still owns a reference to a +1 +>>> del b +>>> num_a_instances() +0 """ def run(args = None): import sys From d023d577b2bf22726cd79d839aac7e66592687b5 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 3 Feb 2002 22:33:11 +0000 Subject: [PATCH 262/369] extra semicolon removed (cxx 6.3 diag.) [SVN r12677] --- src/converter/builtin_converters.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/converter/builtin_converters.cpp b/src/converter/builtin_converters.cpp index 26834635..fcd7a2cd 100644 --- a/src/converter/builtin_converters.cpp +++ b/src/converter/builtin_converters.cpp @@ -194,7 +194,7 @@ namespace void register_int_converters(T* = 0) { static scalar_from_python x; - }; + } } #define REGISTER_INT_CONVERTERS(U) register_int_converters() From 1ec58c1161cde52eb1c7a70cd6dcbecc77977309 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 3 Feb 2002 23:21:48 +0000 Subject: [PATCH 263/369] bug fix [SVN r12678] --- include/boost/python/detail/returning.hpp | 2 +- include/boost/python/object/value_holder.hpp | 110 +++++++++---------- 2 files changed, 56 insertions(+), 56 deletions(-) diff --git a/include/boost/python/detail/returning.hpp b/include/boost/python/detail/returning.hpp index 99bbc572..599e5d37 100644 --- a/include/boost/python/detail/returning.hpp +++ b/include/boost/python/detail/returning.hpp @@ -1216,7 +1216,7 @@ struct returning # endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template - static PyObject* call(R (*pf)(), PyObject*, PyObject*, P const& policies) + static PyObject* call(R (*pf)(), PyObject* args, PyObject*, P const& policies) { (*pf)(); diff --git a/include/boost/python/object/value_holder.hpp b/include/boost/python/object/value_holder.hpp index 85e3797f..01431370 100644 --- a/include/boost/python/object/value_holder.hpp +++ b/include/boost/python/object/value_holder.hpp @@ -23,113 +23,113 @@ struct value_holder : instance_holder template value_holder(PyObject*, A1 a1) : m_held( - (unwrap_reference::type&)(a1) + (typename unwrap_reference::type&)(a1) ) {} template value_holder(PyObject*, A1 a1, A2 a2) : m_held( - (unwrap_reference::type&)(a1) - , (unwrap_reference::type&)(a2) + (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) ) {} template value_holder(PyObject*, A1 a1, A2 a2, A3 a3) : m_held( - (unwrap_reference::type&)(a1) - , (unwrap_reference::type&)(a2) - , (unwrap_reference::type&)(a3) + (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) ) {} template value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) : m_held( - (unwrap_reference::type&)(a1) - , (unwrap_reference::type&)(a2) - , (unwrap_reference::type&)(a3) - , (unwrap_reference::type&)(a4) + (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) ) {} template value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : m_held( - (unwrap_reference::type&)(a1) - , (unwrap_reference::type&)(a2) - , (unwrap_reference::type&)(a3) - , (unwrap_reference::type&)(a4) - , (unwrap_reference::type&)(a5) + (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) ) {} template value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) : m_held( - (unwrap_reference::type&)(a1) - , (unwrap_reference::type&)(a2) - , (unwrap_reference::type&)(a3) - , (unwrap_reference::type&)(a4) - , (unwrap_reference::type&)(a5) - , (unwrap_reference::type&)(a6) + (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) ) {} template value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) : m_held( - (unwrap_reference::type&)(a1) - , (unwrap_reference::type&)(a2) - , (unwrap_reference::type&)(a3) - , (unwrap_reference::type&)(a4) - , (unwrap_reference::type&)(a5) - , (unwrap_reference::type&)(a6) - , (unwrap_reference::type&)(a7) + (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) ) {} template value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) : m_held( - (unwrap_reference::type&)(a1) - , (unwrap_reference::type&)(a2) - , (unwrap_reference::type&)(a3) - , (unwrap_reference::type&)(a4) - , (unwrap_reference::type&)(a5) - , (unwrap_reference::type&)(a6) - , (unwrap_reference::type&)(a7) - , (unwrap_reference::type&)(a8) + (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) + , (typename unwrap_reference::type&)(a8) ) {} template value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) : m_held( - (unwrap_reference::type&)(a1) - , (unwrap_reference::type&)(a2) - , (unwrap_reference::type&)(a3) - , (unwrap_reference::type&)(a4) - , (unwrap_reference::type&)(a5) - , (unwrap_reference::type&)(a6) - , (unwrap_reference::type&)(a7) - , (unwrap_reference::type&)(a8) - , (unwrap_reference::type&)(a9) + (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) + , (typename unwrap_reference::type&)(a8) + , (typename unwrap_reference::type&)(a9) ) {} template value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) : m_held( - (unwrap_reference::type&)(a1) - , (unwrap_reference::type&)(a2) - , (unwrap_reference::type&)(a3) - , (unwrap_reference::type&)(a4) - , (unwrap_reference::type&)(a5) - , (unwrap_reference::type&)(a6) - , (unwrap_reference::type&)(a7) - , (unwrap_reference::type&)(a8) - , (unwrap_reference::type&)(a9) - , (unwrap_reference::type&)(a10) + (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) + , (typename unwrap_reference::type&)(a8) + , (typename unwrap_reference::type&)(a9) + , (typename unwrap_reference::type&)(a10) ) {} From 1dc6600b59b79a551f46f85dbf6197013a834465 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 3 Feb 2002 23:51:16 +0000 Subject: [PATCH 264/369] kill extra ; [SVN r12679] --- include/boost/python/return_internal_reference.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/python/return_internal_reference.hpp b/include/boost/python/return_internal_reference.hpp index 2066b7a9..d696c7fa 100644 --- a/include/boost/python/return_internal_reference.hpp +++ b/include/boost/python/return_internal_reference.hpp @@ -22,7 +22,7 @@ namespace detail {} # endif ; -}; +} struct internal_reference_to_python_generator { From 9f33aa2afc143ab78e4b049c55c1add37dee961a Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 3 Feb 2002 23:58:10 +0000 Subject: [PATCH 265/369] bug fix [SVN r12680] --- include/boost/python/class.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index 4f30dc8d..978a226a 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -192,7 +192,9 @@ inline class_::class_(char const* name) template inline ref class_::object() const { - return this->class_base::object(); + typedef objects::class_base base; + + return this->base::object(); } }} // namespace boost::python From 47c77487071bf47bf73c5652bc62aeef552e8822 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 4 Feb 2002 01:42:47 +0000 Subject: [PATCH 266/369] bug fix [SVN r12681] --- .../boost/python/object/pointer_holder.hpp | 110 +++++++++--------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/include/boost/python/object/pointer_holder.hpp b/include/boost/python/object/pointer_holder.hpp index 81fcac0c..21fe8e96 100644 --- a/include/boost/python/object/pointer_holder.hpp +++ b/include/boost/python/object/pointer_holder.hpp @@ -28,113 +28,113 @@ struct pointer_holder : instance_holder template pointer_holder(PyObject*, A1 a1) : m_p(new Value( - (unwrap_reference::type&)(a1) + (typename unwrap_reference::type&)(a1) )) {} template pointer_holder(PyObject*, A1 a1, A2 a2) : m_p(new Value( - (unwrap_reference::type&)(a1) - , (unwrap_reference::type&)(a2) + (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) )) {} template pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3) : m_p(new Value( - (unwrap_reference::type&)(a1) - , (unwrap_reference::type&)(a2) - , (unwrap_reference::type&)(a3) + (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) )) {} template pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) : m_p(new Value( - (unwrap_reference::type&)(a1) - , (unwrap_reference::type&)(a2) - , (unwrap_reference::type&)(a3) - , (unwrap_reference::type&)(a4) + (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) )) {} template pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : m_p(new Value( - (unwrap_reference::type&)(a1) - , (unwrap_reference::type&)(a2) - , (unwrap_reference::type&)(a3) - , (unwrap_reference::type&)(a4) - , (unwrap_reference::type&)(a5) + (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) )) {} template pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) : m_p(new Value( - (unwrap_reference::type&)(a1) - , (unwrap_reference::type&)(a2) - , (unwrap_reference::type&)(a3) - , (unwrap_reference::type&)(a4) - , (unwrap_reference::type&)(a5) - , (unwrap_reference::type&)(a6) + (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) )) {} template pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) : m_p(new Value( - (unwrap_reference::type&)(a1) - , (unwrap_reference::type&)(a2) - , (unwrap_reference::type&)(a3) - , (unwrap_reference::type&)(a4) - , (unwrap_reference::type&)(a5) - , (unwrap_reference::type&)(a6) - , (unwrap_reference::type&)(a7) + (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) )) {} template pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) : m_p(new Value( - (unwrap_reference::type&)(a1) - , (unwrap_reference::type&)(a2) - , (unwrap_reference::type&)(a3) - , (unwrap_reference::type&)(a4) - , (unwrap_reference::type&)(a5) - , (unwrap_reference::type&)(a6) - , (unwrap_reference::type&)(a7) - , (unwrap_reference::type&)(a8) + (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) + , (typename unwrap_reference::type&)(a8) )) {} template pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) : m_p(new Value( - (unwrap_reference::type&)(a1) - , (unwrap_reference::type&)(a2) - , (unwrap_reference::type&)(a3) - , (unwrap_reference::type&)(a4) - , (unwrap_reference::type&)(a5) - , (unwrap_reference::type&)(a6) - , (unwrap_reference::type&)(a7) - , (unwrap_reference::type&)(a8) - , (unwrap_reference::type&)(a9) + (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) + , (typename unwrap_reference::type&)(a8) + , (typename unwrap_reference::type&)(a9) )) {} template pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) : m_p(new Value( - (unwrap_reference::type&)(a1) - , (unwrap_reference::type&)(a2) - , (unwrap_reference::type&)(a3) - , (unwrap_reference::type&)(a4) - , (unwrap_reference::type&)(a5) - , (unwrap_reference::type&)(a6) - , (unwrap_reference::type&)(a7) - , (unwrap_reference::type&)(a8) - , (unwrap_reference::type&)(a9) - , (unwrap_reference::type&)(a10) + (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) + , (typename unwrap_reference::type&)(a8) + , (typename unwrap_reference::type&)(a9) + , (typename unwrap_reference::type&)(a10) )) {} From 80f697ef2a312ce49342c6ca7e387a6419f43104 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 4 Feb 2002 01:58:08 +0000 Subject: [PATCH 267/369] more bug fixes for really conformant compilers [SVN r12682] --- include/boost/python/value_from_python.hpp | 5 +++-- src/converter/builtin_converters.cpp | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/boost/python/value_from_python.hpp b/include/boost/python/value_from_python.hpp index 0ff80323..c835de45 100644 --- a/include/boost/python/value_from_python.hpp +++ b/include/boost/python/value_from_python.hpp @@ -16,6 +16,7 @@ namespace boost { namespace python { template struct value_from_python { + typedef value_from_python self; typedef converter::from_python_check from_python_check; value_from_python(from_python_check convertible) @@ -50,13 +51,13 @@ struct value_from_python // Mark successful construction static void constructed(converter::from_python_data& data) { - data.stage1 = get_storage(data); + data.stage1 = self::get_storage(data); } inline static void destroy(converter::from_python_data& data) { // Get the location of the storage for - void* storage = get_storage(data); + void* storage = self::get_storage(data); // Check for successful construction if (data.stage1 == storage) diff --git a/src/converter/builtin_converters.cpp b/src/converter/builtin_converters.cpp index fcd7a2cd..33e1cb50 100644 --- a/src/converter/builtin_converters.cpp +++ b/src/converter/builtin_converters.cpp @@ -91,7 +91,8 @@ namespace : value_from_python > { private: - typedef value_from_python > base; + typedef tp_cref_from_python self; + typedef value_from_python > base; public: tp_cref_from_python() @@ -102,7 +103,7 @@ namespace { unaryfunc converter = *(unaryfunc*)data.stage1; - void* storage = get_storage(data); + void* storage = self::get_storage(data); ref converted(converter(obj)); From 5d30ddac22c872e1413b3ea874edffc28f10ad8d Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 4 Feb 2002 14:49:43 +0000 Subject: [PATCH 268/369] cxx 6.5 fixes [SVN r12689] --- include/boost/python/detail/unwind_type.hpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/include/boost/python/detail/unwind_type.hpp b/include/boost/python/detail/unwind_type.hpp index add3615a..e8ccd0c8 100644 --- a/include/boost/python/detail/unwind_type.hpp +++ b/include/boost/python/detail/unwind_type.hpp @@ -141,9 +141,12 @@ inline typename Generator::result_type unwind_type(type*p = 0, Generator* = 0) { BOOST_STATIC_CONSTANT(int, indirection - = (pointer_ * is_pointer::value) - | (reference_ * is_reference::value) - | (reference_to_pointer_ * is_reference_to_pointer::value)); + = (is_pointer::value ? pointer_ : 0) + + (is_reference_to_pointer::value + ? reference_to_pointer_ + : is_reference::value + ? reference_ + : 0)); return unwind_helper2::execute((U(*)())0,(Generator*)0); } From 8ff5450ece1658bdc973c01b58587e3182eb96c1 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 4 Feb 2002 20:14:53 +0000 Subject: [PATCH 269/369] moved contents of builtin_to_python_converters.hpp to builtin_converters.hpp [SVN r12705] --- .../python/converter/builtin_converters.hpp | 60 +++++++++++++++++- .../builtin_to_python_converters.hpp | 62 ------------------- include/boost/python/to_python_value.hpp | 2 +- 3 files changed, 58 insertions(+), 66 deletions(-) delete mode 100644 include/boost/python/converter/builtin_to_python_converters.hpp diff --git a/include/boost/python/converter/builtin_converters.hpp b/include/boost/python/converter/builtin_converters.hpp index 9c19cbc5..a21fd27b 100644 --- a/include/boost/python/converter/builtin_converters.hpp +++ b/include/boost/python/converter/builtin_converters.hpp @@ -5,11 +5,65 @@ // to its suitability for any purpose. #ifndef BUILTIN_CONVERTERS_DWA2002124_HPP # define BUILTIN_CONVERTERS_DWA2002124_HPP +# include +# include -namespace boost { namespace python { namespace converter { +namespace boost { namespace python { -void initialize_builtin_converters(); +// Provide specializations of to_python_value +template struct to_python_value; -}}} // namespace boost::python::converter +namespace detail +{ + struct builtin_to_python + { + static bool convertible() { return true; } + }; +} + +# define BOOST_PYTHON_TO_PYTHON_BY_VALUE(T, expr) \ + template <> struct to_python_value \ + : detail::builtin_to_python \ + { \ + PyObject* operator()(T const& x) const \ + { \ + return (expr); \ + } \ + }; \ + template <> struct to_python_value \ + : detail::builtin_to_python \ + { \ + PyObject* operator()(T const& x) const \ + { \ + return (expr); \ + } \ + }; + + +# define BOOST_PYTHON_TO_INT(T) \ + BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, PyInt_FromLong(x)) \ + BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned T, PyInt_FromLong(x)) + +BOOST_PYTHON_TO_INT(char) +BOOST_PYTHON_TO_INT(short) +BOOST_PYTHON_TO_INT(int) +BOOST_PYTHON_TO_INT(long) +# undef BOOST_TO_PYTHON_INT + +BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, PyString_FromString(x)) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, PyString_FromString(x.c_str())) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, PyFloat_FromDouble(x)) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, PyFloat_FromDouble(x)) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, PyFloat_FromDouble(x)) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(PyObject*, x) + +namespace converter +{ + + void initialize_builtin_converters(); + +} + +}} // namespace boost::python::converter #endif // BUILTIN_CONVERTERS_DWA2002124_HPP diff --git a/include/boost/python/converter/builtin_to_python_converters.hpp b/include/boost/python/converter/builtin_to_python_converters.hpp deleted file mode 100644 index 89ad7b86..00000000 --- a/include/boost/python/converter/builtin_to_python_converters.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright David Abrahams 2002. 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 BUILTIN_TO_PYTHON_CONVERTERS_DWA2002129_HPP -# define BUILTIN_TO_PYTHON_CONVERTERS_DWA2002129_HPP -# include -# include - -namespace boost { namespace python { - -// Provide specializations of to_python_value -template struct to_python_value; - -namespace detail -{ - struct builtin_to_python - { - static bool convertible() { return true; } - }; -} - -# define BOOST_PYTHON_TO_PYTHON_BY_VALUE(T, expr) \ - template <> struct to_python_value \ - : detail::builtin_to_python \ - { \ - PyObject* operator()(T const& x) const \ - { \ - return (expr); \ - } \ - }; \ - template <> struct to_python_value \ - : detail::builtin_to_python \ - { \ - PyObject* operator()(T const& x) const \ - { \ - return (expr); \ - } \ - }; - - -# define BOOST_PYTHON_TO_INT(T) \ - BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, PyInt_FromLong(x)) \ - BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned T, PyInt_FromLong(x)) - -BOOST_PYTHON_TO_INT(char) -BOOST_PYTHON_TO_INT(short) -BOOST_PYTHON_TO_INT(int) -BOOST_PYTHON_TO_INT(long) -# undef BOOST_TO_PYTHON_INT - -BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, PyString_FromString(x)) -BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, PyString_FromString(x.c_str())) -BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, PyFloat_FromDouble(x)) -BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, PyFloat_FromDouble(x)) -BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, PyFloat_FromDouble(x)) -BOOST_PYTHON_TO_PYTHON_BY_VALUE(PyObject*, x) - -}} // namespace boost::python::converter - -#endif // BUILTIN_TO_PYTHON_CONVERTERS_DWA2002129_HPP diff --git a/include/boost/python/to_python_value.hpp b/include/boost/python/to_python_value.hpp index a222e9a9..ecff5808 100644 --- a/include/boost/python/to_python_value.hpp +++ b/include/boost/python/to_python_value.hpp @@ -10,7 +10,7 @@ # include # include # include -# include +# include namespace boost { namespace python { From e37a97e2d57f3fd598ff222d1d4cbbfe5785e5f2 Mon Sep 17 00:00:00 2001 From: Darin Adler Date: Fri, 8 Feb 2002 20:08:15 +0000 Subject: [PATCH 270/369] Always say "private noncopyable" to avoid warnings. [SVN r12762] --- include/boost/python/classes.hpp | 2 +- include/boost/python/converter/handle.hpp | 2 +- include/boost/python/object/class.hpp | 4 ++-- test/comprehensive.hpp | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/boost/python/classes.hpp b/include/boost/python/classes.hpp index 31af430f..2725ed7b 100644 --- a/include/boost/python/classes.hpp +++ b/include/boost/python/classes.hpp @@ -233,7 +233,7 @@ class BOOST_PYTHON_DECL_TEMPLATE meta_class boost::python::detail::getattrable< boost::python::detail::setattrable< boost::python::detail::type_object > > > > >, - boost::noncopyable + private boost::noncopyable { public: meta_class(); diff --git a/include/boost/python/converter/handle.hpp b/include/boost/python/converter/handle.hpp index bc06be38..82e085b0 100644 --- a/include/boost/python/converter/handle.hpp +++ b/include/boost/python/converter/handle.hpp @@ -16,7 +16,7 @@ struct BOOST_PYTHON_DECL body; // The common base class for unwrap_ and wrap_ handle objects. They // share a common base so that handles can be linked into a chain // within a function wrapper which is managed by a single object. -struct BOOST_PYTHON_DECL handle : boost::noncopyable +struct BOOST_PYTHON_DECL handle : private boost::noncopyable { public: // member functions diff --git a/include/boost/python/object/class.hpp b/include/boost/python/object/class.hpp index 53d886fa..35280074 100644 --- a/include/boost/python/object/class.hpp +++ b/include/boost/python/object/class.hpp @@ -26,7 +26,7 @@ template struct holder; // To identify a class, we don't need cv/reference decorations typedef converter::undecorated_type_id_t class_id; -struct BOOST_PYTHON_DECL class_base : noncopyable +struct BOOST_PYTHON_DECL class_base : private noncopyable { // constructor class_base( @@ -44,7 +44,7 @@ struct BOOST_PYTHON_DECL class_base : noncopyable }; // Base class for all holders -struct BOOST_PYTHON_DECL instance_holder : noncopyable +struct BOOST_PYTHON_DECL instance_holder : private noncopyable { public: instance_holder(); diff --git a/test/comprehensive.hpp b/test/comprehensive.hpp index deb68a88..370f7d04 100644 --- a/test/comprehensive.hpp +++ b/test/comprehensive.hpp @@ -27,8 +27,8 @@ namespace bpl_test { // example: Foo, Bar, and Baz are C++ classes we want to wrap. // -class Foo // prohibit copying, proving that it doesn't choke - : boost::noncopyable // our generation of to_python(). +class Foo // prohibit copying, proving that it doesn't choke + : private boost::noncopyable // our generation of to_python(). { public: // constructor/destructor Foo(int x) : m_x(x) {} From 93735c7bf1538572018fedae9c76b05f46298d12 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 8 Feb 2002 22:04:01 +0000 Subject: [PATCH 271/369] Updated docs and provided backwards compatibility for handle_exception() [SVN r12764] --- doc/example1.html | 7 ------- doc/exporting_classes.html | 7 ------- doc/inheritance.html | 33 +++++++++++++-------------------- doc/overriding.html | 13 +++---------- example/getting_started1.cpp | 5 +++++ 5 files changed, 21 insertions(+), 44 deletions(-) diff --git a/doc/example1.html b/doc/example1.html index 402cc7a6..ee01e72c 100644 --- a/doc/example1.html +++ b/doc/example1.html @@ -37,19 +37,12 @@ namespace python = boost::python; BOOST_PYTHON_MODULE_INIT(getting_started1) { - try - { // Create an object representing this extension module. python::module_builder this_module("getting_started1"); // Add regular functions to the module. this_module.def(greet, "greet"); this_module.def(square, "square"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } }
  • diff --git a/doc/exporting_classes.html b/doc/exporting_classes.html index 61c5ef88..cbeb8a9e 100644 --- a/doc/exporting_classes.html +++ b/doc/exporting_classes.html @@ -47,8 +47,6 @@ namespace python = boost::python; BOOST_PYTHON_MODULE_INIT(getting_started2) { - try - { // Create an object representing this extension module. python::module_builder this_module("getting_started2"); @@ -65,11 +63,6 @@ BOOST_PYTHON_MODULE_INIT(getting_started2) // Even better, invite() can also be made a member of hello_class!!! hello_class.def(invite, "invite"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } }

    diff --git a/doc/inheritance.html b/doc/inheritance.html index cd95c744..3cceb0d0 100644 --- a/doc/inheritance.html +++ b/doc/inheritance.html @@ -78,26 +78,19 @@ namespace python = boost::python; BOOST_PYTHON_MODULE_INIT(my_module) { -    try -    { -       python::module_builder my_module("my_module"); - -       python::class_builder<Base> base_class(my_module, "Base"); -       base_class.def(python::constructor<void>()); - -       python::class_builder<Derived> derived_class(my_module, "Derived"); -       derived_class.def(python::constructor<void>()); - // Establish the inheritance relationship between Base and Derived - derived_class.declare_base(base_class); - - my_module.def(derived_as_base, "derived_as_base"); - my_module.def(get_name, "get_name"); - my_module.def(get_derived_x, "get_derived_x"); -    } -    catch(...) -    { -       python::handle_exception();    // Deal with the exception for Python -    } +    python::module_builder my_module("my_module"); + +    python::class_builder<Base> base_class(my_module, "Base"); +    base_class.def(python::constructor<void>()); + +    python::class_builder<Derived> derived_class(my_module, "Derived"); +    derived_class.def(python::constructor<void>()); + // Establish the inheritance relationship between Base and Derived + derived_class.declare_base(base_class); + + my_module.def(derived_as_base, "derived_as_base"); + my_module.def(get_name, "get_name"); + my_module.def(get_derived_x, "get_derived_x"); } diff --git a/doc/overriding.html b/doc/overriding.html index 02665be5..085d5a7f 100644 --- a/doc/overriding.html +++ b/doc/overriding.html @@ -151,16 +151,9 @@ struct baz_callback { BOOST_PYTHON_MODULE_INIT(foobar) { - try - { - boost::python::module_builder foobar("foobar"); - boost::python::class_builder<baz,baz_callback> baz_class("baz"); - baz_class.def(&baz::calls_pure, "calls_pure"); - } - catch(...) - { - boost::python::handle_exception(); // Deal with the exception for Python - } + boost::python::module_builder foobar("foobar"); + boost::python::class_builder<baz,baz_callback> baz_class("baz"); + baz_class.def(&baz::calls_pure, "calls_pure"); } diff --git a/example/getting_started1.cpp b/example/getting_started1.cpp index 2f180633..91a1f551 100644 --- a/example/getting_started1.cpp +++ b/example/getting_started1.cpp @@ -16,10 +16,15 @@ namespace python = boost::python; // extension module. This is where we build the module contents. BOOST_PYTHON_MODULE_INIT(getting_started1) { + try { // Create an object representing this extension module. python::module_builder this_module("getting_started1"); // Add regular functions to the module. this_module.def(greet, "greet"); this_module.def(square, "square"); + } + catch(...) { + boost::python::handle_exception(); + } } From 9e8273c7f7981d012b13a7d23310dc93ec0d80b1 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 10 Feb 2002 00:49:13 +0000 Subject: [PATCH 272/369] backward-compatibility hack for handle_exception() [SVN r12777] --- include/boost/python/errors.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/boost/python/errors.hpp b/include/boost/python/errors.hpp index b9eb4363..d0f71a24 100644 --- a/include/boost/python/errors.hpp +++ b/include/boost/python/errors.hpp @@ -28,6 +28,13 @@ bool handle_exception(T f) return handle_exception_impl(function0(boost::ref(f))); } +namespace detail { inline void rethrow() { throw; } } + +inline void handle_exception() +{ + handle_exception(detail::rethrow); +} + BOOST_PYTHON_DECL PyObject* expect_non_null(PyObject* x); template From 44e43d3b47295269f67e6f1e17bfacca12af60bb Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 14 Feb 2002 03:39:41 +0000 Subject: [PATCH 273/369] Initial checkin of V2 docs [SVN r12797] --- build/Jamfile | 2 +- doc/boost.css | 57 +++++ doc/v2/acknowledgments.html | 31 +++ doc/v2/bibliography.html | 31 +++ doc/v2/call.html | 62 +++++ doc/v2/class.html | 328 +++++++++++++++++++++++++++ doc/v2/class_hpp.py | 20 ++ doc/v2/configuration.html | 90 ++++++++ doc/v2/copy_const_reference.html | 118 ++++++++++ doc/v2/copy_non_const_reference.html | 119 ++++++++++ doc/v2/default_call_policies.html | 144 ++++++++++++ doc/v2/definitions.html | 34 +++ doc/v2/errors.html | 223 ++++++++++++++++++ doc/v2/faq.html | 38 ++++ doc/v2/foo.cpp | 142 ++++++++++++ doc/v2/from_python.html | 156 +++++++++++++ doc/v2/header.html | 181 +++++++++++++++ doc/v2/index.html | 41 ++++ doc/v2/overview.html | 47 ++++ doc/v2/rationale.html | 47 ++++ doc/v2/reference.html | 271 ++++++++++++++++++++++ 21 files changed, 2181 insertions(+), 1 deletion(-) create mode 100644 doc/boost.css create mode 100644 doc/v2/acknowledgments.html create mode 100644 doc/v2/bibliography.html create mode 100644 doc/v2/call.html create mode 100644 doc/v2/class.html create mode 100644 doc/v2/class_hpp.py create mode 100644 doc/v2/configuration.html create mode 100644 doc/v2/copy_const_reference.html create mode 100644 doc/v2/copy_non_const_reference.html create mode 100644 doc/v2/default_call_policies.html create mode 100644 doc/v2/definitions.html create mode 100644 doc/v2/errors.html create mode 100644 doc/v2/faq.html create mode 100644 doc/v2/foo.cpp create mode 100644 doc/v2/from_python.html create mode 100644 doc/v2/header.html create mode 100644 doc/v2/index.html create mode 100644 doc/v2/overview.html create mode 100644 doc/v2/rationale.html create mode 100644 doc/v2/reference.html diff --git a/build/Jamfile b/build/Jamfile index 1ea3665d..7dd6ecfe 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -9,7 +9,7 @@ # 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 +# 1. libboost_python.dll/.so, a dynamic library to be linked with all # Boost.Python modules # # 2. pairs of test targets of the form .test and .run diff --git a/doc/boost.css b/doc/boost.css new file mode 100644 index 00000000..c382d4c6 --- /dev/null +++ b/doc/boost.css @@ -0,0 +1,57 @@ +H1 +{ + FONT-SIZE: 200% + COLOR: #00007f +} +H2 +{ + FONT-SIZE: 150%; +} +H3 +{ + FONT-SIZE: 125%; +} +H4 +{ + FONT-SIZE: 108%; +} +BODY +{ + FONT-SIZE: 100%; + BACKGROUND-COLOR: #ffffff +} +PRE +{ + MARGIN-LEFT: 2pc; + BACKGROUND-COLOR: #dfffff +} +CODE +{ + white-space: pre +} +.index +{ + TEXT-ALIGN: left +} +.page-index +{ + TEXT-ALIGN: left +} +.definition +{ + TEXT-ALIGN: left +} +.footnote +{ + FONT-SIZE: 66%; + VERTICAL-ALIGN: super; + TEXT-DECORATION: none +} +.function-semantics +{ + CLEAR: left +} +.metafunction-semantics +{ + CLEAR: left +} diff --git a/doc/v2/acknowledgments.html b/doc/v2/acknowledgments.html new file mode 100644 index 00000000..bd13fa79 --- /dev/null +++ b/doc/v2/acknowledgments.html @@ -0,0 +1,31 @@ + + + + +Boost.Python - Acknowledgments + + + + + + + +
    +

    C++ Boost

    +
    +

    Boost.Python

    +

    Acknowledgments

    +
    +


    +{{text}} +
    +

    Revised + + 05 November, 2002 + +

    +

    © Copyright Dave Abrahams + 2002. All Rights Reserved.

    + + diff --git a/doc/v2/bibliography.html b/doc/v2/bibliography.html new file mode 100644 index 00000000..e1be0141 --- /dev/null +++ b/doc/v2/bibliography.html @@ -0,0 +1,31 @@ + + + + +Boost.Python - Bibliography + + + + + + + +
    +

    C++ Boost

    +
    +

    Boost.Python

    +

    Bibliography

    +
    +
    +{{bibliographical information}} +
    +

    Revised + + 05 November, 2002 + +

    +

    © Copyright Dave Abrahams + 2002. All Rights Reserved.

    + + diff --git a/doc/v2/call.html b/doc/v2/call.html new file mode 100644 index 00000000..eb3e706c --- /dev/null +++ b/doc/v2/call.html @@ -0,0 +1,62 @@ + + + + +Boost.Python - <call.hpp> + + + + + + + +
    +

    C++ Boost

    +
    +

    Boost.Python

    +

    Header <call.hpp>

    +
    +
    +

    Contents

    +
    +
    Introduction
    + +
    Functions
    +
    +
    call
    +
    + +
    Example(s)
    + +
    +
    +

    Introduction

    +

    {{Introductory text}}

    + +

    Functions

    +
    +call
    +
    +
    +
    Requires: {{text}}
    +
    Effects: {{text}}
    +
    Postconditions: {{text}}
    +
    Returns: {{text}}
    +
    Throws: {{text}}
    +
    Complexity: {{text}}
    +
    Rationale: {{text}}
    +
    + +

    Example(s)

    + +

    {{Example(s)}}

    +

    Revised + + 05 November, 2002 + +

    +

    © Copyright Dave Abrahams + 2002. All Rights Reserved.

    + + diff --git a/doc/v2/class.html b/doc/v2/class.html new file mode 100644 index 00000000..e6eee244 --- /dev/null +++ b/doc/v2/class.html @@ -0,0 +1,328 @@ + + + + +Boost.Python - <boost/python/class.hpp>, <boost/python/class_fwd.hpp> + + + + + + + +
    +

    C++ Boost

    +
    +

    Boost.Python

    +

    Headers <boost/python/class.hpp>, <boost/python/class_fwd.hpp>

    +
    +
    +

    Contents

    +
    +
    Introduction
    + +
    Classes
    + +
    + +
    Class template class_
    +
    +
    Class class_ synopsis
    +
    Class class_ constructors
    +
    Class class_ modifier functions
    +
    Class class_ observer functions
    +
    + +
    Class template bases
    +
    +
    Class bases synopsis
    +
    + +
    Class template args
    +
    +
    Class args synopsis
    +
    + +
    + +
    Example(s)
    +
    +
    +

    Introduction

    + +

    <boost/python/class.hpp> defines the interface through + which users expose their C++ classes to Python. It declares the + class_ class template, which is parameterized on the + class type being exposed, and the args and + bases utility class templates in the anonymous + namespace (the latter definitions will probably be moved in a future + release). + +

    + <boost/python/class_fwd.hpp> contains a forward + declaration of the class_ class template. + + +

    Classes

    + +

    +Class template class_<T, Bases, HolderGenerator>

    + +

    Creates a Python class associated with the C++ type passed as its +first parameter. Its template arguments are: +

    + + + + + +
    Parameter + Description + Default +
    T + The class being exposed to Python +
    Bases + An MPL sequence of C++ base classes + An unspecified empty sequence +
    HolderGenerator + A type generator for the holder which +maintains the C++ object inside the Python instance. + boost::python::objects::value_holder_generator +
    + + + +

    Class template class_ synopsis

    +
    +namespace boost { namespace python
    +{
    +
    +  template <class T
    +            , class Bases = none
    +            , class HolderGenerator = objects::value_holder_generator>
    +  class class_
    +  {
    +    class_();
    +    class_(char const* name);
    +
    +    template <class F>
    +    class_& def(char const* name, F f);
    +
    +    template <class Fn, class CallPolicy>
    +    class_& def(char const* name, Fn fn, CallPolicy policy);
    +    
    +    template <class Args>
    +    class_& def_init(Args const& = Args());
    +
    +    class_& def_init();
    +
    +    ref object() const;
    +  };
    +}}
    +
    + +

    Class template class_ constructors

    +
    +class_()
    +
    +
    + +
    Requires: The platform's + std::type_info::name() implementation produces a string + which corresponds to the type's declaration in C++
    + +
    Effects: Constructs a class_ object which + generates a Boost.Python extension class with the same name as + T.
    + +
    Rationale: Many platforms can generate reasonable names + for Python classes without user intervention.
    + +
    + +
    +class_(char const* name)
    +
    +
    + +
    Requires: Name is a ntbs which conforms to Python's identifier + naming rules.
    + +
    Effects: Constructs a class_ object which + generates a Boost.Python extension class named + name.
    + +
    Rationale: Gives the user full control over class naming.
    + +
    + +

    Class template class_ modifier functions

    + +
    +template <class F>
    +class_& def(char const* name, F f)
    +
    +template <class Fn, class CallPolicy>
    +class_& def(char const* name, Fn fn, CallPolicy policy)
    +
    + +
    +
    Requires: + + f is a non-null pointer-to-function or + pointer-to-member-function. + + name is a ntbs which conforms to Python's identifier + naming rules. + + If supplied, policy conforms to the CallPolicy concept requirements. +
    + +
    Effects: Adds the result of make_function(f) + to the Boost.Python extension class being defined, with the given + name. If the extension class already has an attribute + named name, the usual overloading procedure applies. + +
    + +
    Returns: *this
    +
    + +
    +template <class Args>
    +class_& def_init(Args const& argument_types)
    +
    +class_& def_init()
    +
    + +
    + +
    Requires: in the first form, argument_types must be an MPL sequence of C++ + argument types (A1, A2,... AN) such that if + a1, a2... aN are objects of type + A1, A2,... AN respectively, the expression + T(a1, a2... aN) is + valid. In the second form, the expression T() must be + valid. +
    + +
    Effects: Adds the result of + make_constructor<T,Args,HolderGenerator>() to the + Boost.Python extension class being defined with the name + "__init__". If the 2nd form is used, an unspecified empty + MPL sequence type is + substituted for Args. + If the extension class already has an + "__init__" attribute, the usual overloading procedure applies. + +
    Returns: *this
    + +
    Rationale: Allows users to easily expose a class' + constructor to Python.
    +
    + + +

    Class template class_ observer +functions

    +
    +ref object() const;
    +
    +
    +
    Returns: A ref object which holds a + reference to the Boost.Python extension class object created by the + class_ constructor.
    + +
    Rationale: Mostly not needed by users, since module::add() uses this to + insert the extension class in the module.
    +
    + + +

    +Class template args<T1, T2,...TN>

    + +

    Essentially an alias for boost::mpl::type_list which +users can use in def_init calls to make their code more +readable. Currently it is in the global unnammed namespace, but that +will probably change. + +

    Class template args synopsis

    +
    +namespace
    +{
    +  template <T1 = unspecified,...TN = unspecified>
    +  struct args : ::boost::mpl::type_list<T1,...TN>::type
    +  {};
    +}
    +
    + +

    +Class template bases<T1, T2,...TN>

    + +

    Essentially an alias for boost::mpl::type_list which +users can use in class_<...> +instantiations to make their code more readable. Currently it is in +the global unnammed namespace, but that will probably change. + +

    Class template bases synopsis

    +
    +namespace
    +{
    +  template <T1 = unspecified,...TN = unspecified>
    +  struct bases : ::boost::mpl::type_list<T1,...TN>::type
    +  {};
    +}
    +
    + +

    Example(s)

    + +

    Given a C++ class declaration: + +

    +class Foo : public Bar, public Baz
    +{
    + public:
    +   Foo(int, char const*);
    +   Foo(double);
    +
    +   std::string const& name() { return m_name; }
    +   void name(char const*);
    + private:
    +   ...
    +};
    +
    + +A corresponding Boost.Python extension class can be created with: + +
    +using namespace boost::python;
    +ref foo =
    +class_<Foo,bases<Bar,Baz> >()
    +   .def_init(args<int,char const*>())
    +   .def_init(args<double>())
    +   .def("get_name", &Foo::get_name, return_internal_reference<>())
    +   .def("set_name", &Foo::set_name)
    +   .object();
    +
    + +

    + +

    Revised + + 05 November, 2001 + +

    +

    © Copyright Dave Abrahams + 2002. All Rights Reserved.

    + + diff --git a/doc/v2/class_hpp.py b/doc/v2/class_hpp.py new file mode 100644 index 00000000..9af2cb5c --- /dev/null +++ b/doc/v2/class_hpp.py @@ -0,0 +1,20 @@ +introduction = ''' +''' + +class boost(namespace): pass + +class python(boost): + + class class_(class_template): + T = type() + T.requires = 'a class type' + + Bases = concepts.mpl_sequence('class type') + HolderGenerator = concepts.HolderGenerator() + template_args = (T, Bases, HolderGenerator) + + class def_1(function_template): + name = "def" + args = (('char const*', 'name'), ('F', 'f')) + +class_template diff --git a/doc/v2/configuration.html b/doc/v2/configuration.html new file mode 100644 index 00000000..18b065d1 --- /dev/null +++ b/doc/v2/configuration.html @@ -0,0 +1,90 @@ + + + + +Boost.Python - Configuration + + + + + + + +
    +

    C++ Boost

    +
    +

    Boost.Python

    +

    Configuration

    +
    +
    +
    +
    Introduction
    +
    Application Defined Macros
    +
    Public Library Defined Macros
    +
    Library Defined Implementation Macros
    +
    +

    Introduction

    +

    Boost.Python uses several configuration macros in <boost/config.hpp>, + as well as configuration macros meant to be supplied by the application. These + macros are documented here.

    +

    Application Defined Macros

    +

    These are the macros that may be defined by an application using Boost.Python.

    + + + + + + + + + + + + + +
    MacroMeaning
    {{macro}}{{meaning}}
    {{macro}}{{meaning}}
    +

    Public Library Defined Macros

    +

    These macros are defined by Boost.Python but are expected to be used by application + code.

    + + + + + + + + + + + + + +
    MacroMeaning
    {{macro}}{{meaning}}
    {{macro}}{{meaning}}
    +

    Library Defined Implementation Macros

    +

    These macros are defined by Boost.Python and are implementation details of interest + only to implementers.

    + + + + + + + + + + + + + +
    MacroMeaning
    {{macro}}{{meaning}}
    {{macro}}{{meaning}}
    +
    +

    Revised + + 05 November, 2002 + +

    +

    © Copyright Dave Abrahams + 2002. All Rights Reserved.

    + + diff --git a/doc/v2/copy_const_reference.html b/doc/v2/copy_const_reference.html new file mode 100644 index 00000000..1ce94dbb --- /dev/null +++ b/doc/v2/copy_const_reference.html @@ -0,0 +1,118 @@ + + + + +Boost.Python - <boost/python/copy_const_reference.hpp> + + + + + + + +
    +

    C++ Boost

    +
    +

    Boost.Python

    +

    Header <boost/python/copy_const_reference.hpp>

    +
    +
    +

    Contents

    +
    +
    Classes
    +
    +
    Class copy_const_reference
    +
    +
    Class copy_const_reference synopsis
    +
    Class copy_const_reference metafunctions
    +
    +
    + +
    Example
    +
    +
    + +

    Classes

    + +

    Class copy_const_reference

    +

    +copy_const_reference is a model of ResultConverterGenerator +which can be used to wrap C++ functions returning a reference-to-const +type such that the referenced value is copied into a new Python object. +

    + +

    Class copy_const_reference synopsis

    +
    +namespace boost { namespace python
    +{
    +    struct copy_const_reference
    +    {
    +        template <class T> struct apply;
    +    };
    +}}
    +
    +

    Class copy_const_reference metafunctions

    +
    +template <class T> struct apply
    +
    +
    +
    Requires: T is U const& for some U.
    +
    Returns: typedef to_python_value<T> type;
    +
    + +

    Example

    + +

    In C++: + +

    +#include <boost/python/module.hpp>
    +#include <boost/python/class.hpp>
    +#include <boost/python/copy_const_reference.hpp>
    +#include <boost/python/return_value_policy.hpp>
    +
    +// classes to wrap
    +struct Bar { int x; }
    +
    +struct Foo {
    +   Foo(int x) : { b.x = x; }
    +   Bar const& get_bar() const { return b; }
    + private:
    +   Bar b;
    +};
    +
    +// Wrapper code
    +using namespace boost::python;
    +BOOST_PYTHON_MODULE_INIT(my_module)
    +{
    +   module m("my_module")
    +      .add(
    +         class_<Bar>()
    +         )
    +      .add(
    +         class_<Foo>()
    +            .def_init(args<int>())
    +            .def("get_bar", &Foo::get_bar
    +                , return_value_policy<copy_const_reference>())
    +         );
    +}
    +
    + +In Python: + +
    +>>> from my_module import *
    +>>> f = Foo(3)         # create a Foo object
    +>>> b = f.get_bar()    # make a copy of the internal Bar object
    +
    + +

    Revised + + 05 November, 2001 + +

    +

    © Copyright Dave Abrahams + 2002. All Rights Reserved.

    + + diff --git a/doc/v2/copy_non_const_reference.html b/doc/v2/copy_non_const_reference.html new file mode 100644 index 00000000..c1ed50a3 --- /dev/null +++ b/doc/v2/copy_non_const_reference.html @@ -0,0 +1,119 @@ + + + + +Boost.Python - <boost/python/copy_non_const_reference.hpp> + + + + + + + +
    +

    C++ Boost

    +
    +

    Boost.Python

    +

    Header <boost/python/copy_non_const_reference.hpp>

    +
    +
    +

    Contents

    +
    +
    Classes
    +
    +
    Class copy_non_const_reference
    +
    +
    Class copy_non_const_reference synopsis
    +
    Class copy_non_const_reference metafunctions
    +
    +
    + +
    Example
    +
    +
    + +

    Classes

    + +

    Class copy_non_const_reference

    +

    +copy_non_const_reference is a model of ResultConverterGenerator +which can be used to wrap C++ functions returning a reference-to-non-const +type such that the referenced value is copied into a new Python object. +

    + +

    Class copy_non_const_reference synopsis

    +
    +namespace boost { namespace python
    +{
    +    struct copy_non_const_reference
    +    {
    +        template <class T> struct apply;
    +    };
    +}}
    +
    + +

    Class copy_non_const_reference metafunctions

    +
    +template <class T> struct apply
    +
    +
    +
    Requires: T is U& for some non-const U.
    +
    Returns: typedef to_python_value<T> type;
    +
    + +

    Example

    + +

    C++ code: + +

    +#include <boost/python/module.hpp>
    +#include <boost/python/class.hpp>
    +#include <boost/python/copy_non_const_reference.hpp>
    +#include <boost/python/return_value_policy.hpp>
    +
    +// classes to wrap
    +struct Bar { int x; }
    +
    +struct Foo {
    +   Foo(int x) : { b.x = x; }
    +   Bar& get_bar() { return b; }
    + private:
    +   Bar b;
    +};
    +
    +// Wrapper code
    +using namespace boost::python;
    +BOOST_PYTHON_MODULE_INIT(my_module)
    +{
    +   module m("my_module")
    +      .add(
    +         class_<Bar>()
    +         )
    +      .add(
    +         class_<Foo>()
    +            .def_init(args<int>())
    +            .def("get_bar", &Foo::get_bar
    +                , return_value_policy<copy_non_const_reference>())
    +         );
    +}
    +
    + +Python Code: + +
    +>>> from my_module import *
    +>>> f = Foo(3)         # create a Foo object
    +>>> b = f.get_bar()    # make a copy of the internal Bar object
    +
    + +

    Revised + + 05 November, 2001 + +

    +

    © Copyright Dave Abrahams + 2002. All Rights Reserved.

    + + diff --git a/doc/v2/default_call_policies.html b/doc/v2/default_call_policies.html new file mode 100644 index 00000000..3e60fcc8 --- /dev/null +++ b/doc/v2/default_call_policies.html @@ -0,0 +1,144 @@ + + + + +Boost.Python - <boost/python/default_call_policies.hpp> + + + + + + + +
    +

    C++ Boost

    +
    +

    Boost.Python

    +

    Header <boost/python/default_call_policies.hpp>

    +
    +
    +

    Contents

    +
    +
    Classes
    +
    + +
    Class default_call_policies
    +
    +
    Class default_call_policies synopsis
    +
    Class default_call_policies static functions
    +
    + +
    Class default_result_converter
    +
    +
    Class default_result_converter synopsis
    +
    Class default_result_converter metafunctions
    +
    + +
    + +
    Example
    +
    +
    + +

    Classes

    + +

    Class default_call_policies

    +

    +default_call_policies is a model of CallPolicies with no precall +or postcall behavior and a result_converter +which handles by-value returns. Wrapped C++ functions and member +functions use default_call_policies unless otherwise +specified. You may find it convenient to derive new models of CallPolicies from +default_call_policies. +

    + +

    Class default_call_policies synopsis

    +
    +namespace boost { namespace python
    +{
    +    struct default_call_policies
    +    {
    +        static bool precall(PyObject*);
    +        static PyObject* postcall(PyObject*, PyObject* result);
    +        typedef default_result_converter result_converter;
    +    };
    +}}
    +
    + +

    Class default_call_policies static functions

    +
    +bool precall(PyObject*);
    +
    +
    +
    Returns: true
    +
    Throws: nothing
    +
    + +
    +PyObject* postcall(PyObject*, PyObject* result);
    +
    +
    +
    Returns: result
    +
    Throws: nothing
    +
    + +

    Class default_result_converter

    +

    +default_result_converter is a model of ResultConverterGenerator +which can be used to wrap C++ functions returning non-pointer types, +char const*, and PyObject*, +by-value. +

    + +

    Class default_result_converter synopsis

    +
    +namespace boost { namespace python
    +{
    +    struct default_result_converter
    +    {
    +        template <class T> struct apply;
    +    };
    +}}
    +
    + +

    Class default_result_converter metafunctions

    +
    +template <class T> struct apply
    +
    +
    + +
    Requires: T is not a reference type. If + T is a pointer type, T is const + char* or PyObject*.
    + +
    Returns: typedef to_python_value<T const&> type;
    +
    + +

    Example

    + +

    This example comes from the Boost.Python implementation itself. Because the return_value_policy +class template does not implement precall or +postcall behavior, its default base class is default_call_policies: + +

    +template <class Handler, class Base = default_call_policies>
    +struct return_value_policy : Base
    +{
    +   typedef Handler result_converter;
    +};
    +
    + +

    Revised + + 05 November, 2001 + +

    +

    © Copyright Dave Abrahams + 2002. All Rights Reserved.

    + + diff --git a/doc/v2/definitions.html b/doc/v2/definitions.html new file mode 100644 index 00000000..dd917434 --- /dev/null +++ b/doc/v2/definitions.html @@ -0,0 +1,34 @@ + + + + +Boost.Python - Definitions + + + + + + + +
    +

    C++ Boost

    +
    +

    Boost.Python

    +

    Definitions

    +
    +
    +
    +
    {{term}}: {{definition}}
    +
    {{term}}: {{definition}}
    +
    +
    +

    Revised + + 05 November, 2002 + +

    +

    © Copyright Dave Abrahams + 2002. All Rights Reserved.

    + + diff --git a/doc/v2/errors.html b/doc/v2/errors.html new file mode 100644 index 00000000..b46de25c --- /dev/null +++ b/doc/v2/errors.html @@ -0,0 +1,223 @@ + + + + +Boost.Python - <{{header}}> + + + + + + + +
    +

    C++ Boost

    +
    +

    Boost.Python

    +

    Header <boost/python/errors.hpp>

    +
    +
    +

    Contents

    +
    +
    Introduction
    + +
    Classes
    +
    + +
    Class error_already_set
    +
    +
    Class error_already_set synopsis
    +
    + +
    + +
    Functions
    +
    + +
    handle_exception
    +
    expect_non_null
    + +
    + +
    Examples
    +
    +
    + +

    Introduction

    +

    <boost/python/errors.hpp> provides types and +functions for managing and translating between Python and C++ +exceptions. This is relatively low-level functionality that is mostly +used internally by Boost.Python. Users should seldom need it. + +

    Classes

    + +

    Class error_already_set

    +

    +error_already_set is an exception type which can be +thrown to indicate that a Python error has occurred. If thrown, the +precondition is that PyErr_Occurred() +returns a value convertible to true. +

    + +

    Class error_already_set synopsis

    +
    +namespace boost { namespace python
    +{
    +    class error_already_set {};
    +}}
    +
    + + +

    Functions

    +
    template <class T> bool handle_exception(T f) throw();
    +
    +void handle_exception() throw();
    +
    +
    +
    Requires: The first form requires that the expression + function0<void>(f) + is valid. The second form requires that a C++ exception is currently + being handled (see section 15.1 in the C++ standard). +
    + +
    Effects: The first form calls f() inside a + try block whose catch clauses set an + appropriate Python exception for the C++ exception caught, returning + true if an exception was caught, false + otherwise. The second form passes a function which rethrows the + exception currently being handled to the first form.
    + +
    Postconditions: No exception is being handled
    + +
    Throws: nothing
    + +
    Rationale: At inter-language boundaries it is important + to ensure that no C++ exceptions escape, since the calling language + usually doesn't have the equipment neccessary to properly unwind the + stack. Use handle_exception to manage exception + translation whenever your C++ code is called directly from the + Python API. This is done for you automatically by the usual function + wrapping facilities: make_function(), make_constructor(), + module::def and class_::def). The second form can be + more convenient to use + (see the example below), but various + compilers have problems when exceptions are rethrown from within an + enclosing try block.
    +
    + +
    +PyObject* expect_non_null(PyObject* x);
    +
    +template <class T> T* expect_non_null(T* x);
    +
    +
    +
    Returns: x
    +
    Throws: error_already_set() iff x == 0.
    +
    Rationale: Simplifies error-handling when calling many + functions in the Python/C + API, which return 0 on error.
    +
    + +

    Examples

    +

    +

    +#include <string>
    +#include <boost/python/errors.hpp>
    +#include <boost/python/reference.hpp>
    +
    +// Returns a std::string which has the same value as obj's "__name__"
    +// attribute.
    +std::string get_name(boost::python::ref obj)
    +{
    +   // throws if there's no __name__ attribute
    +   PyObject* p = boost::python::expect_non_null(
    +      PyObject_GetAttrString(obj.get(), "__name__"));
    +
    +   // throws if it's not a Python string
    +   std::string result(
    +      boost::python::expect_non_null(
    +         PyString_AsString(p)));
    +
    +   Py_XDECREF(p); // Done with p
    +   
    +   return result;
    +}
    +
    +//
    +// Demonstrate form 1 of handle_exception
    +//
    +
    +// Place a Python Int object whose value is 1 if a and b have
    +// identical "__name__" attributes, 0 otherwise.
    +void same_name_impl(PyObject*& result, PyObject* a, PyObject* b)
    +{
    +   result = PyInt_FromLong(
    +      get_name(boost::python::ref(a1)) == get_name(boost::python::ref(a2)));
    +}
    +
    +// This is an example Python 'C' API interface function
    +extern "C" PyObject*
    +same_name(PyObject* args, PyObject* keywords)
    +{
    +   PyObject* a1;
    +   PyObject* a2;
    +   PyObject* result = 0;
    +
    +   if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
    +      return 0;
    +   
    +   // Use boost::bind to make an object compatible with
    +   // boost::Function0<void>
    +   if (boost::python::handle_exception(
    +         boost::bind<void>(same_name_impl, boost::ref(result), a1, a2)))
    +   {
    +      // an exception was thrown; the Python error was set by
    +      // handle_exception()
    +      return 0;
    +   }
    +
    +   return result;
    +}
    +
    +//
    +// Demonstrate form 2 of handle_exception. Not well-supported by all
    +// compilers.
    +//
    +extern "C" PyObject*
    +same_name2(PyObject* args, PyObject* keywords)
    +{
    +   PyObject* a1;
    +   PyObject* a2;
    +   PyObject* result = 0;
    +
    +   if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
    +      return 0;
    +   try {
    +      return PyInt_FromLong(
    +         get_name(boost::python::ref(a1)) == get_name(boost::python::ref(a2)));
    +   }
    +   catch(...)
    +   {
    +      // If an exception was thrown, translate it to Python
    +      boost::python::handle_exception();
    +      return 0;
    +   }
    +}
    +
    +

    +

    Revised + + 05 November, 2001 + +

    +

    © Copyright Dave Abrahams + 2002. All Rights Reserved.

    + + diff --git a/doc/v2/faq.html b/doc/v2/faq.html new file mode 100644 index 00000000..dae93fa5 --- /dev/null +++ b/doc/v2/faq.html @@ -0,0 +1,38 @@ + + + + +Boost.Python - FAQ + + + + + + + +
    +

    C++ Boost

    +
    +

    Boost.Python

    +

    Frequently Asked Questions (FAQs)

    +
    +
    +
    +
    {{question}}
    +
    {{question}}
    +
    +

    {{question}}

    +

    {{answer}}

    +

    {{question}}

    +

    {{answer}}

    +
    +

    Revised + + 05 November, 2002 + +

    +

    © Copyright Dave Abrahams + 2002. All Rights Reserved.

    + + diff --git a/doc/v2/foo.cpp b/doc/v2/foo.cpp new file mode 100644 index 00000000..e92c2d72 --- /dev/null +++ b/doc/v2/foo.cpp @@ -0,0 +1,142 @@ +// Copyright David Abrahams 2002. 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. + + +#include +#include +#include +#include + +class Bar { int x; } + +class Foo +{ + public: + Foo(int x) : b(x) {} + Bar const& get_bar() const { return b; } + private: + Bar b; +}; + +using namespace boost::python; +BOOST_PYTHON_MODULE_INIT(my_module) +{ + module m("my_module") + .add( + class_() + ) + .add( + class_() + .def_init(args()) + .def("get_bar", &Foo::get_bar + , return_value_policy()) + ) +} + +using namespace boost::python; +ref foo = +class_ >() + .def_init(args()) + .def_init(args()) + .def("get_name", &Foo::get_name, return_internal_reference<>()) + .def("set_name", &Foo::set_name) + .object(); + + +
    +#include <string>
    +#include <boost/python/errors.hpp>
    +#include <boost/python/reference.hpp>
    +
    +// Returns a std::string which has the same value as obj's "__name__"
    +// attribute.
    +std::string get_name(boost::python::ref obj)
    +{
    +    // throws if there's no __name__ attribute
    +    PyObject* p = boost::python::expect_non_null(
    +        PyObject_GetAttrString(obj.get(), "__name__"));
    +
    +    // throws if it's not a Python string
    +    std::string result(
    +        boost::python::expect_non_null(
    +            PyString_AsString(p)));
    +
    +    Py_XDECREF(p); // Done with p
    +    
    +    return result;
    +}
    +
    +//
    +// Demonstrate form 1 of handle_exception
    +//
    +
    +// Place a Python Int object whose value is 1 if a and b have
    +// identical "__name__" attributes, 0 otherwise.
    +void same_name_impl(PyObject*& result, PyObject* a, PyObject* b)
    +{
    +    result = PyInt_FromLong(
    +        get_name(boost::python::ref(a1)) == get_name(boost::python::ref(a2)));
    +}
    +
    +// This is an example Python 'C' API interface function
    +extern "C" PyObject*
    +same_name(PyObject* args, PyObject* keywords)
    +{
    +    PyObject* a1;
    +    PyObject* a2;
    +    PyObject* result = 0;
    +
    +    if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
    +        return 0;
    +    
    +    // Use boost::bind to make an object compatible with
    +    // boost::Function0<void>
    +    if (boost::python::handle_exception(
    +            boost::bind<void>(same_name_impl, boost::ref(result), a1, a2)))
    +    {
    +        // an exception was thrown; the Python error was set by
    +        // handle_exception()
    +        return 0;
    +    }
    +
    +    return result;
    +}
    +
    +//
    +// Demonstrate form 2 of handle_exception. Not well-supported by all
    +// compilers.
    +//
    +extern "C" PyObject*
    +same_name2(PyObject* args, PyObject* keywords)
    +{
    +    PyObject* a1;
    +    PyObject* a2;
    +    PyObject* result = 0;
    +
    +    if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
    +        return 0;
    +    try {
    +        return PyInt_FromLong(
    +            get_name(boost::python::ref(a1)) == get_name(boost::python::ref(a2)));
    +    }
    +    catch(...)
    +    {
    +        // If an exception was thrown, translate it to Python
    +        boost::python::handle_exception();
    +        return 0;
    +    }
    +}
    +
    +
    + + +template +struct from_python +{ + from_python(PyObject*); + bool convertible() const; + X operator()(PyObject*) const; +}; diff --git a/doc/v2/from_python.html b/doc/v2/from_python.html new file mode 100644 index 00000000..94ae7019 --- /dev/null +++ b/doc/v2/from_python.html @@ -0,0 +1,156 @@ + + + + +Boost.Python - <boost/python/from_python.hpp> + + + + + + + +
    +

    C++ Boost

    +
    +

    Boost.Python

    +

    Header <boost/python/from_python.hpp>

    +
    +
    +

    Contents

    +
    +
    Introduction
    + +
    Classes
    +
    + +
    Class Templatefrom_python
    +
    +
    Class Template from_python synopsis
    +
    Class Template from_python constructor
    +
    Class Template from_python observer functions
    +
    +
    +
    Example
    +
    +
    +

    Introduction

    +

    + +<boost/python/from_python.hpp> introduces a class +template from_python<T> for extracting a C++ object +of type T from a Python object. + +

    + + +

    Classes

    +

    Class Template from_python<class T>

    + +

    +from_python<T> is the type used internally by +Boost.Python to extract C++ function arguments from a Python argument +tuple when calling a wrapped function. It can also be used directly to +make similar conversions in other contexts. +

    + +

    Class Template from_python synopsis

    +
    +namespace boost { namespace python
    +{
    +   template <class T>
    +   struct from_python : private boost::noncopyable // Exposition only.
    +       // from_python<T> meets the NonCopyable requirements
    +   {
    +      from_python(PyObject*);
    +      bool convertible() const;
    +      convertible-to-T operator()(PyObject*) const;
    +   };
    +}
    +
    + +

    Class Template from_python constructor

    +
    +from_python(PyObject* p);
    +
    +
    +
    Requires: p != 0
    + +
    Effects: Constructs a from_python object + suitable for extracting a C++ object of type T from + p.
    +
    + +

    Class Template from_python observer functions

    + +
    +bool convertible() const;
    +
    +
    + +
    Returns: false if the conversion cannot succeed. This indicates that either: +
      +
    1. No from_python_converter was registered for +T, or + +
    2. any such converter rejected the constructor argument +p by returning 0 from its +convertible() function +
    + +Note that conversion may still fail in operator() due to an exception. + +
    + +
    Throws: nothing
    + +
    Rationale: Because from_python<> is used in + overload resolution, and throwing an exception can be slow, it is + useful to be able to rule out a broad class of unsuccessful + conversions without throwing an exception.
    +
    + +
    +convertible-to-T operator()(PyObject* p) const;
    +
    +
    + +
    Requires: *p refers to the same object which + was passed to the constructor, and convertible() + returns true.
    + +
    Effects: performs the conversion
    +
    Returns: an object convertible to T.
    +
    + +

    Example

    + +

    +

    +#include <string>
    +#include <boost/python/from_python.hpp>
    +
    +// If a std::string can be extracted from p, return its
    +// length. Otherwise, return 0.
    +std::size_t length_if_string(PyObject* p)
    +{
    +   from_python<std::string> converter(p);
    +   if (!converter.convertible())
    +      return 0;
    +   else
    +      return converter().size();
    +}
    +
    +

    + +

    Revised + + 05 November, 2001 + +

    +

    © Copyright Dave Abrahams + 2002. All Rights Reserved.

    + + diff --git a/doc/v2/header.html b/doc/v2/header.html new file mode 100644 index 00000000..c0fa972f --- /dev/null +++ b/doc/v2/header.html @@ -0,0 +1,181 @@ + + + + +Boost.Python - <{{header}}> + + + + + + + +
    +

    C++ Boost

    +
    +

    Boost.Python

    +

    Header <{{header}}>

    +
    +
    +

    Contents

    +
    +
    Introduction
    +
    Macros
    +
    +
    {{macro name}}
    +
    +
    Values
    +
    +
    {{value name}}
    +
    +
    Types
    +
    +
    {{type name}}
    +
    +
    Classes
    +
    +
    Class {{class name}}
    +
    +
    Class {{class name}} synopsis
    +
    Class {{class name}} constructors and destructor
    +
    Class {{class name}} comparison functions
    +
    Class {{class name}} modifier functions
    +
    Class {{class name}} observer functions
    +
    Class {{class name}} static functions
    +
    +
    +
    Functions
    +
    +
    {{function name}}
    +
    +
    Objects
    +
    +
    {{object name}}
    +
    +
    Example(s)
    +
    +
    +

    Introduction

    +

    {{Introductory text}}

    +

    Macros

    +

    {{Macro specifications}}

    +

    Values

    +

    {{Value specifications}}

    +

    Types

    +

    {{Type specifications}}

    +

    Classes

    +

    Class {{name}}

    +

    {{class overview text}}

    +

    Class {{name}} synopsis

    +
    +namespace boost
    +{
    +    class {{name}}
    +	{
    +	};
    +};
    +
    +

    Class {{name}} constructors and destructor

    +
    +{{constructor}}
    +
    +
    +
    Requires: {{text}}
    +
    Effects: {{text}}
    +
    Postconditions: {{text}}
    +
    Returns: {{text}}
    +
    Throws: {{text}}
    +
    Complexity: {{text}}
    +
    Rationale: {{text}}
    +
    +
    +{{destructor}}
    +
    +
    +
    Requires: {{text}}
    +
    Effects: {{text}}
    +
    Postconditions: {{text}}
    +
    Returns: {{text}}
    +
    Throws: {{text}}
    +
    Complexity: {{text}}
    +
    Rationale: {{text}}
    +
    +

    Class {{name}} comparison functions

    +
    +{{function}}
    +
    +
    +
    Requires: {{text}}
    +
    Effects: {{text}}
    +
    Postconditions: {{text}}
    +
    Returns: {{text}}
    +
    Throws: {{text}}
    +
    Complexity: {{text}}
    +
    Rationale: {{text}}
    +
    +

    Class {{name}} modifier functions

    +
    +{{function}}
    +
    +
    +
    Requires: {{text}}
    +
    Effects: {{text}}
    +
    Postconditions: {{text}}
    +
    Returns: {{text}}
    +
    Throws: {{text}}
    +
    Complexity: {{text}}
    +
    Rationale: {{text}}
    +
    +

    Class {{name}} observer functions

    +
    +{{function}}
    +
    +
    +
    Requires: {{text}}
    +
    Effects: {{text}}
    +
    Postconditions: {{text}}
    +
    Returns: {{text}}
    +
    Throws: {{text}}
    +
    Complexity: {{text}}
    +
    Rationale: {{text}}
    +
    +

    Class {{name}} static functions

    +
    +{{function}}
    +
    +
    +
    Requires: {{text}}
    +
    Effects: {{text}}
    +
    Postconditions: {{text}}
    +
    Returns: {{text}}
    +
    Throws: {{text}}
    +
    Complexity: {{text}}
    +
    Rationale: {{text}}
    +
    +

    Functions

    +
    +{{function}}
    +
    +
    +
    Requires: {{text}}
    +
    Effects: {{text}}
    +
    Postconditions: {{text}}
    +
    Returns: {{text}}
    +
    Throws: {{text}}
    +
    Complexity: {{text}}
    +
    Rationale: {{text}}
    +
    +

    Objects

    +

    {{Object specifications}}

    +

    Example(s)

    +

    {{Example(s)}}

    +

    Revised + + 05 November, 2001 + +

    +

    © Copyright Dave Abrahams + 2002. All Rights Reserved.

    + + diff --git a/doc/v2/index.html b/doc/v2/index.html new file mode 100644 index 00000000..dea1db6e --- /dev/null +++ b/doc/v2/index.html @@ -0,0 +1,41 @@ + + + + +Boost.Python + + + + + + + +
    +

    C++ Boost

    +
    +

    Boost.Python

    +

    Index

    +
    +
    +

    Contents

    +
    +
    Overview
    +
    Reference
    +
    Configuration Information
    +
    Rationale
    +
    Definitions
    +
    Frequently Asked Questions (FAQs)
    +
    Bibliography
    +
    Acknowledgments
    +
    +
    +

    Revised + + 05 November, 2002 + +

    +

    © Copyright Dave Abrahams + 2002. All Rights Reserved.

    + + diff --git a/doc/v2/overview.html b/doc/v2/overview.html new file mode 100644 index 00000000..57d0e36e --- /dev/null +++ b/doc/v2/overview.html @@ -0,0 +1,47 @@ + + + + +Boost.Python - Overview + + + + + + + +
    +

    C++ Boost

    +
    +

    Boost.Python

    +

    Overview

    +
    +
    +
    +
    Introduction
    +
    First topic
    +
    Second topic
    +
    Footnotes
    +
    +

    Introduction

    +

    {{text}}

    +

    First Topic

    +

    {{text}}

    +

    Second Topic

    +

    {{text}}

    +

    Footnotes

    +
    +
    (1) {{text}}
    +
    (2) {{text}}
    +
    +
    +

    Revised + + 05 November, 2002 + +

    +

    © Copyright Dave Abrahams + 2002. All Rights Reserved.

    + + diff --git a/doc/v2/rationale.html b/doc/v2/rationale.html new file mode 100644 index 00000000..da7e9217 --- /dev/null +++ b/doc/v2/rationale.html @@ -0,0 +1,47 @@ + + + + +Boost.Python - Rationale + + + + + + + +
    +

    C++ Boost

    +
    +

    Boost.Python

    +

    Rationale

    +
    +
    +
    +
    Introduction
    +
    First topic
    +
    Second topic
    +
    Footnotes
    +
    +

    Introduction

    +

    {{text}}

    +

    First Topic

    +

    {{text}}

    +

    Second Topic

    +

    {{text}}

    +

    Footnotes

    +
    +
    (1) {{text}}
    +
    (2) {{text}}
    +
    +
    +

    Revised + + 05 November, 2002 + +

    +

    © Copyright Dave Abrahams + 2002. All Rights Reserved.

    + + diff --git a/doc/v2/reference.html b/doc/v2/reference.html new file mode 100644 index 00000000..0aa546e5 --- /dev/null +++ b/doc/v2/reference.html @@ -0,0 +1,271 @@ + + + + +Boost.Python - Reference + + + + + + + +
    +

    C++ Boost

    +
    +

    Boost.Python

    +

    Reference

    +
    +
    +

    Contents

    +
    +
    High Level Components
    +
    Framework Elements
    +
    Utilities
    +
    Index By Name
    +
    + +

    High Level Components

    +
    + +

    General Purpose

    +
    + +
    class.hpp/class_fwd.hpp
    +
    +
    Classes
    +
    +
    class_
    +
    bases
    +
    args
    +
    + + +
    + +
    errors.hpp
    +
    + +
    Classes
    +
    +
    error_already_set
    +
    +
    Functions
    +
    +
    handle_exception
    +
    expect_non_null
    +
    +
    + +
    make_function.hpp
    +
    +
    Functions
    +
    +
    make_function
    +
    make_constructor
    +
    +
    + +
    module.hpp
    +
    +
    Classes
    +
    +
    module
    +
    + +
    + +
    objects.hpp
    +
    +
    Classes
    +
    +
    not yet documented
    +
    + +
    + +
    reference.hpp
    +
    +
    Classes
    +
    +
    reference
    +
    + +
    Types
    +
    +
    ref
    +
    + +
    + + +
    + +

    To/From Python Type Conversion

    +
    + +
    from_python.hpp
    +
    +
    Classes
    +
    +
    from_python
    +
    +
    + +
    to_python_converter.hpp
    +
    +
    Classes
    +
    +
    to_python_converter
    +
    + +
    + +
    to_python_indirect.hpp
    +
    +
    Classes
    +
    +
    to_python_indirect
    +
    + +
    + +
    to_python_value.hpp
    +
    +
    Classes
    +
    +
    to_python_value
    +
    + +
    + +
    type_from_python.hpp
    +
    +
    Classes
    +
    +
    type_from_python
    +
    + +
    + + +
    value_from_python.hpp
    +
    +
    Classes
    +
    +
    value_from_python
    +
    + +
    + +
    + + +

    Models of CallPolicies

    +
    + +
    default_call_policies.hpp
    +
    +
    Classes
    +
    +
    default_call_policies
    +
    default_result_converter
    +
    + +
    + +
    return_internal_reference.hpp
    +
    +
    Classes
    +
    +
    return_internal_reference
    +
    + +
    + +
    return_value_policy.hpp
    +
    +
    Classes
    +
    +
    return_value_policy
    +
    + +
    + +
    with_custodian_and_ward.hpp
    +
    +
    Classes
    +
    +
    with_custodian_and_ward
    +
    with_custodian_and_ward_postcall
    +
    + +
    + +
    + +

    Models of ReturnHandlerGenerator

    +
    + +
    copy_const_reference.hpp
    +
    +
    Classes
    +
    +
    copy_const_reference
    +
    + +
    + +
    copy_non_const_reference.hpp
    +
    +
    Classes
    +
    +
    copy_non_const_reference
    +
    + +
    + + +
    manage_new_object.hpp
    +
    +
    Classes
    +
    +
    manage_new_object
    +
    + +
    + +
    reference_existing_object.hpp
    +
    +
    Classes
    +
    +
    reference_existing_object
    +
    + +
    + +
    reference_from_python.hpp
    +
    +
    Classes
    +
    +
    reference_from_python
    +
    get_member
    +
    + +
    + +
    + +
    + +
    +

    Revised + + 05 November, 2002 + +

    +

    © Copyright Dave Abrahams + 2002. All Rights Reserved.

    + + From 08c909fd410df8ea9d837996034e0edb6edd3dce Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Thu, 14 Feb 2002 04:08:20 +0000 Subject: [PATCH 274/369] Updated the basic Jamfiles for the new Boost.Build changes. [SVN r12798] --- build/Jamfile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/build/Jamfile b/build/Jamfile index 7dd6ecfe..c9f6fa75 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -66,7 +66,7 @@ local PYTHON_PROPERTIES = $(PYTHON_PROPERTIES) BOOST_PYTHON_DYNAMIC_LIB ####################### rule bpl-test ( test-name : sources + ) { - boost-python-test $(test-name) : $(sources) libboost_python ; + boost-python-test $(test-name) : $(sources) boost_python ; } ####################### @@ -81,14 +81,14 @@ local CPP_SOURCES = init_function module_builder objects cross_module errors ; -lib libboost_python_static : ../src/$(CPP_SOURCES).cpp +lib boost_python_static : ../src/$(CPP_SOURCES).cpp # requirements : $(BOOST_PYTHON_INCLUDES) true BOOST_PYTHON_STATIC_LIB=1 $(PYTHON_PROPERTIES) ; -dll libboost_python +dll boost_python # $(SUFDLL[1]) : ../src/$(CPP_SOURCES).cpp # requirements @@ -104,7 +104,7 @@ bpl-test boost_python_test : ../test/comprehensive.cpp ; boost-python-runtest comprehensive - : ../test/comprehensive.py boost_python_test libboost_python ; + : ../test/comprehensive.py boost_python_test boost_python ; ############# simple tests from ../example ############ @@ -114,7 +114,7 @@ rule boost-python-example-runtest ( name ) : ../example/$(name).cpp ; boost-python-runtest $(name) - : ../example/test_$(name).py $(name) ; + : ../example/test_$(name).py $(name) ; } @@ -139,7 +139,7 @@ bpl-test noncopyable_import : ../example/noncopyable_import.cpp ; rule boost-python-multi-example-runtest ( test-name : modules + ) { boost-python-runtest $(test-name) - : ../example/tst_$(test-name).py $(modules) libboost_python + : ../example/tst_$(test-name).py $(modules) boost_python : : : $(PYTHON_VECT_ITERATIONS) ; } From 12c798145089290c17f101e7de8e028f8a025f48 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 14 Feb 2002 15:57:40 +0000 Subject: [PATCH 275/369] *** empty log message *** [SVN r12805] --- doc/v2/class.html | 17 +- doc/v2/errors.html | 2 +- doc/v2/foo.cpp | 142 ------------ doc/v2/make_function.html | 155 +++++++++++++ doc/v2/manage_new_object.html | 115 ++++++++++ include/boost/python/call.hpp | 210 ------------------ .../python/converter/builtin_converters.hpp | 6 +- .../boost/python/converter/from_python.hpp | 1 + include/boost/python/module.hpp | 4 +- src/converter/builtin_converters.cpp | 28 +++ test/test_builtin_converters.cpp | 2 + test/test_builtin_converters.py | 12 + 12 files changed, 331 insertions(+), 363 deletions(-) delete mode 100644 doc/v2/foo.cpp create mode 100644 doc/v2/make_function.html create mode 100644 doc/v2/manage_new_object.html delete mode 100644 include/boost/python/call.hpp diff --git a/doc/v2/class.html b/doc/v2/class.html index e6eee244..12ad5d23 100644 --- a/doc/v2/class.html +++ b/doc/v2/class.html @@ -76,19 +76,24 @@ first parameter. Its template arguments are: -
    Parameter - Description + Requirements Default
    T - The class being exposed to Python + A class type.
    Bases - An MPL sequence of C++ base classes + + An MPL + sequence of C++ base classes of T. + An unspecified empty sequence +
    HolderGenerator - A type generator for the holder which -maintains the C++ object inside the Python instance. + HolderGenerator + + A model of HolderGenerator. + boost::python::objects::value_holder_generator
    diff --git a/doc/v2/errors.html b/doc/v2/errors.html index b46de25c..e0bfa89d 100644 --- a/doc/v2/errors.html +++ b/doc/v2/errors.html @@ -78,7 +78,7 @@ void handle_exception() throw();
     convertible-to-T operator()(PyObject* p) const;
     
    -
    -
    Requires: *p refers to the same object which - was passed to the constructor, and convertible() - returns true.
    +
    +
    Requires: *p refers to the same object which was + passed to the constructor, and convertible() returns + true. -
    Effects: performs the conversion
    -
    Returns: an object convertible to T.
    -
    +
    Effects: performs the conversion -

    Example

    +
    Returns: an object convertible to T. +
    -

    +

    Example

     #include <string>
     #include <boost/python/from_python.hpp>
    @@ -143,14 +154,13 @@ std::size_t length_if_string(PyObject* p)
           return converter().size();
     }
     
    -

    -

    Revised - - 05 November, 2001 - -

    -

    © Copyright Dave Abrahams - 2002. All Rights Reserved.

    - - +

    Revised + + 05 November, 2001 + + + +

    © Copyright Dave + Abrahams 2002. All Rights Reserved. + diff --git a/doc/v2/header.html b/doc/v2/header.html index c0fa972f..7b36a65c 100644 --- a/doc/v2/header.html +++ b/doc/v2/header.html @@ -1,181 +1,293 @@ - - - - -Boost.Python - <{{header}}> - - - + + + + + Boost.Python - <{{header}}> + +
    - - - - -
    -

    C++ Boost

    -
    -

    Boost.Python

    -

    Header <{{header}}>

    -
    -


    -

    Contents

    -
    -
    Introduction
    -
    Macros
    -
    -
    {{macro name}}
    -
    -
    Values
    -
    -
    {{value name}}
    -
    -
    Types
    -
    -
    {{type name}}
    -
    -
    Classes
    -
    -
    Class {{class name}}
    -
    -
    Class {{class name}} synopsis
    -
    Class {{class name}} constructors and destructor
    -
    Class {{class name}} comparison functions
    -
    Class {{class name}} modifier functions
    -
    Class {{class name}} observer functions
    -
    Class {{class name}} static functions
    -
    -
    -
    Functions
    -
    -
    {{function name}}
    -
    -
    Objects
    -
    -
    {{object name}}
    -
    -
    Example(s)
    -
    -
    -

    Introduction

    -

    {{Introductory text}}

    -

    Macros

    -

    {{Macro specifications}}

    -

    Values

    -

    {{Value specifications}}

    -

    Types

    -

    {{Type specifications}}

    -

    Classes

    -

    Class {{name}}

    -

    {{class overview text}}

    -

    Class {{name}} synopsis

    + + +

    +

    + + +

    Boost.Python

    + +

    Header <{{header}}>

    + +
    + +

    Contents

    + +
    +
    Introduction + +
    Macros + +
    +
    +
    {{macro name}} +
    + +
    Values + +
    +
    +
    {{value name}} +
    + +
    Types + +
    +
    +
    {{type name}} +
    + +
    Classes + +
    +
    +
    Class {{class name}} + +
    +
    +
    Class {{class + name}} synopsis + +
    Class {{class name}} + constructors and destructor + +
    Class {{class + name}} comparison functions + +
    Class {{class + name}} modifier functions + +
    Class {{class + name}} observer functions + +
    Class {{class + name}} static functions +
    +
    + +
    Functions + +
    +
    +
    {{function name}} +
    + +
    Objects + +
    +
    +
    {{object name}} +
    + +
    Example(s) +
    +
    + +

    Introduction

    + +

    {{Introductory text}} + +

    Macros

    + +

    {{Macro specifications}} + +

    Values

    + +

    {{Value specifications}} + +

    Types

    + +

    {{Type specifications}} + +

    Classes

    + +

    Class {{name}}

    + +

    {{class overview text}} + +

    Class {{name}} synopsis

     namespace boost
     {
         class {{name}}
    -	{
    -	};
    +  {
    +  };
     };
     
    -

    Class {{name}} constructors and destructor

    + +

    Class {{name}} constructors and + destructor

     {{constructor}}
     
    -
    -
    Requires: {{text}}
    -
    Effects: {{text}}
    -
    Postconditions: {{text}}
    -
    Returns: {{text}}
    -
    Throws: {{text}}
    -
    Complexity: {{text}}
    -
    Rationale: {{text}}
    -
    + +
    +
    Requires: {{text}} + +
    Effects: {{text}} + +
    Postconditions: {{text}} + +
    Returns: {{text}} + +
    Throws: {{text}} + +
    Complexity: {{text}} + +
    Rationale: {{text}} +
     {{destructor}}
     
    -
    -
    Requires: {{text}}
    -
    Effects: {{text}}
    -
    Postconditions: {{text}}
    -
    Returns: {{text}}
    -
    Throws: {{text}}
    -
    Complexity: {{text}}
    -
    Rationale: {{text}}
    -
    -

    Class {{name}} comparison functions

    + +
    +
    Requires: {{text}} + +
    Effects: {{text}} + +
    Postconditions: {{text}} + +
    Returns: {{text}} + +
    Throws: {{text}} + +
    Complexity: {{text}} + +
    Rationale: {{text}} +
    + +

    Class {{name}} comparison + functions

     {{function}}
     
    -
    -
    Requires: {{text}}
    -
    Effects: {{text}}
    -
    Postconditions: {{text}}
    -
    Returns: {{text}}
    -
    Throws: {{text}}
    -
    Complexity: {{text}}
    -
    Rationale: {{text}}
    -
    -

    Class {{name}} modifier functions

    + +
    +
    Requires: {{text}} + +
    Effects: {{text}} + +
    Postconditions: {{text}} + +
    Returns: {{text}} + +
    Throws: {{text}} + +
    Complexity: {{text}} + +
    Rationale: {{text}} +
    + +

    Class {{name}} modifier + functions

     {{function}}
     
    -
    -
    Requires: {{text}}
    -
    Effects: {{text}}
    -
    Postconditions: {{text}}
    -
    Returns: {{text}}
    -
    Throws: {{text}}
    -
    Complexity: {{text}}
    -
    Rationale: {{text}}
    -
    -

    Class {{name}} observer functions

    + +
    +
    Requires: {{text}} + +
    Effects: {{text}} + +
    Postconditions: {{text}} + +
    Returns: {{text}} + +
    Throws: {{text}} + +
    Complexity: {{text}} + +
    Rationale: {{text}} +
    + +

    Class {{name}} observer + functions

     {{function}}
     
    -
    -
    Requires: {{text}}
    -
    Effects: {{text}}
    -
    Postconditions: {{text}}
    -
    Returns: {{text}}
    -
    Throws: {{text}}
    -
    Complexity: {{text}}
    -
    Rationale: {{text}}
    -
    -

    Class {{name}} static functions

    + +
    +
    Requires: {{text}} + +
    Effects: {{text}} + +
    Postconditions: {{text}} + +
    Returns: {{text}} + +
    Throws: {{text}} + +
    Complexity: {{text}} + +
    Rationale: {{text}} +
    + +

    Class {{name}} static functions

     {{function}}
     
    -
    -
    Requires: {{text}}
    -
    Effects: {{text}}
    -
    Postconditions: {{text}}
    -
    Returns: {{text}}
    -
    Throws: {{text}}
    -
    Complexity: {{text}}
    -
    Rationale: {{text}}
    -
    -

    Functions

    + +
    +
    Requires: {{text}} + +
    Effects: {{text}} + +
    Postconditions: {{text}} + +
    Returns: {{text}} + +
    Throws: {{text}} + +
    Complexity: {{text}} + +
    Rationale: {{text}} +
    + +

    Functions

    +
    +
     {{function}}
     
    -
    -
    Requires: {{text}}
    -
    Effects: {{text}}
    -
    Postconditions: {{text}}
    -
    Returns: {{text}}
    -
    Throws: {{text}}
    -
    Complexity: {{text}}
    -
    Rationale: {{text}}
    -
    -

    Objects

    -

    {{Object specifications}}

    -

    Example(s)

    -

    {{Example(s)}}

    -

    Revised - - 05 November, 2001 - -

    -

    © Copyright Dave Abrahams - 2002. All Rights Reserved.

    - - + +
    +
    Requires: {{text}} + +
    Effects: {{text}} + +
    Postconditions: {{text}} + +
    Returns: {{text}} + +
    Throws: {{text}} + +
    Complexity: {{text}} + +
    Rationale: {{text}} +
    + +

    Objects

    + +

    {{Object specifications}} + +

    Example(s)

    + +

    {{Example(s)}} + +

    Revised + + 05 November, 2001 + + + +

    © Copyright Dave + Abrahams 2002. All Rights Reserved. + diff --git a/doc/v2/make_function.html b/doc/v2/make_function.html index e7c4b421..7f40703b 100644 --- a/doc/v2/make_function.html +++ b/doc/v2/make_function.html @@ -1,116 +1,109 @@ - - - - -Boost.Python - <boost/python/make_function.hpp> - - - + + + + + Boost.Python - <boost/python/make_function.hpp> + +
    - - - - -
    -

    C++ Boost

    -
    -

    Boost.Python

    -

    Header <boost/python/make_function.hpp>

    -
    -


    -

    Contents

    -
    -
    Introduction
    + + +

    +

    -
    Functions
    -
    -
    make_function
    -
    make_constructor
    -
    + +

    Boost.Python

    -
    Example
    +

    Header <boost/python/make_function.hpp>

    + +
    -
    -
    -

    Introduction

    -

    +

    Contents

    -make_function() and -make_constructor() -are the functions used internally by class_<>::def, -class_<>::def, -and -class_<>::def_init -to produce Python callable objects which wrap C++ functions and member -functions. -

    +
    +
    Introduction -

    Functions

    +
    Functions +
    +
    +
    make_function + +
    make_constructor +
    + +
    Example +
    +
    + +

    Introduction

    + +

    make_function() and + make_constructor() are + the functions used internally by class_<>::def, class_<>::def, and + class_<>::def_init to produce Python + callable objects which wrap C++ functions and member functions. + +

    Functions

    -template <class F>
    +template <class F>
     objects::function* make_function(F f)</a>
     
     template <class F, class Policies>
     objects::function* make_function(F f, Policies const& policies)
     
    -
    -
    Requires: F is a function pointer or member - function pointer type
    +
    +
    Requires: F is a function pointer or member + function pointer type -
    Effects: Creates a Python callable object which, when - called from Python, converts its arguments to C++ and calls - f. If F is a pointer-to-member-function - type, the target object of the function call (*this) - will be taken from the first Python argument, and subsequent Python - arguments will be used as the arguments to f. If - policies are supplied, it must be a model of CallPolicies, and will be applied to - the function as described here.
    - -
    Returns: A pointer convertible to PyObject* - which refers to the new Python callable object.
    -
    +
    Effects: Creates a Python callable object which, when called + from Python, converts its arguments to C++ and calls f. If + F is a pointer-to-member-function type, the target object of + the function call (*this) will be taken from the first + Python argument, and subsequent Python arguments will be used as the + arguments to f. If policies are supplied, it + must be a model of CallPolicies, and will + be applied to the function as described here. +
    Returns: A pointer convertible to PyObject* which + refers to the new Python callable object. +
    -template <class T, class ArgList, class Generator>
    +template <class T, class ArgList, class Generator>
     objects::function* make_constructor();
     
    -
    -
    Requires: T is a class - type. ArgList is an MPL sequence of C++ - argument types (A1, A2,... AN) such that if - a1, a2... aN are objects of type - A1, A2,... AN respectively, the expression - new Generator::apply<T>::type(a1, a2... aN) is - valid. Generator is a model of HolderGenerator. -
    +
    +
    Requires: T is a class type. ArgList + is an MPL sequence of C++ + argument types (A1, A2,... AN) such that if + a1, a2... aN are objects of type + A1, A2,... AN respectively, the expression new + Generator::apply<T>::type(a1, a2... aN) is + valid. Generator is a model of HolderGenerator. -
    Effects: Creates a Python callable object which, when - called from Python, expects its first argument to be a Boost.Python - extension class object. It converts its remaining its arguments to - C++ and passes them to the constructor of a dynamically-allocated - Generator::apply<T>::type object. The result is - installed in the extension class object. +
    Effects: Creates a Python callable object which, when called + from Python, expects its first argument to be a Boost.Python extension + class object. It converts its remaining its arguments to C++ and passes + them to the constructor of a dynamically-allocated + Generator::apply<T>::type object. The result is + installed in the extension class object. -
    +
    Returns: The new Python callable object +
    -
    Returns: The new Python callable object
    - -
    - -

    Example

    - -

    C++ function exposed below returns a callable object wrapping one -of two functions. +

    Example

    +

    C++ function exposed below returns a callable object wrapping one of two + functions.

     #include <boost/python/make_function.hpp>
     #include <boost/python/module.hpp>
    @@ -132,8 +125,7 @@ BOOST_PYTHON_MODULE_INIT(make_function_test)
             .def("choose_function", choose_function);
     }
     
    -

    -It can be used this way in Python: + It can be used this way in Python:
     >>> from make_function_test import *
     >>> f = choose_function(1)
    @@ -144,12 +136,11 @@ It can be used this way in Python:
     'bar'
     
    -

    - -14 February 2002 - -

    -

    © Copyright Dave Abrahams - 2002. All Rights Reserved.

    - - +

    + + 14 February 2002 + + +

    © Copyright Dave + Abrahams 2002. All Rights Reserved. + diff --git a/doc/v2/manage_new_object.html b/doc/v2/manage_new_object.html index cc5aab2a..112e540f 100644 --- a/doc/v2/manage_new_object.html +++ b/doc/v2/manage_new_object.html @@ -1,50 +1,62 @@ - - - - -Boost.Python - <boost/python/manage_new_object.hpp> - - - + + + + + Boost.Python - <boost/python/manage_new_object.hpp> + +
    - - - - -
    -

    C++ Boost

    -
    -

    Boost.Python

    -

    Header <boost/python/manage_new_object.hpp>

    -
    -


    -

    Contents

    -
    -
    Classes
    -
    -
    Class manage_new_object
    -
    -
    Class manage_new_object synopsis
    -
    Class manage_new_object metafunctions
    -
    -
    + + +

    +

    -
    Example
    -
    -
    + +

    Boost.Python

    -

    Classes

    +

    Header + <boost/python/manage_new_object.hpp>

    + +
    -

    Class manage_new_object

    -

    -manage_new_object is a model of ResultConverterGenerator -which can be used to wrap C++ functions which return a pointer to an -object allocated with a new-expression, and expect the caller -to take responsibility for deleting that object. -

    +

    Contents

    -

    Class manage_new_object synopsis

    +
    +
    Classes + +
    +
    +
    Class + manage_new_object + +
    +
    +
    Class + manage_new_object synopsis + +
    Class + manage_new_object metafunctions +
    +
    + +
    Example +
    +
    + +

    Classes

    + +

    Class + manage_new_object

    + +

    manage_new_object is a model of ResultConverterGenerator which can be + used to wrap C++ functions which return a pointer to an object allocated + with a new-expression, and expect the caller to take responsibility + for deleting that object. + +

    Class + manage_new_object synopsis

     namespace boost { namespace python
     {
    @@ -54,19 +66,25 @@ namespace boost { namespace python
         };
     }}
     
    -

    Class manage_new_object metafunctions

    + +

    Class + manage_new_object metafunctions

     template <class T> struct apply
     
    -
    -
    Requires: T is U* for some U.
    -
    Returns: typedef to_python_indirect<T> type;
    -
    -

    Example

    +
    +
    Requires: T is U* for some + U. -

    In C++: +

    Returns: typedef to_python_indirect<T> + type; +
    +

    Example

    + +

    In C++:

     #include <boost/python/module.hpp>
     #include <boost/python/class.hpp>
    @@ -87,16 +105,14 @@ using namespace boost::python;
     BOOST_PYTHON_MODULE_INIT(my_module)
     {
        module m("my_module")
    -      .def("make_foo", make_foo)
    +      .def("make_foo", make_foo)
           .add(
              class_<Foo>()
    -            .def("get_x", &Foo::get_x)
    +            .def("get_x", &Foo::get_x)
              )
     }
     
    - -In Python: - +In Python:
     >>> from my_module import *
     >>> f = make_foo(3)     # create a Foo object
    @@ -104,12 +120,11 @@ In Python:
     3
     
    -

    Revised - - 14 February 2002 - -

    -

    © Copyright Dave Abrahams - 2002. All Rights Reserved.

    - - +

    Revised + + 14 February 2002 + + +

    © Copyright Dave + Abrahams 2002. All Rights Reserved. + diff --git a/doc/v2/reference.html b/doc/v2/reference.html index 0aa546e5..5e2e4463 100644 --- a/doc/v2/reference.html +++ b/doc/v2/reference.html @@ -1,271 +1,383 @@ - - - - -Boost.Python - Reference - - - + + + + + Boost.Python - Reference + +
    - - - - -
    -

    C++ Boost

    -
    -

    Boost.Python

    -

    Reference

    -
    -


    -

    Contents

    -
    -
    High Level Components
    -
    Framework Elements
    -
    Utilities
    -
    Index By Name
    -
    + + +

    +

    -

    High Level Components

    -
    + +

    Boost.Python

    -

    General Purpose

    -
    +

    Reference

    + +
    -
    class.hpp/class_fwd.hpp
    -
    -
    Classes
    -
    -
    class_
    -
    bases
    -
    args
    -
    +

    Contents

    + +
    +
    High Level Components + +
    Framework Elements + +
    Utilities + +
    Index By Name +
    + + +

    High Level Components

    + +
    +
    + + +

    General Purpose

    + +
    +
    class.hpp/class_fwd.hpp + +
    +
    +
    Classes + +
    +
    +
    class_ + +
    bases + +
    args +
    +
    + +
    errors.hpp + +
    +
    +
    Classes + +
    +
    +
    error_already_set +
    + +
    Functions + +
    +
    +
    handle_exception + +
    expect_non_null +
    +
    + +
    make_function.hpp + +
    +
    +
    Functions + +
    +
    +
    make_function + +
    make_constructor +
    +
    + +
    module.hpp + +
    +
    +
    Classes + +
    +
    +
    module +
    +
    + +
    objects.hpp + +
    +
    +
    Classes + +
    +
    +
    not yet documented +
    +
    + +
    reference.hpp + +
    +
    +
    Classes + +
    +
    +
    reference +
    + +
    Types + +
    +
    +
    ref +
    +
    +
    + + +

    To/From Python Type Conversion

    + +
    +
    from_python.hpp + +
    +
    +
    Classes + +
    +
    +
    from_python +
    +
    + +
    to_python_converter.hpp + +
    +
    +
    Classes + +
    +
    +
    to_python_converter +
    +
    + +
    to_python_indirect.hpp + +
    +
    +
    Classes + +
    +
    +
    to_python_indirect +
    +
    + +
    to_python_value.hpp + +
    +
    +
    Classes + +
    +
    +
    to_python_value +
    +
    + +
    type_from_python.hpp + +
    +
    +
    Classes + +
    +
    +
    type_from_python +
    +
    + +
    value_from_python.hpp + +
    +
    +
    Classes + +
    +
    +
    value_from_python +
    +
    +
    + + +

    Models of CallPolicies

    + +
    +
    default_call_policies.hpp + +
    +
    +
    Classes + +
    +
    +
    default_call_policies + +
    default_result_converter +
    +
    + +
    return_internal_reference.hpp + +
    +
    +
    Classes + +
    +
    +
    + return_internal_reference +
    +
    + +
    return_value_policy.hpp + +
    +
    +
    Classes + +
    +
    +
    return_value_policy +
    +
    + +
    with_custodian_and_ward.hpp + +
    +
    +
    Classes + +
    +
    +
    with_custodian_and_ward + +
    + with_custodian_and_ward_postcall +
    +
    +
    + + +

    Models of ReturnHandlerGenerator

    + +
    +
    copy_const_reference.hpp + +
    +
    +
    Classes + +
    +
    +
    copy_const_reference +
    +
    + +
    copy_non_const_reference.hpp + +
    +
    +
    Classes + +
    +
    +
    + copy_non_const_reference +
    +
    + +
    manage_new_object.hpp + +
    +
    +
    Classes + +
    +
    +
    manage_new_object +
    +
    + +
    reference_existing_object.hpp + +
    +
    +
    Classes + +
    +
    +
    + reference_existing_object +
    +
    + +
    reference_from_python.hpp + +
    +
    +
    Classes + +
    +
    +
    reference_from_python + +
    get_member +
    +
    +
    +
    +
    + +

    Revised + + 05 November, 2002 + -

    +

    © Copyright Dave + Abrahams 2002. All Rights Reserved. -

    errors.hpp
    -
    - -
    Classes
    -
    -
    error_already_set
    -
    -
    Functions
    -
    -
    handle_exception
    -
    expect_non_null
    -
    -
    - -
    make_function.hpp
    -
    -
    Functions
    -
    -
    make_function
    -
    make_constructor
    -
    -
    - -
    module.hpp
    -
    -
    Classes
    -
    -
    module
    -
    - -
    - -
    objects.hpp
    -
    -
    Classes
    -
    -
    not yet documented
    -
    - -
    - -
    reference.hpp
    -
    -
    Classes
    -
    -
    reference
    -
    - -
    Types
    -
    -
    ref
    -
    - -
    - - -
    - -

    To/From Python Type Conversion

    -
    - -
    from_python.hpp
    -
    -
    Classes
    -
    -
    from_python
    -
    -
    - -
    to_python_converter.hpp
    -
    -
    Classes
    -
    -
    to_python_converter
    -
    - -
    - -
    to_python_indirect.hpp
    -
    -
    Classes
    -
    -
    to_python_indirect
    -
    - -
    - -
    to_python_value.hpp
    -
    -
    Classes
    -
    -
    to_python_value
    -
    - -
    - -
    type_from_python.hpp
    -
    -
    Classes
    -
    -
    type_from_python
    -
    - -
    - - -
    value_from_python.hpp
    -
    -
    Classes
    -
    -
    value_from_python
    -
    - -
    - -
    - - -

    Models of CallPolicies

    -
    - -
    default_call_policies.hpp
    -
    -
    Classes
    -
    -
    default_call_policies
    -
    default_result_converter
    -
    - -
    - -
    return_internal_reference.hpp
    -
    -
    Classes
    -
    -
    return_internal_reference
    -
    - -
    - -
    return_value_policy.hpp
    -
    -
    Classes
    -
    -
    return_value_policy
    -
    - -
    - -
    with_custodian_and_ward.hpp
    -
    -
    Classes
    -
    -
    with_custodian_and_ward
    -
    with_custodian_and_ward_postcall
    -
    - -
    - -
    - -

    Models of ReturnHandlerGenerator

    -
    - -
    copy_const_reference.hpp
    -
    -
    Classes
    -
    -
    copy_const_reference
    -
    - -
    - -
    copy_non_const_reference.hpp
    -
    -
    Classes
    -
    -
    copy_non_const_reference
    -
    - -
    - - -
    manage_new_object.hpp
    -
    -
    Classes
    -
    -
    manage_new_object
    -
    - -
    - -
    reference_existing_object.hpp
    -
    -
    Classes
    -
    -
    reference_existing_object
    -
    - -
    - -
    reference_from_python.hpp
    -
    -
    Classes
    -
    -
    reference_from_python
    -
    get_member
    -
    - -
    - -
    - -
    - -
    -

    Revised - - 05 November, 2002 - -

    -

    © Copyright Dave Abrahams - 2002. All Rights Reserved.

    - - diff --git a/doc/v2/reference_existing_object.html b/doc/v2/reference_existing_object.html index 3d19826a..c5d39756 100644 --- a/doc/v2/reference_existing_object.html +++ b/doc/v2/reference_existing_object.html @@ -1,62 +1,72 @@ - - - - -Boost.Python - <boost/python/reference_existing_object.hpp> - - - + + + + + Boost.Python - + <boost/python/reference_existing_object.hpp> + +
    - - - - -
    -

    C++ Boost

    -
    -

    Boost.Python

    -

    Header <boost/python/reference_existing_object.hpp>

    -
    -
    -

    Contents

    -
    -
    Classes
    -
    -
    Class reference_existing_object
    -
    -
    Class reference_existing_object synopsis
    -
    Class reference_existing_object metafunctions
    -
    -
    + + +

    +

    -
    Example
    -
    -
    + +

    Boost.Python

    -

    Classes

    +

    Header + <boost/python/reference_existing_object.hpp>

    + +
    -

    Class reference_existing_object

    -

    -reference_existing_object is a model of ResultConverterGenerator -which can be used to wrap C++ functions which return a reference or -pointer to a C++ object. When the wrapped function is called, the -value referenced by its return value is not copied. A new Python -object is created which contains a pointer to the referent, and no -attempt is made to ensure that the lifetime of the referent is at -least as long as that of the corresponding Python object. Thus, it can -be highly dangerous to use -reference_existing_object without additional lifetime -management from such models of CallPolicies as with_custodian_and_ward. This class is used in the implementation -of return_internal_reference. -

    +

    Contents

    -

    Class reference_existing_object synopsis

    +
    +
    Classes + +
    +
    +
    Class + reference_existing_object + +
    +
    +
    Class + reference_existing_object synopsis + +
    Class + reference_existing_object metafunctions +
    +
    + +
    Example +
    +
    + +

    Classes

    + +

    Class + reference_existing_object

    + +

    reference_existing_object is a model of ResultConverterGenerator which can be + used to wrap C++ functions which return a reference or pointer to a C++ + object. When the wrapped function is called, the value referenced by its + return value is not copied. A new Python object is created which contains a + pointer to the referent, and no attempt is made to ensure that the lifetime + of the referent is at least as long as that of the corresponding Python + object. Thus, it can be highly + dangerous to use reference_existing_object without + additional lifetime management from such models of CallPolicies as with_custodian_and_ward. + This class is used in the implementation of return_internal_reference. + +

    Class + reference_existing_object synopsis

     namespace boost { namespace python
     {
    @@ -66,27 +76,29 @@ namespace boost { namespace python
         };
     }}
     
    -

    Class reference_existing_object metafunctions

    + +

    Class + reference_existing_object metafunctions

     template <class T> struct apply
     
    -
    -
    Requires: T is U& or U*for some U.
    -
    Returns: typedef to_python_indirect<T,V> - type, where V is a which - constructs an instance holder containing an unowned - U* pointing to the referent of the wrapped function's - return value.
    +
    +
    Requires: T is U& or + U*for some U. -
    +
    Returns: typedef to_python_indirect<T,V> + type, where V is a HolderObjectGenerator + which constructs an instance holder containing an unowned + U* pointing to the referent of the wrapped function's return + value. +
    -

    Example

    - -

    In C++: +

    Example

    +

    In C++:

     #include <boost/python/module.hpp>
     #include <boost/python/class.hpp>
    @@ -119,16 +131,14 @@ using namespace boost::python;
     BOOST_PYTHON_MODULE_INIT(singleton)
     {
        module m("singleton")
    -      .def("get_it", get_it)
    +      .def("get_it", get_it)
           .add(
              class_<Singleton>()
    -            .def("exchange", &Singleton::exchange)
    +            .def("exchange", &Singleton::exchange)
              );
     }
     
    - -In Python: - + In Python:
     >>> import singleton
     >>> s1 = singleton.get_it()  
    @@ -141,12 +151,11 @@ In Python:
     42
     
    -

    Revised - - 14 February 2002 - -

    -

    © Copyright Dave Abrahams - 2002. All Rights Reserved.

    - - +

    Revised + + 14 February 2002 + + +

    © Copyright Dave + Abrahams 2002. All Rights Reserved. + From 4481c3badae4cca6d0acc7d1e516b374378baa2b Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 15 Feb 2002 16:20:22 +0000 Subject: [PATCH 279/369] initial checkin [SVN r12818] --- doc/v2/lvalue_from_python.html | 278 +++++++++++++++++++++++++++++++++ 1 file changed, 278 insertions(+) create mode 100644 doc/v2/lvalue_from_python.html diff --git a/doc/v2/lvalue_from_python.html b/doc/v2/lvalue_from_python.html new file mode 100644 index 00000000..74e94a23 --- /dev/null +++ b/doc/v2/lvalue_from_python.html @@ -0,0 +1,278 @@ + + + + + + Boost.Python - <boost/python/lvalue_from_python.hpp> + + + +
    +

    +

    + +
    +

    Boost.Python

    + +

    Header <boost/python/lvalue_from_python.hpp>

    +
    +


    + +

    Contents

    + +
    +
    Introduction + + +
    Classes + +
    +
    +
    Class Template lvalue_from_python + +
    +
    + +
    Class Template + lvalue_from_python synopsis + +
    Class Template + lvalue_from_python constructor +
    +
    + +
    +
    Class Template get_member + +
    +
    + +
    Class Template + get_member synopsis + +
    Class Template + get_member static functions +
    +
    + +
    Example +
    +
    + +

    Introduction

    + + <boost/python/lvalue_from_python.hpp> supplies + a facility for extracting C++ objects from within instances of a + given Python type. This is typically useful for dealing with + "traditional" Python extension types. + +

    Classes

    + +

    Class template lvalue_from_python

    + +

    Class template lvalue_from_python will register + from_python converters which extract a references and pointers to + a C++ type which is held within an object of a given Python + type. Its template arguments are: + +

    + + + + + + + + + +
    + lvalue_from_python Requirements
    + + In the table below, x denotes an object of type PythonObject& + +
    Parameter + + Requirements + + Description + + Default + +
    python_type + + A compile-time constant PyTypeObject* + + The Python type of instances convertible by this + converter. Python subtypes are also convertible. + +
    Value + + A non-reference type. + + The C++ type to be extracted + +
    PythonObject + + initial sizeof(PyObject) bytes are + layout-compatible with PyObject. + + The C++ type used to hold Python instances of + python_type. + + Value + +
    Extract + + Value& v = Extract::execute(x); + + A type whose static execute function extracts a Value reference from within an object of type PythonObject. + + An unspecified type whose execute function consists of return x; +
    + + If only the first two template arguments are supplied, these + converters extract the entire PythonObject as a + whole. + +

    + + If the lifetime of the lvalue_from_python object ends + before the last attempt to convert to one its target types, the + behavior is undefined. The easiest way to ensure correct behavior + is to declare an lvalue_from_python instance as a + static local in a module init + function, as shown in the example + below. + +

    Class template lvalue_from_python synopsis

    +
    +namespace boost { namespace python
    +{
    +   template <
    +      PyTypeObject const* python_type
    +      , class Value
    +      , class PythonObject = Value
    +      , class Extract = unspecified
    +      >
    +   class lvalue_from_python
    +   {
    +      lvalue_from_python();
    +   };
    +}}
    +
    + +

    Class template lvalue_from_python constructor

    +
    +lvalue_from_python();
    +
    + +
    + +
    Effects: Registers from_python converters which + extract + Value&, Value const&, + Value*, or Value const* from Python + objects of type python_type using + Extract::execute(). + +
    + +

    Class template get_member

    + +

    get_member can be used with + lvalue_from_python in the common case where the C++ + type to be extracted is a member of the Python object. + +

    Class template get_member synopsis

    +
    +namespace boost { namespace python
    +{
    +  template <class Class, class Member, Member (Class::*mp)>
    +  struct get_member
    +  {
    +     static Member& execute(Class& c);
    +  };
    +}}
    +
    + +

    Class template get_member static functions

    +
    +Member& execute(Class& c);
    +
    + +
    + +
    Returns: c.*mp + +
    + + +

    Example(s)

    + +This example presumes that someone has implemented the standard noddy +example module from the Python documentation, and we want to build +a module which manipulates Noddys. Since +noddy_NoddyObject is so simple that it carries no +interesting information, the example is a bit contrived: it assumes +you want to keep track of one particular object for some reason. + +

    C++ module definition

    + +
    +#include <boost/python/reference.hpp>
    +#include <boost/python/module.hpp>
    +
    +// definition lifted from the Python docs
    +typedef struct {
    +   PyObject_HEAD
    +} noddy_NoddyObject;
    +
    +using namespace boost::python;
    +static ref cache;
    +
    +bool is_cached(noddy_NoddyObject* x)
    +{
    +   return x == cache.get();
    +}
    +
    +void set_cache(noddy_NoddyObject* x)
    +{
    +   cache.reset((PyObject*)x, ref::increment_count);
    +}
    +
    +BOOST_PYTHON_MODULE_INIT(noddy_cache)
    +{
    +   module noddy_cache("noddy_cache")
    +      .def("is_cached", is_cached)
    +      .def("set_cache", set_cache)
    +      ;
    +}
    +
    + +

    Python code

    + +
    +>>> import noddy
    +>>> n = noddy.new_noddy()
    +>>> import noddy_cache
    +>>> noddy_cache.is_cached(n)
    +0
    +>>> noddy_cache.set_cache(n)
    +>>> noddy_cache.is_cached(n)
    +1
    +>>> noddy_cache.is_cached(noddy.new_noddy())
    +0
    +
    + +

    Revised + + 05 November, 2001 + + + +

    © Copyright Dave + Abrahams 2002. All Rights Reserved. + From 371723a5d4d2b3e94c57163a6adf0ed59bce6c43 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 15 Feb 2002 16:37:00 +0000 Subject: [PATCH 280/369] little fixes [SVN r12819] --- doc/v2/lvalue_from_python.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/v2/lvalue_from_python.html b/doc/v2/lvalue_from_python.html index 74e94a23..03af54f8 100644 --- a/doc/v2/lvalue_from_python.html +++ b/doc/v2/lvalue_from_python.html @@ -98,7 +98,8 @@ python_type - A compile-time constant PyTypeObject* + A compile-time constant PyTypeObject* The Python type of instances convertible by this converter. Python subtypes are also convertible. @@ -209,7 +210,7 @@ Member& execute(Class& c); -

    Example(s)

    +

    Example

    This example presumes that someone has implemented the standard noddy From b303d49634423240d8a8e0190eb6d7ffcf620b4a Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 15 Feb 2002 16:59:39 +0000 Subject: [PATCH 281/369] remove defunct code [SVN r12820] --- .../python/return_internal_reference.hpp | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/include/boost/python/return_internal_reference.hpp b/include/boost/python/return_internal_reference.hpp index d696c7fa..2f567e55 100644 --- a/include/boost/python/return_internal_reference.hpp +++ b/include/boost/python/return_internal_reference.hpp @@ -7,36 +7,11 @@ # define RETURN_INTERNAL_REFERENCE_DWA2002131_HPP # include -# include # include -# include # include namespace boost { namespace python { -namespace detail -{ - template - struct return_internal_reference_requires_a_pointer_or_reference_return_type -# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__) - {} -# endif - ; -} - -struct internal_reference_to_python_generator -{ - template - struct apply - { - typedef typename mpl::select_type< - is_object::value - , detail::return_internal_reference_requires_a_pointer_or_reference_return_type - , to_python_indirect - >::type type; - }; -}; - template struct return_internal_reference : with_custodian_and_ward_postcall<0, owner_arg, Base> From 09d012a10b5b5c024743bc63faf7082668d3fb4a Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 15 Feb 2002 18:31:22 +0000 Subject: [PATCH 282/369] *** empty log message *** [SVN r12823] --- doc/v2/class.html | 9 +- doc/v2/header.html | 31 ++-- doc/v2/module.html | 12 +- doc/v2/reference.html | 8 +- doc/v2/return_internal_reference.html | 205 ++++++++++++++++++++++++++ 5 files changed, 236 insertions(+), 29 deletions(-) create mode 100644 doc/v2/return_internal_reference.html diff --git a/doc/v2/class.html b/doc/v2/class.html index 85e24993..fc64eabd 100644 --- a/doc/v2/class.html +++ b/doc/v2/class.html @@ -191,7 +191,7 @@ template <class F> class_& def(char const* name, F f) template <class Fn, class CallPolicy> -class_& def(char const* name, Fn fn, CallPolicy policy) +class_& def(char const* name, Fn f, CallPolicy policy)
    @@ -199,8 +199,11 @@ class_& def(char const* name, Fn fn, CallPolicy policy) pointer-to-member-function. name is a ntbs which conforms to Python's identifier - naming rules. If supplied, policy conforms to the CallPolicy concept requirements. + naming rules. In the first form, the return type of + f is not a reference and is not a pointer other + than char const* or PyObject*. In the + second form policy is a model of CallPolicies.
    Effects: Adds the result of make_function(f) to diff --git a/doc/v2/header.html b/doc/v2/header.html index 7b36a65c..7b65547d 100644 --- a/doc/v2/header.html +++ b/doc/v2/header.html @@ -49,27 +49,22 @@
    -
    Class {{class name}} +
    Class {{name}}
    -
    Class {{class - name}} synopsis +
    Class {{name}} synopsis -
    Class {{class name}} +
    Class {{name}} constructors and destructor -
    Class {{class - name}} comparison functions +
    Class {{name}} comparison functions -
    Class {{class - name}} modifier functions +
    Class {{name}} modifier functions -
    Class {{class - name}} observer functions +
    Class {{name}} observer functions -
    Class {{class - name}} static functions +
    Class {{name}} static functions
    @@ -113,7 +108,7 @@

    {{class overview text}} -

    Class {{name}} synopsis

    +

    Class {{name}} synopsis

     namespace boost
     {
    @@ -123,7 +118,7 @@ namespace boost
     };
     
    -

    Class {{name}} constructors and +

    Class {{name}} constructors and destructor

     {{constructor}}
    @@ -164,7 +159,7 @@ namespace boost
           
    Rationale: {{text}}
    -

    Class {{name}} comparison +

    Class {{name}} comparison functions

    Requires: The first form requires that the expression function0<void>(f) + href="../../../function/doc/reference.html#functionN">function0<void>(f) is valid. The second form requires that a C++ exception is currently being handled (see section 15.1 in the C++ standard).
    diff --git a/doc/v2/foo.cpp b/doc/v2/foo.cpp deleted file mode 100644 index e92c2d72..00000000 --- a/doc/v2/foo.cpp +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright David Abrahams 2002. 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. - - -#include -#include -#include -#include - -class Bar { int x; } - -class Foo -{ - public: - Foo(int x) : b(x) {} - Bar const& get_bar() const { return b; } - private: - Bar b; -}; - -using namespace boost::python; -BOOST_PYTHON_MODULE_INIT(my_module) -{ - module m("my_module") - .add( - class_() - ) - .add( - class_() - .def_init(args()) - .def("get_bar", &Foo::get_bar - , return_value_policy()) - ) -} - -using namespace boost::python; -ref foo = -class_ >() - .def_init(args()) - .def_init(args()) - .def("get_name", &Foo::get_name, return_internal_reference<>()) - .def("set_name", &Foo::set_name) - .object(); - - -
    -#include <string>
    -#include <boost/python/errors.hpp>
    -#include <boost/python/reference.hpp>
    -
    -// Returns a std::string which has the same value as obj's "__name__"
    -// attribute.
    -std::string get_name(boost::python::ref obj)
    -{
    -    // throws if there's no __name__ attribute
    -    PyObject* p = boost::python::expect_non_null(
    -        PyObject_GetAttrString(obj.get(), "__name__"));
    -
    -    // throws if it's not a Python string
    -    std::string result(
    -        boost::python::expect_non_null(
    -            PyString_AsString(p)));
    -
    -    Py_XDECREF(p); // Done with p
    -    
    -    return result;
    -}
    -
    -//
    -// Demonstrate form 1 of handle_exception
    -//
    -
    -// Place a Python Int object whose value is 1 if a and b have
    -// identical "__name__" attributes, 0 otherwise.
    -void same_name_impl(PyObject*& result, PyObject* a, PyObject* b)
    -{
    -    result = PyInt_FromLong(
    -        get_name(boost::python::ref(a1)) == get_name(boost::python::ref(a2)));
    -}
    -
    -// This is an example Python 'C' API interface function
    -extern "C" PyObject*
    -same_name(PyObject* args, PyObject* keywords)
    -{
    -    PyObject* a1;
    -    PyObject* a2;
    -    PyObject* result = 0;
    -
    -    if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
    -        return 0;
    -    
    -    // Use boost::bind to make an object compatible with
    -    // boost::Function0<void>
    -    if (boost::python::handle_exception(
    -            boost::bind<void>(same_name_impl, boost::ref(result), a1, a2)))
    -    {
    -        // an exception was thrown; the Python error was set by
    -        // handle_exception()
    -        return 0;
    -    }
    -
    -    return result;
    -}
    -
    -//
    -// Demonstrate form 2 of handle_exception. Not well-supported by all
    -// compilers.
    -//
    -extern "C" PyObject*
    -same_name2(PyObject* args, PyObject* keywords)
    -{
    -    PyObject* a1;
    -    PyObject* a2;
    -    PyObject* result = 0;
    -
    -    if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
    -        return 0;
    -    try {
    -        return PyInt_FromLong(
    -            get_name(boost::python::ref(a1)) == get_name(boost::python::ref(a2)));
    -    }
    -    catch(...)
    -    {
    -        // If an exception was thrown, translate it to Python
    -        boost::python::handle_exception();
    -        return 0;
    -    }
    -}
    -
    -
    - - -template -struct from_python -{ - from_python(PyObject*); - bool convertible() const; - X operator()(PyObject*) const; -}; diff --git a/doc/v2/make_function.html b/doc/v2/make_function.html new file mode 100644 index 00000000..e7c4b421 --- /dev/null +++ b/doc/v2/make_function.html @@ -0,0 +1,155 @@ + + + + +Boost.Python - <boost/python/make_function.hpp> + + + + + + + +
    +

    C++ Boost

    +
    +

    Boost.Python

    +

    Header <boost/python/make_function.hpp>

    +
    +
    +

    Contents

    +
    +
    Introduction
    + +
    Functions
    +
    +
    make_function
    +
    make_constructor
    +
    + +
    Example
    + +
    +
    +

    Introduction

    +

    + +make_function() and +make_constructor() +are the functions used internally by class_<>::def, +class_<>::def, +and +class_<>::def_init +to produce Python callable objects which wrap C++ functions and member +functions. +

    + +

    Functions

    + +
    +template <class F>
    +objects::function* make_function(F f)</a>
    +
    +template <class F, class Policies>
    +objects::function* make_function(F f, Policies const& policies)
    +
    +
    + +
    Requires: F is a function pointer or member + function pointer type
    + +
    Effects: Creates a Python callable object which, when + called from Python, converts its arguments to C++ and calls + f. If F is a pointer-to-member-function + type, the target object of the function call (*this) + will be taken from the first Python argument, and subsequent Python + arguments will be used as the arguments to f. If + policies are supplied, it must be a model of CallPolicies, and will be applied to + the function as described here.
    + +
    Returns: A pointer convertible to PyObject* + which refers to the new Python callable object.
    +
    + +
    +template <class T, class ArgList, class Generator>
    +objects::function* make_constructor();
    +
    +
    + +
    Requires: T is a class + type. ArgList is an MPL sequence of C++ + argument types (A1, A2,... AN) such that if + a1, a2... aN are objects of type + A1, A2,... AN respectively, the expression + new Generator::apply<T>::type(a1, a2... aN) is + valid. Generator is a model of HolderGenerator. +
    + +
    Effects: Creates a Python callable object which, when + called from Python, expects its first argument to be a Boost.Python + extension class object. It converts its remaining its arguments to + C++ and passes them to the constructor of a dynamically-allocated + Generator::apply<T>::type object. The result is + installed in the extension class object. + +
    + +
    Returns: The new Python callable object
    + +
    + +

    Example

    + +

    C++ function exposed below returns a callable object wrapping one +of two functions. + +

    +#include <boost/python/make_function.hpp>
    +#include <boost/python/module.hpp>
    +
    +char const* foo() { return "foo"; }
    +char const* bar() { return "bar"; }
    +
    +PyObject* choose_function(bool selector)
    +{
    +    if (selector)
    +        return boost::python::make_function(foo);
    +    else
    +        return boost::python::make_function(bar);
    +}
    +
    +BOOST_PYTHON_MODULE_INIT(make_function_test)
    +{
    +    module("make_function_test")
    +        .def("choose_function", choose_function);
    +}
    +
    +

    +It can be used this way in Python: +
    +>>> from make_function_test import *
    +>>> f = choose_function(1)
    +>>> g = choose_function(0)
    +>>> f()
    +'foo'
    +>>> g()
    +'bar'
    +
    + +

    + +14 February 2002 + +

    +

    © Copyright Dave Abrahams + 2002. All Rights Reserved.

    + + diff --git a/doc/v2/manage_new_object.html b/doc/v2/manage_new_object.html new file mode 100644 index 00000000..cc5aab2a --- /dev/null +++ b/doc/v2/manage_new_object.html @@ -0,0 +1,115 @@ + + + + +Boost.Python - <boost/python/manage_new_object.hpp> + + + + + + + +
    +

    C++ Boost

    +
    +

    Boost.Python

    +

    Header <boost/python/manage_new_object.hpp>

    +
    +
    +

    Contents

    +
    +
    Classes
    +
    +
    Class manage_new_object
    +
    +
    Class manage_new_object synopsis
    +
    Class manage_new_object metafunctions
    +
    +
    + +
    Example
    +
    +
    + +

    Classes

    + +

    Class manage_new_object

    +

    +manage_new_object is a model of ResultConverterGenerator +which can be used to wrap C++ functions which return a pointer to an +object allocated with a new-expression, and expect the caller +to take responsibility for deleting that object. +

    + +

    Class manage_new_object synopsis

    +
    +namespace boost { namespace python
    +{
    +    struct manage_new_object
    +    {
    +        template <class T> struct apply;
    +    };
    +}}
    +
    +

    Class manage_new_object metafunctions

    +
    +template <class T> struct apply
    +
    +
    +
    Requires: T is U* for some U.
    +
    Returns: typedef to_python_indirect<T> type;
    +
    + +

    Example

    + +

    In C++: + +

    +#include <boost/python/module.hpp>
    +#include <boost/python/class.hpp>
    +#include <boost/python/manage_new_object.hpp>
    +#include <boost/python/return_value_policy.hpp>
    +
    +
    +struct Foo {
    +   Foo(int x) : x(x){}
    +   int get_x() { return x; }
    +   int x;
    +};
    +
    +Foo* make_foo(int x) { return new Foo(x); }
    +
    +// Wrapper code
    +using namespace boost::python;
    +BOOST_PYTHON_MODULE_INIT(my_module)
    +{
    +   module m("my_module")
    +      .def("make_foo", make_foo)
    +      .add(
    +         class_<Foo>()
    +            .def("get_x", &Foo::get_x)
    +         )
    +}
    +
    + +In Python: + +
    +>>> from my_module import *
    +>>> f = make_foo(3)     # create a Foo object
    +>>> f.get_x()
    +3
    +
    + +

    Revised + + 14 February 2002 + +

    +

    © Copyright Dave Abrahams + 2002. All Rights Reserved.

    + + diff --git a/include/boost/python/call.hpp b/include/boost/python/call.hpp deleted file mode 100644 index b95a31d5..00000000 --- a/include/boost/python/call.hpp +++ /dev/null @@ -1,210 +0,0 @@ -// 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_call.py - -#ifndef CALL_DWA20011214_HPP -# define CALL_DWA20011214_HPP - -# include - -namespace boost { namespace python { - -template -inline PyObject* call(R (*f)(), PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (*f)(A0), PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (*f)(A0, A1), PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (*f)(A0, A1, A2), PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (*f)(A0, A1, A2, A3), PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (*f)(A0, A1, A2, A3, A4), PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (*f)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -// Member functions -template -inline PyObject* call(R (A0::*f)(), PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (A0::*f)(A1), PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (A0::*f)(A1, A2), PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (A0::*f)(A1, A2, A3), PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (A0::*f)(A1, A2, A3, A4), PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5), PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (A0::*f)() const, PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (A0::*f)(A1) const, PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (A0::*f)(A1, A2) const, PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (A0::*f)(A1, A2, A3) const, PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (A0::*f)(A1, A2, A3, A4) const, PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (A0::*f)() volatile, PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (A0::*f)(A1) volatile, PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (A0::*f)(A1, A2) volatile, PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (A0::*f)(A1, A2, A3) volatile, PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (A0::*f)(A1, A2, A3, A4) volatile, PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5) volatile, PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (A0::*f)() const volatile, PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (A0::*f)(A1) const volatile, PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (A0::*f)(A1, A2) const volatile, PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (A0::*f)(A1, A2, A3) const volatile, PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (A0::*f)(A1, A2, A3, A4) const volatile, PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - -template -inline PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5) const volatile, PyObject* args, PyObject* keywords) -{ - return detail::returning::call(f, args, keywords); -} - - -}} // namespace boost::python - -#endif // CALL_DWA20011214_HPP - diff --git a/include/boost/python/converter/builtin_converters.hpp b/include/boost/python/converter/builtin_converters.hpp index a21fd27b..8293b0a7 100644 --- a/include/boost/python/converter/builtin_converters.hpp +++ b/include/boost/python/converter/builtin_converters.hpp @@ -6,6 +6,7 @@ #ifndef BUILTIN_CONVERTERS_DWA2002124_HPP # define BUILTIN_CONVERTERS_DWA2002124_HPP # include +# include # include namespace boost { namespace python { @@ -44,18 +45,19 @@ namespace detail BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, PyInt_FromLong(x)) \ BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned T, PyInt_FromLong(x)) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(bool, PyInt_FromLong(x)) BOOST_PYTHON_TO_INT(char) BOOST_PYTHON_TO_INT(short) BOOST_PYTHON_TO_INT(int) BOOST_PYTHON_TO_INT(long) # undef BOOST_TO_PYTHON_INT -BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, PyString_FromString(x)) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, x ? PyString_FromString(x) : detail::none()) BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, PyString_FromString(x.c_str())) BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, PyFloat_FromDouble(x)) BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, PyFloat_FromDouble(x)) BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, PyFloat_FromDouble(x)) -BOOST_PYTHON_TO_PYTHON_BY_VALUE(PyObject*, x) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(PyObject*, x ? x : detail::none()) namespace converter { diff --git a/include/boost/python/converter/from_python.hpp b/include/boost/python/converter/from_python.hpp index ee16a741..b6e1edc4 100644 --- a/include/boost/python/converter/from_python.hpp +++ b/include/boost/python/converter/from_python.hpp @@ -13,6 +13,7 @@ # include # include # include +# include namespace boost { namespace python { namespace converter { diff --git a/include/boost/python/module.hpp b/include/boost/python/module.hpp index 1d4fdd6d..11b0b6c7 100644 --- a/include/boost/python/module.hpp +++ b/include/boost/python/module.hpp @@ -30,7 +30,7 @@ class BOOST_PYTHON_DECL module_base void add_type(ref); // Return a reference to the Python module object being built - ref module() const; + ref object() const; private: ref m_module; @@ -76,7 +76,7 @@ class module : public module_base // // inline implementations // -inline ref module_base::module() const +inline ref module_base::object() const { return m_module; } diff --git a/src/converter/builtin_converters.cpp b/src/converter/builtin_converters.cpp index 33e1cb50..9cf5f110 100644 --- a/src/converter/builtin_converters.cpp +++ b/src/converter/builtin_converters.cpp @@ -150,6 +150,31 @@ namespace } }; + extern "C" PyObject* identity_unaryfunc(PyObject* x) + { + Py_INCREF(x); + return x; + } + + unaryfunc non_null = identity_unaryfunc; + + struct convertible_to_bool + { + static unaryfunc* execute(PyObject* obj) + { + return &non_null; + } + }; + + struct py_object_as_bool + { + static bool execute(PyObject* obj) + { + return PyObject_IsTrue(obj); + } + }; + + struct convertible_to_double { static unaryfunc* execute(PyObject* obj) @@ -203,6 +228,9 @@ namespace void initialize_builtin_converters() { + static scalar_from_python< + bool, convertible_to_bool, py_object_as_bool> bool_from_python; + REGISTER_INT_CONVERTERS2(char); REGISTER_INT_CONVERTERS2(short); REGISTER_INT_CONVERTERS2(int); diff --git a/test/test_builtin_converters.cpp b/test/test_builtin_converters.cpp index 7e21e046..f95ebe2b 100644 --- a/test/test_builtin_converters.cpp +++ b/test/test_builtin_converters.cpp @@ -29,6 +29,7 @@ BOOST_PYTHON_MODULE_INIT(builtin_converters_ext) { boost::python::module("builtin_converters_ext") + .def("rewrap_value_bool", by_value::rewrap) .def("rewrap_value_signed_char", by_value::rewrap) .def("rewrap_value_unsigned_char", by_value::rewrap) .def("rewrap_value_int", by_value::rewrap) @@ -44,6 +45,7 @@ BOOST_PYTHON_MODULE_INIT(builtin_converters_ext) .def("rewrap_value_cstring", by_value::rewrap) + .def("rewrap_const_reference_bool", by_const_reference::rewrap) .def("rewrap_const_reference_signed_char", by_const_reference::rewrap) .def("rewrap_const_reference_unsigned_char", by_const_reference::rewrap) .def("rewrap_const_reference_int", by_const_reference::rewrap) diff --git a/test/test_builtin_converters.py b/test/test_builtin_converters.py index 3941a29c..50b58ce6 100644 --- a/test/test_builtin_converters.py +++ b/test/test_builtin_converters.py @@ -1,5 +1,11 @@ """ >>> from builtin_converters_ext import * +>>> rewrap_value_bool(None) +0 +>>> rewrap_value_bool(0) +0 +>>> rewrap_value_bool(33) +1 >>> rewrap_value_signed_char(42) 42 >>> rewrap_value_unsigned_char(42) @@ -29,6 +35,12 @@ >>> rewrap_value_string('yo, wassup?') 'yo, wassup?' +>>> rewrap_const_reference_bool(None) +0 +>>> rewrap_const_reference_bool(0) +0 +>>> rewrap_const_reference_bool('yes') +1 >>> rewrap_const_reference_signed_char(42) 42 >>> rewrap_const_reference_unsigned_char(42) From 586b4db968d0951682125a9c8f8afc95192f1395 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 14 Feb 2002 18:12:50 +0000 Subject: [PATCH 276/369] initial checkin [SVN r12807] --- doc/v2/module.html | 258 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 258 insertions(+) create mode 100644 doc/v2/module.html diff --git a/doc/v2/module.html b/doc/v2/module.html new file mode 100644 index 00000000..f39ff4e8 --- /dev/null +++ b/doc/v2/module.html @@ -0,0 +1,258 @@ + + + + + + Boost.Python - <boost/python/module.hpp> + + + +
    +

    +

    + +
    +

    Boost.Python

    + +

    Header <boost/python/module.hpp>

    +
    +
    + +

    Contents

    + +
    +
    Introduction + +
    Macros + +
    +
    +
    BOOST_PYTHON_MODULE_INIT +
    + +
    Classes + +
    +
    +
    Class module + +
    +
    +
    Class module + synopsis + +
    Class module + constructor + +
    Class module + modifier functions + +
    Class module + observer functions +
    +
    + +
    Example(s) +
    +
    + +

    Introduction

    + +

    {{Introductory text}} + +

    Macros

    + +

    BOOST_PYTHON_MODULE_INIT(name) + is used to declare Python + module initialization functions. The name argument must + exactly match the name of the module to be initialized, and must conform to + Python's identifier naming + rules. Where you would normally write +

    +void initname()
    +{
    +   ...
    +
    + Boost.Python modules should be initialized with +
    +BOOST_PYTHON_MODULE_INIT(name)
    +{
    +   ...
    +
    + +

    Classes

    + +

    Class module

    + +

    This class represents the Python extension module under construction. It + provides functions for adding attributes and for retrieving the underlying + Python module object. + +

    Class module + synopsis

    +
    +namespace boost { namespace python
    +{
    +  class module : public module_base
    +  {
    +   public:
    +      module(const char* name);
    +
    +      // modifier functions
    +      module& setattr(const char* name, PyObject*);
    +      module& setattr(const char* name, PyTypeObject*);
    +      module& setattr(const char* name, ref const&);
    +
    +      module& add(PyTypeObject* x);
    +      template <class T, class Bases, class HolderGenerator>
    +      module& add(class_<T,Bases,HolderGenerator> const& c);
    +
    +      template <class Fn>
    +      module& def(char const* name, Fn fn);
    +      template <class Fn, class ResultHandler>
    +      module& def(char const* name, Fn fn, ResultHandler handler);
    +
    +      // observer function
    +      ref object() const;
    +  };
    +
    +}}
    +
    + +

    Class module + constructor

    +
    +module(const char* name);
    +
    + +
    +
    Requires: name is a ntbs whose value matches the + argument passed to BOOST_PYTHON_MODULE_INIT. + +
    Effects: Creates a module object representing a + Python module named name. +
    + +

    Class module modifier + functions

    +
    +module& setattr(const char* name, PyObject* obj);
    +module& setattr(const char* name, PyTypeObject* obj);
    +module& setattr(const char* name, ref const& r);
    +
    + +
    +
    Requires: name is a ntbs which conforms to + Python's identifier + naming rules. In the first two forms, obj is non-null. + In the third form, r.get() is non-null. + +
    Effects: Adds the given Python object to the module. If the + object is a product of make_function(), the + usual overloading procedure applies. + In the first two forms, ownership of a reference to obj is transferred + from caller to callee, even if an exception is thrown. + +
    Returns: *this +
    +
    +module& add(PyTypeObject* x);
    +
    +template <class T, class Bases, class HolderGenerator>
    +module& add(class_<T,Bases,HolderGenerator> const& c);
    +
    + +
    +
    Requires: In the first form, x is non-null + +
    Effects: The first form adds the Python type object named by + x to the Python module under construction, with the name + given by the type's tp_name + field. The second form adds the extension class object being constructed + by c to the module, with the same name that was passed to + c's constructor. + +
    Returns: *this + +
    Rationale: Provides a way to set type attributes in the module + without having to explicitly specify the name. +
    +
    +template <class Fn>
    +module& def(char const* name, Fn fn);
    +
    +template <class Fn, class ResultHandler>
    +module& def(char const* name, Fn fn, ResultHandler handler);
    +
    + +
    +
    Requires: f is a non-null pointer-to-function or + pointer-to-member-function. name is a ntbs which conforms to + Python's identifier + naming rules. If supplied, policy conforms to the CallPolicy concept requirements. + +
    Effects: Adds the result of make_function(f) to + the extension module being defined, with the given name. If + the module already has an attribute named name, the + usual overloading procedure applies. + +
    Returns: *this +
    + +

    Class module observer + functions

    +
    +ref object() const;
    +
    + +
    +
    Returns: A ref object which holds a reference to + the Python module object created by the module constructor. +
    + +

    Example(s)

    + +

    C++ module definition: +

    +#include <boost/python/module.hpp>
    +
    +char const* greet()
    +{
    +    return "hello, Boost.Python!";
    +}
    +
    +BOOST_PYTHON_MODULE_INIT(boost_greet)
    +{
    +    module("boost_greet")
    +        .def("greet", greet);
    +}
    +
    + +Interactive Python: +
    +>>> import boost_greet
    +>>> boost_greet.greet()
    +'hello, Boost.Python!'
    +
    + +

    Revised + + 14 February, 2002 + + + +

    © Copyright Dave + Abrahams 2002. All Rights Reserved. + From ebc641440e076f581021621e2a4e809307e4f44b Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 14 Feb 2002 19:44:11 +0000 Subject: [PATCH 277/369] initial checkin [SVN r12808] --- doc/v2/reference_existing_object.html | 152 ++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 doc/v2/reference_existing_object.html diff --git a/doc/v2/reference_existing_object.html b/doc/v2/reference_existing_object.html new file mode 100644 index 00000000..3d19826a --- /dev/null +++ b/doc/v2/reference_existing_object.html @@ -0,0 +1,152 @@ + + + + +Boost.Python - <boost/python/reference_existing_object.hpp> + + + + + + + +
    +

    C++ Boost

    +
    +

    Boost.Python

    +

    Header <boost/python/reference_existing_object.hpp>

    +
    +


    +

    Contents

    +
    +
    Classes
    +
    +
    Class reference_existing_object
    +
    +
    Class reference_existing_object synopsis
    +
    Class reference_existing_object metafunctions
    +
    +
    + +
    Example
    +
    +
    + +

    Classes

    + +

    Class reference_existing_object

    +

    +reference_existing_object is a model of ResultConverterGenerator +which can be used to wrap C++ functions which return a reference or +pointer to a C++ object. When the wrapped function is called, the +value referenced by its return value is not copied. A new Python +object is created which contains a pointer to the referent, and no +attempt is made to ensure that the lifetime of the referent is at +least as long as that of the corresponding Python object. Thus, it can +be highly dangerous to use +reference_existing_object without additional lifetime +management from such models of CallPolicies as with_custodian_and_ward. This class is used in the implementation +of return_internal_reference. +

    + +

    Class reference_existing_object synopsis

    +
    +namespace boost { namespace python
    +{
    +    struct reference_existing_object
    +    {
    +        template <class T> struct apply;
    +    };
    +}}
    +
    +

    Class reference_existing_object metafunctions

    +
    +template <class T> struct apply
    +
    +
    +
    Requires: T is U& or U*for some U.
    + +
    Returns: typedef to_python_indirect<T,V> + type, where V is a which + constructs an instance holder containing an unowned + U* pointing to the referent of the wrapped function's + return value.
    + +
    + +

    Example

    + +

    In C++: + +

    +#include <boost/python/module.hpp>
    +#include <boost/python/class.hpp>
    +#include <boost/python/reference_existing_object.hpp>
    +#include <boost/python/return_value_policy.hpp>
    +#include <utility>
    +
    +// classes to wrap
    +struct Singleton
    +{
    +   Singleton() : x(0) {}
    +
    +   int exchange(int n)  // set x and return the old value
    +   {
    +        std::swap(n, x);
    +        return n;
    +   }
    +
    +   int x;
    +};
    +
    +Singleton& get_it()
    +{
    +   static Singleton just_one;
    +   return just_one;
    +}
    +
    +// Wrapper code
    +using namespace boost::python;
    +BOOST_PYTHON_MODULE_INIT(singleton)
    +{
    +   module m("singleton")
    +      .def("get_it", get_it)
    +      .add(
    +         class_<Singleton>()
    +            .def("exchange", &Singleton::exchange)
    +         );
    +}
    +
    + +In Python: + +
    +>>> import singleton
    +>>> s1 = singleton.get_it()  
    +>>> s2 = singleton.get_it()
    +>>> id(s1) == id(s2)  # s1 and s2 are not the same object
    +0
    +>>> s1.exchange(42)   # but they reference the same C++ Singleton
    +0
    +>>> s2.exchange(99)
    +42
    +
    + +

    Revised + + 14 February 2002 + +

    +

    © Copyright Dave Abrahams + 2002. All Rights Reserved.

    + + From 70bb30b95af551390c3d9f5702dad1d6122b7386 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 14 Feb 2002 20:09:51 +0000 Subject: [PATCH 278/369] Tidy [SVN r12810] --- doc/v2/class.html | 389 ++++++++-------- doc/v2/copy_const_reference.html | 136 +++--- doc/v2/copy_non_const_reference.html | 136 +++--- doc/v2/default_call_policies.html | 208 +++++---- doc/v2/errors.html | 223 ++++----- doc/v2/from_python.html | 204 ++++---- doc/v2/header.html | 418 +++++++++++------ doc/v2/make_function.html | 191 ++++---- doc/v2/manage_new_object.html | 141 +++--- doc/v2/reference.html | 640 +++++++++++++++----------- doc/v2/reference_existing_object.html | 173 +++---- 11 files changed, 1588 insertions(+), 1271 deletions(-) diff --git a/doc/v2/class.html b/doc/v2/class.html index 12ad5d23..85e24993 100644 --- a/doc/v2/class.html +++ b/doc/v2/class.html @@ -1,105 +1,127 @@ - - - - -Boost.Python - <boost/python/class.hpp>, <boost/python/class_fwd.hpp> - - - + + + + + Boost.Python - <boost/python/class.hpp>, + <boost/python/class_fwd.hpp> + +
    - - - - -
    -

    C++ Boost

    -
    -

    Boost.Python

    -

    Headers <boost/python/class.hpp>, <boost/python/class_fwd.hpp>

    -
    -
    -

    Contents

    -
    -
    Introduction
    + + +

    +

    -
    Classes
    + +

    Boost.Python

    -
    +

    Headers <boost/python/class.hpp>, + <boost/python/class_fwd.hpp>

    + +
    -
    Class template class_
    -
    -
    Class class_ synopsis
    -
    Class class_ constructors
    -
    Class class_ modifier functions
    -
    Class class_ observer functions
    -
    +

    Contents

    -
    Class template bases
    -
    -
    Class bases synopsis
    -
    +
    +
    Introduction -
    Class template args
    -
    -
    Class args synopsis
    -
    +
    Classes -
    +
    +
    +
    Class template class_ -
    Example(s)
    -
    -
    -

    Introduction

    +
    +
    +
    Class class_ + synopsis -

    <boost/python/class.hpp> defines the interface through - which users expose their C++ classes to Python. It declares the - class_ class template, which is parameterized on the - class type being exposed, and the args and - bases utility class templates in the anonymous - namespace (the latter definitions will probably be moved in a future - release). +

    Class class_ + constructors -

    - <boost/python/class_fwd.hpp> contains a forward - declaration of the class_ class template. +

    Class class_ + modifier functions + +
    Class class_ + observer functions +
    + +
    Class template bases + +
    +
    +
    Class bases + synopsis +
    + +
    Class template args + +
    +
    +
    Class args + synopsis +
    +
    + +
    Example(s) +
    +
    + +

    Introduction

    + +

    <boost/python/class.hpp> defines the interface + through which users expose their C++ classes to Python. It declares the + class_ class template, which is parameterized on the class + type being exposed, and the args and bases + utility class templates in the anonymous namespace (the latter definitions + will probably be moved in a future release). + +

    <boost/python/class_fwd.hpp> contains a forward + declaration of the class_ class template. + +

    Classes

    + +

    Class template class_<T, Bases, HolderGenerator>

    + +

    Creates a Python class associated with the C++ type passed as its first + parameter. Its template arguments are:
    +
    -

    Classes

    - -

    -Class template class_<T, Bases, HolderGenerator>

    - -

    Creates a Python class associated with the C++ type passed as its -first parameter. Its template arguments are: -

    - - + + -
    Parameter - Requirements - Default -
    T - A class type. -
    Bases - An MPL - sequence of C++ base classes of T. + Requirements + + Default + +
    T + + A class type. + +
    Bases + + An MPL sequence of + C++ base classes of T. An unspecified empty sequence
    HolderGenerator + HolderGenerator - A model of HolderGenerator. + A model of HolderGenerator. - boost::python::objects::value_holder_generator -
    + boost::python::objects::value_holder_generator + - - -

    Class template class_ synopsis

    +

    Class template class_ + synopsis

     namespace boost { namespace python
     {
    @@ -128,44 +150,42 @@ namespace boost { namespace python
     }}
     
    -

    Class template class_ constructors

    +

    Class template class_ + constructors

     class_()
     
    -
    -
    Requires: The platform's - std::type_info::name() implementation produces a string - which corresponds to the type's declaration in C++
    +
    +
    Requires: The platform's std::type_info::name() + implementation produces a string which corresponds to the type's + declaration in C++ -
    Effects: Constructs a class_ object which - generates a Boost.Python extension class with the same name as - T.
    - -
    Rationale: Many platforms can generate reasonable names - for Python classes without user intervention.
    - -
    +
    Effects: Constructs a class_ object which + generates a Boost.Python extension class with the same name as + T. +
    Rationale: Many platforms can generate reasonable names for + Python classes without user intervention. +
     class_(char const* name)
     
    -
    -
    Requires: Name is a ntbs which conforms to Python's identifier - naming rules.
    +
    +
    Requires: name is a ntbs which conforms to + Python's identifier + naming rules. -
    Effects: Constructs a class_ object which - generates a Boost.Python extension class named - name.
    +
    Effects: Constructs a class_ object which + generates a Boost.Python extension class named name. -
    Rationale: Gives the user full control over class naming.
    - -
    - -

    Class template class_ modifier functions

    +
    Rationale: Gives the user full control over class naming. +
    +

    Class template class_ + modifier functions

     template <class F>
     class_& def(char const* name, F f)
    @@ -174,32 +194,23 @@ template <class Fn, class CallPolicy>
     class_& def(char const* name, Fn fn, CallPolicy policy)
     
    -
    -
    Requires: +
    +
    Requires: f is a non-null pointer-to-function or + pointer-to-member-function. name is a ntbs which conforms to + Python's identifier + naming rules. If supplied, policy conforms to the CallPolicy concept requirements. - f is a non-null pointer-to-function or - pointer-to-member-function. - - name is a ntbs which conforms to Python's identifier - naming rules. - - If supplied, policy conforms to the CallPolicy concept requirements. -
    - -
    Effects: Adds the result of make_function(f) - to the Boost.Python extension class being defined, with the given - name. If the extension class already has an attribute - named name, the usual overloading procedure applies. - -
    - -
    Returns: *this
    -
    +
    Effects: Adds the result of make_function(f) to + the Boost.Python extension class being defined, with the given + name. If the extension class already has an attribute named + name, the usual overloading procedure applies. +
    Returns: *this +
     template <class Args>
     class_& def_init(Args const& argument_types)
    @@ -207,61 +218,56 @@ class_& def_init(Args const& argument_types)
     class_& def_init()
     
    -
    +
    +
    Requires: in the first form, argument_types must be an MPL sequence of C++ argument + types (A1, A2,... AN) such that if + a1, a2... aN are objects of type + A1, A2,... AN respectively, the expression + T(a1, a2... aN) is valid. In the second form, + the expression T() must be valid. -
    Requires: in the first form, argument_types must be an MPL sequence of C++ - argument types (A1, A2,... AN) such that if - a1, a2... aN are objects of type - A1, A2,... AN respectively, the expression - T(a1, a2... aN) is - valid. In the second form, the expression T() must be - valid. -
    +
    Effects: Adds the result of make_constructor<T,Args,HolderGenerator>() + to the Boost.Python extension class being defined with the name + "__init__". If the 2nd form is used, an unspecified empty MPL sequence type is substituted + for Args. If the extension class already has an "__init__" + attribute, the usual overloading + procedure applies. -
    Effects: Adds the result of - make_constructor<T,Args,HolderGenerator>() to the - Boost.Python extension class being defined with the name - "__init__". If the 2nd form is used, an unspecified empty - MPL sequence type is - substituted for Args. - If the extension class already has an - "__init__" attribute, the usual overloading procedure applies. +
    Returns: *this -
    Returns: *this
    +
    Rationale: Allows users to easily expose a class' constructor + to Python. +
    -
    Rationale: Allows users to easily expose a class' - constructor to Python.
    -
    - - -

    Class template class_ observer -functions

    +

    Class template class_ + observer functions

     ref object() const;
     
    -
    -
    Returns: A ref object which holds a - reference to the Boost.Python extension class object created by the - class_ constructor.
    -
    Rationale: Mostly not needed by users, since module::add() uses this to - insert the extension class in the module.
    -
    +
    +
    Returns: A ref object which holds a reference to + the Boost.Python extension class object created by the + class_ constructor. +
    Rationale: Mostly not needed by users, since module::add() uses this to insert the + extension class in the module. +
    -

    -Class template args<T1, T2,...TN>

    +

    Class template + args<T1, T2,...TN>

    -

    Essentially an alias for boost::mpl::type_list which -users can use in def_init calls to make their code more -readable. Currently it is in the global unnammed namespace, but that -will probably change. +

    Essentially an alias for boost::mpl::type_list which users + can use in def_init calls to make their code more readable. + Currently it is in the global unnammed namespace, but that will probably + change. -

    Class template args synopsis

    +

    Class template args + synopsis

     namespace
     {
    @@ -271,15 +277,16 @@ namespace
     }
     
    -

    -Class template bases<T1, T2,...TN>

    +

    Class template + bases<T1, T2,...TN>

    -

    Essentially an alias for boost::mpl::type_list which -users can use in class_<...> -instantiations to make their code more readable. Currently it is in -the global unnammed namespace, but that will probably change. +

    Essentially an alias for boost::mpl::type_list which users + can use in class_<...> instantiations to + make their code more readable. Currently it is in the global unnammed + namespace, but that will probably change. -

    Class template bases synopsis

    +

    Class template bases + synopsis

     namespace
     {
    @@ -289,10 +296,9 @@ namespace
     }
     
    -

    Example(s)

    - -

    Given a C++ class declaration: +

    Example(s)

    +

    Given a C++ class declaration:

     class Foo : public Bar, public Baz
     {
    @@ -306,9 +312,7 @@ class Foo : public Bar, public Baz
        ...
     };
     
    - -A corresponding Boost.Python extension class can be created with: - + A corresponding Boost.Python extension class can be created with:
     using namespace boost::python;
     ref foo =
    @@ -319,15 +323,12 @@ class_<Foo,bases<Bar,Baz> >()
        .def("set_name", &Foo::set_name)
        .object();
     
    + Revised + + 05 November, 2001 + + -

    +

    © Copyright Dave + Abrahams 2002. All Rights Reserved. -

    Revised - - 05 November, 2001 - -

    -

    © Copyright Dave Abrahams - 2002. All Rights Reserved.

    - - diff --git a/doc/v2/copy_const_reference.html b/doc/v2/copy_const_reference.html index 1ce94dbb..f80db61f 100644 --- a/doc/v2/copy_const_reference.html +++ b/doc/v2/copy_const_reference.html @@ -1,49 +1,61 @@ - - - - -Boost.Python - <boost/python/copy_const_reference.hpp> - - - + + + + + Boost.Python - <boost/python/copy_const_reference.hpp> + +
    - - - - -
    -

    C++ Boost

    -
    -

    Boost.Python

    -

    Header <boost/python/copy_const_reference.hpp>

    -
    -
    -

    Contents

    -
    -
    Classes
    -
    -
    Class copy_const_reference
    -
    -
    Class copy_const_reference synopsis
    -
    Class copy_const_reference metafunctions
    -
    -
    + + +

    +

    -
    Example
    -
    -
    + +

    Boost.Python

    -

    Classes

    +

    Header + <boost/python/copy_const_reference.hpp>

    + +
    -

    Class copy_const_reference

    -

    -copy_const_reference is a model of ResultConverterGenerator -which can be used to wrap C++ functions returning a reference-to-const -type such that the referenced value is copied into a new Python object. -

    +

    Contents

    -

    Class copy_const_reference synopsis

    +
    +
    Classes + +
    +
    +
    Class + copy_const_reference + +
    +
    +
    Class + copy_const_reference synopsis + +
    Class + copy_const_reference metafunctions +
    +
    + +
    Example +
    +
    + +

    Classes

    + +

    Class + copy_const_reference

    + +

    copy_const_reference is a model of ResultConverterGenerator which can be + used to wrap C++ functions returning a reference-to-const type such that + the referenced value is copied into a new Python object. + +

    Class + copy_const_reference synopsis

     namespace boost { namespace python
     {
    @@ -53,19 +65,25 @@ namespace boost { namespace python
         };
     }}
     
    -

    Class copy_const_reference metafunctions

    + +

    Class + copy_const_reference metafunctions

     template <class T> struct apply
     
    -
    -
    Requires: T is U const& for some U.
    -
    Returns: typedef to_python_value<T> type;
    -
    -

    Example

    +
    +
    Requires: T is U const& for some + U. -

    In C++: +

    Returns: typedef to_python_value<T> + type; +
    +

    Example

    + +

    In C++:

     #include <boost/python/module.hpp>
     #include <boost/python/class.hpp>
    @@ -98,21 +116,19 @@ BOOST_PYTHON_MODULE_INIT(my_module)
              );
     }
     
    - -In Python: - + In Python:
     >>> from my_module import *
     >>> f = Foo(3)         # create a Foo object
     >>> b = f.get_bar()    # make a copy of the internal Bar object
     
    -

    Revised - - 05 November, 2001 - -

    -

    © Copyright Dave Abrahams - 2002. All Rights Reserved.

    - - +

    Revised + + 05 November, 2001 + + + +

    © Copyright Dave + Abrahams 2002. All Rights Reserved. + diff --git a/doc/v2/copy_non_const_reference.html b/doc/v2/copy_non_const_reference.html index c1ed50a3..ea2a99c7 100644 --- a/doc/v2/copy_non_const_reference.html +++ b/doc/v2/copy_non_const_reference.html @@ -1,49 +1,62 @@ - - - - -Boost.Python - <boost/python/copy_non_const_reference.hpp> - - - + + + + + Boost.Python - + <boost/python/copy_non_const_reference.hpp> + +
    - - - - -
    -

    C++ Boost

    -
    -

    Boost.Python

    -

    Header <boost/python/copy_non_const_reference.hpp>

    -
    -


    -

    Contents

    -
    -
    Classes
    -
    -
    Class copy_non_const_reference
    -
    -
    Class copy_non_const_reference synopsis
    -
    Class copy_non_const_reference metafunctions
    -
    -
    + + +

    +

    -
    Example
    -
    -
    + +

    Boost.Python

    -

    Classes

    +

    Header + <boost/python/copy_non_const_reference.hpp>

    + +
    -

    Class copy_non_const_reference

    -

    -copy_non_const_reference is a model of ResultConverterGenerator -which can be used to wrap C++ functions returning a reference-to-non-const -type such that the referenced value is copied into a new Python object. -

    +

    Contents

    -

    Class copy_non_const_reference synopsis

    +
    +
    Classes + +
    +
    +
    Class + copy_non_const_reference + +
    +
    +
    Class + copy_non_const_reference synopsis + +
    Class + copy_non_const_reference metafunctions +
    +
    + +
    Example +
    +
    + +

    Classes

    + +

    Class + copy_non_const_reference

    + +

    copy_non_const_reference is a model of ResultConverterGenerator which can be + used to wrap C++ functions returning a reference-to-non-const type such + that the referenced value is copied into a new Python object. + +

    Class + copy_non_const_reference synopsis

     namespace boost { namespace python
     {
    @@ -54,19 +67,24 @@ namespace boost { namespace python
     }}
     
    -

    Class copy_non_const_reference metafunctions

    +

    Class + copy_non_const_reference metafunctions

     template <class T> struct apply
     
    -
    -
    Requires: T is U& for some non-const U.
    -
    Returns: typedef to_python_value<T> type;
    -
    -

    Example

    +
    +
    Requires: T is U& for some + non-const U. -

    C++ code: +

    Returns: typedef to_python_value<T> + type; +
    +

    Example

    + +

    C++ code:

     #include <boost/python/module.hpp>
     #include <boost/python/class.hpp>
    @@ -99,21 +117,19 @@ BOOST_PYTHON_MODULE_INIT(my_module)
              );
     }
     
    - -Python Code: - + Python Code:
     >>> from my_module import *
     >>> f = Foo(3)         # create a Foo object
     >>> b = f.get_bar()    # make a copy of the internal Bar object
     
    -

    Revised - - 05 November, 2001 - -

    -

    © Copyright Dave Abrahams - 2002. All Rights Reserved.

    - - +

    Revised + + 05 November, 2001 + + + +

    © Copyright Dave + Abrahams 2002. All Rights Reserved. + diff --git a/doc/v2/default_call_policies.html b/doc/v2/default_call_policies.html index 3e60fcc8..876baf7a 100644 --- a/doc/v2/default_call_policies.html +++ b/doc/v2/default_call_policies.html @@ -1,61 +1,78 @@ - - - - -Boost.Python - <boost/python/default_call_policies.hpp> - - - + + + + + Boost.Python - + <boost/python/default_call_policies.hpp> + +
    - - - - -
    -

    C++ Boost

    -
    -

    Boost.Python

    -

    Header <boost/python/default_call_policies.hpp>

    -
    -


    -

    Contents

    -
    -
    Classes
    -
    + + +

    +

    -
    Class default_call_policies
    -
    -
    Class default_call_policies synopsis
    -
    Class default_call_policies static functions
    -
    + +

    Boost.Python

    -
    Class default_result_converter
    -
    -
    Class default_result_converter synopsis
    -
    Class default_result_converter metafunctions
    -
    +

    Header + <boost/python/default_call_policies.hpp>

    + +
    -
    +

    Contents

    -
    Example
    -
    -
    +
    +
    Classes -

    Classes

    +
    +
    +
    Class + default_call_policies -

    Class default_call_policies

    -

    -default_call_policies is a model of CallPolicies with no precall -or postcall behavior and a result_converter -which handles by-value returns. Wrapped C++ functions and member -functions use default_call_policies unless otherwise -specified. You may find it convenient to derive new models of CallPolicies from -default_call_policies. -

    +
    +
    +
    Class + default_call_policies synopsis -

    Class default_call_policies synopsis

    +
    Class + default_call_policies static functions +
    + +
    Class + default_result_converter + +
    +
    +
    Class + default_result_converter synopsis + +
    Class + default_result_converter metafunctions +
    +
    + +
    Example +
    +
    + +

    Classes

    + +

    Class + default_call_policies

    + +

    default_call_policies is a model of CallPolicies with no precall or + postcall behavior and a result_converter which + handles by-value returns. Wrapped C++ functions and member functions use + default_call_policies unless otherwise specified. You may find + it convenient to derive new models of CallPolicies from + default_call_policies. + +

    Class + default_call_policies synopsis

     namespace boost { namespace python
     {
    @@ -63,38 +80,43 @@ namespace boost { namespace python
         {
             static bool precall(PyObject*);
             static PyObject* postcall(PyObject*, PyObject* result);
    -        typedef default_result_converter result_converter;
    +        typedef default_result_converter result_converter;
         };
     }}
     
    -

    Class default_call_policies static functions

    +

    Class + default_call_policies static functions

     bool precall(PyObject*);
     
    -
    -
    Returns: true
    -
    Throws: nothing
    -
    +
    +
    Returns: true + +
    Throws: nothing +
     PyObject* postcall(PyObject*, PyObject* result);
     
    -
    -
    Returns: result
    -
    Throws: nothing
    -
    -

    Class default_result_converter

    -

    -default_result_converter is a model of ResultConverterGenerator -which can be used to wrap C++ functions returning non-pointer types, -char const*, and PyObject*, -by-value. -

    +
    +
    Returns: result -

    Class default_result_converter synopsis

    +
    Throws: nothing +
    + +

    Class + default_result_converter

    + +

    default_result_converter is a model of ResultConverterGenerator which can be + used to wrap C++ functions returning non-pointer types, char + const*, and PyObject*, by-value. + +

    Class + default_result_converter synopsis

     namespace boost { namespace python
     {
    @@ -105,26 +127,30 @@ namespace boost { namespace python
     }}
     
    -

    Class default_result_converter metafunctions

    +

    Class + default_result_converter metafunctions

     template <class T> struct apply
     
    -
    -
    Requires: T is not a reference type. If - T is a pointer type, T is const - char* or PyObject*.
    +
    +
    Requires: T is not a reference type. If + T is a pointer type, T is const + char* or PyObject*. -
    Returns: typedef to_python_value<T const&> type;
    -
    +
    Returns: typedef to_python_value<T + const&> type; +
    -

    Example

    - -

    This example comes from the Boost.Python implementation itself. Because the return_value_policy -class template does not implement precall or -postcall behavior, its default base class is default_call_policies: +

    Example

    +

    This example comes from the Boost.Python implementation itself. Because + the return_value_policy + class template does not implement precall or + postcall behavior, its default base class is + default_call_policies:

     template <class Handler, class Base = default_call_policies>
     struct return_value_policy : Base
    @@ -133,12 +159,12 @@ struct return_value_policy : Base
     };
     
    -

    Revised - - 05 November, 2001 - -

    -

    © Copyright Dave Abrahams - 2002. All Rights Reserved.

    - - +

    Revised + + 05 November, 2001 + + + +

    © Copyright Dave + Abrahams 2002. All Rights Reserved. + diff --git a/doc/v2/errors.html b/doc/v2/errors.html index e0bfa89d..e52f29f7 100644 --- a/doc/v2/errors.html +++ b/doc/v2/errors.html @@ -1,132 +1,141 @@ - - - - -Boost.Python - <{{header}}> - - - + + + + + Boost.Python - <{{header}}> + +
    - - - - -
    -

    C++ Boost

    -
    -

    Boost.Python

    -

    Header <boost/python/errors.hpp>

    -
    -


    -

    Contents

    -
    -
    Introduction
    + + +

    +

    -
    Classes
    -
    + +

    Boost.Python

    -
    Class error_already_set
    -
    -
    Class error_already_set synopsis
    -
    +

    Header <boost/python/errors.hpp>

    + +
    -
    +

    Contents

    -
    Functions
    -
    +
    +
    Introduction -
    handle_exception
    -
    expect_non_null
    +
    Classes -
    +
    +
    +
    Class error_already_set -
    Examples
    -
    -
    +
    +
    +
    Class + error_already_set synopsis +
    +
    -

    Introduction

    -

    <boost/python/errors.hpp> provides types and -functions for managing and translating between Python and C++ -exceptions. This is relatively low-level functionality that is mostly -used internally by Boost.Python. Users should seldom need it. +

    Functions -

    Classes

    +
    +
    +
    handle_exception -

    Class error_already_set

    -

    -error_already_set is an exception type which can be -thrown to indicate that a Python error has occurred. If thrown, the -precondition is that PyErr_Occurred() -returns a value convertible to true. -

    +
    expect_non_null +
    -

    Class error_already_set synopsis

    +
    Examples +
    +
    + +

    Introduction

    + +

    <boost/python/errors.hpp> provides types and + functions for managing and translating between Python and C++ exceptions. + This is relatively low-level functionality that is mostly used internally + by Boost.Python. Users should seldom need it. + +

    Classes

    + +

    Class + error_already_set

    + +

    error_already_set is an exception type which can be thrown + to indicate that a Python error has occurred. If thrown, the precondition + is that PyErr_Occurred() + returns a value convertible to true. + +

    Class error_already_set synopsis

     namespace boost { namespace python
     {
    -    class error_already_set {};
    +    class error_already_set {};
     }}
     
    - -

    Functions

    -
    template <class T> bool handle_exception(T f) throw();
    +    

    Functions

    +
    +template <class T> bool handle_exception(T f) throw();
     
     void handle_exception() throw();
     
    -
    -
    Requires: The first form requires that the expression - function0<void>(f) - is valid. The second form requires that a C++ exception is currently - being handled (see section 15.1 in the C++ standard). -
    -
    Effects: The first form calls f() inside a - try block whose catch clauses set an - appropriate Python exception for the C++ exception caught, returning - true if an exception was caught, false - otherwise. The second form passes a function which rethrows the - exception currently being handled to the first form.
    +
    +
    Requires: The first form requires that the expression function0<void>(f) + is valid. The second form requires that a C++ exception is currently + being handled (see section 15.1 in the C++ standard). -
    Postconditions: No exception is being handled
    +
    Effects: The first form calls f() inside a + try block whose catch clauses set an + appropriate Python exception for the C++ exception caught, returning + true if an exception was caught, false + otherwise. The second form passes a function which rethrows the exception + currently being handled to the first form. -
    Throws: nothing
    +
    Postconditions: No exception is being handled -
    Rationale: At inter-language boundaries it is important - to ensure that no C++ exceptions escape, since the calling language - usually doesn't have the equipment neccessary to properly unwind the - stack. Use handle_exception to manage exception - translation whenever your C++ code is called directly from the - Python API. This is done for you automatically by the usual function - wrapping facilities: make_function(), make_constructor(), - module::def and class_::def). The second form can be - more convenient to use - (see the example below), but various - compilers have problems when exceptions are rethrown from within an - enclosing try block.
    -
    +
    Throws: nothing +
    Rationale: At inter-language boundaries it is important to + ensure that no C++ exceptions escape, since the calling language usually + doesn't have the equipment neccessary to properly unwind the stack. Use + handle_exception to manage exception translation whenever + your C++ code is called directly from the Python API. This is done for + you automatically by the usual function wrapping facilities: make_function(), make_constructor(), module::def and class_::def). The second form can be more + convenient to use (see the example below), but + various compilers have problems when exceptions are rethrown from within + an enclosing try block. +
     PyObject* expect_non_null(PyObject* x);
     
     template <class T> T* expect_non_null(T* x);
     
    -
    -
    Returns: x
    -
    Throws: error_already_set() iff x == 0.
    -
    Rationale: Simplifies error-handling when calling many - functions in the Python/C - API, which return 0 on error.
    -
    -

    Examples

    -

    +

    +
    Returns: x + +
    Throws: error_already_set() iff x == + 0. + +
    Rationale: Simplifies error-handling when calling many + functions in the Python/C API, which + return 0 on error. +
    + +

    Examples

     #include <string>
     #include <boost/python/errors.hpp>
    @@ -211,13 +220,13 @@ same_name2(PyObject* args, PyObject* keywords)
        }
     }
     
    -

    -

    Revised - - 05 November, 2001 - -

    -

    © Copyright Dave Abrahams - 2002. All Rights Reserved.

    - - + +

    Revised + + 05 November, 2001 + + + +

    © Copyright Dave + Abrahams 2002. All Rights Reserved. + diff --git a/doc/v2/from_python.html b/doc/v2/from_python.html index 94ae7019..d888bb38 100644 --- a/doc/v2/from_python.html +++ b/doc/v2/from_python.html @@ -1,68 +1,79 @@ - - - - -Boost.Python - <boost/python/from_python.hpp> - - - + + + + + Boost.Python - <boost/python/from_python.hpp> + +
    - - - - -
    -

    C++ Boost

    -
    -

    Boost.Python

    -

    Header <boost/python/from_python.hpp>

    -
    -


    -

    Contents

    -
    -
    Introduction
    + + +

    +

    -
    Classes
    -
    + +

    Boost.Python

    -
    Class Templatefrom_python
    -
    -
    Class Template from_python synopsis
    -
    Class Template from_python constructor
    -
    Class Template from_python observer functions
    -
    -
    -
    Example
    -
    -
    -

    Introduction

    -

    +

    Header <boost/python/from_python.hpp>

    + +
    -<boost/python/from_python.hpp> introduces a class -template from_python<T> for extracting a C++ object -of type T from a Python object. +

    Contents

    -

    +
    +
    Introduction +
    Classes -

    Classes

    -

    Class Template from_python<class T>

    +
    +
    +
    Class + Templatefrom_python -

    -from_python<T> is the type used internally by -Boost.Python to extract C++ function arguments from a Python argument -tuple when calling a wrapped function. It can also be used directly to -make similar conversions in other contexts. -

    +
    +
    +
    Class Template + from_python synopsis -

    Class Template from_python synopsis

    +
    Class Template + from_python constructor + +
    Class Template + from_python observer functions +
    +
    + +
    Example +
    +
    + +

    Introduction

    + +

    <boost/python/from_python.hpp> introduces a class + template from_python<T> for extracting a C++ object of + type T from a Python object. + +

    Classes

    + +

    Class Template + from_python<class T>

    + +

    from_python<T> is the type used internally by + Boost.Python to extract C++ function arguments from a Python argument tuple + when calling a wrapped function. It can also be used directly to make + similar conversions in other contexts. + +

    Class Template + from_python synopsis

     namespace boost { namespace python
     {
        template <class T>
        struct from_python : private boost::noncopyable // Exposition only.
    -       // from_python<T> meets the NonCopyable requirements
    +"../../../utility/utility.htm#Class noncopyable">boost::noncopyable // Exposition only.
    +       // from_python<T> meets the NonCopyable requirements
        {
           from_python(PyObject*);
           bool convertible() const;
    @@ -71,63 +82,63 @@ namespace boost { namespace python
     }
     
    -

    Class Template from_python constructor

    +

    Class Template + from_python constructor

     from_python(PyObject* p);
     
    -
    -
    Requires: p != 0
    -
    Effects: Constructs a from_python object - suitable for extracting a C++ object of type T from - p.
    -
    +
    +
    Requires: p != 0 -

    Class Template from_python observer functions

    +
    Effects: Constructs a from_python object suitable + for extracting a C++ object of type T from p. +
    +

    Class Template + from_python observer functions

     bool convertible() const;
     
    -
    -
    Returns: false if the conversion cannot succeed. This indicates that either: -
      -
    1. No from_python_converter was registered for -T, or +
      +
      Returns: false if the conversion cannot succeed. + This indicates that either: -
    2. any such converter rejected the constructor argument -p by returning 0 from its -convertible() function -
    +
    +
      +
    1. No from_python_converter was registered for + T, or -Note that conversion may still fail in operator() due to an exception. +
    2. any such converter rejected the constructor argument + p by returning 0 from its + convertible() function +
    + Note that conversion may still fail in operator() due to + an exception. - - -
    Throws: nothing
    - -
    Rationale: Because from_python<> is used in - overload resolution, and throwing an exception can be slow, it is - useful to be able to rule out a broad class of unsuccessful - conversions without throwing an exception.
    -
    +
    Throws: nothing +
    Rationale: Because from_python<> is used in + overload resolution, and throwing an exception can be slow, it is useful + to be able to rule out a broad class of unsuccessful conversions without + throwing an exception. +
     {{function}}
    @@ -186,7 +181,7 @@ namespace boost
           
    Rationale: {{text}} -

    Class {{name}} modifier +

    Class {{name}} modifier functions

     {{function}}
    @@ -208,7 +203,7 @@ namespace boost
           
    Rationale: {{text}} -

    Class {{name}} observer +

    Class {{name}} observer functions

     {{function}}
    @@ -230,7 +225,7 @@ namespace boost
           
    Rationale: {{text}} -

    Class {{name}} static functions

    +

    Class {{name}} static functions

     {{function}}
     
    diff --git a/doc/v2/module.html b/doc/v2/module.html index f39ff4e8..0e3516ed 100644 --- a/doc/v2/module.html +++ b/doc/v2/module.html @@ -188,19 +188,23 @@ module& add(class_<T,Bases,HolderGenerator> const& c);
     template <class Fn>
    -module& def(char const* name, Fn fn);
    +module& def(char const* name, Fn f);
     
     template <class Fn, class ResultHandler>
    -module& def(char const* name, Fn fn, ResultHandler handler);
    +module& def(char const* name, Fn f, ResultHandler handler);
     
    +
    Requires: f is a non-null pointer-to-function or pointer-to-member-function. name is a ntbs which conforms to Python's identifier - naming rules. If supplied, policy conforms to the CallPolicy concept requirements. + naming rules. In the first form, the return type of + f is not a reference and is not a pointer other + than char const* or PyObject*. In the + second form policy is a model of CallPolicy.
    Effects: Adds the result of make_function(f) to diff --git a/doc/v2/reference.html b/doc/v2/reference.html index 5e2e4463..5f82fe4d 100644 --- a/doc/v2/reference.html +++ b/doc/v2/reference.html @@ -353,19 +353,19 @@
    reference_from_python.hpp + "lvalue_from_python.html">reference_from_python.hpp
    -
    Classes +
    Classes
    reference_from_python + "lvalue_from_python.html#reference_from_python-spec">reference_from_python
    get_member + "lvalue_from_python.html#get_member-spec">get_member
    diff --git a/doc/v2/return_internal_reference.html b/doc/v2/return_internal_reference.html new file mode 100644 index 00000000..c1b62a56 --- /dev/null +++ b/doc/v2/return_internal_reference.html @@ -0,0 +1,205 @@ + + + + + + Boost.Python - <boost/python/return_internal_reference.hpp> + + + +
    +

    +

    + +
    +

    Boost.Python

    + +

    Header <boost/python/return_internal_reference.hpp>

    +
    +
    + +

    Contents

    + +
    +
    Introduction + + +
    Classes + +
    +
    +
    Class Template return_internal_reference + +
    +
    + +
    Class Template + return_internal_reference synopsis + +
    Class + return_internal_reference static functions +
    +
    + + +
    Example +
    +
    + +

    Introduction

    + + return_internal_reference instantiations are models of CallPolicies which allow pointers and + references to objects held internally by a free or member function + argument or from the target of a member function to be returned + safely without making a copy of the referent. The default for its + first template argument handles the common case where the + containing object is the target (*this) of a wrapped member function. + +

    Classes

    + +

    Class template return_internal_reference

    + + + + + + + +
    + return_internal_reference template parameters +
    Parameter + + Requirements + + Description + + Default + +
    owner_arg + + A positive compile-time constant of type + std::size_t. + + The index of the parameter which contains the object to + which the reference or pointer is being returned. If used to + wrap a member function, parameter 1 is the target object + (*this). + + 1 + +
    Base + + A model of CallPolicies + + Used for policy composition. Any + result_converter it supplies will be overridden by + return_internal_reference, but its + precall and postcall policies are + composed as described here CallPolicies. + + default_call_policies + +
    + +

    Class template return_internal_reference synopsis

    +
    +namespace boost { namespace python {
    +   template <std::size_t owner_arg = 1, class Base = default_call_policies>
    +   struct return_internal_reference : Base
    +   {
    +      static PyObject* postcall(PyObject*, PyObject* result);
    +      typedef reference_existing_object result_converter;
    +   };
    +}}
    +
    + +

    Class + default_call_policies static functions

    + +
    +PyObject* postcall(PyObject* args, PyObject* result);
    +
    + +
    +
    Requires: PyTuple_Check(args) != 0 + +
    Returns: make_custodian_and_ward_postcall::postcall(args, result) +
    + + +

    Example

    + +

    C++ module definition

    + +
    +#include <boost/python/module.hpp>
    +#include <boost/python/class.hpp>
    +#include <boost/python/return_internal_reference.hpp>
    +
    +class Bar
    +{
    +   Bar(int x) : x(x) {}
    +   int get_x() const { return x; }
    +   void set_x(int x) { this->x = x; }
    + private:
    +   int x;
    +}
    +
    +class Foo
    +{
    + public:
    +   Foo(int x) : b(x) {}
    +
    +   // Returns an internal reference
    +   Bar const& get_bar() const { return b; }
    +
    + private:
    +   Bar b;
    +};
    +
    +using namespace boost::python;
    +BOOST_PYTHON_MODULE_INIT(internal_refs)
    +{
    +   module m("internal_refs")
    +      .add(
    +         class_<Bar>()
    +            .def("get_x", &Bar::get_x)
    +            .def("set_x", &Bar::set_x)
    +         )
    +      .add(
    +         class_<Foo>()
    +            .def_init(args<int>())
    +            .def("get_bar", &Foo::get_bar
    +                , return_internal_reference<>())
    +         )
    +      ;
    +}
    +
    + +

    Python code

    + +
    +>>> from internal_refs import *
    +>>> f = Foo(3)
    +>>> b1 = f.get_bar()
    +>>> b2 = f.get_bar()
    +>>> b1.get_x()
    +3
    +>>> b2.get_x()
    +3
    +>>> b1.set_x(42)
    +>>> b2.get_x()
    +42
    +
    + +

    Revised + + 15 February, 2002 + + +

    © Copyright Dave + Abrahams 2002. All Rights Reserved. + From 607631604f065cbb5d038ea8fc14d2e29a2c1ad4 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 15 Feb 2002 18:32:57 +0000 Subject: [PATCH 283/369] *** empty log message *** [SVN r12824] --- doc/v2/return_internal_reference.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/v2/return_internal_reference.html b/doc/v2/return_internal_reference.html index c1b62a56..8cbfc167 100644 --- a/doc/v2/return_internal_reference.html +++ b/doc/v2/return_internal_reference.html @@ -106,7 +106,8 @@

    Class template return_internal_reference synopsis

    -namespace boost { namespace python {
    +namespace boost { namespace python
    +{
        template <std::size_t owner_arg = 1, class Base = default_call_policies>
        struct return_internal_reference : Base
        {
    
    From f697d2daa17746ef6aee87c5e8317bd5d02ecc28 Mon Sep 17 00:00:00 2001
    From: Dave Abrahams 
    Date: Fri, 15 Feb 2002 18:53:55 +0000
    Subject: [PATCH 284/369] *** empty log message ***
    
    [SVN r12825]
    ---
     doc/v2/copy_const_reference.html |   9 +-
     doc/v2/return_value_policy.html  | 148 +++++++++++++++++++++++++++++++
     2 files changed, 153 insertions(+), 4 deletions(-)
     create mode 100644 doc/v2/return_value_policy.html
    
    diff --git a/doc/v2/copy_const_reference.html b/doc/v2/copy_const_reference.html
    index f80db61f..ec76fa1a 100644
    --- a/doc/v2/copy_const_reference.html
    +++ b/doc/v2/copy_const_reference.html
    @@ -83,7 +83,7 @@ template <class T> struct apply
     
         

    Example

    -

    In C++: +

    C++ Module Definition

     #include <boost/python/module.hpp>
     #include <boost/python/class.hpp>
    @@ -113,10 +113,11 @@ BOOST_PYTHON_MODULE_INIT(my_module)
                 .def_init(args<int>())
                 .def("get_bar", &Foo::get_bar
                     , return_value_policy<copy_const_reference>())
    -         );
    +         )
    +       ;
     }
     
    - In Python: +

    Python Code

     >>> from my_module import *
     >>> f = Foo(3)         # create a Foo object
    @@ -125,7 +126,7 @@ BOOST_PYTHON_MODULE_INIT(my_module)
     
         

    Revised - 05 November, 2001 + 15 February, 2002 diff --git a/doc/v2/return_value_policy.html b/doc/v2/return_value_policy.html new file mode 100644 index 00000000..5741be8f --- /dev/null +++ b/doc/v2/return_value_policy.html @@ -0,0 +1,148 @@ + + + + + + Boost.Python - <boost/python/return_value_policy.hpp> + + + +
    +

    +

    + +
    +

    Boost.Python

    + +

    Header <boost/python/return_value_policy.hpp>

    +
    +


    + +

    Contents

    + +
    +
    Introduction + + +
    Classes + +
    +
    +
    Class Template return_value_policy + +
    +
    + +
    Class Template + return_value_policy synopsis +
    +
    + + +
    Example +
    +
    + +

    Introduction

    + + return_value_policy instantiations are simply models + of CallPolicies which are composed of a ResultConverterGenerator and optional Base CallPolicies. + +

    Classes

    + +

    Class template return_value_policy

    + + + + + + + +
    + return_value_policy template parameters +
    Parameter + + Requirements + + Default + +
    ResultConverterGenerator + + A model of ResultConverterGenerator. + +
    Base + + A model of CallPolicies + + default_call_policies + +
    + +

    Class template return_value_policy synopsis

    +
    +namespace boost { namespace python
    +{
    +  template <class ResultConverterGenerator, class Base = default_call_policies>
    +  struct return_value_policy : Base
    +  {
    +      typedef ResultConverterGenerator result_converter;
    +  };
    +}}
    +
    + +

    Example

    + +

    C++ Module Definition

    +
    +#include <boost/python/module.hpp>
    +#include <boost/python/class.hpp>
    +#include <boost/python/copy_const_reference.hpp>
    +#include <boost/python/return_value_policy.hpp>
    +
    +// classes to wrap
    +struct Bar { int x; }
    +
    +struct Foo {
    +   Foo(int x) : { b.x = x; }
    +   Bar const& get_bar() const { return b; }
    + private:
    +   Bar b;
    +};
    +
    +// Wrapper code
    +using namespace boost::python;
    +BOOST_PYTHON_MODULE_INIT(my_module)
    +{
    +   module m("my_module")
    +      .add(
    +         class_<Bar>()
    +         )
    +      .add(
    +         class_<Foo>()
    +            .def_init(args<int>())
    +            .def("get_bar", &Foo::get_bar
    +                , return_value_policy<copy_const_reference>())
    +         )
    +       ;
    +}
    +
    +

    Python Code

    +
    +>>> from my_module import *
    +>>> f = Foo(3)         # create a Foo object
    +>>> b = f.get_bar()    # make a copy of the internal Bar object
    +
    + +

    Revised + + 15 February, 2002 + + +

    © Copyright Dave + Abrahams 2002. All Rights Reserved. + From 39646acf5bab3252b1ca14bc60c20404171741c4 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 16 Feb 2002 00:25:16 +0000 Subject: [PATCH 285/369] updates to be compatible with Rene's new system [SVN r12831] --- Jamfile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Jamfile b/Jamfile index ac32456b..aa804505 100644 --- a/Jamfile +++ b/Jamfile @@ -31,39 +31,39 @@ PYTHON_PROPERTIES ; # -------- general test ------- - extension m1 : test/m1.cpp bpl + extension m1 : test/m1.cpp bpl : : debug-python ; - extension m2 : test/m2.cpp bpl + extension m2 : test/m2.cpp bpl : : debug-python ; - boost-python-runtest try : test/newtest.py m1 m2 : : debug-python ; + boost-python-runtest try : test/newtest.py m1 m2 : : debug-python ; # ----------- builtin converters ----------- - extension builtin_converters_ext : test/test_builtin_converters.cpp bpl + extension builtin_converters_ext : test/test_builtin_converters.cpp bpl : : debug-python ; boost-python-runtest test_builtin_converters : test/test_builtin_converters.py - builtin_converters_ext + builtin_converters_ext : : debug-python ; # ----------- pointer adoption ----------- - extension test_pointer_adoption_ext : test/test_pointer_adoption.cpp bpl + extension test_pointer_adoption_ext : test/test_pointer_adoption.cpp bpl : : debug-python ; boost-python-runtest test_pointer_adoption : test/test_pointer_adoption.py - test_pointer_adoption_ext + test_pointer_adoption_ext : : debug-python ; From edd93c80a1f15c35b9a2b0dfd550d66b8eb9e521 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 16 Feb 2002 15:42:09 +0000 Subject: [PATCH 286/369] inital checkin [SVN r12835] --- doc/v2/to_python_converter.html | 189 ++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 doc/v2/to_python_converter.html diff --git a/doc/v2/to_python_converter.html b/doc/v2/to_python_converter.html new file mode 100644 index 00000000..63db8c71 --- /dev/null +++ b/doc/v2/to_python_converter.html @@ -0,0 +1,189 @@ + + + + + + Boost.Python - <boost/python/to_python_converter.hpp> + + + +
    +

    +

    + +
    +

    Boost.Python

    + +

    Header <boost/python/to_python_converter.hpp>

    +
    +


    + +

    Contents

    + +
    +
    Introduction + + +
    Classes + +
    +
    +
    Class Template to_python_converter + +
    +
    + +
    Class Template + to_python_converter synopsis + +
    Class Template + to_python_converter constructor +
    +
    + +
    Example +
    +
    + +

    Introduction

    + + to_python_converter registers a conversion from + objects of a given C++ type into a Python object. + +

    Classes

    + +

    Class template to_python_converter

    + + to_python_converter adds a wrapper around a static + member function of its second template parameter, handling + low-level details such as insertion into the converter registry. + + + + + + + +
    + to_python_converter template parameters
    +In the table below, x denotes an object of type T +
    Parameter + + Requirements + + Description + +
    T + + + + The C++ type of the source object in the conversion + +
    Conversion + + PyObject* p = Conversion::convert(x),
    + if p == 0, PyErr_Occurred() != 0. + +
    A class type whose static member function + convert does the real work of the conversion. + +
    + +

    Class template to_python_converter synopsis

    +
    +namespace boost { namespace python
    +{
    +  template <class T, class Conversion>
    +  struct to_python_converter
    +  {
    +      to_python_converter();
    +  };
    +}}
    +
    + +

    Class template to_python_converter constructor

    +
    +to_python_converter();
    +
    + +
    + +
    Effects: Registers a to_python converter which uses + Conversion::convert() to do its work. + +
    + +

    Example

    + +This example presumes that someone has implemented the standard noddy example +module from the Python documentation, and placed the corresponding +declarations in "noddy.h". Because +noddy_NoddyObject is the ultimate trivial extension type, +the example is a bit contrived: it wraps a function for which all +information is contained in the type of its return value. + +

    C++ module definition

    + +
    +#include <boost/python/reference.hpp>
    +#include <boost/python/module.hpp>
    +#include "noddy.h"
    +
    +struct tag {};
    +tag make_tag() { return tag(); }
    +
    +using namespace boost::python;
    +
    +struct tag_to_noddy
    +{
    +    static PyObject* convert(tag const& x)
    +    {
    +        return PyObject_New(noddy_NoddyObject, &noddy_NoddyType);
    +    }
    +};
    +
    +BOOST_PYTHON_MODULE_INIT(to_python_converter)
    +{
    +    module to_python("to_python_converter")
    +        .def("make_tag", make_tag)
    +        ;
    +    to_python_converter<tag, tag_to_noddy>();
    +}
    +
    + +

    Python code

    + +
    +>>> import to_python_converter
    +>>> def always_none():
    +...     return None
    +...
    +>>> def choose_function(x):
    +...     if (x % 2 != 0):
    +...         return to_python_converter.make_tag
    +...     else:
    +...         return always_none
    +...
    +>>> a = [ choose_function(x) for x in range(5) ]
    +>>> b = [ f() for f in a ]
    +>>> type(b[0])
    +<type 'NoneType'>
    +>>> type(b[1])
    +<type 'Noddy'>
    +>>> type(b[2])
    +<type 'NoneType'>
    +>>> type(b[3])
    +<type 'Noddy'>
    +
    + +

    Revised + + 05 November, 2001 + + + +

    © Copyright Dave + Abrahams 2002. All Rights Reserved. + From 80effaa541f56a973a8f03e03b444500d1af4ece Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 16 Feb 2002 16:01:37 +0000 Subject: [PATCH 287/369] *** empty log message *** [SVN r12836] --- doc/boost.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/boost.css b/doc/boost.css index c382d4c6..cf5c8a97 100644 --- a/doc/boost.css +++ b/doc/boost.css @@ -23,10 +23,12 @@ BODY PRE { MARGIN-LEFT: 2pc; + FONT-SIZE: 80%; BACKGROUND-COLOR: #dfffff } CODE { + FONT-SIZE: 95%; white-space: pre } .index From dcae0eadd5af2bdc631d0428ff0c5dfc2ede0c4d Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 16 Feb 2002 16:42:26 +0000 Subject: [PATCH 288/369] *** empty log message *** [SVN r12839] --- doc/v2/return_internal_reference.html | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/doc/v2/return_internal_reference.html b/doc/v2/return_internal_reference.html index 8cbfc167..42b8c97e 100644 --- a/doc/v2/return_internal_reference.html +++ b/doc/v2/return_internal_reference.html @@ -55,7 +55,8 @@ argument or from the target of a member function to be returned safely without making a copy of the referent. The default for its first template argument handles the common case where the - containing object is the target (*this) of a wrapped member function. + containing object is the target (*this) of a wrapped + member function.

    Classes

    @@ -84,7 +85,10 @@ The index of the parameter which contains the object to which the reference or pointer is being returned. If used to wrap a member function, parameter 1 is the target object - (*this). + (*this). Note that if the target Python object + type doesn't support weak references, a Python + TypeError exception will be raised when the + function being wrapped is called. 1 @@ -125,7 +129,7 @@ PyObject* postcall(PyObject* args, PyObject* result);
    -
    Requires: PyTuple_Check(args) != 0 +
    Requires: PyTuple_Check(args) != 0
    Returns: make_custodian_and_ward_postcall::postcall(args, result)
    From aeccf45d4e0041c6a4a56ce31d4e8fc2f1ef8fce Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 16 Feb 2002 18:10:30 +0000 Subject: [PATCH 289/369] *** empty log message *** [SVN r12840] --- doc/v2/to_python_indirect.html | 194 +++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 doc/v2/to_python_indirect.html diff --git a/doc/v2/to_python_indirect.html b/doc/v2/to_python_indirect.html new file mode 100644 index 00000000..8910cd97 --- /dev/null +++ b/doc/v2/to_python_indirect.html @@ -0,0 +1,194 @@ + + + + + + Boost.Python - <boost/python/to_python_indirect.hpp> + + + +
    +

    +

    + +
    +

    Boost.Python

    + +

    Header <boost/python/to_python_indirect.hpp>

    +
    +
    + +

    Contents

    + +
    +
    Introduction + + +
    Classes + +
    +
    +
    Class Template to_python_indirect + +
    +
    + +
    Class Template + to_python_indirect synopsis + +
    Class Template + to_python_indirect observer functions + +
    Class Template + to_python_indirect static functions +
    +
    + +
    Example +
    +
    + +

    Introduction

    + + <boost/python/to_python_indirect.hpp> supplies + a way to construct new Python objects that hold wrapped C++ class + instances via a pointer or smart pointer. + +

    Classes

    + +

    Class template to_python_indirect

    +

    Class template to_python_indirect converts objects +of its first argument type to python as extension class instances, using the ownership policy provided by its 2nd argument. + +

    + + + + + + + +
    + to_python_indirect Requirements
    + + In the table below, x denotes an object of + type T, h denotes an + object of type + boost::python::objects::instance_holder*, and + p denotes an object of type + U*. + +
    Parameter + + Requirements + + Description + +
    T + + Either U cv& + (where cv is any optional cv-qualification) or a Dereferenceable type such that + *x is convertible to U const&, where + U is a class type. + + A type deferencing a C++ class exposed to Python using + class template class_. + +
    MakeHolder + + h = MakeHolder::execute(p); + + A class whose static execute() creates an + instance_holder. + +
    + + Instantiations of to_python_indirect are models of ResultConverter. + + +

    Class template to_python_indirect synopsis

    +
    +namespace boost { namespace python
    +{
    +  template <class T, class MakeHolder>
    +  struct to_python_indirect
    +  {
    +     static bool convertible();
    +     PyObject* operator()(T ptr_or_reference) const;
    +   private:
    +     static PyTypeObject* type();
    +  };
    +}}
    +
    + +

    Class template to_python_indirect observers

    +
    +PyObject* operator()(T x) const;
    +
    + +
    + +
    Requires: x refers to an object (if it + is a pointer type, it is non-null). convertible() == + true. + +
    Effects: Creates an appropriately-typed Boost.Python + extension class instance, uses MakeHolder to create + an instance_holder from x, installs + the instance_holder in the new extension class + instance, and returns a pointer to it. + +
    + + +

    Class template to_python_indirect statics

    +
    +bool convertible();
    +
    + +
    Effects: Returns true iff any module has + registered a Python type corresponding to U. + +

    Example

    + +This example replicates the functionality of reference_existing_object, +but without some of the compile-time error checking. + + +
    +
    +struct make_reference_holder
    +{
    +   typedef boost::python::objects::instance_holder* result_type;
    +   template <class T>
    +   static result_type execute(T* p)
    +   {
    +      return new boost::python::objects::pointer_holder<T*, T>(p);
    +   }
    +};
    +
    +struct reference_existing_object
    +{
    +   // metafunction returning the ResultConverter
    +   template <class T>
    +   struct apply
    +   {
    +      typedef boost::python::to_python_indirect<T,make_reference_holder> type;
    +   };
    +};
    +
    + +

    Revised + + 16 February, 2002 + + + +

    © Copyright Dave + Abrahams 2002. All Rights Reserved. + From ca872af3c8147c8fc3eef2594698b08a8b147a7d Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 16 Feb 2002 18:11:24 +0000 Subject: [PATCH 290/369] HolderGenerator renamed to MakeHolder [SVN r12841] --- include/boost/python/to_python_indirect.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/boost/python/to_python_indirect.hpp b/include/boost/python/to_python_indirect.hpp index e68eced0..306b3246 100644 --- a/include/boost/python/to_python_indirect.hpp +++ b/include/boost/python/to_python_indirect.hpp @@ -14,7 +14,7 @@ namespace boost { namespace python { -template +template struct to_python_indirect { static bool convertible(); @@ -61,14 +61,14 @@ namespace detail }; } -template -inline bool to_python_indirect::convertible() +template +inline bool to_python_indirect::convertible() { return type() != 0; } -template -inline PyObject* to_python_indirect::operator()(T x) const +template +inline PyObject* to_python_indirect::operator()(T x) const { PyObject* raw_result = type()->tp_alloc(type(), 0); @@ -82,7 +82,7 @@ inline PyObject* to_python_indirect::operator()(T x) const // Build a value_holder to contain the object using the copy // constructor objects::instance_holder* p = - detail::unwind_type(x); + detail::unwind_type(x); // Install it in the instance p->install(raw_result); @@ -91,8 +91,8 @@ inline PyObject* to_python_indirect::operator()(T x) const return result.release(); } -template -inline PyTypeObject* to_python_indirect::type() +template +inline PyTypeObject* to_python_indirect::type() { return detail::unwind_type(); } From 8af49161fbe031ebe59458123c133fe37bd4ef87 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 17 Feb 2002 04:37:35 +0000 Subject: [PATCH 291/369] no message [SVN r12845] --- doc/v2/class.html | 4 ++-- doc/v2/class_hpp.py | 20 -------------------- doc/v2/errors.html | 4 ++-- doc/v2/lvalue_from_python.html | 4 ++-- doc/v2/module.html | 10 +++++----- 5 files changed, 11 insertions(+), 31 deletions(-) delete mode 100644 doc/v2/class_hpp.py diff --git a/doc/v2/class.html b/doc/v2/class.html index fc64eabd..393510eb 100644 --- a/doc/v2/class.html +++ b/doc/v2/class.html @@ -175,7 +175,7 @@ class_(char const* name)

    Requires: name is a ntbs which conforms to Python's identifier + "http://www.python.org/doc/2.2/ref/identifiers.html">identifier naming rules.
    Effects: Constructs a class_ object which @@ -198,7 +198,7 @@ class_& def(char const* name, Fn f, CallPolicy policy)
    Requires: f is a non-null pointer-to-function or pointer-to-member-function. name is a ntbs which conforms to Python's identifier + "http://www.python.org/doc/2.2/ref/identifiers.html">identifier naming rules. In the first form, the return type of f is not a reference and is not a pointer other than char const* or PyObject*. In the diff --git a/doc/v2/class_hpp.py b/doc/v2/class_hpp.py deleted file mode 100644 index 9af2cb5c..00000000 --- a/doc/v2/class_hpp.py +++ /dev/null @@ -1,20 +0,0 @@ -introduction = ''' -''' - -class boost(namespace): pass - -class python(boost): - - class class_(class_template): - T = type() - T.requires = 'a class type' - - Bases = concepts.mpl_sequence('class type') - HolderGenerator = concepts.HolderGenerator() - template_args = (T, Bases, HolderGenerator) - - class def_1(function_template): - name = "def" - args = (('char const*', 'name'), ('F', 'f')) - -class_template diff --git a/doc/v2/errors.html b/doc/v2/errors.html index e52f29f7..603bd28b 100644 --- a/doc/v2/errors.html +++ b/doc/v2/errors.html @@ -65,7 +65,7 @@

    error_already_set is an exception type which can be thrown to indicate that a Python error has occurred. If thrown, the precondition is that PyErr_Occurred() + "http://www.python.org/doc/2.2/api/exceptionHandling.html#l2h-71">PyErr_Occurred() returns a value convertible to true.

    Class error_already_set synopsis

    @@ -131,7 +131,7 @@ template <class T> T* expect_non_null(T* x);
    Rationale: Simplifies error-handling when calling many functions in the Python/C API, which + "http://www.python.org/doc/2.2/api/api.html">Python/C API, which return 0 on error.
    diff --git a/doc/v2/lvalue_from_python.html b/doc/v2/lvalue_from_python.html index 03af54f8..a0591128 100644 --- a/doc/v2/lvalue_from_python.html +++ b/doc/v2/lvalue_from_python.html @@ -99,7 +99,7 @@ python_type A compile-time constant PyTypeObject* + href="http://www.python.org/doc/2.2/ext/dnt-type-methods.html">PyTypeObject* The Python type of instances convertible by this converter. Python subtypes are also convertible. @@ -213,7 +213,7 @@ Member& execute(Class& c);

    Example

    This example presumes that someone has implemented the standard noddy +href="http://www.python.org/doc/2.2/ext/dnt-basics.html">noddy example module from the Python documentation, and we want to build a module which manipulates Noddys. Since noddy_NoddyObject is so simple that it carries no diff --git a/doc/v2/module.html b/doc/v2/module.html index 0e3516ed..847ff017 100644 --- a/doc/v2/module.html +++ b/doc/v2/module.html @@ -67,11 +67,11 @@

    BOOST_PYTHON_MODULE_INIT(name) is used to declare Python + "http://www.python.org/doc/2.2/ext/methodTable.html#SECTION003400000000000000000"> module initialization functions. The name argument must exactly match the name of the module to be initialized, and must conform to Python's identifier naming + "http://www.python.org/doc/2.2/ref/identifiers.html">identifier naming rules. Where you would normally write

     void initname()
    @@ -150,7 +150,7 @@ module& setattr(const char* name, ref const& r);
         
    Requires: name is a ntbs which conforms to Python's identifier + "http://www.python.org/doc/2.2/ref/identifiers.html">identifier naming rules. In the first two forms, obj is non-null. In the third form, r.get() is non-null. @@ -176,7 +176,7 @@ module& add(class_<T,Bases,HolderGenerator> const& c);
    Effects: The first form adds the Python type object named by x to the Python module under construction, with the name given by the type's tp_name + "http://www.python.org/doc/2.2/ext/dnt-type-methods.html">tp_name field. The second form adds the extension class object being constructed by c to the module, with the same name that was passed to c's constructor. @@ -199,7 +199,7 @@ module& def(char const* name, Fn f, ResultHandler handler);
    Requires: f is a non-null pointer-to-function or pointer-to-member-function. name is a ntbs which conforms to Python's identifier + "http://www.python.org/doc/2.2/ref/identifiers.html">identifier naming rules. In the first form, the return type of f is not a reference and is not a pointer other than char const* or PyObject*. In the From b75d11da3ac1165a607633624963b615abcce54c Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 17 Feb 2002 22:29:43 +0000 Subject: [PATCH 292/369] Bug fix thanks to Min Xu [SVN r12849] --- src/object/class.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/object/class.cpp b/src/object/class.cpp index 6a839fb2..60a803f9 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -205,7 +205,7 @@ namespace std::vector::const_iterator p = boost::detail::lower_bound(start, finish, id); - if (p == finish && p->key != id) + if (p == finish || p->key != id) { string report("extension class wrapper for base class "); (report += id.name()) += " has not been created yet"; From 622ff9d764e8ddbc94af41260f579a1525ed0b62 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 18 Feb 2002 23:00:06 +0000 Subject: [PATCH 293/369] *** empty log message *** [SVN r12855] --- doc/v2/class.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/v2/class.html b/doc/v2/class.html index 393510eb..c28f0317 100644 --- a/doc/v2/class.html +++ b/doc/v2/class.html @@ -210,7 +210,7 @@ class_& def(char const* name, Fn f, CallPolicy policy) the Boost.Python extension class being defined, with the given name. If the extension class already has an attribute named name, the usual overloading procedure applies. + "overloading.html">overloading procedure applies.
    Returns: *this
    From 266923d9e8fbdaa65bdb2e63850a41f37393c5cc Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 20 Feb 2002 05:12:47 +0000 Subject: [PATCH 294/369] Removed useless default arg -- it was confusing MSVC [SVN r12860] --- include/boost/python/class.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index 978a226a..8dede0e3 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -122,7 +122,7 @@ class class_ : private objects::class_base // Define the constructor with the given Args, which should be an // MPL sequence of types. template - self& def_init(Args const& = Args()) + self& def_init(Args const&) { def("__init__", make_constructor()); return *this; From 07abc9fac480b6674702a8317186ee718e9b20c6 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 20 Feb 2002 05:13:24 +0000 Subject: [PATCH 295/369] initial checkin [SVN r12861] --- include/boost/python/lvalue_from_python.hpp | 96 +++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 include/boost/python/lvalue_from_python.hpp diff --git a/include/boost/python/lvalue_from_python.hpp b/include/boost/python/lvalue_from_python.hpp new file mode 100644 index 00000000..c5d09ff5 --- /dev/null +++ b/include/boost/python/lvalue_from_python.hpp @@ -0,0 +1,96 @@ +// Copyright David Abrahams 2002. 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 LVALUE_FROM_PYTHON_DWA2002130_HPP +# define LVALUE_FROM_PYTHON_DWA2002130_HPP + +# include +# include + +namespace boost { namespace python { + +// Utility which produces a member extractor function on platforms +// other than VC6. +template +struct get_member +{ + static Member& execute(Class& c) + { + return c.*mp; + } +}; + +namespace detail +{ + template + struct extract_identity + { + static Class& execute(Class& c) + { + return c; + } + }; +} + +template < + PyTypeObject const* python_type + , class Value + , class PythonObject = Value + , class Extract = detail::extract_identity + > +class lvalue_from_python +{ + typedef type_from_python convertible_t; + public: + + lvalue_from_python() + : m_mutable_converter( + &convertible_t::convertible, convert_mutable) + + , m_const_converter( + &convertible_t::convertible, convert_const) + + , m_mutable_pointer_converter( + &convertible_t::convertible, convert_mutable_pointer) + + , m_const_pointer_converter( + &convertible_t::convertible, convert_const_pointer) + {} + + private: + static Value& convert_mutable(PyObject* op, converter::from_python_data&) + { + return Extract::execute(*(PythonObject*)op); + } + + static Value const& convert_const(PyObject* op, converter::from_python_data&) + { + return Extract::execute(*(PythonObject*)op); + } + + static Value* convert_mutable_pointer(PyObject* op, converter::from_python_data&) + { + return &Extract::execute(*(PythonObject*)op); + } + + static Value const* convert_const_pointer(PyObject* op, converter::from_python_data&) + { + return &Extract::execute(*(PythonObject*)op); + } + + typedef converter::from_python_converter mutable_converter; + typedef converter::from_python_converter const_converter; + typedef converter::from_python_converter mutable_pointer_converter; + typedef converter::from_python_converter const_pointer_converter; + + mutable_converter m_mutable_converter; + const_converter m_const_converter; + mutable_pointer_converter m_mutable_pointer_converter; + const_pointer_converter m_const_pointer_converter; +}; + +}} // namespace boost::python + +#endif // LVALUE_FROM_PYTHON_DWA2002130_HPP From 47c1c6288ccd4a92fbb6f856ddf484640897c094 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 20 Feb 2002 05:14:41 +0000 Subject: [PATCH 296/369] Added error checking [SVN r12862] --- .../python/return_internal_reference.hpp | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/include/boost/python/return_internal_reference.hpp b/include/boost/python/return_internal_reference.hpp index 2f567e55..356bc9ed 100644 --- a/include/boost/python/return_internal_reference.hpp +++ b/include/boost/python/return_internal_reference.hpp @@ -9,14 +9,32 @@ # include # include # include +# include namespace boost { namespace python { +namespace detail +{ + template + struct return_internal_reference_owner_arg_must_be_greater_than_zero +# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__) + {} +# endif + ; +} + template struct return_internal_reference : with_custodian_and_ward_postcall<0, owner_arg, Base> { - typedef reference_existing_object result_converter; + private: + BOOST_STATIC_CONSTANT(bool, legal = owner_arg > 0); + public: + typedef typename mpl::select_type< + legal + , reference_existing_object + , detail::return_internal_reference_owner_arg_must_be_greater_than_zero + >::type result_converter; }; }} // namespace boost::python From 361455678a781b9629c1730ef1b2e490d1c2d93d Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 20 Feb 2002 05:15:14 +0000 Subject: [PATCH 297/369] updated concept names [SVN r12864] --- include/boost/python/return_value_policy.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/python/return_value_policy.hpp b/include/boost/python/return_value_policy.hpp index 0beec47b..6a2036d7 100644 --- a/include/boost/python/return_value_policy.hpp +++ b/include/boost/python/return_value_policy.hpp @@ -9,10 +9,10 @@ namespace boost { namespace python { -template +template struct return_value_policy : Base { - typedef Handler result_converter; + typedef ResultConverterGenerator result_converter; }; }} // namespace boost::python From 7f420361b1efa72126ce74632dea921677ad542e Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 20 Feb 2002 05:15:40 +0000 Subject: [PATCH 298/369] updated template parameter names [SVN r12865] --- include/boost/python/to_python_converter.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/python/to_python_converter.hpp b/include/boost/python/to_python_converter.hpp index 6bea9822..7e46c505 100644 --- a/include/boost/python/to_python_converter.hpp +++ b/include/boost/python/to_python_converter.hpp @@ -12,7 +12,7 @@ namespace boost { namespace python { -template +template struct to_python_converter { to_python_converter(); @@ -22,11 +22,11 @@ struct to_python_converter // implementation // -template -to_python_converter::to_python_converter() +template +to_python_converter::to_python_converter() { typedef converter::as_to_python_value_function< - T, Derived + T, Conversion > normalized; converter::registry::insert( From 43bcbf771e822acffe8244edf96e42e13f06909b Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 20 Feb 2002 05:18:12 +0000 Subject: [PATCH 299/369] added more-rigorous tests [SVN r12866] --- test/m1.cpp | 40 ++++++++++++++++++++++++++++++++++++---- test/newtest.py | 12 ++++++++++++ 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/test/m1.cpp b/test/m1.cpp index b42742ab..723b471d 100644 --- a/test/m1.cpp +++ b/test/m1.cpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include @@ -141,6 +141,26 @@ int f(simple const& s) return strlen(s.s); } +int f_mutable_ref(simple& s) +{ + return strlen(s.s); +} + +int f_mutable_ptr(simple* s) +{ + return strlen(s->s); +} + +int f_const_ptr(simple const* s) +{ + return strlen(s->s); +} + +int f2(SimpleObject const& s) +{ + return strlen(s.x.s); +} + // A trivial passthru function for simple objects simple const& g(simple const& x) { @@ -188,7 +208,7 @@ BOOST_PYTHON_MODULE_INIT(m1) using boost::python::module; using boost::python::class_; using boost::python::converter::from_python_converter; - using boost::python::reference_from_python; + using boost::python::lvalue_from_python; using boost::python::value_from_python; using boost::python::type_from_python; using boost::python::get_member; @@ -205,14 +225,21 @@ BOOST_PYTHON_MODULE_INIT(m1) static from_python_converter c3( &(boost::python::type_from_python<&NoddyType>::convertible), noddy_to_int_ref); - static boost::python::reference_from_python< + static boost::python::lvalue_from_python< &SimpleType , simple , SimpleObject +#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 + , boost::python::get_member +#else , extract_simple_object +#endif > unwrap_simple; + static boost::python::lvalue_from_python<&SimpleType, SimpleObject> + unwrap_simple2; + module m1("m1"); typedef boost::python::objects::pointer_holder_generator< @@ -229,9 +256,14 @@ BOOST_PYTHON_MODULE_INIT(m1) .def("new_noddy", new_noddy) .def("new_simple", new_simple) - // Expose f() + // Expose f() in all its variations .def("f", f) + .def("f_mutable_ref", f_mutable_ref) + .def("f_mutable_ptr", f_mutable_ptr) + .def("f_const_ptr", f_const_ptr) + .def("f2", f2) + // Expose g() .def("g", g , return_value_policy() ) diff --git a/test/newtest.py b/test/newtest.py index 4e6de142..b89764d1 100644 --- a/test/newtest.py +++ b/test/newtest.py @@ -57,6 +57,18 @@ try: wrap_int_ref(n) >>> f(g(s)) 12 +>>> f_mutable_ref(g(s)) +12 + +>>> f_const_ptr(g(s)) +12 + +>>> f_mutable_ptr(g(s)) +12 + +>>> f2(g(s)) +12 + Create an extension class which wraps "complicated" (init1 and get_n) are a complicated constructor and member function, respectively. From d660c12a745d840c6a81221b2da7a562275158f2 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 20 Feb 2002 05:19:39 +0000 Subject: [PATCH 300/369] editorial fix [SVN r12867] --- doc/v2/return_internal_reference.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/v2/return_internal_reference.html b/doc/v2/return_internal_reference.html index 42b8c97e..347db88c 100644 --- a/doc/v2/return_internal_reference.html +++ b/doc/v2/return_internal_reference.html @@ -131,7 +131,7 @@ PyObject* postcall(PyObject* args, PyObject* result);
    Requires: PyTuple_Check(args) != 0 -
    Returns: make_custodian_and_ward_postcall::postcall(args, result) +
    Returns: with_custodian_and_ward_postcall::postcall(args, result)
    From d965b41bddee5db615ff7c10d87baa7d1c05c00c Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 21 Feb 2002 01:24:28 +0000 Subject: [PATCH 301/369] Fix GC problems [SVN r12869] --- src/object/class.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/object/class.cpp b/src/object/class.cpp index 60a803f9..d35a7b5e 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -45,8 +45,8 @@ PyTypeObject class_metatype_object = { 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ + Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC + | Py_TPFLAGS_BASETYPE, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ @@ -119,8 +119,8 @@ PyTypeObject class_type_object = { 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ + Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC + | Py_TPFLAGS_BASETYPE, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ From 6c7d3e1eab3b1b166c8f1ea5ed96373e0a84fb62 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 23 Feb 2002 21:26:55 +0000 Subject: [PATCH 302/369] inital checkin [SVN r12915] --- .../python/converter/pointer_type_id.hpp | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 include/boost/python/converter/pointer_type_id.hpp diff --git a/include/boost/python/converter/pointer_type_id.hpp b/include/boost/python/converter/pointer_type_id.hpp new file mode 100644 index 00000000..79a30b02 --- /dev/null +++ b/include/boost/python/converter/pointer_type_id.hpp @@ -0,0 +1,69 @@ +// Copyright David Abrahams 2002. 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 POINTER_TYPE_ID_DWA2002222_HPP +# define POINTER_TYPE_ID_DWA2002222_HPP + +# include +# include + +namespace boost { namespace python { namespace converter { + +namespace detail +{ + template + struct pointer_typeid_select + { + template + static inline undecorated_type_id_t execute(T*(*)() = 0) + { + return undecorated_type_id(); + } + }; + + template <> + struct pointer_typeid_select + { + template + static inline undecorated_type_id_t execute(T* const volatile&(*)() = 0) + { + return undecorated_type_id(); + } + + template + static inline undecorated_type_id_t execute(T*volatile&(*)() = 0) + { + return undecorated_type_id(); + } + + template + static inline undecorated_type_id_t execute(T*const&(*)() = 0) + { + return undecorated_type_id(); + } + + template + static inline undecorated_type_id_t execute(T*&(*)() = 0) + { + return undecorated_type_id(); + } + }; +} + +// Usage: pointer_type_id() +// +// Returns an undecorated_type_id_t associated with the type pointed +// to by T, which may be a pointer or a reference to a pointer. +template +undecorated_type_id_t pointer_type_id(T(*)() = 0) +{ + return detail::pointer_typeid_select< + is_reference::value + >::execute((T(*)())0); +} + +}}} // namespace boost::python::converter + +#endif // POINTER_TYPE_ID_DWA2002222_HPP From a04cbd111c85a64acf4f4a70d2f1b8589765636b Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 24 Feb 2002 04:47:48 +0000 Subject: [PATCH 303/369] bug fix [SVN r12922] --- include/boost/python/detail/indirect_traits.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/boost/python/detail/indirect_traits.hpp b/include/boost/python/detail/indirect_traits.hpp index 41681719..8c096a2f 100644 --- a/include/boost/python/detail/indirect_traits.hpp +++ b/include/boost/python/detail/indirect_traits.hpp @@ -27,13 +27,13 @@ struct is_reference_to_const template struct is_reference_to_non_const { - BOOST_STATIC_CONSTANT(bool, value = false); -}; - -template -struct is_reference_to_non_const -{ - BOOST_STATIC_CONSTANT(bool, value = true); + BOOST_STATIC_CONSTANT( + bool, value = ( + ::boost::type_traits::ice_and< + ::boost::is_reference::value + , !::boost::python::detail::is_reference_to_const::value + >::value) + ); }; template From e11b457b79093b038ee1edcf0ec6ed021cf6a067 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 24 Feb 2002 05:24:48 +0000 Subject: [PATCH 304/369] Major rearchitecture of from_python mechanism [SVN r12924] --- Jamfile | 34 +- doc/v2/module.html | 2 +- include/boost/python/converter/body.hpp | 62 --- include/boost/python/converter/class.hpp | 75 ---- .../python/converter/find_from_python.hpp | 25 ++ .../boost/python/converter/from_python.hpp | 386 +++++++++++------- .../python/converter/from_python_data.hpp | 89 ++-- .../python/converter/from_python_function.hpp | 9 +- .../converter/from_python_stage1_data.hpp | 21 + .../boost/python/converter/registrations.hpp | 28 ++ include/boost/python/converter/registry.hpp | 19 +- include/boost/python/converter/target.hpp | 191 --------- .../boost/python/converter/unwrapper_base.hpp | 36 -- include/boost/python/detail/destroy.hpp | 83 ++++ include/boost/python/from_python.hpp | 5 +- include/boost/python/lvalue_from_python.hpp | 96 ----- include/boost/python/object/class.hpp | 18 +- .../boost/python/object/class_converters.hpp | 7 +- .../boost/python/object/pointer_holder.hpp | 8 +- include/boost/python/object/value_holder.hpp | 6 +- .../boost/python/reference_from_python.hpp | 62 --- include/boost/python/type_from_python.hpp | 87 +++- include/boost/python/value_from_python.hpp | 73 ---- src/converter/body.cpp | 18 - src/converter/builtin_converters.cpp | 247 +++++------ src/converter/from_python.cpp | 43 +- src/converter/handle.cpp | 35 -- src/converter/registry.cpp | 53 ++- src/converter/unwrap.cpp | 36 -- src/converter/unwrapper.cpp | 31 -- src/converter/wrapper.cpp | 41 -- src/object/class.cpp | 2 +- test/destroy_test.cpp | 81 ++++ test/indirect_traits_test.cpp | 48 +++ test/m1.cpp | 51 +-- test/pointer_type_id_test.cpp | 39 ++ 36 files changed, 929 insertions(+), 1218 deletions(-) delete mode 100644 include/boost/python/converter/body.hpp delete mode 100644 include/boost/python/converter/class.hpp create mode 100644 include/boost/python/converter/find_from_python.hpp create mode 100644 include/boost/python/converter/from_python_stage1_data.hpp create mode 100644 include/boost/python/converter/registrations.hpp delete mode 100644 include/boost/python/converter/target.hpp delete mode 100644 include/boost/python/converter/unwrapper_base.hpp create mode 100644 include/boost/python/detail/destroy.hpp delete mode 100644 include/boost/python/lvalue_from_python.hpp delete mode 100644 include/boost/python/reference_from_python.hpp delete mode 100644 include/boost/python/value_from_python.hpp delete mode 100644 src/converter/body.cpp delete mode 100644 src/converter/handle.cpp delete mode 100644 src/converter/unwrap.cpp delete mode 100644 src/converter/unwrapper.cpp delete mode 100644 src/converter/wrapper.cpp create mode 100644 test/destroy_test.cpp create mode 100644 test/indirect_traits_test.cpp create mode 100644 test/pointer_type_id_test.cpp diff --git a/Jamfile b/Jamfile index aa804505..79dfd9e5 100644 --- a/Jamfile +++ b/Jamfile @@ -4,14 +4,18 @@ subproject libs/python ; SEARCH on python.jam = $(BOOST_BUILD_PATH) ; include python.jam ; -PYTHON_PROPERTIES - += <*>"-inline deferred" - <*>$(BOOST_ROOT)/boost/compatibility/cpp_c_headers - BOOST_PYTHON_DYNAMIC_LIB - BOOST_PYTHON_V2 - ; { + local BOOST_PYTHON_V2_PROPERTIES + = $(PYTHON_PROPERTIES) + <*>"-inline deferred" + <*>$(BOOST_ROOT)/boost/compatibility/cpp_c_headers + BOOST_PYTHON_DYNAMIC_LIB + BOOST_PYTHON_V2 + ; + + local PYTHON_PROPERTIES = $(BOOST_PYTHON_V2_PROPERTIES) ; + dll bpl : src/converter/from_python.cpp @@ -26,7 +30,7 @@ PYTHON_PROPERTIES src/objects.cpp src/converter/builtin_converters.cpp : - $(PYTHON_PROPERTIES) + $(BOOST_PYTHON_V2_PROPERTIES) BOOST_PYTHON_SOURCE ; @@ -67,4 +71,20 @@ PYTHON_PROPERTIES : : debug-python ; + } + +unit-test indirect_traits_test + : test/indirect_traits_test.cpp : $(BOOST_ROOT) ; +unit-test destroy_test + : test/destroy_test.cpp : $(BOOST_ROOT) ; +unit-test pointer_type_id_test + : test/pointer_type_id_test.cpp : $(BOOST_ROOT) ; + +unit-test select_from_python_test + : test/select_from_python_test.cpp + src/converter/type_id.cpp + src/converter/registry.cpp # MWerks needs this for some reason + : $(PYTHON_PROPERTIES) + ; + diff --git a/doc/v2/module.html b/doc/v2/module.html index 847ff017..3775e4d1 100644 --- a/doc/v2/module.html +++ b/doc/v2/module.html @@ -157,7 +157,7 @@ module& setattr(const char* name, ref const& r);
    Effects: Adds the given Python object to the module. If the object is a product of make_function(), the - usual overloading procedure applies. + usual overloading procedure applies. In the first two forms, ownership of a reference to obj is transferred from caller to callee, even if an exception is thrown. diff --git a/include/boost/python/converter/body.hpp b/include/boost/python/converter/body.hpp deleted file mode 100644 index d9170839..00000000 --- a/include/boost/python/converter/body.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// 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 BODY_DWA2001127_HPP -# define BODY_DWA2001127_HPP -# include -# include - -namespace boost { namespace python { namespace converter { - -namespace registry -{ - class entry; -} - -struct BOOST_PYTHON_DECL body -{ - public: - body(type_id_t key); - virtual ~body() {} - - type_id_t key() const; - - protected: - // true iff the registry is still alive - bool can_unregister() const; - - private: - // called when the registry is destroyed, to prevent it from being - // unregistered. - void do_not_unregister(); - friend class registry::entry; - - private: - type_id_t m_key; - bool m_can_unregister; -}; - -// -// implementations -// -inline body::body(type_id_t key) - : m_key(key) - , m_can_unregister(true) -{ -} - -inline type_id_t body::key() const -{ - return m_key; -} - -inline bool body::can_unregister() const -{ - return m_can_unregister; -} - -}}} // namespace boost::python::converter - -#endif // BODY_DWA2001127_HPP diff --git a/include/boost/python/converter/class.hpp b/include/boost/python/converter/class.hpp deleted file mode 100644 index 67de6fad..00000000 --- a/include/boost/python/converter/class.hpp +++ /dev/null @@ -1,75 +0,0 @@ -// 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 CLASS_DWA20011215_HPP -# define CLASS_DWA20011215_HPP - -# include -# include - -namespace boost { namespace python { namespace converter { - -template -struct class_from_python_converter -{ - class_from_python_converter(); - - static void* convertible(PyObject*); - static T& convert_ref(PyObject*, from_python_data&); - static T const& convert_cref(PyObject*, from_python_data&); - static T* convert_ptr(PyObject*, from_python_data&); - static T const* convert_cptr(PyObject*, from_python_data&); - - from_python_converter to_ref; - from_python_converter to_cref; - from_python_converter to_ptr; - from_python_converter to_cptr; -}; - -// -// implementations -// -template -class_from_python_converter::class_from_python_converter() - : to_ref(convertible, convert_ref) - , to_cref(convertible, convert_cref) - , to_ptr(convertible, convert_ptr) - , to_cptr(convertible, convert_cptr) -{} - -template -T& class_from_python_converter::convert_ref(PyObject*, from_python_data& x) -{ - return *static_cast(x.stage1); -} - -template -T const& class_from_python_converter::convert_cref(PyObject*, from_python_data& x) -{ - return *static_cast(x.stage1); -} - - -template -T* class_from_python_converter::convert_ptr(PyObject*, from_python_data& x) -{ - return static_cast(x.stage1); -} - -template -T const* class_from_python_converter::convert_cptr(PyObject*, from_python_data& x) -{ - return static_cast(x.stage1); -} - -template -void* class_from_python_converter::convertible(PyObject* p) -{ - return objects::find_instance(p); -} - -}}} // namespace boost::python::converter - -#endif // CLASS_DWA20011215_HPP diff --git a/include/boost/python/converter/find_from_python.hpp b/include/boost/python/converter/find_from_python.hpp new file mode 100644 index 00000000..863c44a6 --- /dev/null +++ b/include/boost/python/converter/find_from_python.hpp @@ -0,0 +1,25 @@ +// Copyright David Abrahams 2002. 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 FIND_FROM_PYTHON_DWA2002223_HPP +# define FIND_FROM_PYTHON_DWA2002223_HPP + +# include +# include + +namespace boost { namespace python { namespace converter { + +struct lvalue_from_python_registration; +struct rvalue_from_python_registration; +struct rvalue_stage1_data; + +BOOST_PYTHON_DECL void* find( + PyObject* source, lvalue_from_python_registration const*); +BOOST_PYTHON_DECL void* find( + PyObject* source, rvalue_from_python_registration const*, rvalue_stage1_data&); + +}}} // namespace boost::python::converter + +#endif // FIND_FROM_PYTHON_DWA2002223_HPP diff --git a/include/boost/python/converter/from_python.hpp b/include/boost/python/converter/from_python.hpp index b6e1edc4..0881a06a 100644 --- a/include/boost/python/converter/from_python.hpp +++ b/include/boost/python/converter/from_python.hpp @@ -6,193 +6,279 @@ #ifndef FROM_PYTHON_DWA2002127_HPP # define FROM_PYTHON_DWA2002127_HPP -# include -# include -# include -# include -# include -# include +# include # include -# include +# include +# include +# include +# include +# include +# include -namespace boost { namespace python { namespace converter { +namespace boost { namespace python { namespace converter { -// The type of convertibility checking functions -typedef void* (*from_python_check)(PyObject*); -typedef void (*from_python_destructor)(from_python_data&); - -// forward declaration -template struct from_python_lookup; - -// from_python -- -// A body class representing a conversion from python to C++. - -struct BOOST_PYTHON_DECL from_python_converter_base : body +struct from_python_base { - from_python_converter_base(type_id_t, from_python_check); // registers + public: // member functions + from_python_base(void* result); + from_python_base(PyObject*, lvalue_from_python_registration const* chain); + bool convertible() const; + + protected: // member functions + void*const& result() const; + + private: // data members + void* m_result; +}; - // Must return non-null iff the conversion will be successful. Any - // non-null pointer is acceptable, and will be passed on to the - // convert() function, so useful data can be stored there. - inline void* convertible(PyObject*) const; - - // Given the head of a from_python converter chain, find the - // converter which can convert p, leaving its intermediate data in - // data. - inline static from_python_converter_base const* - find(from_python_converter_base const*chain, PyObject* p, void*& data); +// Used when T == U*const& +template +struct pointer_const_reference_from_python +{ + pointer_const_reference_from_python(PyObject*); + T operator()(PyObject*) const; + bool convertible() const; private: - from_python_check m_convertible; - from_python_converter_base* m_next; + detail::referent_storage::type m_result; + + static lvalue_from_python_registration*& chain; }; - +// Used when T == U* template -struct from_python_converter : from_python_converter_base +struct pointer_from_python : from_python_base { - public: // types - typedef typename from_python_function::type conversion_function; + pointer_from_python(PyObject*); + T operator()(PyObject*) const; - public: // member functions - from_python_converter(from_python_check, conversion_function, from_python_destructor = 0); - T convert(PyObject*, from_python_data&) const; - void destroy(from_python_data&) const; - - // Find a converter for converting p to a T. - static from_python_converter const* find(PyObject* p, void*& data); - - private: // data members - conversion_function m_convert; - from_python_destructor m_destroy; - - // Keeps the chain of converters which convert from PyObject* to T - static from_python_converter_base*const& chain; + static lvalue_from_python_registration*& chain; }; -// Initialized to refer to a common place in the registry. +// Used when T == U& and (T != V const& or T == W volatile&) template -from_python_converter_base*const& -from_python_converter::chain = registry::from_python_chain(type_id()); - -// ------------------------------------------------------------------------- - -// A class which implements from_python with a registry lookup. -template -struct from_python_lookup // : from_python_base +struct reference_from_python : from_python_base { - public: // types + reference_from_python(PyObject*); + T operator()(PyObject*) const; - public: // member functions - from_python_lookup(PyObject* source); - ~from_python_lookup(); + static lvalue_from_python_registration*& chain; +}; +// ------- rvalue converters --------- + +// Used for the case where T is a non-pointer, non-reference type OR +// is a const non-volatile reference to a non-pointer type. +template +class rvalue_from_python +{ + typedef typename boost::add_reference< + typename boost::add_const::type + >::type result_type; + + public: + rvalue_from_python(PyObject*); + ~rvalue_from_python(); bool convertible() const; - T operator()(PyObject*); - - public: // functions for use by conversion implementations - // Get the converter object - from_python_converter const* converter() const; - private: // data members - typedef typename from_python_intermediate_data::type intermediate_t; - mutable intermediate_t m_intermediate_data; - from_python_converter const* m_converter; + result_type operator()(PyObject*); + + private: + rvalue_data m_data; + static rvalue_from_python_registration*& chain; +}; + +template +struct select_from_python +{ + BOOST_STATIC_CONSTANT( + bool, ptr = is_pointer::value); + + BOOST_STATIC_CONSTANT( + bool, ptr_cref + = boost::python::detail::is_reference_to_pointer::value + && boost::python::detail::is_reference_to_const::value + && !boost::python::detail::is_reference_to_volatile::value); + + + BOOST_STATIC_CONSTANT( + bool, ref = + boost::python::detail::is_reference_to_non_const::value + || boost::python::detail::is_reference_to_volatile::value); + + typedef typename mpl::select_type< + ptr + , pointer_from_python + , typename mpl::select_type< + ptr_cref + , pointer_const_reference_from_python + , typename mpl::select_type< + ref + , reference_from_python + , rvalue_from_python + >::type + >::type + >::type type; }; // // implementations // -inline void* from_python_converter_base::convertible(PyObject* o) const +inline from_python_base::from_python_base(void* result) + : m_result(result) { - return m_convertible(o); } -inline from_python_converter_base const* -from_python_converter_base::find( - from_python_converter_base const* chain, PyObject* p, void*& data) +inline from_python_base::from_python_base( + PyObject* const source + , lvalue_from_python_registration const* chain) + : m_result(find(source, chain)) { - for (from_python_converter_base const* q = chain; q != 0 ; q = q->m_next) - { - void* d = q->convertible(p); - if (d != 0) - { - data = d; - return q; - } - } - return 0; +} + +inline bool from_python_base::convertible() const +{ + return m_result != 0; +} + +inline void*const& from_python_base::result() const +{ + return m_result; +} + +// -------- + +namespace detail +{ + template + inline U& void_ptr_to_reference(void const volatile* p, U&(*)()) + { + return *(U*)p; + } + + template + struct null_ptr_owner + { + static T value; + }; + template T null_ptr_owner::value = 0; + + template + inline U& null_ptr_reference(U&(*)()) + { + return null_ptr_owner::value; + } + + template + inline void write_void_ptr(void const volatile* storage, void* ptr, T*) + { + *(T**)storage = (T*)ptr; + } + + // writes U(ptr) into the storage + template + inline void write_void_ptr_reference(void const volatile* storage, void* ptr, U&(*)()) + { + write_void_ptr(storage, ptr, U(0)); + } } template -inline from_python_converter::from_python_converter( - from_python_check checker - , conversion_function converter - , from_python_destructor destructor // = 0 - ) - : from_python_converter_base(type_id(), checker) - , m_convert(converter) - , m_destroy(destructor) +inline pointer_const_reference_from_python::pointer_const_reference_from_python(PyObject* p) { + detail::write_void_ptr_reference( + m_result.bytes + , p == Py_None ? p : find(p, chain) + , (T(*)())0); +} + +template +inline bool pointer_const_reference_from_python::convertible() const +{ + return detail::void_ptr_to_reference(m_result.bytes, (T(*)())0) != 0; +} +template +inline T pointer_const_reference_from_python::operator()(PyObject* p) const +{ + return (p == Py_None) + ? detail::null_ptr_reference((T(*)())0) + : detail::void_ptr_to_reference(m_result.bytes, (T(*)())0); +} + +template +lvalue_from_python_registration*& pointer_const_reference_from_python::chain + = registry::lvalue_converters(pointer_type_id()); + +// -------- + +template +inline pointer_from_python::pointer_from_python(PyObject* p) + : from_python_base(p == Py_None ? p : find(p, chain)) +{ +} + +template +inline T pointer_from_python::operator()(PyObject* p) const +{ + return (p == Py_None) ? 0 : T(result()); +} + +template +lvalue_from_python_registration*& pointer_from_python::chain + = registry::lvalue_converters(pointer_type_id()); + +// -------- + +template +inline reference_from_python::reference_from_python(PyObject* p) + : from_python_base(find(p,chain)) +{ +} + +template +inline T reference_from_python::operator()(PyObject*) const +{ + return detail::void_ptr_to_reference(result(), (T(*)())0); +} + +template +lvalue_from_python_registration*& reference_from_python::chain + = registry::lvalue_converters(undecorated_type_id()); + +// ------- + +template +inline rvalue_from_python::rvalue_from_python(PyObject* obj) +{ + find(obj, chain, m_data.stage1); +} + +template +inline rvalue_from_python::~rvalue_from_python() +{ + if (m_data.stage1.convertible == m_data.storage.bytes) + python::detail::destroy_reference(m_data.storage.bytes); +} + +template +inline bool rvalue_from_python::convertible() const +{ + return m_data.stage1.convertible != 0; +} + +template +inline typename rvalue_from_python::result_type +rvalue_from_python::operator()(PyObject* p) +{ + if (m_data.stage1.construct != 0) + m_data.stage1.construct(p, &m_data.stage1); + return detail::void_ptr_to_reference(m_data.stage1.convertible, (result_type(*)())0); } template -inline from_python_converter const* -from_python_converter::find(PyObject* p, void*& data) -{ - return static_cast const*>( - from_python_converter_base::find(chain, p, data)); -} - -template -inline T from_python_converter::convert(PyObject* src, from_python_data& data) const -{ - return this->m_convert(src, data); -} - -template -inline void from_python_converter::destroy(from_python_data& data) const -{ - if (this->m_destroy) - { - this->m_destroy(data); - } -} - -template -inline from_python_lookup::from_python_lookup(PyObject* src) - : m_converter( - from_python_converter::find( - src, m_intermediate_data.stage1)) -{ -} - -template -inline from_python_lookup::~from_python_lookup() -{ - if (m_converter != 0) - m_converter->destroy(m_intermediate_data); -} - -template -inline bool from_python_lookup::convertible() const -{ - return this->m_converter != 0; -} - -template -inline T from_python_lookup::operator()(PyObject* obj) -{ - return this->m_converter->convert(obj, m_intermediate_data); -} - -template -inline from_python_converter const* -from_python_lookup::converter() const -{ - return this->m_converter; -} +rvalue_from_python_registration*& rvalue_from_python::chain + = registry::rvalue_converters(undecorated_type_id()); }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/from_python_data.hpp b/include/boost/python/converter/from_python_data.hpp index 3edcbad7..57a3d76e 100644 --- a/include/boost/python/converter/from_python_data.hpp +++ b/include/boost/python/converter/from_python_data.hpp @@ -9,26 +9,20 @@ # include # include # include -# include +# include +# include +# include +# include // Keep these for the metaprogram which EDG is choking on. # if !defined(__EDG__) || (__EDG_VERSION__ > 245) # include # include -# include # include # endif namespace boost { namespace python { namespace converter { -// A POD which is layout-compatible with the real intermediate data -// for all from_python conversions. There may be additional storage if -// we are converting a reference type. -struct from_python_data -{ - void* stage1; -}; - namespace detail { template struct referent_alignment; @@ -74,8 +68,8 @@ namespace detail template struct referent_size { - static T t; - BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(t)); + static T f(); + BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(f())); }; # endif @@ -130,17 +124,13 @@ namespace detail #endif // EDG is too slow template - struct aligned_storage + union aligned_storage { - typedef Align align_t; - union - { - Align align; - char bytes[size - // this is just a STATIC_ASSERT. For some reason - // MSVC was barfing on the boost one. - - (is_same::value ? size : 0)]; - }; + Align align; + char bytes[size + // this is just a STATIC_ASSERT. For some reason + // MSVC was barfing on the boost one. + - (is_same::value ? size : 0)]; }; template @@ -151,56 +141,39 @@ namespace detail typedef mpl::for_each< align_types , unknown_alignment - , best_alignment_type::value> + , best_alignment_type< + referent_alignment::value + > > loop; + typedef typename loop::state align_t; #else // The Python source makes the assumption that double has // maximal alignment anyway typedef double align_t; -#endif - + +#endif + BOOST_STATIC_CONSTANT(std::size_t, alignment1 = alignment_of::value); + BOOST_STATIC_CONSTANT(std::size_t, alignment2 = referent_alignment::value); + + BOOST_STATIC_ASSERT(alignment1 >= alignment2); + BOOST_STATIC_ASSERT(alignment1 % alignment2 == 0); + typedef aligned_storage::value> type; }; - - template - struct intermediate_data : from_python_data - { - typename referent_storage::type stage2; - }; - - template <> - struct intermediate_data : from_python_data - { - }; - + } -// ------------------------------------------------------------------------- -// Auxiliary POD storage where the convertible and/or convert functions of a -// from_python object may place arbitrary data. -// -// Always starts with a void* -// -// For references, we produce additional aligned storage sufficient to -// store the referent - template -struct from_python_intermediate_data +struct rvalue_data { - typedef typename mpl::select_type< - is_reference::value, T, void>::type just_reference_t; - - typedef detail::intermediate_data type; + rvalue_stage1_data stage1; + + typename detail::referent_storage< + typename add_reference::type + >::type storage; }; -template -void* get_storage(from_python_data& x, boost::type* = 0) -{ - typedef typename from_python_intermediate_data::type layout; - return static_cast(&x)->stage2.bytes; -} - }}} // namespace boost::python::converter #endif // FROM_PYTHON_AUX_DATA_DWA2002128_HPP diff --git a/include/boost/python/converter/from_python_function.hpp b/include/boost/python/converter/from_python_function.hpp index 0cf90459..eea96372 100644 --- a/include/boost/python/converter/from_python_function.hpp +++ b/include/boost/python/converter/from_python_function.hpp @@ -10,13 +10,8 @@ namespace boost { namespace python { namespace converter { -struct from_python_data; - -template -struct from_python_function -{ - typedef T (*type)(PyObject*, from_python_data&); -}; +struct rvalue_stage1_data; +typedef void (*constructor_function)(PyObject* source, rvalue_stage1_data*); }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/from_python_stage1_data.hpp b/include/boost/python/converter/from_python_stage1_data.hpp new file mode 100644 index 00000000..50fd74ad --- /dev/null +++ b/include/boost/python/converter/from_python_stage1_data.hpp @@ -0,0 +1,21 @@ +// Copyright David Abrahams 2002. 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 FROM_PYTHON_STAGE1_DATA_DWA2002223_HPP +# define FROM_PYTHON_STAGE1_DATA_DWA2002223_HPP + +# include + +namespace boost { namespace python { namespace converter { + +struct rvalue_stage1_data +{ + void* convertible; + constructor_function construct; +}; + +}}} // namespace boost::python::converter + +#endif // FROM_PYTHON_STAGE1_DATA_DWA2002223_HPP diff --git a/include/boost/python/converter/registrations.hpp b/include/boost/python/converter/registrations.hpp new file mode 100644 index 00000000..8a27741c --- /dev/null +++ b/include/boost/python/converter/registrations.hpp @@ -0,0 +1,28 @@ +// Copyright David Abrahams 2002. 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 REGISTRATIONS_DWA2002223_HPP +# define REGISTRATIONS_DWA2002223_HPP + +# include + +namespace boost { namespace python { namespace converter { + +struct lvalue_from_python_registration +{ + void* (*convert)(PyObject* source); + lvalue_from_python_registration* next; +}; + +struct rvalue_from_python_registration +{ + void* (*convertible)(PyObject*); + constructor_function construct; + rvalue_from_python_registration* next; +}; + +}}} // namespace boost::python::converter + +#endif // REGISTRATIONS_DWA2002223_HPP diff --git a/include/boost/python/converter/registry.hpp b/include/boost/python/converter/registry.hpp index bdb64254..a511a1a4 100644 --- a/include/boost/python/converter/registry.hpp +++ b/include/boost/python/converter/registry.hpp @@ -9,20 +9,33 @@ # include # include # include +# include namespace boost { namespace python { namespace converter { -struct BOOST_PYTHON_DECL from_python_converter_base; +struct lvalue_from_python_registration; +struct rvalue_from_python_registration; // This namespace acts as a sort of singleton namespace registry { + BOOST_PYTHON_DECL lvalue_from_python_registration*& lvalue_converters(undecorated_type_id_t); + BOOST_PYTHON_DECL rvalue_from_python_registration*& rvalue_converters(undecorated_type_id_t); + BOOST_PYTHON_DECL to_python_value_function const& to_python_function(undecorated_type_id_t); BOOST_PYTHON_DECL void insert(to_python_value_function, undecorated_type_id_t); - - BOOST_PYTHON_DECL from_python_converter_base*& from_python_chain(type_id_t); + + // Insert an lvalue from_python converter + BOOST_PYTHON_DECL void insert(void* (*convert)(PyObject*), undecorated_type_id_t); + + // Insert an rvalue from_python converter + BOOST_PYTHON_DECL void insert( + void* (*convertible)(PyObject*) + , constructor_function + , undecorated_type_id_t + ); BOOST_PYTHON_DECL PyTypeObject*& class_object(undecorated_type_id_t key); } diff --git a/include/boost/python/converter/target.hpp b/include/boost/python/converter/target.hpp deleted file mode 100644 index f8f33171..00000000 --- a/include/boost/python/converter/target.hpp +++ /dev/null @@ -1,191 +0,0 @@ -// 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 TARGET_DWA20011119_HPP -# define TARGET_DWA20011119_HPP -# include -# include -# include -# include -# include - -namespace boost { namespace python { namespace converter { - -// target -- -// -// This type generator (see -// ../../../more/generic_programming.html#type_generator) is used -// to select the return type of the appropriate converter for -// unwrapping a given type. - -// Strategy: -// -// 1. reduce everything to a common, un-cv-qualified reference -// type where possible. This will save on registering many different -// converter types. -// -// 2. Treat built-in types specially: when unwrapping a value or -// constant reference to one of these, use a value for the target -// type. It will bind to a const reference if neccessary, and more -// importantly, avoids having to dynamically allocate room for -// an lvalue of types which can be cheaply copied. -// - -// Target Source -// int int -// int const& int -// int& int& -// int volatile& int volatile& -// int const volatile& int const volatile& - -// On compilers supporting partial specialization: -// -// Target Source -// T T const& -// T& T& -// T const& T const& -// T volatile T& -// T const volatile& T const& -// T* T* -// T const* T const* -// T volatile T* -// T const volatile* T const* -// T cv*const& same as T cv* -// T cv*& T*& <- should this be legal? -// T cv*volatile& T*& <- should this be legal? -// T cv*const volatile& T*& <- should this be legal? - -// On others: -// -// Target Source -// T T& -// T cv& T cv& -// T cv* T cv* -// T cv*cv& T cv*cv& - -// As you can see, in order to handle the same range of types without -// partial specialization, more converters need to be registered. - -template -struct target -{ - // Some pointer types are handled in a more sophisticated way on - // compilers supporting partial specialization. - BOOST_STATIC_CONSTANT(bool, use_identity = (::boost::is_scalar::value)); - - typedef typename mpl::select_type< - use_identity - , T - , typename add_reference< - typename add_const< - typename remove_volatile::type - >::type - >::type - >::type type; -}; - -// When partial specialization is not present, we'll simply need to -// register many more converters. -# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -template -struct target -{ - typedef typename remove_volatile::type& type; -}; - -template -struct target -{ - typedef typename boost::mpl::select_type< - is_scalar::value - , typename remove_cv::type - , typename remove_volatile::type const& - >::type type; -}; - -template -struct target -{ - typedef typename remove_volatile::type* type; -}; - -// Handle T*-cv for completeness. Function arguments in a signature -// are never actually cv-qualified, but who knows how these converters -// might be used, or whether compiler bugs lurk which make it seem -// otherwise? -template -struct target -{ - typedef typename remove_volatile::type* type; -}; - -template -struct target -{ - typedef typename remove_volatile::type* type; -}; - -template -struct target -{ - typedef typename remove_volatile::type* type; -}; - -// non-const references to pointers should be handled by the -// specialization for T&, above. -template -struct target -{ - typedef typename remove_volatile::type* type; -}; -# endif - -// Fortunately, we can handle T const& where T is an arithmetic type -// by explicit specialization. These specializations will cause value -// and const& arguments to be converted to values, rather than to -// references. -# define BOOST_PYTHON_UNWRAP_VALUE(T) \ -template <> \ -struct target \ -{ \ - typedef T type; \ -}; \ -template <> \ -struct target \ -{ \ - typedef T type; \ -}; \ -template <> \ -struct target \ -{ \ - typedef T type; \ -}; \ -template <> \ -struct target \ -{ \ - typedef T type; \ -}; \ -template <> \ -struct target \ -{ \ - typedef T type; \ -} - -BOOST_PYTHON_UNWRAP_VALUE(char); -BOOST_PYTHON_UNWRAP_VALUE(unsigned char); -BOOST_PYTHON_UNWRAP_VALUE(signed char); -BOOST_PYTHON_UNWRAP_VALUE(unsigned int); -BOOST_PYTHON_UNWRAP_VALUE(signed int); -BOOST_PYTHON_UNWRAP_VALUE(unsigned short); -BOOST_PYTHON_UNWRAP_VALUE(signed short); -BOOST_PYTHON_UNWRAP_VALUE(unsigned long); -BOOST_PYTHON_UNWRAP_VALUE(signed long); -BOOST_PYTHON_UNWRAP_VALUE(char const*); - -}}} // namespace boost::python::converter - -#endif // TARGET_DWA20011119_HPP diff --git a/include/boost/python/converter/unwrapper_base.hpp b/include/boost/python/converter/unwrapper_base.hpp deleted file mode 100644 index ea437eb2..00000000 --- a/include/boost/python/converter/unwrapper_base.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// 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 UNWRAPPER_BASE_DWA20011215_HPP -# define UNWRAPPER_BASE_DWA20011215_HPP -# include -# include -# include -# include - -namespace boost { namespace python { namespace converter { - -struct BOOST_PYTHON_DECL unwrapper_base : body -{ - public: - unwrapper_base(type_id_t); // registers - ~unwrapper_base(); // unregisters - - // Must return non-null iff the conversion will be successful. Any - // non-null pointer is acceptable, and will be passed on to the - // convert() function, so useful data can be stored there. - virtual void* can_convert(PyObject*) const = 0; - - protected: - // this is an arbitrary non-null pointer you can use to indicate success - static void* const non_null; - - private: // body required interface implementation - void destroy_handle(handle*) const {} -}; - -}}} // namespace boost::python::converter - -#endif // UNWRAPPER_BASE_DWA20011215_HPP diff --git a/include/boost/python/detail/destroy.hpp b/include/boost/python/detail/destroy.hpp new file mode 100644 index 00000000..07738e2f --- /dev/null +++ b/include/boost/python/detail/destroy.hpp @@ -0,0 +1,83 @@ +// Copyright David Abrahams 2002. 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 DESTROY_DWA2002221_HPP +# define DESTROY_DWA2002221_HPP + +# include +# include + +namespace boost { namespace python { namespace detail { + +template struct value_destroyer; + +template <> +struct value_destroyer +{ + template + static void execute(T const volatile* p) + { + p->T::~T(); + } +}; + +template <> +struct value_destroyer +{ + template + static void execute(A*, T const volatile* const first) + { + for (T const volatile* p = first; p != first + sizeof(A)/sizeof(T); ++p) + value_destroyer< + boost::is_array::value + ,boost::has_trivial_destructor::value + >::execute(p); + } + + template + static void execute(T const volatile* p) + { + execute(p, *p); + } +}; + +template <> +struct value_destroyer +{ + template + static void execute(T const volatile* p) + { + } +}; + +template <> +struct value_destroyer +{ + template + static void execute(T const volatile* p) + { + } +}; + +template +inline void destroy_reference_impl(void* p, T& (*)()) +{ + // note: cv-qualification needed for MSVC6 + // must come *before* T for metrowerks + value_destroyer< + (boost::is_array::value) + , (boost::has_trivial_destructor::value) + >::execute((const volatile T*)p); +} + +template +inline void destroy_reference(void* p, T(*)() = 0) +{ + destroy_reference_impl(p, (T(*)())0); +} + +}}} // namespace boost::python::detail + +#endif // DESTROY_DWA2002221_HPP diff --git a/include/boost/python/from_python.hpp b/include/boost/python/from_python.hpp index 995f7877..62b340f1 100644 --- a/include/boost/python/from_python.hpp +++ b/include/boost/python/from_python.hpp @@ -7,15 +7,14 @@ # define FROM_PYTHON_DWA2002128_HPP # include -# include namespace boost { namespace python { template struct from_python - : converter::from_python_lookup::type> + : converter::select_from_python::type { - typedef converter::from_python_lookup::type> base; + typedef typename converter::select_from_python::type base; from_python(PyObject*); }; diff --git a/include/boost/python/lvalue_from_python.hpp b/include/boost/python/lvalue_from_python.hpp deleted file mode 100644 index c5d09ff5..00000000 --- a/include/boost/python/lvalue_from_python.hpp +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright David Abrahams 2002. 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 LVALUE_FROM_PYTHON_DWA2002130_HPP -# define LVALUE_FROM_PYTHON_DWA2002130_HPP - -# include -# include - -namespace boost { namespace python { - -// Utility which produces a member extractor function on platforms -// other than VC6. -template -struct get_member -{ - static Member& execute(Class& c) - { - return c.*mp; - } -}; - -namespace detail -{ - template - struct extract_identity - { - static Class& execute(Class& c) - { - return c; - } - }; -} - -template < - PyTypeObject const* python_type - , class Value - , class PythonObject = Value - , class Extract = detail::extract_identity - > -class lvalue_from_python -{ - typedef type_from_python convertible_t; - public: - - lvalue_from_python() - : m_mutable_converter( - &convertible_t::convertible, convert_mutable) - - , m_const_converter( - &convertible_t::convertible, convert_const) - - , m_mutable_pointer_converter( - &convertible_t::convertible, convert_mutable_pointer) - - , m_const_pointer_converter( - &convertible_t::convertible, convert_const_pointer) - {} - - private: - static Value& convert_mutable(PyObject* op, converter::from_python_data&) - { - return Extract::execute(*(PythonObject*)op); - } - - static Value const& convert_const(PyObject* op, converter::from_python_data&) - { - return Extract::execute(*(PythonObject*)op); - } - - static Value* convert_mutable_pointer(PyObject* op, converter::from_python_data&) - { - return &Extract::execute(*(PythonObject*)op); - } - - static Value const* convert_const_pointer(PyObject* op, converter::from_python_data&) - { - return &Extract::execute(*(PythonObject*)op); - } - - typedef converter::from_python_converter mutable_converter; - typedef converter::from_python_converter const_converter; - typedef converter::from_python_converter mutable_pointer_converter; - typedef converter::from_python_converter const_pointer_converter; - - mutable_converter m_mutable_converter; - const_converter m_const_converter; - mutable_pointer_converter m_mutable_pointer_converter; - const_pointer_converter m_const_pointer_converter; -}; - -}} // namespace boost::python - -#endif // LVALUE_FROM_PYTHON_DWA2002130_HPP diff --git a/include/boost/python/object/class.hpp b/include/boost/python/object/class.hpp index 35280074..04f0e992 100644 --- a/include/boost/python/object/class.hpp +++ b/include/boost/python/object/class.hpp @@ -53,7 +53,7 @@ struct BOOST_PYTHON_DECL instance_holder : private noncopyable // return the next holder in a chain instance_holder* next() const; - virtual void* holds(converter::type_id_t) = 0; + virtual void* holds(converter::undecorated_type_id_t) = 0; void install(PyObject* inst) throw(); @@ -85,15 +85,19 @@ struct instance instance_holder* objects; }; -// Given a type_id, find the instance data which corresponds to it, or -// return 0 in case no such type is held. -BOOST_PYTHON_DECL void* find_instance_impl(PyObject*, converter::type_id_t); +// Given an undecorated type_id, find the instance data which +// corresponds to it, or return 0 in case no such type is held. +BOOST_PYTHON_DECL void* find_instance_impl(PyObject*, converter::undecorated_type_id_t); +// This produces a function with the right signature for use in from_python conversions template -T* find_instance(PyObject* p, T* = 0) +struct instance_finder { - return static_cast(find_instance_impl(p, converter::type_id())); -} + static inline void* execute(PyObject* p) + { + return find_instance_impl(p, converter::undecorated_type_id()); + } +}; BOOST_PYTHON_DECL ref class_metatype(); BOOST_PYTHON_DECL ref class_type(); diff --git a/include/boost/python/object/class_converters.hpp b/include/boost/python/object/class_converters.hpp index d5978af7..540565bf 100644 --- a/include/boost/python/object/class_converters.hpp +++ b/include/boost/python/object/class_converters.hpp @@ -6,10 +6,10 @@ #ifndef CLASS_CONVERTERS_DWA2002119_HPP # define CLASS_CONVERTERS_DWA2002119_HPP -# include # include # include # include +# include namespace boost { namespace python { namespace objects { @@ -24,7 +24,6 @@ struct class_converters class_converters(ref const& python_class); private: // data members - converter::class_from_python_converter m_unwrapper; class_wrapper m_wrapper; }; @@ -90,6 +89,10 @@ template class_converters::class_converters(ref const& type_object) : m_wrapper(type_object) { + converter::registry::insert( + &instance_finder::execute + , converter::undecorated_type_id()); + // register all up/downcasts here register_dynamic_id(); diff --git a/include/boost/python/object/pointer_holder.hpp b/include/boost/python/object/pointer_holder.hpp index 21fe8e96..c307f019 100644 --- a/include/boost/python/object/pointer_holder.hpp +++ b/include/boost/python/object/pointer_holder.hpp @@ -139,7 +139,7 @@ struct pointer_holder : instance_holder {} private: // required holder implementation - void* holds(converter::type_id_t); + void* holds(converter::undecorated_type_id_t); private: // data members Pointer m_p; @@ -186,12 +186,12 @@ pointer_holder::pointer_holder(Pointer p) } template -void* pointer_holder::holds(converter::type_id_t dst_t) +void* pointer_holder::holds(converter::undecorated_type_id_t dst_t) { - if (dst_t == converter::type_id()) + if (dst_t == converter::undecorated_type_id()) return &this->m_p; - converter::type_id_t src_t = converter::type_id(); + converter::type_id_t src_t = converter::undecorated_type_id(); return src_t == dst_t ? &*this->m_p : find_dynamic_type(&*this->m_p, src_t, dst_t); } diff --git a/include/boost/python/object/value_holder.hpp b/include/boost/python/object/value_holder.hpp index 01431370..6533bc39 100644 --- a/include/boost/python/object/value_holder.hpp +++ b/include/boost/python/object/value_holder.hpp @@ -134,7 +134,7 @@ struct value_holder : instance_holder {} private: // required holder implementation - void* holds(converter::type_id_t); + void* holds(converter::undecorated_type_id_t); private: // data members Held m_held; @@ -151,9 +151,9 @@ struct value_holder_generator }; template -void* value_holder::holds(converter::type_id_t dst_t) +void* value_holder::holds(converter::undecorated_type_id_t dst_t) { - converter::type_id_t src_t = converter::type_id(); + converter::undecorated_type_id_t src_t = converter::undecorated_type_id(); return src_t == dst_t ? &m_held : find_static_type(&m_held, src_t, dst_t); } diff --git a/include/boost/python/reference_from_python.hpp b/include/boost/python/reference_from_python.hpp deleted file mode 100644 index a9631dc5..00000000 --- a/include/boost/python/reference_from_python.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright David Abrahams 2002. 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 REFERENCE_FROM_PYTHON_DWA2002130_HPP -# define REFERENCE_FROM_PYTHON_DWA2002130_HPP - -# include -# include - -namespace boost { namespace python { - -// Utility which produces a member extractor function on platforms -// other than VC6. -template -struct get_member -{ - static Member& execute(Class* c) - { - return c->*mp; - } -}; - -template < - PyTypeObject const* python_type - , class Value - , class PythonObject - , class Extract - > -struct reference_from_python -{ - typedef type_from_python convertible_t; - - reference_from_python() - : m_mutable_converter( - &convertible_t::convertible, convert_mutable) - - , m_const_converter( - &convertible_t::convertible, convert_const) - {} - - static Value& convert_mutable(PyObject* op, converter::from_python_data&) - { - return Extract::execute(*(PythonObject*)op); - } - - static Value const& convert_const(PyObject* op, converter::from_python_data&) - { - return Extract::execute(*(PythonObject*)op); - } - - private: - typedef converter::from_python_converter mutable_converter; - typedef converter::from_python_converter const_converter; - mutable_converter m_mutable_converter; - const_converter m_const_converter; -}; - -}} // namespace boost::python - -#endif // REFERENCE_FROM_PYTHON_DWA2002130_HPP diff --git a/include/boost/python/type_from_python.hpp b/include/boost/python/type_from_python.hpp index 46d59d13..16b8da81 100644 --- a/include/boost/python/type_from_python.hpp +++ b/include/boost/python/type_from_python.hpp @@ -6,15 +6,94 @@ #ifndef TYPE_FROM_PYTHON_DWA2002130_HPP # define TYPE_FROM_PYTHON_DWA2002130_HPP +# include + namespace boost { namespace python { -template +namespace detail +{ + // Given a pointer-to-function of 1 parameter returning a reference + // type, return the type_id of the function's return type. + template + inline converter::undecorated_type_id_t extractor_type_id(T&(*)(U)) + { + return converter::undecorated_type_id(); + } + + // A function generator whose static execute() function is an lvalue + // from_python converter using the given Extractor. U is exepcted to + // be the actual type of the PyObject instance from which the result + // is being extracted. + template + struct normalized_extractor + { + static inline void* execute(PyObject* op) + { + typedef typename boost::add_reference::type param; + return &Extractor::execute( + boost::python::converter::detail::void_ptr_to_reference( + op, (param(*)())0 ) + ); + } + }; + + // Given an Extractor type and a pointer to its execute function, + // return a new object whose static execute function does the same + // job but is a conforming lvalue from_python conversion function. + // + // usage: normalize(&Extractor::execute) + template + inline normalized_extractor + normalize(T(*)(U), Extractor* = 0) + { + return normalized_extractor(); + } +} + +// An Extractor which extracts the given member from a Python object +// whose instances are stored as InstanceType. +template +struct member_extractor +{ + static MemberType& execute(InstanceType& c) + { + (void)c.ob_type; // static assertion + return c.*member; + } +}; + +// An Extractor which simply extracts the entire python object +// instance of InstanceType. +template +struct identity_extractor +{ + static InstanceType& execute(InstanceType& c) + { + (void)c.ob_type; // static assertion + return c; + } +}; + +// Registers a from_python conversion which extracts lvalues using +// Extractor's static execute function from Python objects whose type +// object is python_type. +template struct type_from_python { - static void* convertible(PyObject* op) + type_from_python() { - return PyObject_TypeCheck( - op, const_cast(python_type)) ? op : 0; + converter::registry::insert( + &extract, detail::extractor_type_id(&Extractor::execute)); + } + + static void* extract(PyObject* op) + { + return PyObject_TypeCheck(op, const_cast(python_type)) + ? const_cast( + static_cast( + detail::normalize(&Extractor::execute).execute(op))) + : 0 + ; } }; diff --git a/include/boost/python/value_from_python.hpp b/include/boost/python/value_from_python.hpp deleted file mode 100644 index c835de45..00000000 --- a/include/boost/python/value_from_python.hpp +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright David Abrahams 2002. 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 VALUE_FROM_PYTHON_DWA2002130_HPP -# define VALUE_FROM_PYTHON_DWA2002130_HPP - -# include -# include -# include -# include - -namespace boost { namespace python { - -template -struct value_from_python -{ - typedef value_from_python self; - typedef converter::from_python_check from_python_check; - - value_from_python(from_python_check convertible) - : m_converter( - convertible - , &Derived::convert - - // Change this to a compile-time check later to avoid - // generating destroy function - , has_trivial_destructor::value ? 0 : &Derived::destroy - ) - { - } - - value_from_python() - : m_converter( - &Derived::convertible - , &Derived::convert - - // Change this to a compile-time check later to avoid - // generating destroy function - , has_trivial_destructor::value ? 0 : &Derived::destroy - ) - { - } - - static void* get_storage(converter::from_python_data& data) - { - return converter::get_storage(data); - } - - // Mark successful construction - static void constructed(converter::from_python_data& data) - { - data.stage1 = self::get_storage(data); - } - - inline static void destroy(converter::from_python_data& data) - { - // Get the location of the storage for - void* storage = self::get_storage(data); - - // Check for successful construction - if (data.stage1 == storage) - static_cast(storage)->~T(); - } - - private: - converter::from_python_converter m_converter; -}; - -}} // namespace boost::python - -#endif // VALUE_FROM_PYTHON_DWA2002130_HPP diff --git a/src/converter/body.cpp b/src/converter/body.cpp deleted file mode 100644 index 637f8c3e..00000000 --- a/src/converter/body.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// 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. -#include - -namespace boost { namespace python { namespace converter { - -// default implementation is a no-op. Most handles will not hold any -// data that needs to be managed. Unwrap objects which convert -// by-value are an exception. Fortunately, the concrete body subclass -// has that knowledge. -void body::destroy_handle(handle*) const -{ -} - -}}} // namespace boost::python::converter diff --git a/src/converter/builtin_converters.cpp b/src/converter/builtin_converters.cpp index 9cf5f110..8db20586 100644 --- a/src/converter/builtin_converters.cpp +++ b/src/converter/builtin_converters.cpp @@ -7,177 +7,120 @@ #include #include #include -#include -#include #include +#include #include #include -//#include #include namespace boost { namespace python { namespace converter { namespace { - // Only an object which we know is holding a char const* can be - // converted to one - struct convertible_to_cstring + // An lvalue conversion function which extracts a char const* from a + // Python String. + void* convert_to_cstring(PyObject* obj) { - static unaryfunc* execute(PyObject* obj) - { - return PyString_Check(obj) ? &obj->ob_type->tp_str : 0; - } - }; + return PyString_Check(obj) ? PyString_AsString(obj) : 0; + } - struct extract_cstring + // Given a target type and a SlotPolicy describing how to perform a + // given conversion, registers from_python converters which use the + // SlotPolicy to extract the type. + template + struct slot_rvalue_from_python { - static char const* execute(PyObject* obj) - { - return PyString_AsString(obj); - } - }; - - // Any object which can be converted to a Python string can also be - // converted to a C++ string, since the latter owns its bytes. - struct convertible_to_string - { - static unaryfunc* execute(PyObject* obj) - { - return obj->ob_type->tp_str ? &obj->ob_type->tp_str : 0; - } - }; - - // Transform a function returning a unaryfunc* into one that returns a void* - template - struct return_void_ptr - { - static void* execute(PyObject* p) { return F::execute(p); } - }; - - template < - class T // The target type - , class Convertible // returns a pointer to a unaryfunc producing an object - , class TExtract // ...from which TExtract extracts T's constructor argument - > - struct tp_scalar_from_python - : from_python_converter - { - private: - typedef return_void_ptr convertible_fn; - public: - tp_scalar_from_python() - : from_python_converter( - &convertible_fn::execute - , convert) - {} - - static T convert(PyObject* obj, from_python_data& data) + slot_rvalue_from_python() { - unaryfunc converter = *(unaryfunc*)data.stage1; - ref converted(converter(obj)); - return TExtract::execute(converted.get()); + registry::insert( + &slot_rvalue_from_python::convertible + , &slot_rvalue_from_python::construct + , undecorated_type_id() + ); } - }; - - // Extract a reference to T using the functions in the source - // object's type slots - template < - class T // The target type - , class Convertible // returns a pointer to a unaryfunc producing an object - , class TExtract // ...from which TExtract extracts T's constructor argument - > - struct tp_cref_from_python - : value_from_python > - { + private: - typedef tp_cref_from_python self; - typedef value_from_python > base; - - public: - tp_cref_from_python() - : base(&return_void_ptr::execute) - {} - - static T const& convert(PyObject* obj, from_python_data& data) + static void* convertible(PyObject* obj) { - unaryfunc converter = *(unaryfunc*)data.stage1; - - void* storage = self::get_storage(data); - - ref converted(converter(obj)); - - T* const p = new (storage) T(TExtract::execute(converted.get())); - - // note that construction is successful. - data.stage1 = p; - - return *p; + unaryfunc* slot = SlotPolicy::get_slot(obj); + return slot && *slot ? slot : 0; + } + + static void construct(PyObject* obj, rvalue_stage1_data* data) + { + // Get the (intermediate) source object + unaryfunc creator = *static_cast(data->convertible); + ref intermediate(creator(obj)); + + // Get the location in which to construct + void* storage = ((rvalue_data*)data)->storage.bytes; + new (storage) T(SlotPolicy::extract(intermediate.get())); + + // record successful construction + data->convertible = storage; } }; - struct convertible_to_int + // A SlotPolicy for extracting integer types from Python objects + struct int_rvalue_from_python { - static unaryfunc* execute(PyObject* obj) + static unaryfunc* get_slot(PyObject* obj) { PyNumberMethods* number_methods = obj->ob_type->tp_as_number; if (number_methods == 0) return 0; // For floating types, return the float conversion slot to avoid - // creating a new object. We'll handle that in - // py_int_or_float_as_long, below + // creating a new object. We'll handle that below if (PyObject_TypeCheck(obj, &PyFloat_Type) && number_methods->nb_float) return &number_methods->nb_float; - return number_methods && number_methods->nb_int - ? &number_methods->nb_int : 0; + return &number_methods->nb_int; } - }; - - struct py_int_or_float_as_long - { - static long execute(PyObject* obj) + + static long extract(PyObject* intermediate) { - if (PyObject_TypeCheck(obj, &PyFloat_Type)) + if (PyObject_TypeCheck(intermediate, &PyFloat_Type)) { - return numeric_cast(PyFloat_AS_DOUBLE(obj)); + return numeric_cast(PyFloat_AS_DOUBLE(intermediate)); } else { - return PyInt_AS_LONG(obj); + return PyInt_AS_LONG(intermediate); } } }; + + // identity_unaryfunc/non_null -- manufacture a unaryfunc "slot" + // which just returns its argument. Used for bool conversions, since + // all Python objects are directly convertible to bool extern "C" PyObject* identity_unaryfunc(PyObject* x) { Py_INCREF(x); return x; } - unaryfunc non_null = identity_unaryfunc; - - struct convertible_to_bool + + // A SlotPolicy for extracting bool from a Python object + struct bool_rvalue_from_python { - static unaryfunc* execute(PyObject* obj) + static unaryfunc* get_slot(PyObject*) { return &non_null; } - }; - - struct py_object_as_bool - { - static bool execute(PyObject* obj) + + static bool extract(PyObject* intermediate) { - return PyObject_IsTrue(obj); + return PyObject_IsTrue(intermediate); } }; - - struct convertible_to_double + // A SlotPolicy for extracting floating types from Python objects. + struct float_rvalue_from_python { - static unaryfunc* execute(PyObject* obj) + static unaryfunc* get_slot(PyObject* obj) { PyNumberMethods* number_methods = obj->ob_type->tp_as_number; if (number_methods == 0) @@ -189,67 +132,63 @@ namespace if (PyObject_TypeCheck(obj, &PyInt_Type) && number_methods->nb_int) return &number_methods->nb_int; - return number_methods && number_methods->nb_float - ? &number_methods->nb_float : 0; + return &number_methods->nb_float; } - }; - - struct py_float_or_int_as_double - { - static double execute(PyObject* obj) + + static double extract(PyObject* intermediate) { - if (PyObject_TypeCheck(obj, &PyInt_Type)) + if (PyObject_TypeCheck(intermediate, &PyInt_Type)) { - return PyInt_AS_LONG(obj); + return PyInt_AS_LONG(intermediate); } else { - return PyFloat_AS_DOUBLE(obj); + return PyFloat_AS_DOUBLE(intermediate); } } }; - template - struct scalar_from_python + // A SlotPolicy for extracting C++ strings from Python objects. + struct string_rvalue_from_python { - tp_cref_from_python cref_converter; - tp_scalar_from_python value_converter; - }; - - template - void register_int_converters(T* = 0) - { - static scalar_from_python x; - } -} + // If the underlying object is "string-able" this will succeed + static unaryfunc* get_slot(PyObject* obj) + { + return &obj->ob_type->tp_str; + }; -#define REGISTER_INT_CONVERTERS(U) register_int_converters() + // Remember that this will be used to construct the result object + static char const* extract(PyObject* intermediate) + { + return PyString_AsString(intermediate); + } + }; +} + +#define REGISTER_INT_CONVERTERS(U) slot_rvalue_from_python() #define REGISTER_INT_CONVERTERS2(U) REGISTER_INT_CONVERTERS(signed U); REGISTER_INT_CONVERTERS(unsigned U) void initialize_builtin_converters() { - static scalar_from_python< - bool, convertible_to_bool, py_object_as_bool> bool_from_python; - + // booleans + slot_rvalue_from_python(); + + // integer types REGISTER_INT_CONVERTERS2(char); REGISTER_INT_CONVERTERS2(short); REGISTER_INT_CONVERTERS2(int); REGISTER_INT_CONVERTERS2(long); - static scalar_from_python< - float,convertible_to_double,py_float_or_int_as_double> float_from_python; + // floating types + slot_rvalue_from_python(); + slot_rvalue_from_python(); + slot_rvalue_from_python(); - static scalar_from_python< - double,convertible_to_double,py_float_or_int_as_double> double_from_python; - - static scalar_from_python< - long double,convertible_to_double,py_float_or_int_as_double> long_double_from_python; - - static scalar_from_python< - char const*, convertible_to_cstring, extract_cstring> cstring_from_python; + // Add an lvalue converter for char which gets us char const* + registry::insert(convert_to_cstring,undecorated_type_id()); - static tp_cref_from_python< - std::string, convertible_to_string, extract_cstring> string_from_python; + // Register by-value converters to std::string + slot_rvalue_from_python(); } }}} // namespace boost::python::converter diff --git a/src/converter/from_python.cpp b/src/converter/from_python.cpp index 2e844acf..0650fcbb 100644 --- a/src/converter/from_python.cpp +++ b/src/converter/from_python.cpp @@ -4,23 +4,40 @@ // "as is" without express or implied warranty, and with no claim as // to its suitability for any purpose. -#include -#include +#include +#include +#include namespace boost { namespace python { namespace converter { -from_python_converter_base::from_python_converter_base( - type_id_t type - , from_python_check checker - ) - : body(type) - , m_convertible(checker) - +BOOST_PYTHON_DECL void* find( + PyObject* source + , rvalue_from_python_registration const* chain + , rvalue_stage1_data& data) { - // Insert this in the converter chain. - from_python_converter_base*& head = registry::from_python_chain(type); - m_next = head; - head = this; + for (;chain != 0; chain = chain->next) + { + void* r = chain->convertible(source); + if (r != 0) + { + data.construct = chain->construct; + return data.convertible = r; + } + } + return data.convertible = 0; +} + +BOOST_PYTHON_DECL void* find( + PyObject* const source + , lvalue_from_python_registration const* chain) +{ + for (;chain != 0; chain = chain->next) + { + void* r = chain->convert(source); + if (r != 0) + return r; + } + return 0; } }}} // namespace boost::python::converter diff --git a/src/converter/handle.cpp b/src/converter/handle.cpp deleted file mode 100644 index 1a2b8c31..00000000 --- a/src/converter/handle.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// 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. -#include -#include - -namespace boost { namespace python { namespace converter { - -bool handle::convertible() const -{ - for (handle const* p = this; p != 0; p = p->m_next) - { - if (p->m_body == 0) - return false; - } - return true; -} - -void handle::destroy() -{ - // Recurse down the chain releasing from tail to head - if (m_next != 0) - m_next->destroy(); - - // Our body knows how to destroy us. If we never got a body, - // there's nothing to do. - if (m_body) - m_body->destroy_handle(this); -} - -// void handle::dummy::nonnull() {} - -}}} // namespace boost::python::converter diff --git a/src/converter/registry.cpp b/src/converter/registry.cpp index c90d709d..bdfa1c8a 100644 --- a/src/converter/registry.cpp +++ b/src/converter/registry.cpp @@ -4,6 +4,7 @@ // "as is" without express or implied warranty, and with no claim as // to its suitability for any purpose. #include +#include #include #include #include @@ -19,20 +20,23 @@ namespace // // The unique to_python converter for the associated C++ type. to_python_value_function m_to_python_converter; - + // The collection of from_python converters for the associated // C++ type. - from_python_converter_base* m_from_python_converters; + lvalue_from_python_registration* m_lvalue_from_python; + rvalue_from_python_registration* m_rvalue_from_python; // The class object associated with this type PyTypeObject* m_class_object; }; - typedef std::map registry_t; + typedef std::map registry_t; registry_t& entries() { static registry_t registry; + +#ifdef BOOST_PYTHON_DYNAMIC_LIB // this conditional should go away eventually. static bool builtin_converters_initialized = false; if (!builtin_converters_initialized) { @@ -42,17 +46,19 @@ namespace // initialize_builtin_converters(); } +#endif return registry; } - entry* find(type_id_t type) + entry* find(undecorated_type_id_t type) { return &entries()[type]; } entry::entry() : m_to_python_converter(0) - , m_from_python_converters(0) + , m_lvalue_from_python(0) + , m_rvalue_from_python(0) , m_class_object(0) { } @@ -78,15 +84,46 @@ namespace registry slot = f; } - from_python_converter_base*& from_python_chain(type_id_t key) + // Insert an lvalue from_python converter + void insert(void* (*convert)(PyObject*), undecorated_type_id_t key) { - return find(key)->m_from_python_converters; + entry* found = find(key); + lvalue_from_python_registration *registration = new lvalue_from_python_registration; + registration->convert = convert; + registration->next = found->m_lvalue_from_python; + found->m_lvalue_from_python = registration; + + insert(convert, 0, key); } - + + // Insert an rvalue from_python converter + void insert(void* (*convertible)(PyObject*) + , constructor_function construct + , undecorated_type_id_t key) + { + entry* found = find(key); + rvalue_from_python_registration *registration = new rvalue_from_python_registration; + registration->convertible = convertible; + registration->construct = construct; + registration->next = found->m_rvalue_from_python; + found->m_rvalue_from_python = registration; + } + PyTypeObject*& class_object(undecorated_type_id_t key) { return find(key)->m_class_object; } + + lvalue_from_python_registration*& lvalue_converters(undecorated_type_id_t key) + { + return find(key)->m_lvalue_from_python; + } + + rvalue_from_python_registration*& rvalue_converters(undecorated_type_id_t key) + { + return find(key)->m_rvalue_from_python; + } + } // namespace registry }}} // namespace boost::python::converter diff --git a/src/converter/unwrap.cpp b/src/converter/unwrap.cpp deleted file mode 100644 index 6a72ab77..00000000 --- a/src/converter/unwrap.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// 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. - -#include - -namespace boost { namespace python { namespace converter { - -namespace -{ - struct pyobject_unwrapper : unwrapper_base - { - pyobject_unwrapper(); - void* can_convert(PyObject*) const; - }; - - pyobject_unwrapper static_unwrapper; - std::pair unwrapper_pair(&static_unwrapper,&static_unwrapper); - - pyobject_unwrapper::pyobject_unwrapper() - : unwrapper_base(type_id()) - { - } - - void* pyobject_unwrapper::can_convert(PyObject*) const - { - return non_null; - } -} - -BOOST_PYTHON_DECL std::pair& -unwrap_more_::m_unwrapper = unwrapper_pair; - -}}} // namespace boost::python::converter diff --git a/src/converter/unwrapper.cpp b/src/converter/unwrapper.cpp deleted file mode 100644 index 6279febf..00000000 --- a/src/converter/unwrapper.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// 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. -#include -#include -#include - -namespace boost { namespace python { namespace converter { - -unwrapper_base::unwrapper_base(type_id_t key) - : body(key) -{ - registry::insert(*this); -} - -unwrapper_base::~unwrapper_base() -{ - if (can_unregister()) - registry::remove(*this); -} - -namespace -{ - int arbitrary; -} - -void* const unwrapper_base::non_null = &arbitrary; - -}}} // namespace boost::python::converter diff --git a/src/converter/wrapper.cpp b/src/converter/wrapper.cpp deleted file mode 100644 index 567ff99d..00000000 --- a/src/converter/wrapper.cpp +++ /dev/null @@ -1,41 +0,0 @@ -// 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. - -#include -#include - -namespace boost { namespace python { namespace converter { - -wrapper_base::wrapper_base(type_id_t type) - : body(type) -{ - registry::insert(*this); -} - -wrapper_base::~wrapper_base() -{ - if (can_unregister()) - registry::remove(*this); -} - -namespace -{ - // This doesn't actually get called, but we need something to fill - // in the slot in the wrap class. - struct identity_wrapper_t : wrapper - { - PyObject* convert(PyObject* source) const - { - return source; - } - }; - - identity_wrapper_t identity_wrapper_object; -} - -BOOST_PYTHON_DECL body& identity_wrapper = identity_wrapper_object; - -}}} // namespace boost::python::converter diff --git a/src/object/class.cpp b/src/object/class.cpp index d35a7b5e..8186f9be 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -163,7 +163,7 @@ void instance_holder::install(PyObject* self) throw() } BOOST_PYTHON_DECL void* -find_instance_impl(PyObject* inst, converter::type_id_t type) +find_instance_impl(PyObject* inst, converter::undecorated_type_id_t type) { if (inst->ob_type->ob_type != &class_metatype_object) return 0; diff --git a/test/destroy_test.cpp b/test/destroy_test.cpp new file mode 100644 index 00000000..c6be42fc --- /dev/null +++ b/test/destroy_test.cpp @@ -0,0 +1,81 @@ +#include +#include + +struct bar; + +namespace boost +{ + // lie to the library about bar so we can show that it's destructor is optimized away. + template <> + struct has_trivial_destructor + { + BOOST_STATIC_CONSTANT(bool, value=true); + }; +} + + +int count; +int marks[] = { + -1 + , -1, -1 + , -1, -1, -1, -1 + , -1 +}; +int* kills = marks; + +struct foo +{ + foo() : n(count++) {} + ~foo() + { + *kills++ = n; + } + int n; +}; + +struct bar : foo {}; + +void assert_destructions(int n) +{ + for (int i = 0; i < n; ++i) + assert(marks[i] == i); + assert(marks[n] == -1); +} + +int main() +{ + assert_destructions(0); + typedef int a[2]; + + foo* f1 = new foo; + boost::python::detail::destroy_reference(f1); + assert_destructions(1); + + foo* f2 = new foo[2]; + typedef foo x[2]; + + boost::python::detail::destroy_reference(f2); + assert_destructions(3); + + typedef foo y[2][2]; + x* f3 = new y; + boost::python::detail::destroy_reference(f3); + assert_destructions(7); + + bar* b1 = new bar; + boost::python::detail::destroy_reference(b1); + assert_destructions(7); + + bar* b2 = new bar[2]; + typedef bar xb[2]; + + boost::python::detail::destroy_reference(b2); + assert_destructions(7); + + typedef bar yb[2][2]; + xb* b3 = new yb; + boost::python::detail::destroy_reference(b3); + assert_destructions(7); + + return 0; +} diff --git a/test/indirect_traits_test.cpp b/test/indirect_traits_test.cpp new file mode 100644 index 00000000..a15e7f85 --- /dev/null +++ b/test/indirect_traits_test.cpp @@ -0,0 +1,48 @@ +//#include +#include +#include + +//#define print(expr) printf("%s ==> %s\n", #expr, expr) + +int main() +{ +using namespace boost::python::detail; + + assert(is_reference_to_pointer::value); + assert(is_reference_to_pointer::value); + assert(is_reference_to_pointer::value); + assert(is_reference_to_pointer::value); + + assert(!is_reference_to_pointer::value); + assert(!is_reference_to_pointer::value); + assert(!is_reference_to_pointer::value); + + assert(!is_reference_to_const::value); + assert(is_reference_to_const::value); + assert(!is_reference_to_const::value); + assert(is_reference_to_const::value); + + assert(!is_reference_to_const::value); + assert(!is_reference_to_const::value); + assert(!is_reference_to_const::value); + + assert(is_reference_to_non_const::value); + assert(!is_reference_to_non_const::value); + assert(is_reference_to_non_const::value); + assert(!is_reference_to_non_const::value); + + assert(!is_reference_to_non_const::value); + assert(!is_reference_to_non_const::value); + assert(!is_reference_to_non_const::value); + + assert(!is_reference_to_volatile::value); + assert(!is_reference_to_volatile::value); + assert(is_reference_to_volatile::value); + assert(is_reference_to_volatile::value); + + assert(!is_reference_to_volatile::value); + assert(!is_reference_to_volatile::value); + assert(!is_reference_to_volatile::value); + + return 0; +} diff --git a/test/m1.cpp b/test/m1.cpp index 723b471d..439d58e2 100644 --- a/test/m1.cpp +++ b/test/m1.cpp @@ -9,15 +9,13 @@ #include "complicated.hpp" #include #include +#include #include #include #include #include #include -#include -#include #include -#include #include #include #include @@ -105,7 +103,6 @@ PyObject* new_simple() // description of how the type parameters to wrapper<> and unwrapper<> // are selected. // -using boost::python::converter::from_python_data; using boost::python::to_python_converter; // Wrap a simple by copying it into a Simple @@ -120,16 +117,13 @@ struct simple_to_python } }; -int noddy_to_int(PyObject* p, from_python_data&) +struct int_from_noddy_extractor { - return static_cast(p)->x; -} - -// Extract a mutable reference to an int from a Noddy. -int& noddy_to_int_ref(PyObject* p, from_python_data&) -{ - return static_cast(p)->x; -} + static int& execute(NoddyObject& p) + { + return p.x; + } +}; // // Some C++ functions to expose to Python @@ -205,40 +199,23 @@ D take_d(D const& d) { return d; } BOOST_PYTHON_MODULE_INIT(m1) { - using boost::python::module; - using boost::python::class_; - using boost::python::converter::from_python_converter; - using boost::python::lvalue_from_python; - using boost::python::value_from_python; - using boost::python::type_from_python; - using boost::python::get_member; - using boost::python::copy_const_reference; - using boost::python::return_value_policy; + using namespace boost::python; using boost::mpl::type_list; - // Create the converters; they are self-registering/unregistering. - static simple_to_python c1; + simple_to_python(); - static from_python_converter c2( - &(boost::python::type_from_python<&NoddyType>::convertible), noddy_to_int); - - static from_python_converter c3( - &(boost::python::type_from_python<&NoddyType>::convertible), noddy_to_int_ref); + type_from_python<&NoddyType,int_from_noddy_extractor>(); - static boost::python::lvalue_from_python< + boost::python::type_from_python< &SimpleType - , simple - , SimpleObject #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 - , boost::python::get_member + , member_extractor #else , extract_simple_object #endif - > - unwrap_simple; + >(); - static boost::python::lvalue_from_python<&SimpleType, SimpleObject> - unwrap_simple2; + type_from_python<&SimpleType, identity_extractor >(); module m1("m1"); diff --git a/test/pointer_type_id_test.cpp b/test/pointer_type_id_test.cpp new file mode 100644 index 00000000..24035709 --- /dev/null +++ b/test/pointer_type_id_test.cpp @@ -0,0 +1,39 @@ +#include +#include +#include + +int main() +{ + using namespace boost::python::converter; + + undecorated_type_id_t x + = undecorated_type_id(); + + + assert(pointer_type_id() == x); + assert(pointer_type_id() == x); + assert(pointer_type_id() == x); + assert(pointer_type_id() == x); + + assert(pointer_type_id() == x); + assert(pointer_type_id() == x); + assert(pointer_type_id() == x); + assert(pointer_type_id() == x); + + assert(pointer_type_id() == x); + assert(pointer_type_id() == x); + assert(pointer_type_id() == x); + assert(pointer_type_id() == x); + + assert(pointer_type_id() == x); + assert(pointer_type_id() == x); + assert(pointer_type_id() == x); + assert(pointer_type_id() == x); + + assert(pointer_type_id() == x); + assert(pointer_type_id() == x); + assert(pointer_type_id() == x); + assert(pointer_type_id() == x); + + return 0; +} From 389968468698765dcfb1c9a20a98e3ea78150d98 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 24 Feb 2002 05:28:48 +0000 Subject: [PATCH 305/369] inital checkin [SVN r12925] --- test/select_from_python_test.cpp | 148 +++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 test/select_from_python_test.cpp diff --git a/test/select_from_python_test.cpp b/test/select_from_python_test.cpp new file mode 100644 index 00000000..7063767e --- /dev/null +++ b/test/select_from_python_test.cpp @@ -0,0 +1,148 @@ +#include +//#include +//#include +#include +#include + +int result; + +#define ASSERT_SAME(T1,T2) \ + if (!is_same< T1, T2 >::value) { \ + std::cout << "*********************\n"; \ + std::cout << type_id< T1 >() << " != " << type_id< T2 >() << "\n"; \ + std::cout << "*********************\n"; \ + result = 1; \ + } + +int main() +{ + using namespace boost::python::converter; + using namespace boost; + + + ASSERT_SAME( + select_from_python::type, rvalue_from_python + ); + + ASSERT_SAME( + select_from_python::type, rvalue_from_python + ); + + ASSERT_SAME( + select_from_python::type, rvalue_from_python + ); + + ASSERT_SAME( + select_from_python::type, rvalue_from_python + ); + + + + ASSERT_SAME( + select_from_python::type, pointer_from_python + ); + + ASSERT_SAME( + select_from_python::type, pointer_from_python + ); + + ASSERT_SAME( + select_from_python::type, pointer_from_python + ); + + ASSERT_SAME( + select_from_python::type, pointer_from_python + ); + + + + + ASSERT_SAME( + select_from_python::type, reference_from_python + ); + + ASSERT_SAME( + select_from_python::type, rvalue_from_python + ); + + ASSERT_SAME( + select_from_python::type, reference_from_python + ); + + ASSERT_SAME( + select_from_python::type, reference_from_python + ); + + + + ASSERT_SAME( + select_from_python::type, reference_from_python + ); + + ASSERT_SAME( + select_from_python::type, reference_from_python + ); + + ASSERT_SAME( + select_from_python::type, reference_from_python + ); + + ASSERT_SAME( + select_from_python::type, reference_from_python + ); + + + + ASSERT_SAME( + select_from_python::type, pointer_const_reference_from_python + ); + + ASSERT_SAME( + select_from_python::type, pointer_const_reference_from_python + ); + + ASSERT_SAME( + select_from_python::type, pointer_const_reference_from_python + ); + + ASSERT_SAME( + select_from_python::type, pointer_const_reference_from_python + ); + + + + ASSERT_SAME( + select_from_python::type, reference_from_python + ); + + ASSERT_SAME( + select_from_python::type, reference_from_python + ); + + ASSERT_SAME( + select_from_python::type, reference_from_python + ); + + ASSERT_SAME( + select_from_python::type, reference_from_python + ); + + + + ASSERT_SAME( + select_from_python::type, reference_from_python + ); + + ASSERT_SAME( + select_from_python::type, reference_from_python + ); + + ASSERT_SAME( + select_from_python::type, reference_from_python + ); + + ASSERT_SAME( + select_from_python::type, reference_from_python + ); + return result; +} From e0147657977f5693a3af72f031ac84b4a3144d39 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 24 Feb 2002 20:18:46 +0000 Subject: [PATCH 306/369] More use of ice_xxx for old EDG compilers [SVN r12929] --- include/boost/python/detail/indirect_traits.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/boost/python/detail/indirect_traits.hpp b/include/boost/python/detail/indirect_traits.hpp index 8c096a2f..f925eaee 100644 --- a/include/boost/python/detail/indirect_traits.hpp +++ b/include/boost/python/detail/indirect_traits.hpp @@ -31,7 +31,8 @@ struct is_reference_to_non_const bool, value = ( ::boost::type_traits::ice_and< ::boost::is_reference::value - , !::boost::python::detail::is_reference_to_const::value + , ::boost::type_traits::ice_not< + ::boost::python::detail::is_reference_to_const::value>::value >::value) ); }; From f6381e7e5e6809062d209b960efe266ed2bd0af5 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 25 Feb 2002 21:20:05 +0000 Subject: [PATCH 307/369] Added complex support, and support for user-defined conversions of classic instances [SVN r12938] --- .../python/converter/builtin_converters.hpp | 4 + src/converter/builtin_converters.cpp | 97 ++++++++++++++++--- test/test_builtin_converters.cpp | 8 +- test/test_builtin_converters.py | 36 +++++++ 4 files changed, 132 insertions(+), 13 deletions(-) diff --git a/include/boost/python/converter/builtin_converters.hpp b/include/boost/python/converter/builtin_converters.hpp index 8293b0a7..7ae7a357 100644 --- a/include/boost/python/converter/builtin_converters.hpp +++ b/include/boost/python/converter/builtin_converters.hpp @@ -8,6 +8,7 @@ # include # include # include +# include namespace boost { namespace python { @@ -58,6 +59,9 @@ BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, PyFloat_FromDouble(x)) BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, PyFloat_FromDouble(x)) BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, PyFloat_FromDouble(x)) BOOST_PYTHON_TO_PYTHON_BY_VALUE(PyObject*, x ? x : detail::none()) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, PyComplex_FromDoubles(x.real(), x.imag())) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, PyComplex_FromDoubles(x.real(), x.imag())) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, PyComplex_FromDoubles(x.real(), x.imag())) namespace converter { diff --git a/src/converter/builtin_converters.cpp b/src/converter/builtin_converters.cpp index 8db20586..2e9bcbec 100644 --- a/src/converter/builtin_converters.cpp +++ b/src/converter/builtin_converters.cpp @@ -10,8 +10,10 @@ #include #include #include +#include #include #include +#include namespace boost { namespace python { namespace converter { @@ -73,15 +75,18 @@ namespace // For floating types, return the float conversion slot to avoid // creating a new object. We'll handle that below - if (PyObject_TypeCheck(obj, &PyFloat_Type) && number_methods->nb_float) + if (PyFloat_Check(obj)) return &number_methods->nb_float; - + + if (PyInstance_Check(obj) && !PyObject_HasAttrString(obj, "__int__")) + return 0; + return &number_methods->nb_int; } static long extract(PyObject* intermediate) { - if (PyObject_TypeCheck(intermediate, &PyFloat_Type)) + if (PyFloat_Check(intermediate)) { return numeric_cast(PyFloat_AS_DOUBLE(intermediate)); } @@ -93,22 +98,23 @@ namespace }; - // identity_unaryfunc/non_null -- manufacture a unaryfunc "slot" - // which just returns its argument. Used for bool conversions, since - // all Python objects are directly convertible to bool + // identity_unaryfunc/py_object_identity -- manufacture a unaryfunc + // "slot" which just returns its argument. Used for bool + // conversions, since all Python objects are directly convertible to + // bool extern "C" PyObject* identity_unaryfunc(PyObject* x) { Py_INCREF(x); return x; } - unaryfunc non_null = identity_unaryfunc; + unaryfunc py_object_identity = identity_unaryfunc; // A SlotPolicy for extracting bool from a Python object struct bool_rvalue_from_python { static unaryfunc* get_slot(PyObject*) { - return &non_null; + return &py_object_identity; } static bool extract(PyObject* intermediate) @@ -127,17 +133,19 @@ namespace return 0; // For integer types, return the tp_int conversion slot to avoid - // creating a new object. We'll handle that in - // py_float_or_int_as_double, below - if (PyObject_TypeCheck(obj, &PyInt_Type) && number_methods->nb_int) + // creating a new object. We'll handle that below + if (PyInt_Check(obj)) return &number_methods->nb_int; + if (PyInstance_Check(obj) && !PyObject_HasAttrString(obj, "__float__")) + return 0; + return &number_methods->nb_float; } static double extract(PyObject* intermediate) { - if (PyObject_TypeCheck(intermediate, &PyInt_Type)) + if (PyInt_Check(intermediate)) { return PyInt_AS_LONG(intermediate); } @@ -154,6 +162,9 @@ namespace // If the underlying object is "string-able" this will succeed static unaryfunc* get_slot(PyObject* obj) { + if (PyInstance_Check(obj) && !PyObject_HasAttrString(obj, "__str__")) + return 0; + return &obj->ob_type->tp_str; }; @@ -163,6 +174,64 @@ namespace return PyString_AsString(intermediate); } }; + + + // identity_unaryfunc/non_null -- manufacture a unaryfunc "slot" + // which just returns its argument. Used for bool conversions, since + // all Python objects are directly convertible to bool + extern "C" PyObject* to_complex_unaryfunc(PyObject* x) + { + return PyObject_CallMethod(x, "__complex__", const_cast("()")); + } + unaryfunc py_object_to_complex = to_complex_unaryfunc; + + struct complex_rvalue_from_python + { + static unaryfunc* get_slot(PyObject* obj) + { + + if (PyComplex_Check(obj)) + return &py_object_identity; + + PyNumberMethods* number_methods = obj->ob_type->tp_as_number; + + // For integer types, return the tp_int conversion slot to avoid + // creating a new object. We'll handle that below + if (PyInt_Check(obj) && number_methods) + return &number_methods->nb_int; + + if (PyFloat_Check(obj) && number_methods) + return &number_methods->nb_float; + + if (!PyObject_HasAttrString((PyObject*)obj, "__complex__")) + return 0; + + return &py_object_to_complex; + } + + static std::complex extract(PyObject* intermediate) + { + if (PyComplex_Check(intermediate)) + { + return std::complex( + PyComplex_RealAsDouble(intermediate) + , PyComplex_ImagAsDouble(intermediate)); + } + else if (PyInt_Check(intermediate)) + { + return PyInt_AS_LONG(intermediate); + } + else if (PyFloat_Check(intermediate)) + { + return PyFloat_AS_DOUBLE(intermediate); + } + else + { + PyErr_SetString(PyExc_TypeError, "__complex__ method did not return a Complex object"); + throw error_already_set(); + } + } + }; } #define REGISTER_INT_CONVERTERS(U) slot_rvalue_from_python() @@ -184,6 +253,10 @@ void initialize_builtin_converters() slot_rvalue_from_python(); slot_rvalue_from_python(); + slot_rvalue_from_python,complex_rvalue_from_python>(); + slot_rvalue_from_python,complex_rvalue_from_python>(); + slot_rvalue_from_python,complex_rvalue_from_python>(); + // Add an lvalue converter for char which gets us char const* registry::insert(convert_to_cstring,undecorated_type_id()); diff --git a/test/test_builtin_converters.cpp b/test/test_builtin_converters.cpp index f95ebe2b..4c07d9f4 100644 --- a/test/test_builtin_converters.cpp +++ b/test/test_builtin_converters.cpp @@ -5,7 +5,7 @@ // to its suitability for any purpose. #include #include - +#include template struct by_value @@ -41,6 +41,9 @@ BOOST_PYTHON_MODULE_INIT(builtin_converters_ext) .def("rewrap_value_float", by_value::rewrap) .def("rewrap_value_double", by_value::rewrap) .def("rewrap_value_long_double", by_value::rewrap) + .def("rewrap_value_complex_float", by_value >::rewrap) + .def("rewrap_value_complex_double", by_value >::rewrap) + .def("rewrap_value_complex_long_double", by_value >::rewrap) .def("rewrap_value_string", by_value::rewrap) .def("rewrap_value_cstring", by_value::rewrap) @@ -57,6 +60,9 @@ BOOST_PYTHON_MODULE_INIT(builtin_converters_ext) .def("rewrap_const_reference_float", by_const_reference::rewrap) .def("rewrap_const_reference_double", by_const_reference::rewrap) .def("rewrap_const_reference_long_double", by_const_reference::rewrap) + .def("rewrap_const_reference_complex_float", by_const_reference >::rewrap) + .def("rewrap_const_reference_complex_double", by_const_reference >::rewrap) + .def("rewrap_const_reference_complex_long_double", by_const_reference >::rewrap) .def("rewrap_const_reference_string", by_const_reference::rewrap) .def("rewrap_const_reference_cstring", by_const_reference::rewrap) diff --git a/test/test_builtin_converters.py b/test/test_builtin_converters.py index 50b58ce6..3a4722c7 100644 --- a/test/test_builtin_converters.py +++ b/test/test_builtin_converters.py @@ -30,6 +30,13 @@ >>> rewrap_value_long_double(4.2) - 4.2 0.0 +>>> abs(rewrap_value_complex_float(4+.2j) - (4+.2j)) < .000001 +1 +>>> abs(rewrap_value_complex_double(4+.2j) - (4+.2j)) < .000001 +1 +>>> abs(rewrap_value_complex_long_double(4+.2j) - (4+.2j)) < .000001 +1 + >>> rewrap_value_cstring('hello, world') 'hello, world' >>> rewrap_value_string('yo, wassup?') @@ -57,6 +64,7 @@ 42 >>> rewrap_const_reference_unsigned_long(42) 42 + >>> abs(rewrap_const_reference_float(4.2) - 4.2) < .000001 1 >>> rewrap_const_reference_double(4.2) - 4.2 @@ -64,6 +72,13 @@ >>> rewrap_const_reference_long_double(4.2) - 4.2 0.0 +>>> abs(rewrap_const_reference_complex_float(4+.2j) - (4+.2j)) < .000001 +1 +>>> abs(rewrap_const_reference_complex_double(4+.2j) - (4+.2j)) < .000001 +1 +>>> abs(rewrap_const_reference_complex_long_double(4+.2j) - (4+.2j)) < .000001 +1 + >>> rewrap_const_reference_cstring('hello, world') 'hello, world' >>> rewrap_const_reference_string('yo, wassup?') @@ -83,6 +98,27 @@ Now check implicit conversions between floating/integer types >>> rewrap_value_int(42.0) 42 +Check that classic classes also work + +>>> class FortyTwo: +... def __int__(self): +... return 42 +... def __float__(self): +... return 42.0 +... def __complex__(self): +... return complex(4+.2j) +... def __str__(self): +... return '42' + +>>> rewrap_const_reference_float(FortyTwo()) +42.0 +>>> rewrap_value_int(FortyTwo()) +42 +>>> rewrap_const_reference_string(FortyTwo()) +'42' +>>> abs(rewrap_value_complex_double(FortyTwo()) - (4+.2j)) < .000001 +1 + """ def run(args = None): import sys From a16ff296389a88375cc908186aa679eb13fc403f Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 27 Feb 2002 17:29:01 +0000 Subject: [PATCH 308/369] Fixed generation [SVN r12957] --- include/boost/python/detail/returning.hpp | 1339 ++++++++++++--------- src/gen_returning.py | 60 +- 2 files changed, 777 insertions(+), 622 deletions(-) diff --git a/include/boost/python/detail/returning.hpp b/include/boost/python/detail/returning.hpp index 599e5d37..d7e98cd8 100644 --- a/include/boost/python/detail/returning.hpp +++ b/include/boost/python/detail/returning.hpp @@ -1,5 +1,5 @@ -// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears +// (C) Copyright David Abrahams 2001,2002. 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. // @@ -23,10 +23,10 @@ template struct returning { template - static PyObject* call(R (A0::*pmf)(), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; // find the result converter @@ -34,20 +34,20 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + ) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)() ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } template - static PyObject* call(R (A0::*pmf)(A1), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; // find the result converter @@ -55,22 +55,22 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1))) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))) ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } template - static PyObject* call(R (A0::*pmf)(A1, A2), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; // find the result converter @@ -78,24 +78,25 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2))) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))) ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; // find the result converter @@ -103,26 +104,28 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3))) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))) ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; - from_python c4(PyTuple_GET_ITEM(args, 4)); + from_python c4(PyTuple_GET_ITEM(args_, 4)); if (!c4.convertible()) return 0; // find the result converter @@ -130,28 +133,31 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3)) + , c4(PyTuple_GET_ITEM(args_, 4))) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))) ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; - from_python c4(PyTuple_GET_ITEM(args, 4)); + from_python c4(PyTuple_GET_ITEM(args_, 4)); if (!c4.convertible()) return 0; - from_python c5(PyTuple_GET_ITEM(args, 5)); + from_python c5(PyTuple_GET_ITEM(args_, 5)); if (!c5.convertible()) return 0; // find the result converter @@ -159,19 +165,23 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3)) + , c4(PyTuple_GET_ITEM(args_, 4)) + , c5(PyTuple_GET_ITEM(args_, 5))) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))) ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } template - static PyObject* call(R (A0::*pmf)() const, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)() const, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; // find the result converter @@ -179,20 +189,20 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + ) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)() ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } template - static PyObject* call(R (A0::*pmf)(A1) const, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1) const, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; // find the result converter @@ -200,22 +210,22 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1))) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))) ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } template - static PyObject* call(R (A0::*pmf)(A1, A2) const, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2) const, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; // find the result converter @@ -223,24 +233,25 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2))) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))) ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3) const, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3) const, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; // find the result converter @@ -248,26 +259,28 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3))) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))) ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; - from_python c4(PyTuple_GET_ITEM(args, 4)); + from_python c4(PyTuple_GET_ITEM(args_, 4)); if (!c4.convertible()) return 0; // find the result converter @@ -275,28 +288,31 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3)) + , c4(PyTuple_GET_ITEM(args_, 4))) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))) ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; - from_python c4(PyTuple_GET_ITEM(args, 4)); + from_python c4(PyTuple_GET_ITEM(args_, 4)); if (!c4.convertible()) return 0; - from_python c5(PyTuple_GET_ITEM(args, 5)); + from_python c5(PyTuple_GET_ITEM(args_, 5)); if (!c5.convertible()) return 0; // find the result converter @@ -304,19 +320,23 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3)) + , c4(PyTuple_GET_ITEM(args_, 4)) + , c5(PyTuple_GET_ITEM(args_, 5))) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))) ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } template - static PyObject* call(R (A0::*pmf)() volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)() volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; // find the result converter @@ -324,20 +344,20 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + ) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)() ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } template - static PyObject* call(R (A0::*pmf)(A1) volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1) volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; // find the result converter @@ -345,22 +365,22 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1))) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))) ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } template - static PyObject* call(R (A0::*pmf)(A1, A2) volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2) volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; // find the result converter @@ -368,24 +388,25 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2))) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))) ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3) volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3) volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; // find the result converter @@ -393,26 +414,28 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3))) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))) ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; - from_python c4(PyTuple_GET_ITEM(args, 4)); + from_python c4(PyTuple_GET_ITEM(args_, 4)); if (!c4.convertible()) return 0; // find the result converter @@ -420,28 +443,31 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3)) + , c4(PyTuple_GET_ITEM(args_, 4))) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))) ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; - from_python c4(PyTuple_GET_ITEM(args, 4)); + from_python c4(PyTuple_GET_ITEM(args_, 4)); if (!c4.convertible()) return 0; - from_python c5(PyTuple_GET_ITEM(args, 5)); + from_python c5(PyTuple_GET_ITEM(args_, 5)); if (!c5.convertible()) return 0; // find the result converter @@ -449,22 +475,26 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3)) + , c4(PyTuple_GET_ITEM(args_, 4)) + , c5(PyTuple_GET_ITEM(args_, 5))) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))) ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } // missing const volatile type traits # ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template - static PyObject* call(R (A0::*pmf)() const volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)() const volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; // find the result converter @@ -472,20 +502,20 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + ) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)() ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } template - static PyObject* call(R (A0::*pmf)(A1) const volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1) const volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; // find the result converter @@ -493,22 +523,22 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1))) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))) ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } template - static PyObject* call(R (A0::*pmf)(A1, A2) const volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2) const volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; // find the result converter @@ -516,24 +546,25 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2))) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))) ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3) const volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3) const volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; // find the result converter @@ -541,26 +572,28 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3))) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))) ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; - from_python c4(PyTuple_GET_ITEM(args, 4)); + from_python c4(PyTuple_GET_ITEM(args_, 4)); if (!c4.convertible()) return 0; // find the result converter @@ -568,28 +601,31 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3)) + , c4(PyTuple_GET_ITEM(args_, 4))) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))) ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; - from_python c4(PyTuple_GET_ITEM(args, 4)); + from_python c4(PyTuple_GET_ITEM(args_, 4)); if (!c4.convertible()) return 0; - from_python c5(PyTuple_GET_ITEM(args, 5)); + from_python c5(PyTuple_GET_ITEM(args_, 5)); if (!c5.convertible()) return 0; // find the result converter @@ -597,176 +633,193 @@ struct returning typename eval::type cr; if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3)) + , c4(PyTuple_GET_ITEM(args_, 4)) + , c5(PyTuple_GET_ITEM(args_, 5))) ); - PyObject* result = cr( ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))) ); - - if (!result) return 0; - return policies.postcall(args, result); + return policies.postcall(args_, result); } # endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - - + template - static PyObject* call(R (*pf)(), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (*pf)(), PyObject* args_, PyObject*, P const& policies) { // find the result converter typedef typename P::result_converter result_converter; - typename eval::type c0; - if (!c0.convertible()) return 0; + typename eval::type cr; + if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; - PyObject* result = c0( (*pf)() ); - - if (!result) return 0; - return policies.postcall(args, result); + PyObject* result = cr( (*pf)( + ) ); + + return policies.postcall(args_, result); } - template - static PyObject* call(R (*pf)(A0), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (*pf)(A0), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; // find the result converter typedef typename P::result_converter result_converter; - typename eval::type c1; - if (!c1.convertible()) return 0; + typename eval::type cr; + if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; - PyObject* result = c1( (*pf)(c0(PyTuple_GET_ITEM(args, 0))) ); - - if (!result) return 0; - return policies.postcall(args, result); + PyObject* result = cr( (*pf)( + c0(PyTuple_GET_ITEM(args_, 0))) ); + + return policies.postcall(args_, result); } template - static PyObject* call(R (*pf)(A0, A1), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (*pf)(A0, A1), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; // find the result converter typedef typename P::result_converter result_converter; - typename eval::type c2; - if (!c2.convertible()) return 0; + typename eval::type cr; + if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; - PyObject* result = c2( (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1))) ); - - if (!result) return 0; - return policies.postcall(args, result); + PyObject* result = cr( (*pf)( + c0(PyTuple_GET_ITEM(args_, 0)) + , c1(PyTuple_GET_ITEM(args_, 1))) ); + + return policies.postcall(args_, result); } template - static PyObject* call(R (*pf)(A0, A1, A2), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (*pf)(A0, A1, A2), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; // find the result converter typedef typename P::result_converter result_converter; - typename eval::type c3; - if (!c3.convertible()) return 0; + typename eval::type cr; + if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; - PyObject* result = c3( (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))) ); - - if (!result) return 0; - return policies.postcall(args, result); + PyObject* result = cr( (*pf)( + c0(PyTuple_GET_ITEM(args_, 0)) + , c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2))) ); + + return policies.postcall(args_, result); } template - static PyObject* call(R (*pf)(A0, A1, A2, A3), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (*pf)(A0, A1, A2, A3), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; // find the result converter typedef typename P::result_converter result_converter; - typename eval::type c4; - if (!c4.convertible()) return 0; + typename eval::type cr; + if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; - PyObject* result = c4( (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))) ); - - if (!result) return 0; - return policies.postcall(args, result); + PyObject* result = cr( (*pf)( + c0(PyTuple_GET_ITEM(args_, 0)) + , c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3))) ); + + return policies.postcall(args_, result); } template - static PyObject* call(R (*pf)(A0, A1, A2, A3, A4), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (*pf)(A0, A1, A2, A3, A4), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; - from_python c4(PyTuple_GET_ITEM(args, 4)); + from_python c4(PyTuple_GET_ITEM(args_, 4)); if (!c4.convertible()) return 0; // find the result converter typedef typename P::result_converter result_converter; - typename eval::type c5; - if (!c5.convertible()) return 0; + typename eval::type cr; + if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; - PyObject* result = c5( (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))) ); - - if (!result) return 0; - return policies.postcall(args, result); + PyObject* result = cr( (*pf)( + c0(PyTuple_GET_ITEM(args_, 0)) + , c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3)) + , c4(PyTuple_GET_ITEM(args_, 4))) ); + + return policies.postcall(args_, result); } template - static PyObject* call(R (*pf)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (*pf)(A0, A1, A2, A3, A4, A5), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; - from_python c4(PyTuple_GET_ITEM(args, 4)); + from_python c4(PyTuple_GET_ITEM(args_, 4)); if (!c4.convertible()) return 0; - from_python c5(PyTuple_GET_ITEM(args, 5)); + from_python c5(PyTuple_GET_ITEM(args_, 5)); if (!c5.convertible()) return 0; // find the result converter typedef typename P::result_converter result_converter; - typename eval::type c6; - if (!c6.convertible()) return 0; + typename eval::type cr; + if (!cr.convertible()) return 0; - if (!policies.precall(args)) return 0; + if (!policies.precall(args_)) return 0; - PyObject* result = c6( (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))) ); - - if (!result) return 0; - return policies.postcall(args, result); + PyObject* result = cr( (*pf)( + c0(PyTuple_GET_ITEM(args_, 0)) + , c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3)) + , c4(PyTuple_GET_ITEM(args_, 4)) + , c5(PyTuple_GET_ITEM(args_, 5))) ); + + return policies.postcall(args_, result); } }; @@ -775,560 +828,646 @@ struct returning { typedef void R; template - static PyObject* call(R (A0::*pmf)(), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + ); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (A0::*pmf)(A1), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1))); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (A0::*pmf)(A1, A2), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2))); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3))); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; - from_python c4(PyTuple_GET_ITEM(args, 4)); + from_python c4(PyTuple_GET_ITEM(args_, 4)); if (!c4.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3)) + , c4(PyTuple_GET_ITEM(args_, 4))); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; - from_python c4(PyTuple_GET_ITEM(args, 4)); + from_python c4(PyTuple_GET_ITEM(args_, 4)); if (!c4.convertible()) return 0; - from_python c5(PyTuple_GET_ITEM(args, 5)); + from_python c5(PyTuple_GET_ITEM(args_, 5)); if (!c5.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3)) + , c4(PyTuple_GET_ITEM(args_, 4)) + , c5(PyTuple_GET_ITEM(args_, 5))); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (A0::*pmf)() const, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)() const, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + ); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (A0::*pmf)(A1) const, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1) const, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1))); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (A0::*pmf)(A1, A2) const, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2) const, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2))); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3) const, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3) const, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3))); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; - from_python c4(PyTuple_GET_ITEM(args, 4)); + from_python c4(PyTuple_GET_ITEM(args_, 4)); if (!c4.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3)) + , c4(PyTuple_GET_ITEM(args_, 4))); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; - from_python c4(PyTuple_GET_ITEM(args, 4)); + from_python c4(PyTuple_GET_ITEM(args_, 4)); if (!c4.convertible()) return 0; - from_python c5(PyTuple_GET_ITEM(args, 5)); + from_python c5(PyTuple_GET_ITEM(args_, 5)); if (!c5.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3)) + , c4(PyTuple_GET_ITEM(args_, 4)) + , c5(PyTuple_GET_ITEM(args_, 5))); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (A0::*pmf)() volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)() volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + ); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (A0::*pmf)(A1) volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1) volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1))); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (A0::*pmf)(A1, A2) volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2) volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2))); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3) volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3) volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3))); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; - from_python c4(PyTuple_GET_ITEM(args, 4)); + from_python c4(PyTuple_GET_ITEM(args_, 4)); if (!c4.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3)) + , c4(PyTuple_GET_ITEM(args_, 4))); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; - from_python c4(PyTuple_GET_ITEM(args, 4)); + from_python c4(PyTuple_GET_ITEM(args_, 4)); if (!c4.convertible()) return 0; - from_python c5(PyTuple_GET_ITEM(args, 5)); + from_python c5(PyTuple_GET_ITEM(args_, 5)); if (!c5.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3)) + , c4(PyTuple_GET_ITEM(args_, 4)) + , c5(PyTuple_GET_ITEM(args_, 5))); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } // missing const volatile type traits # ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template - static PyObject* call(R (A0::*pmf)() const volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)() const volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + ); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (A0::*pmf)(A1) const volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1) const volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1))); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1))); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (A0::*pmf)(A1, A2) const volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2) const volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2))); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3) const volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3) const volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3))); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; - from_python c4(PyTuple_GET_ITEM(args, 4)); + from_python c4(PyTuple_GET_ITEM(args_, 4)); if (!c4.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3)) + , c4(PyTuple_GET_ITEM(args_, 4))); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const volatile, PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const volatile, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; - from_python c4(PyTuple_GET_ITEM(args, 4)); + from_python c4(PyTuple_GET_ITEM(args_, 4)); if (!c4.convertible()) return 0; - from_python c5(PyTuple_GET_ITEM(args, 5)); + from_python c5(PyTuple_GET_ITEM(args_, 5)); if (!c5.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + ((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3)) + , c4(PyTuple_GET_ITEM(args_, 4)) + , c5(PyTuple_GET_ITEM(args_, 5))); - if (!policies.precall(args)) return 0; - - ((c0(PyTuple_GET_ITEM(args, 0))).*pmf)(c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))); - - return policies.postcall(args, detail::none()); + return policies.postcall(args_, detail::none()); } # endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - + template - static PyObject* call(R (*pf)(), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (*pf)(), PyObject* args_, PyObject*, P const& policies) { - (*pf)(); - - return policies.postcall(args, detail::none()); + (*pf)( + ); + + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (*pf)(A0), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (*pf)(A0), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; + + if (!policies.precall(args_)) return 0; - if (!policies.precall(args)) return 0; - - (*pf)(c0(PyTuple_GET_ITEM(args, 0))); - - return policies.postcall(args, detail::none()); + (*pf)( + c0(PyTuple_GET_ITEM(args_, 0))); + + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (*pf)(A0, A1), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (*pf)(A0, A1), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; + + if (!policies.precall(args_)) return 0; - if (!policies.precall(args)) return 0; - - (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1))); - - return policies.postcall(args, detail::none()); + (*pf)( + c0(PyTuple_GET_ITEM(args_, 0)) + , c1(PyTuple_GET_ITEM(args_, 1))); + + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (*pf)(A0, A1, A2), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (*pf)(A0, A1, A2), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; + + if (!policies.precall(args_)) return 0; - if (!policies.precall(args)) return 0; - - (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2))); - - return policies.postcall(args, detail::none()); + (*pf)( + c0(PyTuple_GET_ITEM(args_, 0)) + , c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2))); + + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (*pf)(A0, A1, A2, A3), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (*pf)(A0, A1, A2, A3), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; + + if (!policies.precall(args_)) return 0; - if (!policies.precall(args)) return 0; - - (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3))); - - return policies.postcall(args, detail::none()); + (*pf)( + c0(PyTuple_GET_ITEM(args_, 0)) + , c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3))); + + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (*pf)(A0, A1, A2, A3, A4), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (*pf)(A0, A1, A2, A3, A4), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; - from_python c4(PyTuple_GET_ITEM(args, 4)); + from_python c4(PyTuple_GET_ITEM(args_, 4)); if (!c4.convertible()) return 0; + + if (!policies.precall(args_)) return 0; - if (!policies.precall(args)) return 0; - - (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4))); - - return policies.postcall(args, detail::none()); + (*pf)( + c0(PyTuple_GET_ITEM(args_, 0)) + , c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3)) + , c4(PyTuple_GET_ITEM(args_, 4))); + + return policies.postcall(args_, detail::none()); } template - static PyObject* call(R (*pf)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject*, P const& policies) + static PyObject* call(R (*pf)(A0, A1, A2, A3, A4, A5), PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - from_python c0(PyTuple_GET_ITEM(args, 0)); + from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; - from_python c1(PyTuple_GET_ITEM(args, 1)); + from_python c1(PyTuple_GET_ITEM(args_, 1)); if (!c1.convertible()) return 0; - from_python c2(PyTuple_GET_ITEM(args, 2)); + from_python c2(PyTuple_GET_ITEM(args_, 2)); if (!c2.convertible()) return 0; - from_python c3(PyTuple_GET_ITEM(args, 3)); + from_python c3(PyTuple_GET_ITEM(args_, 3)); if (!c3.convertible()) return 0; - from_python c4(PyTuple_GET_ITEM(args, 4)); + from_python c4(PyTuple_GET_ITEM(args_, 4)); if (!c4.convertible()) return 0; - from_python c5(PyTuple_GET_ITEM(args, 5)); + from_python c5(PyTuple_GET_ITEM(args_, 5)); if (!c5.convertible()) return 0; + + if (!policies.precall(args_)) return 0; - if (!policies.precall(args)) return 0; - - (*pf)(c0(PyTuple_GET_ITEM(args, 0)), c1(PyTuple_GET_ITEM(args, 1)), c2(PyTuple_GET_ITEM(args, 2)), c3(PyTuple_GET_ITEM(args, 3)), c4(PyTuple_GET_ITEM(args, 4)), c5(PyTuple_GET_ITEM(args, 5))); - - return policies.postcall(args, detail::none()); + (*pf)( + c0(PyTuple_GET_ITEM(args_, 0)) + , c1(PyTuple_GET_ITEM(args_, 1)) + , c2(PyTuple_GET_ITEM(args_, 2)) + , c3(PyTuple_GET_ITEM(args_, 3)) + , c4(PyTuple_GET_ITEM(args_, 4)) + , c5(PyTuple_GET_ITEM(args_, 5))); + + return policies.postcall(args_, detail::none()); } }; diff --git a/src/gen_returning.py b/src/gen_returning.py index 80e3342b..8f7c866c 100644 --- a/src/gen_returning.py +++ b/src/gen_returning.py @@ -1,4 +1,4 @@ -# (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and +# (C) Copyright David Abrahams 2001,2002. 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. @@ -8,8 +8,8 @@ from gen_function import * import string -header = '''// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears +header = '''// (C) Copyright David Abrahams 2001,2002. 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. // @@ -24,11 +24,10 @@ body_sections = ( #ifndef RETURNING_DWA20011201_HPP # define RETURNING_DWA20011201_HPP -//# include # include # include -# include # include +# include namespace boost { namespace python { namespace detail { @@ -62,32 +61,49 @@ struct returning #' -member_function = ''' template - static PyObject* call(R (A0::*pmf)(%(A%+%:, %))%1, PyObject* args, PyObject* /* keywords */ ) +member_function = ''' template + static PyObject* call(R (A0::*pmf)(%(A%+%:, %))%1, PyObject* args_, PyObject*, P const& policies) { // check that each of the arguments is convertible - unwrap c0(PyTuple_GET_ITEM(args, 0)); -%( unwrap_more c%+(PyTuple_GET_ITEM(args, %+), c%n); + from_python c0(PyTuple_GET_ITEM(args_, 0)); + if (!c0.convertible()) return 0; +%( from_python c%+(PyTuple_GET_ITEM(args_, %+)); + if (!c%+.convertible()) return 0; %) %[r%: // find the result converter - wrap_more r(c%n); -%] if (!c0) return 0; - %[r%:return r( %]((*c0).*pmf)(%(*c%+%:, %))%[r%: )%];%[v%: - return detail::none();%] + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + +%] if (!policies.precall(args_)) return 0; + + %[r%:PyObject* result = cr( %]((c0(PyTuple_GET_ITEM(args_, 0)))->*pmf)( + %(c%+(PyTuple_GET_ITEM(args_, %+))%: + , %))%[r%: )%]; + + return policies.postcall(args_, %[r%:result%]%[v%:detail::none()%]); } ''' -free_function = '''%{ template <%(class A%n%:, %)> -%} static PyObject* call(R (*pf)(%(A%n%:, %)), PyObject*%{ args%}, PyObject* /* keywords */ ) +free_function = ''' template + static PyObject* call(R (*pf)(%(A%n%:, %)), PyObject* args_, PyObject*, P const& policies) {%{ // check that each of the arguments is convertible -%}%( unwrap%{_more%} c%n(PyTuple_GET_ITEM(args, %n)%{, c%-%}); -%)%[r%: - // find the result converter - wrap%{_more%} c%n%{(c%-)%};%]%[not-void-and-0-arg%: - if (!c0) return 0;%] - %[r%:return c%n( %](*pf)(%(*c%n%:, %))%[r%: )%];%[v%: - return detail::none();%] +%}%( from_python c%n(PyTuple_GET_ITEM(args_, %n)); + if (!c%n.convertible()) return 0; +%) +%[r%: // find the result converter + typedef typename P::result_converter result_converter; + typename eval::type cr; + if (!cr.convertible()) return 0; + +%]%[not-void-and-0-arg%: if (!policies.precall(args_)) return 0; + +%] %[r%:PyObject* result = cr( %](*pf)( + %(c%n(PyTuple_GET_ITEM(args_, %n))%: + , %))%[r%: )%]; + + return policies.postcall(args_, %[r%:result%]%[v%:detail::none()%]); } ''' From 8a956bcdf63cfc329732e0bc67609e0149d88f87 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 27 Feb 2002 21:12:52 +0000 Subject: [PATCH 309/369] missing typename fix [SVN r12960] --- include/boost/python/converter/from_python.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/python/converter/from_python.hpp b/include/boost/python/converter/from_python.hpp index 0881a06a..4fe240ce 100644 --- a/include/boost/python/converter/from_python.hpp +++ b/include/boost/python/converter/from_python.hpp @@ -40,7 +40,7 @@ struct pointer_const_reference_from_python bool convertible() const; private: - detail::referent_storage::type m_result; + typename detail::referent_storage::type m_result; static lvalue_from_python_registration*& chain; }; From 0ef39e4440113748831aebd103c5e63f2c86e095 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 27 Feb 2002 21:13:02 +0000 Subject: [PATCH 310/369] improvements for EDG [SVN r12961] --- .../python/converter/from_python_data.hpp | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/include/boost/python/converter/from_python_data.hpp b/include/boost/python/converter/from_python_data.hpp index 57a3d76e..d88eb90e 100644 --- a/include/boost/python/converter/from_python_data.hpp +++ b/include/boost/python/converter/from_python_data.hpp @@ -19,6 +19,8 @@ # include # include # include +# else +# include # endif namespace boost { namespace python { namespace converter { @@ -105,24 +107,23 @@ namespace detail bool, choose_t2 = ( aligned2 && ( is_same::value - | (align2 < alignment_of::value) + | (align2 < align1) | (sizeof(T2) < sizeof(T1))) )); - typedef mpl::select_type::type type; + typedef typename mpl::select_type::type type; }; }; typedef mpl::type_list< - char,short,int,long,float,double,long double + char,short,int,long, float,double,long double ,void* ,void(*)() ,void (alignment_dummy::*)() , char (alignment_dummy::*) - > + >::type align_types; -#endif // EDG is too slow - +#endif // EDG is too slow template union aligned_storage { @@ -148,10 +149,27 @@ namespace detail typedef typename loop::state align_t; #else + typedef typename remove_cv::type>::type referent; + // The Python source makes the assumption that double has - // maximal alignment anyway - typedef double align_t; - + // maximal alignment, but that fails on some platforms + BOOST_STATIC_CONSTANT( + std::size_t, target_align = alignment_of::value); + + // Here we make some assumptions and leave out some possible + // types worth checking, but this should work most of the time. + typedef typename mpl::select_type< + is_POD::value + , referent + , typename mpl::select_type< + alignment_of::value >= target_align + , long + , typename mpl::select_type< + alignment_of::value >= target_align + , double + , long double>::type + >::type + >::type align_t; #endif BOOST_STATIC_CONSTANT(std::size_t, alignment1 = alignment_of::value); BOOST_STATIC_CONSTANT(std::size_t, alignment2 = referent_alignment::value); From bbc49e1ba3ecc87f644483c480e4f382f522e6e1 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 27 Feb 2002 21:13:34 +0000 Subject: [PATCH 311/369] go with debug build by default [SVN r12962] --- Jamfile | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/Jamfile b/Jamfile index 79dfd9e5..9bf18e2e 100644 --- a/Jamfile +++ b/Jamfile @@ -14,7 +14,13 @@ include python.jam ; BOOST_PYTHON_V2 ; - local PYTHON_PROPERTIES = $(BOOST_PYTHON_V2_PROPERTIES) ; + local gcc-release-properties + = speed -fomit-frame-pointer + on -foptimize-sibling-calls + ; + + local PYTHON_PROPERTIES = $(BOOST_PYTHON_V2_PROPERTIES) $(gcc-release-properties) +; dll bpl : @@ -37,39 +43,39 @@ include python.jam ; # -------- general test ------- extension m1 : test/m1.cpp bpl : - : debug-python + : ; extension m2 : test/m2.cpp bpl : - : debug-python ; + : ; - boost-python-runtest try : test/newtest.py m1 m2 : : debug-python ; + boost-python-runtest try : test/newtest.py m1 m2 : : ; # ----------- builtin converters ----------- extension builtin_converters_ext : test/test_builtin_converters.cpp bpl : - : debug-python + : ; boost-python-runtest test_builtin_converters : test/test_builtin_converters.py builtin_converters_ext : - : debug-python + : ; # ----------- pointer adoption ----------- extension test_pointer_adoption_ext : test/test_pointer_adoption.cpp bpl : - : debug-python + : ; boost-python-runtest test_pointer_adoption : test/test_pointer_adoption.py test_pointer_adoption_ext : - : debug-python + : ; } From 493ff9c6850aab69ad9b250fec9f24d007c361ed Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 27 Feb 2002 23:18:08 +0000 Subject: [PATCH 312/369] Intel 5 compatibility [SVN r12963] --- include/boost/python/to_python_indirect.hpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/include/boost/python/to_python_indirect.hpp b/include/boost/python/to_python_indirect.hpp index 306b3246..7b77f5ff 100644 --- a/include/boost/python/to_python_indirect.hpp +++ b/include/boost/python/to_python_indirect.hpp @@ -10,6 +10,7 @@ # include # include # include +# include # include namespace boost { namespace python { @@ -34,8 +35,15 @@ namespace detail template static result_type execute(T* p) { - return new objects::pointer_holder, T>( - std::auto_ptr(p)); + // can't use auto_ptr with Intel 5 for some reason +# if defined(__ICL) && __ICL < 600 + typedef boost::shared_ptr smart_pointer; +# else + typedef std::auto_ptr smart_pointer; +# endif + + return new objects::pointer_holder( + smart_pointer(p)); } }; From ee26e13beab1f3ac9277241fbf6d5e8a70e3a6c5 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 28 Feb 2002 00:05:00 +0000 Subject: [PATCH 313/369] Added missing PyObject*const& converter [SVN r12966] --- include/boost/python/from_python.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/boost/python/from_python.hpp b/include/boost/python/from_python.hpp index 62b340f1..8c3f94bb 100644 --- a/include/boost/python/from_python.hpp +++ b/include/boost/python/from_python.hpp @@ -27,6 +27,14 @@ struct from_python PyObject* operator()(PyObject* source) const { return source; } }; +template <> +struct from_python +{ + from_python(PyObject*) {} + bool convertible() const { return true; } + PyObject*const& operator()(PyObject*const& source) const { return source; } +}; + // // implementations // From ccb7a8f94feb0713b6b2a19bf29d50b8126b99fd Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 28 Feb 2002 00:18:07 +0000 Subject: [PATCH 314/369] Make cxx 6.5 bugs happy [SVN r12967] --- src/converter/from_python.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/converter/from_python.cpp b/src/converter/from_python.cpp index 0650fcbb..57aee355 100644 --- a/src/converter/from_python.cpp +++ b/src/converter/from_python.cpp @@ -28,7 +28,7 @@ BOOST_PYTHON_DECL void* find( } BOOST_PYTHON_DECL void* find( - PyObject* const source + PyObject* source , lvalue_from_python_registration const* chain) { for (;chain != 0; chain = chain->next) From 412a00249f24e2b0017a88d49559c31ee7cc2a8c Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 28 Feb 2002 00:24:06 +0000 Subject: [PATCH 315/369] Move module_base to detail, avoiding recompilation dependencies [SVN r12970] --- include/boost/python/detail/module_base.hpp | 44 +++++++++++++++++++++ include/boost/python/module.hpp | 31 +-------------- include/boost/python/object/class.hpp | 1 - src/module.cpp | 7 ++-- src/object/class.cpp | 3 +- 5 files changed, 51 insertions(+), 35 deletions(-) create mode 100644 include/boost/python/detail/module_base.hpp diff --git a/include/boost/python/detail/module_base.hpp b/include/boost/python/detail/module_base.hpp new file mode 100644 index 00000000..e8a00ba6 --- /dev/null +++ b/include/boost/python/detail/module_base.hpp @@ -0,0 +1,44 @@ +// Copyright David Abrahams 2002. 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 MODULE_BASE_DWA2002227_HPP +# define MODULE_BASE_DWA2002227_HPP +# include +# include + +namespace boost { namespace python { namespace detail { + +class BOOST_PYTHON_DECL module_base +{ + public: + // Create a module. REQUIRES: only one module is created per module. + module_base(const char* name); + ~module_base(); + + // Add elements to the module + void setattr(const char* name, PyObject*); + void setattr(const char* name, ref const&); + void add(PyTypeObject* x); // just use the type's name + void add_type(ref); + + // Return a reference to the Python module object being built + inline ref object() const; + + private: + ref m_module; + static PyMethodDef initial_methods[1]; +}; + +// +// inline implementations +// +inline ref module_base::object() const +{ + return m_module; +} + +}}} // namespace boost::python::detail + +#endif // MODULE_BASE_DWA2002227_HPP diff --git a/include/boost/python/module.hpp b/include/boost/python/module.hpp index 11b0b6c7..7df183d5 100644 --- a/include/boost/python/module.hpp +++ b/include/boost/python/module.hpp @@ -8,36 +8,14 @@ # include # include -# include # include # include -# include # include +# include namespace boost { namespace python { -class BOOST_PYTHON_DECL module_base -{ - public: - // Create a module. REQUIRES: only one module is created per module. - module_base(const char* name); - ~module_base(); - - // Add elements to the module - void setattr(const char* name, PyObject*); - void setattr(const char* name, ref const&); - void add(PyTypeObject* x); // just use the type's name - void add_type(ref); - - // Return a reference to the Python module object being built - ref object() const; - - private: - ref m_module; - static PyMethodDef initial_methods[1]; -}; - -class module : public module_base +class module : public detail::module_base { public: module(const char* name) @@ -76,11 +54,6 @@ class module : public module_base // // inline implementations // -inline ref module_base::object() const -{ - return m_module; -} - inline module& module::setattr(const char* name, PyObject* x) { this->module_base::setattr(name, x); diff --git a/include/boost/python/object/class.hpp b/include/boost/python/object/class.hpp index 04f0e992..0d5210c7 100644 --- a/include/boost/python/object/class.hpp +++ b/include/boost/python/object/class.hpp @@ -6,7 +6,6 @@ #ifndef CLASS_DWA20011214_HPP # define CLASS_DWA20011214_HPP -# include # include # include # include diff --git a/src/module.cpp b/src/module.cpp index dbc81729..0291c9c1 100644 --- a/src/module.cpp +++ b/src/module.cpp @@ -6,9 +6,10 @@ // The author gratefully acknowleges the support of Dragon Systems, Inc., in // producing this work. -#include +#include +#include -namespace boost { namespace python { +namespace boost { namespace python { namespace detail { module_base::module_base(const char* name) : m_module( @@ -46,4 +47,4 @@ void module_base::add_type(ref x) PyMethodDef module_base::initial_methods[] = { { 0, 0, 0, 0 } }; -}} // namespace boost::python +}}} // namespace boost::python::detail diff --git a/src/object/class.cpp b/src/object/class.cpp index 8186f9be..b9deb98f 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -3,8 +3,7 @@ // 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. -#include -#include +#include #include #include #include From db9fb22cf445a226c503f139496a8c6bffcb4921 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 28 Feb 2002 00:24:52 +0000 Subject: [PATCH 316/369] Tests for NULL == None [SVN r12971] --- test/test_builtin_converters.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/test_builtin_converters.py b/test/test_builtin_converters.py index 3a4722c7..50d436e5 100644 --- a/test/test_builtin_converters.py +++ b/test/test_builtin_converters.py @@ -84,6 +84,17 @@ >>> rewrap_const_reference_string('yo, wassup?') 'yo, wassup?' + +Check that None <==> NULL + +>>> rewrap_const_reference_cstring(None) + +But when converted to a string rvalue, None becomes 'None': + +>>> rewrap_const_reference_string(None) +'None' + + Now check implicit conversions between floating/integer types >>> rewrap_const_reference_float(42) From a2dec7a05dd8f92591e12a7cf0972d3506a44d92 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 28 Feb 2002 00:48:48 +0000 Subject: [PATCH 317/369] Make cxx 6.5 bugs happy [SVN r12973] --- include/boost/python/converter/from_python.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/python/converter/from_python.hpp b/include/boost/python/converter/from_python.hpp index 4fe240ce..f2680ef3 100644 --- a/include/boost/python/converter/from_python.hpp +++ b/include/boost/python/converter/from_python.hpp @@ -130,7 +130,7 @@ inline from_python_base::from_python_base(void* result) } inline from_python_base::from_python_base( - PyObject* const source + PyObject* source , lvalue_from_python_registration const* chain) : m_result(find(source, chain)) { From b28dc5523752d79df1f524f872c9fd9ab12e74f6 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 28 Feb 2002 06:08:27 +0000 Subject: [PATCH 318/369] suppress warnings with CWPro7 [SVN r12977] --- src/converter/builtin_converters.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/converter/builtin_converters.cpp b/src/converter/builtin_converters.cpp index 2e9bcbec..fe6708e6 100644 --- a/src/converter/builtin_converters.cpp +++ b/src/converter/builtin_converters.cpp @@ -221,15 +221,13 @@ namespace { return PyInt_AS_LONG(intermediate); } - else if (PyFloat_Check(intermediate)) - { - return PyFloat_AS_DOUBLE(intermediate); - } - else + else if (!PyFloat_Check(intermediate)) { PyErr_SetString(PyExc_TypeError, "__complex__ method did not return a Complex object"); throw error_already_set(); } + + return PyFloat_AS_DOUBLE(intermediate); } }; } From 0e597f576875670c699fe33da9191ed74d9e1cc2 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 28 Feb 2002 15:38:21 +0000 Subject: [PATCH 319/369] Suppress some warnings on older EDGs [SVN r12984] --- include/boost/python/converter/from_python.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/boost/python/converter/from_python.hpp b/include/boost/python/converter/from_python.hpp index f2680ef3..f9192be2 100644 --- a/include/boost/python/converter/from_python.hpp +++ b/include/boost/python/converter/from_python.hpp @@ -10,6 +10,7 @@ # include # include # include +# include # include # include # include @@ -179,7 +180,9 @@ namespace detail template inline void write_void_ptr_reference(void const volatile* storage, void* ptr, U&(*)()) { - write_void_ptr(storage, ptr, U(0)); + // stripping CV qualification suppresses warnings on older EDGs + typedef typename remove_cv::type u_stripped; + write_void_ptr(storage, ptr, u_stripped(0)); } } From edad2a1ee5cbc379e1862cc92e219a331a731a36 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 1 Mar 2002 20:33:04 +0000 Subject: [PATCH 320/369] *** empty log message *** [SVN r12999] --- .../python/converter/from_python_data.hpp | 154 ++++++++---------- include/boost/python/detail/eval.hpp | 2 + 2 files changed, 66 insertions(+), 90 deletions(-) diff --git a/include/boost/python/converter/from_python_data.hpp b/include/boost/python/converter/from_python_data.hpp index d88eb90e..fe026172 100644 --- a/include/boost/python/converter/from_python_data.hpp +++ b/include/boost/python/converter/from_python_data.hpp @@ -13,15 +13,12 @@ # include # include # include - -// Keep these for the metaprogram which EDG is choking on. -# if !defined(__EDG__) || (__EDG_VERSION__ > 245) -# include -# include -# include -# else -# include -# endif +# include +# include +//# include +# include +# include +# include namespace boost { namespace python { namespace converter { @@ -75,111 +72,88 @@ namespace detail }; # endif - - struct unknown_alignment - { - void* p; - }; - -// EDG is too slow to handle this metaprogram :( -#if !defined(__EDG__) || (__EDG_VERSION__ > 245) struct alignment_dummy; + typedef void (*function_ptr)(); + typedef int (alignment_dummy::*member_ptr); + typedef int (alignment_dummy::*member_function_ptr)(); - template - struct best_alignment_type +# define BOOST_PYTHON_ALIGNMENT_TYPES BOOST_PP_TUPLE_TO_LIST( \ + 11, ( \ + char, short, int, long, float, double, long double \ + , void*, function_ptr, member_ptr, member_function_ptr)) + +# define BOOST_PYTHON_CHOOSE_LOWER_ALIGNMENT(R,P,I,T) \ + typename mpl::select_type< \ + alignment_of::value <= target, T, char>::type BOOST_PP_CAT(t,I); + +# define BOOST_PYTHON_CHOOSE_LOWER_SIZE(R,P,I,T) \ + typename mpl::select_type< \ + sizeof(T) <= target, T, char>::type BOOST_PP_CAT(t,I); + +# define BOOST_PYTHON_CHOOSE_T(R,P,I,T) T BOOST_PP_CAT(t,I); + + template + union lower_alignment { - template - struct apply - { - BOOST_STATIC_CONSTANT( - std::size_t, align1 = alignment_of::value); - - BOOST_STATIC_CONSTANT( - std::size_t, align2 = alignment_of::value); - - BOOST_STATIC_CONSTANT( - bool, aligned2 = ( - (align2 >= target_alignment) - & (align2 % target_alignment == 0)) - ); - - BOOST_STATIC_CONSTANT( - bool, choose_t2 = ( - aligned2 && ( - is_same::value - | (align2 < align1) - | (sizeof(T2) < sizeof(T1))) - )); - - typedef typename mpl::select_type::type type; - }; + BOOST_PP_LIST_FOR_EACH_I( + BOOST_PYTHON_CHOOSE_LOWER_ALIGNMENT + , ignored, BOOST_PYTHON_ALIGNMENT_TYPES) }; - typedef mpl::type_list< - char,short,int,long, float,double,long double - ,void* - ,void(*)() - ,void (alignment_dummy::*)() - , char (alignment_dummy::*) - >::type - align_types; -#endif // EDG is too slow + template + union lower_size + { + BOOST_PP_LIST_FOR_EACH_I( + BOOST_PYTHON_CHOOSE_LOWER_SIZE + , ignored, BOOST_PYTHON_ALIGNMENT_TYPES) + }; + + union max_align + { + BOOST_PP_LIST_FOR_EACH_I( + BOOST_PYTHON_CHOOSE_T + , ignored, BOOST_PYTHON_ALIGNMENT_TYPES) + }; + template union aligned_storage { Align align; - char bytes[size - // this is just a STATIC_ASSERT. For some reason - // MSVC was barfing on the boost one. - - (is_same::value ? size : 0)]; + char bytes[size]; }; template struct referent_storage { -// EDG is too slow to handle this metaprogram :( -#if !defined(__EDG__) || (__EDG_VERSION__ > 245) - typedef mpl::for_each< - align_types - , unknown_alignment - , best_alignment_type< - referent_alignment::value - > - > loop; - - typedef typename loop::state align_t; -#else typedef typename remove_cv::type>::type referent; - - // The Python source makes the assumption that double has - // maximal alignment, but that fails on some platforms - BOOST_STATIC_CONSTANT( - std::size_t, target_align = alignment_of::value); - // Here we make some assumptions and leave out some possible - // types worth checking, but this should work most of the time. + BOOST_STATIC_CONSTANT(std::size_t, target = referent_alignment::value); + typedef lower_alignment t1; + typedef lower_size::value> t2; + typedef typename mpl::select_type< - is_POD::value - , referent + ::boost::detail::ice_and< + alignment_of::value >= target + , alignment_of::value % target == 0 + >::value + , t1 , typename mpl::select_type< - alignment_of::value >= target_align - , long - , typename mpl::select_type< - alignment_of::value >= target_align - , double - , long double>::type + ::boost::detail::ice_and< + alignment_of::value >= target + , alignment_of::value % target == 0 + >::value + , t2 + , max_align >::type >::type align_t; -#endif - BOOST_STATIC_CONSTANT(std::size_t, alignment1 = alignment_of::value); - BOOST_STATIC_CONSTANT(std::size_t, alignment2 = referent_alignment::value); + + BOOST_STATIC_CONSTANT(std::size_t, found = alignment_of::value); - BOOST_STATIC_ASSERT(alignment1 >= alignment2); - BOOST_STATIC_ASSERT(alignment1 % alignment2 == 0); + BOOST_STATIC_ASSERT(found >= target); + BOOST_STATIC_ASSERT(found % target == 0); typedef aligned_storage::value> type; }; - } template diff --git a/include/boost/python/detail/eval.hpp b/include/boost/python/detail/eval.hpp index 3e799507..8699f701 100644 --- a/include/boost/python/detail/eval.hpp +++ b/include/boost/python/detail/eval.hpp @@ -6,6 +6,8 @@ #ifndef EVAL_DWA2002124_HPP # define EVAL_DWA2002124_HPP +# include + namespace boost { namespace python { namespace detail { template struct undefined; From 71cbe1cf50d6d93d298b6d2744aa06848cb1d036 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 1 Mar 2002 21:24:49 +0000 Subject: [PATCH 321/369] quick fixes for KCC [SVN r13000] --- .../python/converter/from_python_data.hpp | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/include/boost/python/converter/from_python_data.hpp b/include/boost/python/converter/from_python_data.hpp index fe026172..9b418957 100644 --- a/include/boost/python/converter/from_python_data.hpp +++ b/include/boost/python/converter/from_python_data.hpp @@ -15,7 +15,7 @@ # include # include # include -//# include +# include # include # include # include @@ -129,19 +129,23 @@ namespace detail BOOST_STATIC_CONSTANT(std::size_t, target = referent_alignment::value); typedef lower_alignment t1; + + BOOST_STATIC_CONSTANT(bool, t1_aligned = + (alignment_of::value >= target) + & (alignment_of::value % target == 0)); + typedef lower_size::value> t2; + BOOST_STATIC_CONSTANT(bool, t2_aligned = + (alignment_of::value >= target) + & (alignment_of::value % target == 0)); + + typedef typename mpl::select_type< - ::boost::detail::ice_and< - alignment_of::value >= target - , alignment_of::value % target == 0 - >::value + t1_aligned , t1 , typename mpl::select_type< - ::boost::detail::ice_and< - alignment_of::value >= target - , alignment_of::value % target == 0 - >::value + t2_aligned , t2 , max_align >::type From 9644610e049ae06b52b63e9545ae32b62fc13679 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 2 Mar 2002 01:33:55 +0000 Subject: [PATCH 322/369] obsolete [SVN r13004] --- include/boost/python/converter/handle.hpp | 108 ---------------------- 1 file changed, 108 deletions(-) delete mode 100644 include/boost/python/converter/handle.hpp diff --git a/include/boost/python/converter/handle.hpp b/include/boost/python/converter/handle.hpp deleted file mode 100644 index 82e085b0..00000000 --- a/include/boost/python/converter/handle.hpp +++ /dev/null @@ -1,108 +0,0 @@ -// 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 HANDLE_DWA20011130_HPP -# define HANDLE_DWA20011130_HPP -# include -# include -# include - -namespace boost { namespace python { namespace converter { - -struct BOOST_PYTHON_DECL body; - -// The common base class for unwrap_ and wrap_ handle objects. They -// share a common base so that handles can be linked into a chain -// within a function wrapper which is managed by a single object. -struct BOOST_PYTHON_DECL handle : private boost::noncopyable -{ - public: // member functions - - // All constructors take a body* passed from the derived class. - // - // Constructors taking a handle links this into a chain of - // handles, for more efficient management in function wrappers - handle(); - handle(body* body); - handle(body* body, handle& prev); - - // returns true iff all handles in the chain can convert their - // arguments - bool convertible() const; - - // safe_bool idiom from Peter Dimov: provides handles to/from - // bool without enabling handles to integer types/void*. - private: - struct dummy { inline void nonnull() {} }; - typedef void (dummy::*safe_bool)(); - public: - inline operator safe_bool() const; - inline safe_bool operator!() const; - - protected: // member functions for derived classes - // Get the body we hold - inline body* get_body() const; - - inline void set_body(body*); - inline void set_prev(handle&); - - // Release all bodies in the chain, in reverse order of - // initialization. Only actually called for the head of the chain. - void destroy(); - - private: - // Holds implementation - body* m_body; - - // handle for next argument, if any. - handle* m_next; -}; - -// -// implementations -// -inline handle::handle() - : m_next(0) -{} - -inline handle::handle(body* body, handle& prev) - : m_body(body), m_next(0) -{ - prev.m_next = this; -} - -inline handle::handle(body* body) - : m_body(body), m_next(0) -{ -} - -inline handle::operator handle::safe_bool() const -{ - return convertible() ? &dummy::nonnull : 0; -} - -inline handle::safe_bool handle::operator!() const -{ - return convertible() ? 0 : &dummy::nonnull; -} - -inline body* handle::get_body() const -{ - return m_body; -} - -inline void handle::set_body(body* body) -{ - m_body = body; -} - -inline void handle::set_prev(handle& prev) -{ - prev.m_next = this; -} - -}}} // namespace boost::python::converter - -#endif // HANDLE_DWA20011130_HPP From a437af44f8b6ea4ea8d16e5845d70d9823cfd157 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 2 Mar 2002 01:52:38 +0000 Subject: [PATCH 323/369] obsolete [SVN r13005] --- .../python/converter/unwrapper_select.hpp | 33 ------------------- 1 file changed, 33 deletions(-) delete mode 100644 include/boost/python/converter/unwrapper_select.hpp diff --git a/include/boost/python/converter/unwrapper_select.hpp b/include/boost/python/converter/unwrapper_select.hpp deleted file mode 100644 index d60923af..00000000 --- a/include/boost/python/converter/unwrapper_select.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// 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 UNWRAPPER_SELECT_DWA20011229_HPP -# define UNWRAPPER_SELECT_DWA20011229_HPP - -namespace boost { namespace python { namespace converter { - -template struct unwrapper; - -// Select the type returned by unwrapper objects when unwrapping a -// given type. When unwrapping T const&, the unwrapper returns T&, so -// that the same unwrapper object can be used for both conversions (on -// a conforming compiler). -template -struct unwrapper_select -{ - typedef unwrapper type; -}; - -# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -template -struct unwrapper_select -{ - typedef unwrapper type; -}; -# endif - -}}} // namespace boost::python::converter - -#endif // UNWRAPPER_SELECT_DWA20011229_HPP From 1257b32464f60490c366bc26802a27f922c6ba32 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 2 Mar 2002 02:29:06 +0000 Subject: [PATCH 324/369] added missing 'inline' [SVN r13006] --- include/boost/python/from_python.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/python/from_python.hpp b/include/boost/python/from_python.hpp index 8c3f94bb..726928ac 100644 --- a/include/boost/python/from_python.hpp +++ b/include/boost/python/from_python.hpp @@ -39,7 +39,7 @@ struct from_python // implementations // template -from_python::from_python(PyObject* source) +inline from_python::from_python(PyObject* source) : base(source) { } From 087f09e9a6dd68bfd5af5e6591824a6074fb24f3 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 2 Mar 2002 02:52:36 +0000 Subject: [PATCH 325/369] flotsam removal [SVN r13007] --- include/boost/python/with_custodian_and_ward.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/boost/python/with_custodian_and_ward.hpp b/include/boost/python/with_custodian_and_ward.hpp index 4ae975af..517d690f 100644 --- a/include/boost/python/with_custodian_and_ward.hpp +++ b/include/boost/python/with_custodian_and_ward.hpp @@ -11,8 +11,6 @@ namespace boost { namespace python { -enum custodial_timing { pre_call, post_call }; - template struct with_custodian_and_ward : Base { From bd9df7e6199c7e0ad5b0b32f27c13a611d7b568c Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 3 Mar 2002 20:46:06 +0000 Subject: [PATCH 326/369] Apply patch due to Craig Rodriguez [SVN r13049] --- include/boost/python/detail/init_function.hpp | 110 +++++++++--------- src/gen_init_function.py | 2 +- 2 files changed, 56 insertions(+), 56 deletions(-) diff --git a/include/boost/python/detail/init_function.hpp b/include/boost/python/detail/init_function.hpp index ed34f9be..3c6f2380 100644 --- a/include/boost/python/detail/init_function.hpp +++ b/include/boost/python/detail/init_function.hpp @@ -175,106 +175,106 @@ struct init_function template static init* create(signature1) { return new init1::const_reference>; + typename detail::parameter_traits::const_reference>; } template static init* create(signature2) { return new init2::const_reference, - detail::parameter_traits::const_reference>; + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference>; } template static init* create(signature3) { return new init3::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference>; + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference>; } template static init* create(signature4) { return new init4::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference>; + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference>; } template static init* create(signature5) { return new init5::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference>; + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference>; } template static init* create(signature6) { return new init6::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference>; + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference>; } template static init* create(signature7) { return new init7::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference>; + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference>; } template static init* create(signature8) { return new init8::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference>; + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference>; } template static init* create(signature9) { return new init9::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference>; + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference>; } template static init* create(signature10) { return new init10::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference>; + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference, + typename detail::parameter_traits::const_reference>; } }; diff --git a/src/gen_init_function.py b/src/gen_init_function.py index ff294dbb..94e8041a 100644 --- a/src/gen_init_function.py +++ b/src/gen_init_function.py @@ -169,7 +169,7 @@ struct init_function template <%(class A%n%:, %)> %} static init* create(signature%x%{<%(A%n%:, %)>%}) { return new init%x::const_reference%)>; + typename detail::parameter_traits::const_reference%)>; } """, args)+"""}; From 97825fb2c7b2d77c2c0611eb609eb2a77b8ac315 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 6 Mar 2002 01:33:46 +0000 Subject: [PATCH 327/369] Kill some Intel5 warnings [SVN r13108] --- include/boost/python/detail/config.hpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/boost/python/detail/config.hpp b/include/boost/python/detail/config.hpp index c488cb64..efd1500b 100644 --- a/include/boost/python/detail/config.hpp +++ b/include/boost/python/detail/config.hpp @@ -33,10 +33,15 @@ # define BOOST_MSVC6_OR_EARLIER 1 # endif -# pragma warning (disable : 4786) +# pragma warning (disable : 4786) + +# elif defined(__ICL) && __ICL < 600 // Intel C++ 5 + +# pragma warning(disable: 985) // identifier was truncated in debug information # 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. From e79a66851c02c061be6678d3a7118907d7305596 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 8 Mar 2002 14:56:39 +0000 Subject: [PATCH 328/369] Beginning of callback implementation [SVN r13135] --- Jamfile | 104 +++--------------- .../python/converter/builtin_converters.hpp | 24 +++- .../converter/callback_to_python_base.hpp | 45 ++++++++ .../python/converter/find_from_python.hpp | 7 +- .../boost/python/converter/from_python.hpp | 42 +------ .../python/converter/from_python_data.hpp | 37 ++++++- .../converter/lvalue_from_python_chain.hpp | 67 +++++++++++ include/boost/python/converter/registry.hpp | 8 +- .../python/converter/to_python_function.hpp | 44 +++++--- .../converter/to_python_function_type.hpp | 30 +++++ include/boost/python/to_python_converter.hpp | 2 +- include/boost/python/to_python_value.hpp | 16 +-- src/converter/builtin_converters.cpp | 2 +- src/converter/from_python.cpp | 12 +- src/converter/registry.cpp | 8 +- src/object/function.cpp | 30 ++++- test/Jamfile | 75 +++++++++++++ test/test_builtin_converters.cpp | 4 +- test/test_builtin_converters.py | 2 +- 19 files changed, 381 insertions(+), 178 deletions(-) create mode 100644 include/boost/python/converter/callback_to_python_base.hpp create mode 100644 include/boost/python/converter/lvalue_from_python_chain.hpp create mode 100644 include/boost/python/converter/to_python_function_type.hpp create mode 100644 test/Jamfile diff --git a/Jamfile b/Jamfile index 9bf18e2e..4a1af66f 100644 --- a/Jamfile +++ b/Jamfile @@ -4,93 +4,21 @@ subproject libs/python ; SEARCH on python.jam = $(BOOST_BUILD_PATH) ; include python.jam ; - -{ - local BOOST_PYTHON_V2_PROPERTIES - = $(PYTHON_PROPERTIES) - <*>"-inline deferred" - <*>$(BOOST_ROOT)/boost/compatibility/cpp_c_headers - BOOST_PYTHON_DYNAMIC_LIB - BOOST_PYTHON_V2 - ; - - local gcc-release-properties - = speed -fomit-frame-pointer - on -foptimize-sibling-calls - ; - - local PYTHON_PROPERTIES = $(BOOST_PYTHON_V2_PROPERTIES) $(gcc-release-properties) -; - - dll bpl - : - src/converter/from_python.cpp - src/converter/registry.cpp - src/converter/type_id.cpp - src/object/class.cpp - src/object/function.cpp - src/object/inheritance.cpp - src/object/life_support.cpp - src/errors.cpp - src/module.cpp - src/objects.cpp - src/converter/builtin_converters.cpp - : - $(BOOST_PYTHON_V2_PROPERTIES) - BOOST_PYTHON_SOURCE - ; - - # -------- general test ------- - extension m1 : test/m1.cpp bpl - : - : - ; - - extension m2 : test/m2.cpp bpl - : - : ; - - boost-python-runtest try : test/newtest.py m1 m2 : : ; - - # ----------- builtin converters ----------- - - extension builtin_converters_ext : test/test_builtin_converters.cpp bpl - : - : - ; - - boost-python-runtest test_builtin_converters : test/test_builtin_converters.py - builtin_converters_ext - : - : - ; - - # ----------- pointer adoption ----------- - - extension test_pointer_adoption_ext : test/test_pointer_adoption.cpp bpl - : - : - ; - - boost-python-runtest test_pointer_adoption : test/test_pointer_adoption.py - test_pointer_adoption_ext - : - : - ; - -} - -unit-test indirect_traits_test - : test/indirect_traits_test.cpp : $(BOOST_ROOT) ; -unit-test destroy_test - : test/destroy_test.cpp : $(BOOST_ROOT) ; -unit-test pointer_type_id_test - : test/pointer_type_id_test.cpp : $(BOOST_ROOT) ; - -unit-test select_from_python_test - : test/select_from_python_test.cpp +dll bpl + : + src/converter/from_python.cpp + src/converter/registry.cpp src/converter/type_id.cpp - src/converter/registry.cpp # MWerks needs this for some reason - : $(PYTHON_PROPERTIES) + src/object/class.cpp + src/object/function.cpp + src/object/inheritance.cpp + src/object/life_support.cpp + src/errors.cpp + src/module.cpp + src/objects.cpp + src/converter/builtin_converters.cpp + src/converter/callback.cpp + : + $(BOOST_PYTHON_V2_PROPERTIES) + BOOST_PYTHON_SOURCE ; - diff --git a/include/boost/python/converter/builtin_converters.hpp b/include/boost/python/converter/builtin_converters.hpp index 7ae7a357..4db0eb9c 100644 --- a/include/boost/python/converter/builtin_converters.hpp +++ b/include/boost/python/converter/builtin_converters.hpp @@ -7,6 +7,7 @@ # define BUILTIN_CONVERTERS_DWA2002124_HPP # include # include +# include # include # include @@ -23,6 +24,11 @@ namespace detail }; } +namespace converter +{ + template struct callback_to_python; +} + # define BOOST_PYTHON_TO_PYTHON_BY_VALUE(T, expr) \ template <> struct to_python_value \ : detail::builtin_to_python \ @@ -39,7 +45,19 @@ namespace detail { \ return (expr); \ } \ - }; + }; \ + namespace converter \ + { \ + template <> struct callback_to_python< T > \ + { \ + callback_to_python(T const& x) \ + : m_held(expr) {} \ + PyObject* get() const \ + { return m_held.get(); } \ + private: \ + ref m_held; \ + }; \ + } # define BOOST_PYTHON_TO_INT(T) \ @@ -53,12 +71,12 @@ BOOST_PYTHON_TO_INT(int) BOOST_PYTHON_TO_INT(long) # undef BOOST_TO_PYTHON_INT -BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, x ? PyString_FromString(x) : detail::none()) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, x ? PyString_FromString(x) : boost::python::detail::none()) BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, PyString_FromString(x.c_str())) BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, PyFloat_FromDouble(x)) BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, PyFloat_FromDouble(x)) BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, PyFloat_FromDouble(x)) -BOOST_PYTHON_TO_PYTHON_BY_VALUE(PyObject*, x ? x : detail::none()) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(PyObject*, (x ? x : boost::python::detail::none())) BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, PyComplex_FromDoubles(x.real(), x.imag())) BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, PyComplex_FromDoubles(x.real(), x.imag())) BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, PyComplex_FromDoubles(x.real(), x.imag())) diff --git a/include/boost/python/converter/callback_to_python_base.hpp b/include/boost/python/converter/callback_to_python_base.hpp new file mode 100644 index 00000000..c878850e --- /dev/null +++ b/include/boost/python/converter/callback_to_python_base.hpp @@ -0,0 +1,45 @@ +// Copyright David Abrahams 2002. 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 CALLBACK_TO_PYTHON_BASE_DWA200237_HPP +# define CALLBACK_TO_PYTHON_BASE_DWA200237_HPP +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +namespace detail +{ + struct callback_to_python_holder + { + callback_to_python_holder(PyObject* obj); + inline PyObject* get() const; + private: + ref m_held; + }; + + struct BOOST_PYTHON_DECL callback_to_python_base : callback_to_python_holder + { + callback_to_python_base(void const volatile* source, to_python_function_t); + }; + + // + // implmentation + // + inline callback_to_python_holder::callback_to_python_holder(PyObject* obj) + : m_held(obj) + { + } + + inline PyObject* callback_to_python_holder::get() const + { + return m_held.get(); + } +} + +}}} // namespace boost::python::converter + +#endif // CALLBACK_TO_PYTHON_BASE_DWA200237_HPP diff --git a/include/boost/python/converter/find_from_python.hpp b/include/boost/python/converter/find_from_python.hpp index 863c44a6..e7f7ca81 100644 --- a/include/boost/python/converter/find_from_python.hpp +++ b/include/boost/python/converter/find_from_python.hpp @@ -8,17 +8,18 @@ # include # include +# include namespace boost { namespace python { namespace converter { struct lvalue_from_python_registration; struct rvalue_from_python_registration; -struct rvalue_stage1_data; BOOST_PYTHON_DECL void* find( PyObject* source, lvalue_from_python_registration const*); -BOOST_PYTHON_DECL void* find( - PyObject* source, rvalue_from_python_registration const*, rvalue_stage1_data&); + +BOOST_PYTHON_DECL rvalue_stage1_data find( + PyObject* source, rvalue_from_python_registration const*); }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/from_python.hpp b/include/boost/python/converter/from_python.hpp index f9192be2..5fe8901a 100644 --- a/include/boost/python/converter/from_python.hpp +++ b/include/boost/python/converter/from_python.hpp @@ -8,13 +8,14 @@ # include # include -# include # include # include # include # include # include # include +# include +# include namespace boost { namespace python { namespace converter { @@ -42,8 +43,6 @@ struct pointer_const_reference_from_python private: typename detail::referent_storage::type m_result; - - static lvalue_from_python_registration*& chain; }; // Used when T == U* @@ -52,8 +51,6 @@ struct pointer_from_python : from_python_base { pointer_from_python(PyObject*); T operator()(PyObject*) const; - - static lvalue_from_python_registration*& chain; }; // Used when T == U& and (T != V const& or T == W volatile&) @@ -62,8 +59,6 @@ struct reference_from_python : from_python_base { reference_from_python(PyObject*); T operator()(PyObject*) const; - - static lvalue_from_python_registration*& chain; }; // ------- rvalue converters --------- @@ -79,14 +74,12 @@ class rvalue_from_python public: rvalue_from_python(PyObject*); - ~rvalue_from_python(); bool convertible() const; result_type operator()(PyObject*); private: rvalue_data m_data; - static rvalue_from_python_registration*& chain; }; template @@ -191,7 +184,7 @@ inline pointer_const_reference_from_python::pointer_const_reference_from_pyth { detail::write_void_ptr_reference( m_result.bytes - , p == Py_None ? p : find(p, chain) + , p == Py_None ? p : find(p, lvalue_from_python_chain::value) , (T(*)())0); } @@ -208,15 +201,11 @@ inline T pointer_const_reference_from_python::operator()(PyObject* p) const : detail::void_ptr_to_reference(m_result.bytes, (T(*)())0); } -template -lvalue_from_python_registration*& pointer_const_reference_from_python::chain - = registry::lvalue_converters(pointer_type_id()); - // -------- template inline pointer_from_python::pointer_from_python(PyObject* p) - : from_python_base(p == Py_None ? p : find(p, chain)) + : from_python_base(p == Py_None ? p : find(p, lvalue_from_python_chain::value)) { } @@ -226,15 +215,11 @@ inline T pointer_from_python::operator()(PyObject* p) const return (p == Py_None) ? 0 : T(result()); } -template -lvalue_from_python_registration*& pointer_from_python::chain - = registry::lvalue_converters(pointer_type_id()); - // -------- template inline reference_from_python::reference_from_python(PyObject* p) - : from_python_base(find(p,chain)) + : from_python_base(find(p,lvalue_from_python_chain::value)) { } @@ -244,23 +229,12 @@ inline T reference_from_python::operator()(PyObject*) const return detail::void_ptr_to_reference(result(), (T(*)())0); } -template -lvalue_from_python_registration*& reference_from_python::chain - = registry::lvalue_converters(undecorated_type_id()); - // ------- template inline rvalue_from_python::rvalue_from_python(PyObject* obj) + : m_data(find(obj, rvalue_from_python_chain::value)) { - find(obj, chain, m_data.stage1); -} - -template -inline rvalue_from_python::~rvalue_from_python() -{ - if (m_data.stage1.convertible == m_data.storage.bytes) - python::detail::destroy_reference(m_data.storage.bytes); } template @@ -279,10 +253,6 @@ rvalue_from_python::operator()(PyObject* p) return detail::void_ptr_to_reference(m_data.stage1.convertible, (result_type(*)())0); } -template -rvalue_from_python_registration*& rvalue_from_python::chain - = registry::rvalue_converters(undecorated_type_id()); - }}} // namespace boost::python::converter #endif // FROM_PYTHON_DWA2002127_HPP diff --git a/include/boost/python/converter/from_python_data.hpp b/include/boost/python/converter/from_python_data.hpp index 9b418957..9fa9410a 100644 --- a/include/boost/python/converter/from_python_data.hpp +++ b/include/boost/python/converter/from_python_data.hpp @@ -16,6 +16,7 @@ # include # include # include +# include # include # include # include @@ -161,7 +162,7 @@ namespace detail } template -struct rvalue_data +struct rvalue_base_data { rvalue_stage1_data stage1; @@ -170,6 +171,40 @@ struct rvalue_data >::type storage; }; +template +struct rvalue_data : rvalue_base_data +{ + rvalue_data(rvalue_stage1_data const&); + rvalue_data(void*); + ~rvalue_data(); +}; + +// +// Implementataions +// +template +inline rvalue_data::rvalue_data(rvalue_stage1_data const& stage1) +{ + this->stage1 = stage1; +} + +template +inline rvalue_data::rvalue_data(void* convertible) +{ + this->stage1.convertible = convertible; +} + +template +inline rvalue_data::~rvalue_data() +{ + if (this->stage1.convertible == this->storage.bytes) + python::detail::destroy_reference< + add_reference< + add_cv::type + >::type + >(storage.bytes); +} + }}} // namespace boost::python::converter #endif // FROM_PYTHON_AUX_DATA_DWA2002128_HPP diff --git a/include/boost/python/converter/lvalue_from_python_chain.hpp b/include/boost/python/converter/lvalue_from_python_chain.hpp new file mode 100644 index 00000000..f1417460 --- /dev/null +++ b/include/boost/python/converter/lvalue_from_python_chain.hpp @@ -0,0 +1,67 @@ +// Copyright David Abrahams 2002. 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 LVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP +# define LVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP + +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +// Given T == U*cv&, T == U*, or T == U&, lvalue_from_python_chain +// declares a "templated global reference" to the lvalue from_python +// converter chain for U +namespace detail +{ + template + struct ptr_or_ptr_ref_lvalue_from_python_chain + { + static lvalue_from_python_registration*const& value; + }; + + template + lvalue_from_python_registration*const& + ptr_or_ptr_ref_lvalue_from_python_chain::value + = registry::lvalue_converters(pointer_type_id()); + + template + struct ref_lvalue_from_python_chain + { + static lvalue_from_python_registration*const& value; + }; + + template + lvalue_from_python_registration*const& + ref_lvalue_from_python_chain::value + = registry::lvalue_converters(undecorated_type_id()); + + template + struct select_lvalue_from_python_chain + { + BOOST_STATIC_CONSTANT( + bool, ptr = boost::python::detail::is_reference_to_pointer::value + || is_pointer::value); + + typedef typename add_reference::type>::type normalized; + + typedef typename mpl::select_type< + ptr + , ptr_or_ptr_ref_lvalue_from_python_chain + , ref_lvalue_from_python_chain + >::type type; + }; +} + +template +struct lvalue_from_python_chain + : detail::select_lvalue_from_python_chain::type +{ +}; + +}}} // namespace boost::python::converter + +#endif // LVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP diff --git a/include/boost/python/converter/registry.hpp b/include/boost/python/converter/registry.hpp index a511a1a4..1c8dba24 100644 --- a/include/boost/python/converter/registry.hpp +++ b/include/boost/python/converter/registry.hpp @@ -8,7 +8,7 @@ # include # include # include -# include +# include # include namespace boost { namespace python { namespace converter { @@ -22,10 +22,10 @@ namespace registry BOOST_PYTHON_DECL lvalue_from_python_registration*& lvalue_converters(undecorated_type_id_t); BOOST_PYTHON_DECL rvalue_from_python_registration*& rvalue_converters(undecorated_type_id_t); - BOOST_PYTHON_DECL to_python_value_function const& - to_python_function(undecorated_type_id_t); + BOOST_PYTHON_DECL to_python_function_t const& + get_to_python_function(undecorated_type_id_t); - BOOST_PYTHON_DECL void insert(to_python_value_function, undecorated_type_id_t); + BOOST_PYTHON_DECL void insert(to_python_function_t, undecorated_type_id_t); // Insert an lvalue from_python converter BOOST_PYTHON_DECL void insert(void* (*convert)(PyObject*), undecorated_type_id_t); diff --git a/include/boost/python/converter/to_python_function.hpp b/include/boost/python/converter/to_python_function.hpp index a438ce0c..ff3891e2 100644 --- a/include/boost/python/converter/to_python_function.hpp +++ b/include/boost/python/converter/to_python_function.hpp @@ -8,23 +8,41 @@ # include # include +# include +# include +# include +# include namespace boost { namespace python { namespace converter { -// The type of stored function pointers which actually do conversion -// by-value. The void* points to the object to be converted, and -// type-safety is preserved through runtime registration. -typedef PyObject* (*to_python_value_function)(void const*); - -// Given a typesafe to_python conversion function, produces a -// to_python_value_function which can be registered in the usual way. -template -struct as_to_python_value_function +// to_python_function -- +// +// essentially a "templated global reference" which holds the +// converter for converting a type to Python by-value. We "normalize" +// T by adding "const volatile&" so that fewer global variables and +// associated static initializations are generated. +namespace detail +{ + template + struct to_python_function_base + { + static to_python_function_t const& value; + }; + + template + to_python_function_t const& + to_python_function_base::value + = converter::registry::get_to_python_function(undecorated_type_id()); +} + +template +struct to_python_function + : detail::to_python_function_base< + typename add_reference< + typename add_cv::type + >::type + > { - static PyObject* convert(void const* x) - { - return ToPython::convert(*(T const*)x); - } }; }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/to_python_function_type.hpp b/include/boost/python/converter/to_python_function_type.hpp new file mode 100644 index 00000000..197654e5 --- /dev/null +++ b/include/boost/python/converter/to_python_function_type.hpp @@ -0,0 +1,30 @@ +// Copyright David Abrahams 2002. 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 TO_PYTHON_FUNCTION_TYPE_DWA200236_HPP +# define TO_PYTHON_FUNCTION_TYPE_DWA200236_HPP +# include + +namespace boost { namespace python { namespace converter { + +// The type of stored function pointers which actually do conversion +// by-value. The void* points to the object to be converted, and +// type-safety is preserved through runtime registration. +typedef PyObject* (*to_python_function_t)(void const*); + +// Given a typesafe to_python conversion function, produces a +// to_python_function_t which can be registered in the usual way. +template +struct as_to_python_function +{ + static PyObject* convert(void const* x) + { + return ToPython::convert(*(T const*)x); + } +}; + +}}} // namespace boost::python::converter + +#endif // TO_PYTHON_FUNCTION_TYPE_DWA200236_HPP diff --git a/include/boost/python/to_python_converter.hpp b/include/boost/python/to_python_converter.hpp index 7e46c505..47473419 100644 --- a/include/boost/python/to_python_converter.hpp +++ b/include/boost/python/to_python_converter.hpp @@ -25,7 +25,7 @@ struct to_python_converter template to_python_converter::to_python_converter() { - typedef converter::as_to_python_value_function< + typedef converter::as_to_python_function< T, Conversion > normalized; diff --git a/include/boost/python/to_python_value.hpp b/include/boost/python/to_python_value.hpp index ecff5808..ffb68ada 100644 --- a/include/boost/python/to_python_value.hpp +++ b/include/boost/python/to_python_value.hpp @@ -23,25 +23,14 @@ struct to_python_value static bool convertible(); PyObject* operator()(argument_type) const; - - private: - // Note that this is a pointer to a function pointer - static converter::to_python_value_function const* fconvert; }; -template -converter::to_python_value_function const* -to_python_value::fconvert - = &converter::registry::to_python_function(converter::undecorated_type_id()); - - template bool to_python_value::convertible() { // if this assert fires, our static variable hasn't been set up yet. - assert(fconvert != 0); - return *fconvert != 0; + return converter::to_python_function::value != 0; } template @@ -49,8 +38,7 @@ PyObject* to_python_value::operator()(argument_type x) const { // This might be further optimized on platforms which dynamically // link without specific imports/exports - converter::to_python_value_function f = *fconvert; - return f(&x); + return converter::to_python_function::value(&x); } }} // namespace boost::python diff --git a/src/converter/builtin_converters.cpp b/src/converter/builtin_converters.cpp index fe6708e6..87d0d7b4 100644 --- a/src/converter/builtin_converters.cpp +++ b/src/converter/builtin_converters.cpp @@ -56,7 +56,7 @@ namespace ref intermediate(creator(obj)); // Get the location in which to construct - void* storage = ((rvalue_data*)data)->storage.bytes; + void* storage = ((rvalue_base_data*)data)->storage.bytes; new (storage) T(SlotPolicy::extract(intermediate.get())); // record successful construction diff --git a/src/converter/from_python.cpp b/src/converter/from_python.cpp index 57aee355..8a68cc44 100644 --- a/src/converter/from_python.cpp +++ b/src/converter/from_python.cpp @@ -10,21 +10,23 @@ namespace boost { namespace python { namespace converter { -BOOST_PYTHON_DECL void* find( +BOOST_PYTHON_DECL rvalue_stage1_data find( PyObject* source - , rvalue_from_python_registration const* chain - , rvalue_stage1_data& data) + , rvalue_from_python_registration const* chain) { + rvalue_stage1_data data; + data.convertible = 0; for (;chain != 0; chain = chain->next) { void* r = chain->convertible(source); if (r != 0) { + data.convertible = r; data.construct = chain->construct; - return data.convertible = r; + break; } } - return data.convertible = 0; + return data; } BOOST_PYTHON_DECL void* find( diff --git a/src/converter/registry.cpp b/src/converter/registry.cpp index bdfa1c8a..2d104b01 100644 --- a/src/converter/registry.cpp +++ b/src/converter/registry.cpp @@ -19,7 +19,7 @@ namespace // entry(); // The unique to_python converter for the associated C++ type. - to_python_value_function m_to_python_converter; + to_python_function_t m_to_python_converter; // The collection of from_python converters for the associated // C++ type. @@ -66,15 +66,15 @@ namespace // namespace registry { - to_python_value_function const& to_python_function( + to_python_function_t const& get_to_python_function( undecorated_type_id_t key) { return find(key)->m_to_python_converter; } - void insert(to_python_value_function f, undecorated_type_id_t source_t) + void insert(to_python_function_t f, undecorated_type_id_t source_t) { - to_python_value_function& slot = find(source_t)->m_to_python_converter; + to_python_function_t& slot = find(source_t)->m_to_python_converter; assert(slot == 0); // we have a problem otherwise if (slot != 0) { diff --git a/src/object/function.cpp b/src/object/function.cpp index a30e9f15..a9f0c94d 100644 --- a/src/object/function.cpp +++ b/src/object/function.cpp @@ -112,6 +112,30 @@ void function::add_to_namespace( throw error_already_set(); } +namespace +{ + struct bind_return + { + bind_return(PyObject*& result, function const* f, PyObject* args, PyObject* keywords) + : m_result(result) + , m_f(f) + , m_args(args) + , m_keywords(keywords) + {} + + void operator()() const + { + m_result = m_f->call(m_args, m_keywords); + } + + private: + PyObject*& m_result; + function const* m_f; + PyObject* m_args; + PyObject* m_keywords; + }; +} + extern "C" { // Stolen from Python's funcobject.c @@ -130,9 +154,11 @@ extern "C" } static PyObject * - function_call(PyObject *func, PyObject *arg, PyObject *kw) + function_call(PyObject *func, PyObject *args, PyObject *kw) { - return static_cast(func)->call(arg, kw); + PyObject* result = 0; + handle_exception(bind_return(result, static_cast(func), args, kw)); + return result; } } diff --git a/test/Jamfile b/test/Jamfile new file mode 100644 index 00000000..767b07e6 --- /dev/null +++ b/test/Jamfile @@ -0,0 +1,75 @@ +subproject libs/python/test ; + +# bring in the rules for python +SEARCH on python.jam = $(BOOST_BUILD_PATH) ; +include python.jam ; + +local PYTHON_V1_PROPERTIES = $(PYTHON_PROPERTIES) ; +local PYTHON_PROPERTIES = $(BOOST_PYTHON_V2_PROPERTIES) ; + +# +rule bpl-test ( name ? : files * ) +{ + files ?= $(name).py $(name).cpp ; + + local modules ; + local py ; + for local f in $(files) + { + if $(f:S) = .py + { + if $(py) + { + EXIT too many python drivers specified: "$(py)" "$(f)" ; + } + py = $(f) ; + } + } + + name ?= $(py:S=) ; + + for local f in $(files) + { + if $(f:S) != .py + { + local m = $(f:S=) ; + + if $(m) = $(py:S=) + { + m = $(name) ; + + if $(m) = $(py:S=) + { + m = $(m)_ext ; + } + } + extension $(m) : $(f) ../bpl ; + modules += $(m) ; + } + } + + boost-python-runtest $(name) : $(py) $(modules) ; +} + +bpl-test try : newtest.py m1.cpp m2.cpp ; +bpl-test builtin_converters : test_builtin_converters.py test_builtin_converters.cpp ; +bpl-test test_pointer_adoption ; +bpl-test callbacks ; + +# --- unit tests of library components --- +unit-test indirect_traits_test + : indirect_traits_test.cpp : $(BOOST_ROOT) ; +unit-test destroy_test + : destroy_test.cpp : $(BOOST_ROOT) ; +unit-test pointer_type_id_test + : pointer_type_id_test.cpp : $(BOOST_ROOT) ; + +unit-test select_from_python_test + : select_from_python_test.cpp + ../src/converter/type_id.cpp + # ../src/converter/registry.cpp # MWerks needs this for some reason + + : $(BOOST_ROOT) BOOST_PYTHON_STATIC_LIB + $(PYTHON_V1_PROPERTIES) + ; + diff --git a/test/test_builtin_converters.cpp b/test/test_builtin_converters.cpp index 4c07d9f4..939f9dc4 100644 --- a/test/test_builtin_converters.cpp +++ b/test/test_builtin_converters.cpp @@ -25,9 +25,9 @@ struct by_const_reference } }; -BOOST_PYTHON_MODULE_INIT(builtin_converters_ext) +BOOST_PYTHON_MODULE_INIT(builtin_converters) { - boost::python::module("builtin_converters_ext") + boost::python::module("builtin_converters") .def("rewrap_value_bool", by_value::rewrap) .def("rewrap_value_signed_char", by_value::rewrap) diff --git a/test/test_builtin_converters.py b/test/test_builtin_converters.py index 50d436e5..3958c15a 100644 --- a/test/test_builtin_converters.py +++ b/test/test_builtin_converters.py @@ -1,5 +1,5 @@ """ ->>> from builtin_converters_ext import * +>>> from builtin_converters import * >>> rewrap_value_bool(None) 0 >>> rewrap_value_bool(0) From 532833ff705f4446aeeda0029a2bd5de56c9ed23 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 8 Mar 2002 15:29:39 +0000 Subject: [PATCH 329/369] initial checkin [SVN r13136] --- src/converter/callback.cpp | 69 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/converter/callback.cpp diff --git a/src/converter/callback.cpp b/src/converter/callback.cpp new file mode 100644 index 00000000..b3158500 --- /dev/null +++ b/src/converter/callback.cpp @@ -0,0 +1,69 @@ +// Copyright David Abrahams 2002. 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. + +#include +#include +#include +#include + +namespace boost { namespace python { namespace converter { + +namespace detail +{ + + namespace + { + inline PyObject* convert(void const volatile* source, to_python_function_t converter) + { + if (converter == 0) + { + PyErr_SetString( + PyExc_TypeError + , const_cast("no to_python (by-value) converter found for type")); + throw error_already_set(); + } + return converter(const_cast(source)); + } + } + + callback_to_python_base::callback_to_python_base( + void const volatile* source, to_python_function_t converter) + : callback_to_python_holder(convert(source, converter)) + { + } + + BOOST_PYTHON_DECL void throw_if_not_registered(rvalue_stage1_data const& data) + { + if (!data.convertible) + { + PyErr_SetString( + PyExc_TypeError + , const_cast("no from_python (by-value) converters found for type")); + throw error_already_set(); + } + } + + BOOST_PYTHON_DECL void* convert_rvalue(PyObject* src, rvalue_stage1_data& data, void* storage) + { + ref holder(src); + + data = find(src, static_cast(data.convertible)); + + if (!data.convertible) + { + PyErr_SetString( + PyExc_TypeError + , const_cast("no registered from_python (by-value) converter was able to convert type")); + throw error_already_set(); + } + if (data.construct != 0) + data.construct(src, &data); + + return data.convertible; + } +} + +}}} // namespace boost::python::converter From a25021d215d3801f5c671ccdaa299d4f18bac161 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 8 Mar 2002 15:32:32 +0000 Subject: [PATCH 330/369] Initial checkin [SVN r13137] --- .../converter/rvalue_from_python_chain.hpp | 39 ++++++++++ test/callbacks.cpp | 71 +++++++++++++++++++ test/callbacks.py | 43 +++++++++++ 3 files changed, 153 insertions(+) create mode 100644 include/boost/python/converter/rvalue_from_python_chain.hpp create mode 100644 test/callbacks.cpp create mode 100644 test/callbacks.py diff --git a/include/boost/python/converter/rvalue_from_python_chain.hpp b/include/boost/python/converter/rvalue_from_python_chain.hpp new file mode 100644 index 00000000..c57ef564 --- /dev/null +++ b/include/boost/python/converter/rvalue_from_python_chain.hpp @@ -0,0 +1,39 @@ +// Copyright David Abrahams 2002. 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 RVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP +# define RVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +namespace detail +{ + template + struct rvalue_from_python_chain_impl + { + static rvalue_from_python_registration*const& value; + }; + + template + rvalue_from_python_registration*const& rvalue_from_python_chain_impl::value + = registry::rvalue_converters(undecorated_type_id()); +} + +template +struct rvalue_from_python_chain + : detail::rvalue_from_python_chain_impl< + typename add_reference< + typename add_cv::type + >::type + > +{ +}; + +}}} // namespace boost::python::converter + +#endif // RVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP diff --git a/test/callbacks.cpp b/test/callbacks.cpp new file mode 100644 index 00000000..9991e41f --- /dev/null +++ b/test/callbacks.cpp @@ -0,0 +1,71 @@ +// Copyright David Abrahams 2002. 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. +#include +#include +#include +#include + +using namespace boost::python; + +int apply_int_int(PyObject* f, int x) +{ + return returning::call(f, x); +} + +void apply_void_int(PyObject* f, int x) +{ + returning::call(f, x); +} + +struct X +{ + explicit X(int x) : x(x), magic(7654321) { ++counter; } + X(X const& rhs) : x(rhs.x), magic(7654321) { ++counter; } + ~X() { assert(magic == 7654321); magic = 6666666; x = 9999; --counter; } + + void set(int x) { assert(magic == 7654321); this->x = x; } + int value() const { assert(magic == 7654321); return x; } + static int count() { return counter; } + private: + void operator=(X const&); + private: + int x; + long magic; + static int counter; +}; + +X apply_X_X(PyObject* f, X x) +{ + return returning::call(f, x); +} + +void apply_void_X_ref(PyObject* f, X x) +{ + returning::call(f, boost::ref(x)); +} + +int X::counter; + +BOOST_PYTHON_MODULE_INIT(callbacks_ext) +{ + boost::python::module("callbacks_ext") + .def("apply_int_int", apply_int_int) + .def("apply_void_int", apply_void_int) + .def("apply_X_X", apply_X_X) + .def("apply_void_X_ref", apply_void_X_ref) + .add( + class_("X") + .def_init(args()) + .def_init(args()) + .def("value", &X::value) + .def("set", &X::set) + ) + .def("x_count", &X::count) + ; +} + + + diff --git a/test/callbacks.py b/test/callbacks.py new file mode 100644 index 00000000..16c5be94 --- /dev/null +++ b/test/callbacks.py @@ -0,0 +1,43 @@ +''' +>>> from callbacks_ext import * + +>>> def double(x): +... return x + x +... +>>> apply_int_int(double, 42) +84 +>>> apply_void_int(double, 42) + +>>> def identity(x): +... return x + +>>> x = apply_X_X(identity, X(42)) +>>> x.value() +42 +>>> x_count() +1 +>>> del x +>>> x_count() +0 + +>>> def increment(x): +... x.set(x.value() + 1) +... +>>> x = X(42) +>>> apply_void_X_ref(increment, x) +>>> x.value() +43 +''' + +def run(args = None): + import sys + import doctest + + if args is not None: + sys.argv = args + return doctest.testmod(sys.modules.get(__name__)) + +if __name__ == '__main__': + print "running..." + import sys + sys.exit(run()[0]) From 305469472619b2f22dae6c43a9fdb0e40c661ba7 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 8 Mar 2002 16:05:17 +0000 Subject: [PATCH 331/369] conformance fix [SVN r13138] --- include/boost/python/converter/from_python_data.hpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/include/boost/python/converter/from_python_data.hpp b/include/boost/python/converter/from_python_data.hpp index 9fa9410a..dd0a0282 100644 --- a/include/boost/python/converter/from_python_data.hpp +++ b/include/boost/python/converter/from_python_data.hpp @@ -197,12 +197,10 @@ inline rvalue_data::rvalue_data(void* convertible) template inline rvalue_data::~rvalue_data() { + typedef typename add_reference::type>::type ref_type; + if (this->stage1.convertible == this->storage.bytes) - python::detail::destroy_reference< - add_reference< - add_cv::type - >::type - >(storage.bytes); + python::detail::destroy_reference(this->storage.bytes); } }}} // namespace boost::python::converter From 7e76c855356009ceb5d589a9fe8bcb382169d498 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 8 Mar 2002 16:13:32 +0000 Subject: [PATCH 332/369] initial checkin [SVN r13139] --- include/boost/python/converter/callback.hpp | 113 ++++++++++++++ include/boost/python/returning.hpp | 159 ++++++++++++++++++++ 2 files changed, 272 insertions(+) create mode 100644 include/boost/python/converter/callback.hpp create mode 100644 include/boost/python/returning.hpp diff --git a/include/boost/python/converter/callback.hpp b/include/boost/python/converter/callback.hpp new file mode 100644 index 00000000..3e1e462e --- /dev/null +++ b/include/boost/python/converter/callback.hpp @@ -0,0 +1,113 @@ +// Copyright David Abrahams 2002. 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 CALLBACK_DWA2002228_HPP +# define CALLBACK_DWA2002228_HPP + +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +namespace detail +{ + template + struct pointer_callback_from_python + { + pointer_callback_from_python(); + T operator()(PyObject*) const; + }; + + template + struct reference_callback_from_python + { + reference_callback_from_python(); + T operator()(PyObject*) const; + }; + + template + struct rvalue_callback_from_python + { + rvalue_callback_from_python(); + T const& operator()(PyObject*); + private: + rvalue_data m_data; + }; + + template + struct select_callback_from_python + { + BOOST_STATIC_CONSTANT( + bool, ptr = is_pointer::value); + + BOOST_STATIC_CONSTANT( + bool, ref = is_reference::value); + + typedef typename mpl::select_type< + ptr + , pointer_callback_from_python + , typename mpl::select_type< + ref + , reference_callback_from_python + , rvalue_callback_from_python + >::type + >::type type; + }; + + + template + struct reference_callback_to_python + { + + }; +} + +template +struct callback_from_python + : detail::select_callback_from_python::type +{ +}; + +template +struct callback_to_python : detail::callback_to_python_base +{ + public: // member functions + // Throw an exception if the conversion can't succeed + callback_to_python(T const&); +}; + +// +// Implementations +// +namespace detail +{ + template + rvalue_callback_from_python::rvalue_callback_from_python() + : m_data(rvalue_from_python_chain::value) + { + throw_if_not_registered(m_data.stage1); + } + + template + T const& rvalue_callback_from_python::operator()(PyObject* obj) + { + return *(T*)convert_rvalue(obj, m_data.stage1, m_data.storage.bytes); + } +} + +template +callback_to_python::callback_to_python(T const& x) + : callback_to_python_base(&x, to_python_function::value) +{ +} + +}}} // namespace boost::python::converter + +#endif // CALLBACK_DWA2002228_HPP diff --git a/include/boost/python/returning.hpp b/include/boost/python/returning.hpp new file mode 100644 index 00000000..c34f97f6 --- /dev/null +++ b/include/boost/python/returning.hpp @@ -0,0 +1,159 @@ +// (C) Copyright David Abrahams 2001,2002. 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_DWA20020228_HPP +# define RETURNING_DWA20020228_HPP + +# include +# include +# include +# include + +namespace boost { namespace python { + +// Calling C++ from Python +template +struct returning +{ + static R call(char const* name, PyObject* self) + { + converter::callback_from_python cr; + return cr(PyEval_CallMethod( + self + , const_cast(name) + , const_cast("()") + )); + } + + static R call(PyObject* self) + { + converter::callback_from_python cr; + return cr(PyEval_CallFunction(self, const_cast("()") + )); + } + + template + static R call_method(PyObject* self, const char* name, A1 const& a1) + { + converter::callback_from_python cr; + return cr(PyEval_CallMethod( + self + , const_cast(name) + , const_cast("(O)") + , converter::callback_to_python(a1).get() + )); + } + + template + static R call(PyObject* self, A1 const& a1) + { + converter::callback_from_python cr; + return cr(PyEval_CallFunction( + self + , const_cast("(O)") + , converter::callback_to_python(a1).get() + )); + } + + template + static R call_method(PyObject* self, const char* name, A1 const& a1, A2 const& a2) + { + converter::callback_from_python cr; + return cr(PyEval_CallMethod( + self + , const_cast(name) + , const_cast("(O)") + , converter::callback_to_python(a1).get() + , converter::callback_to_python(a2).get() + )); + } + + template + static R call(PyObject* self, A1 const& a1, A2 const& a2) + { + converter::callback_from_python cr; + return cr(PyEval_CallFunction( + self + , const_cast("(O)") + , converter::callback_to_python(a1).get() + , converter::callback_to_python(a2).get() + )); + } + +}; + +template <> +struct returning +{ + typedef void R; + static R call(char const* name, PyObject* self) + { + ref x(PyEval_CallMethod( + self + , const_cast(name) + , const_cast("()") + )); + } + + static R call(PyObject* self) + { + ref x(PyEval_CallFunction(self, const_cast("()") + )); + } + + template + static R call_method(PyObject* self, const char* name, A1 const& a1) + { + ref x(PyEval_CallMethod( + self + , const_cast(name) + , const_cast("(O)") + , converter::callback_to_python(a1).get() + )); + } + + template + static R call(PyObject* self, A1 const& a1) + { + ref x(PyEval_CallFunction( + self + , const_cast("(O)") + , converter::callback_to_python(a1).get() + )); + } + + template + static R call_method(PyObject* self, const char* name, A1 const& a1, A2 const& a2) + { + ref x(PyEval_CallMethod( + self + , const_cast(name) + , const_cast("(O)") + , converter::callback_to_python(a1).get() + , converter::callback_to_python(a2).get() + )); + } + + template + static R call(PyObject* self, A1 const& a1, A2 const& a2) + { + ref x(PyEval_CallFunction( + self + , const_cast("(O)") + , converter::callback_to_python(a1).get() + , converter::callback_to_python(a2).get() + )); + } +}; + +}} // namespace boost::python + +#endif // RETURNING_DWA20020228_HPP + From a16d9f91eea41c8cb1dbe1b2a77aa1d84bd6454a Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 8 Mar 2002 16:14:26 +0000 Subject: [PATCH 333/369] Initial checkin [SVN r13140] --- .../converter/callback_from_python_base.hpp | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 include/boost/python/converter/callback_from_python_base.hpp diff --git a/include/boost/python/converter/callback_from_python_base.hpp b/include/boost/python/converter/callback_from_python_base.hpp new file mode 100644 index 00000000..0eeccb0e --- /dev/null +++ b/include/boost/python/converter/callback_from_python_base.hpp @@ -0,0 +1,20 @@ +// Copyright David Abrahams 2002. 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 CALLBACK_FROM_PYTHON_BASE_DWA200237_HPP +# define CALLBACK_FROM_PYTHON_BASE_DWA200237_HPP + +namespace boost { namespace python { namespace converter { + +namespace detail +{ + // Throw an exception + BOOST_PYTHON_DECL void throw_if_not_registered(rvalue_stage1_data const&); + BOOST_PYTHON_DECL void* convert_rvalue(PyObject*, rvalue_stage1_data& data, void* storage); +} + +}}} // namespace boost::python::converter + +#endif // CALLBACK_FROM_PYTHON_BASE_DWA200237_HPP From 7c009e2443e210fa9fffc53d080c68a6d14dd63d Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 9 Mar 2002 20:51:43 +0000 Subject: [PATCH 334/369] Added static assertion to be sure it's not used on values [SVN r13146] --- include/boost/python/to_python_indirect.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/python/to_python_indirect.hpp b/include/boost/python/to_python_indirect.hpp index 7b77f5ff..fbbfc6f7 100644 --- a/include/boost/python/to_python_indirect.hpp +++ b/include/boost/python/to_python_indirect.hpp @@ -72,6 +72,7 @@ namespace detail template inline bool to_python_indirect::convertible() { + BOOST_STATIC_ASSERT(is_pointer::value || is_reference::value); return type() != 0; } From 0301d4462b8c9a90a7b157c9cfe2da336e94373b Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 9 Mar 2002 21:01:36 +0000 Subject: [PATCH 335/369] Added reference, deep and shallow pointer to_python conversions [SVN r13147] --- include/boost/python/converter/callback.hpp | 121 ++++++++++++++++++-- 1 file changed, 112 insertions(+), 9 deletions(-) diff --git a/include/boost/python/converter/callback.hpp b/include/boost/python/converter/callback.hpp index 3e1e462e..756466e3 100644 --- a/include/boost/python/converter/callback.hpp +++ b/include/boost/python/converter/callback.hpp @@ -8,11 +8,15 @@ # include # include +# include # include # include # include # include # include +# include +# include +# include namespace boost { namespace python { namespace converter { @@ -63,9 +67,64 @@ namespace detail template - struct reference_callback_to_python + struct reference_callback_to_python : callback_to_python_holder { + reference_callback_to_python(T& x); + private: + static PyObject* get_object(T& x); + }; + + template + struct value_callback_to_python : callback_to_python_base + { + // Throw an exception if the conversion can't succeed + value_callback_to_python(T const&); + }; + + template + struct pointer_deep_callback_to_python : callback_to_python_base + { + // Throw an exception if the conversion can't succeed + pointer_deep_callback_to_python(Ptr); + }; + + template + struct pointer_shallow_callback_to_python : callback_to_python_holder + { + // Throw an exception if the conversion can't succeed + pointer_shallow_callback_to_python(Ptr); + private: + static PyObject* get_object(Ptr p); + }; + + template + struct select_callback_to_python + { + BOOST_STATIC_CONSTANT( + bool, ptr = is_pointer::value); + BOOST_STATIC_CONSTANT( + bool, ref_wrapper = is_reference_wrapper::value); + + BOOST_STATIC_CONSTANT( + bool, ptr_wrapper = is_pointer_wrapper::value); + + typedef typename unwrap_reference::type unwrapped_referent; + typedef typename unwrap_pointer::type unwrapped_ptr; + + typedef typename mpl::select_type< + ptr + , pointer_deep_callback_to_python + , typename mpl::select_type< + ptr_wrapper + , pointer_shallow_callback_to_python + , typename mpl::select_type< + ref_wrapper + , reference_callback_to_python + , value_callback_to_python + >::type + >::type + >::type type; }; } @@ -76,11 +135,13 @@ struct callback_from_python }; template -struct callback_to_python : detail::callback_to_python_base +struct callback_to_python + : detail::select_callback_to_python::type { + typedef typename detail::select_callback_to_python::type base; public: // member functions // Throw an exception if the conversion can't succeed - callback_to_python(T const&); + callback_to_python(T const& x); }; // @@ -89,24 +150,66 @@ struct callback_to_python : detail::callback_to_python_base namespace detail { template - rvalue_callback_from_python::rvalue_callback_from_python() + inline rvalue_callback_from_python::rvalue_callback_from_python() : m_data(rvalue_from_python_chain::value) { throw_if_not_registered(m_data.stage1); } template - T const& rvalue_callback_from_python::operator()(PyObject* obj) + inline T const& rvalue_callback_from_python::operator()(PyObject* obj) { return *(T*)convert_rvalue(obj, m_data.stage1, m_data.storage.bytes); } + + BOOST_PYTHON_DECL void throw_no_class_registered(); + + template + inline value_callback_to_python::value_callback_to_python(T const& x) + : callback_to_python_base(&x, to_python_function::value) + { + } + + template + inline pointer_deep_callback_to_python::pointer_deep_callback_to_python(Ptr x) + : callback_to_python_base(x, pointee_to_python_function::value) + { + } + + template + inline PyObject* reference_callback_to_python::get_object(T& x) + { + to_python_indirect convert; + if (!convert.convertible()) + throw_no_class_registered(); + return convert(x); + } + + template + inline reference_callback_to_python::reference_callback_to_python(T& x) + : callback_to_python_holder(get_object(x)) + { + } + + template + inline pointer_shallow_callback_to_python::pointer_shallow_callback_to_python(Ptr x) + : callback_to_python_holder(get_object(x)) + {} + + template + inline PyObject* pointer_shallow_callback_to_python::get_object(Ptr x) + { + to_python_indirect convert; + if (!convert.convertible()) + throw_no_class_registered(); + return x ? convert(x) : python::detail::none(); + } } template -callback_to_python::callback_to_python(T const& x) - : callback_to_python_base(&x, to_python_function::value) -{ -} +inline callback_to_python::callback_to_python(T const& x) + : base(x) +{} }}} // namespace boost::python::converter From 69d7011baf1ed100df3bc5585278c27c00f8d1c5 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 9 Mar 2002 21:02:18 +0000 Subject: [PATCH 336/369] Killed bogus #include [SVN r13148] --- include/boost/python/converter/from_python.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/boost/python/converter/from_python.hpp b/include/boost/python/converter/from_python.hpp index 5fe8901a..03bfcb26 100644 --- a/include/boost/python/converter/from_python.hpp +++ b/include/boost/python/converter/from_python.hpp @@ -10,7 +10,6 @@ # include # include # include -# include # include # include # include From 74fe5bc4dd45dcb852a2d4c2487f799e522a3aea Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 9 Mar 2002 21:05:18 +0000 Subject: [PATCH 337/369] Killed bogus #include msvc6 workaround [SVN r13149] --- include/boost/python/converter/from_python_data.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/boost/python/converter/from_python_data.hpp b/include/boost/python/converter/from_python_data.hpp index dd0a0282..1ce8bd7a 100644 --- a/include/boost/python/converter/from_python_data.hpp +++ b/include/boost/python/converter/from_python_data.hpp @@ -15,7 +15,6 @@ # include # include # include -# include # include # include # include @@ -177,6 +176,8 @@ struct rvalue_data : rvalue_base_data rvalue_data(rvalue_stage1_data const&); rvalue_data(void*); ~rvalue_data(); + private: + typedef typename add_reference::type>::type ref_type; }; // @@ -197,8 +198,6 @@ inline rvalue_data::rvalue_data(void* convertible) template inline rvalue_data::~rvalue_data() { - typedef typename add_reference::type>::type ref_type; - if (this->stage1.convertible == this->storage.bytes) python::detail::destroy_reference(this->storage.bytes); } From 22f66123541e90f825519712ed7c13a25e9312ad Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 9 Mar 2002 21:08:04 +0000 Subject: [PATCH 338/369] Killed ambiguity-causing overload [SVN r13150] --- include/boost/python/detail/unwind_type.hpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/include/boost/python/detail/unwind_type.hpp b/include/boost/python/detail/unwind_type.hpp index e8ccd0c8..72ebef71 100644 --- a/include/boost/python/detail/unwind_type.hpp +++ b/include/boost/python/detail/unwind_type.hpp @@ -68,13 +68,6 @@ struct unwind_helper } }; -template -inline typename Generator::result_type -unwind_type(U& p, Generator* = 0) -{ - return unwind_helper::value>::execute(p, (Generator*)0); -} - template inline typename Generator::result_type unwind_type(U const& p, Generator* = 0) From f271726cd8687370551587e95a92a6b977d136d9 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 9 Mar 2002 21:13:09 +0000 Subject: [PATCH 339/369] Added reference, deep and shallow pointer to_python conversions [SVN r13152] --- .../converter/pointee_to_python_function.hpp | 51 +++++++++++++++++++ src/converter/callback.cpp | 14 ++++- test/callbacks.cpp | 26 ++++++++-- test/callbacks.py | 39 ++++++++++++++ 4 files changed, 125 insertions(+), 5 deletions(-) create mode 100644 include/boost/python/converter/pointee_to_python_function.hpp diff --git a/include/boost/python/converter/pointee_to_python_function.hpp b/include/boost/python/converter/pointee_to_python_function.hpp new file mode 100644 index 00000000..0f1ae99e --- /dev/null +++ b/include/boost/python/converter/pointee_to_python_function.hpp @@ -0,0 +1,51 @@ +// Copyright David Abrahams 2002. 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 POINTEE_TO_PYTHON_FUNCTION_DWA2002128_HPP +# define POINTEE_TO_PYTHON_FUNCTION_DWA2002128_HPP + +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +// pointee_to_python_function -- +// +// essentially a "templated global reference" which holds the +// converter for converting a type to Python by-value. We "normalize" +// T by adding "const volatile&" so that fewer global variables and +// associated static initializations are generated. +namespace detail +{ + template + struct pointee_to_python_function_base + { + static to_python_function_t const& value; + }; + + template + to_python_function_t const& + pointee_to_python_function_base::value + = converter::registry::get_to_python_function(pointer_type_id()); +} + +template +struct pointee_to_python_function + : detail::pointee_to_python_function_base< + typename add_reference< + typename add_cv::type + >::type + > +{ +}; + +}}} // namespace boost::python::converter + +#endif // POINTEE_TO_PYTHON_FUNCTION_DWA2002128_HPP diff --git a/src/converter/callback.cpp b/src/converter/callback.cpp index b3158500..a248f1ad 100644 --- a/src/converter/callback.cpp +++ b/src/converter/callback.cpp @@ -8,6 +8,7 @@ #include #include #include +#include namespace boost { namespace python { namespace converter { @@ -25,7 +26,10 @@ namespace detail , const_cast("no to_python (by-value) converter found for type")); throw error_already_set(); } - return converter(const_cast(source)); + + return source == 0 + ? python::detail::none() + : converter(const_cast(source)); } } @@ -45,6 +49,14 @@ namespace detail throw error_already_set(); } } + + BOOST_PYTHON_DECL void throw_no_class_registered() + { + PyErr_SetString( + PyExc_TypeError + , const_cast("class not registered for to_python type")); + throw error_already_set(); + } BOOST_PYTHON_DECL void* convert_rvalue(PyObject* src, rvalue_stage1_data& data, void* storage) { diff --git a/test/callbacks.cpp b/test/callbacks.cpp index 9991e41f..2bf285b5 100644 --- a/test/callbacks.cpp +++ b/test/callbacks.cpp @@ -7,6 +7,7 @@ #include #include #include +#include using namespace boost::python; @@ -42,9 +43,24 @@ X apply_X_X(PyObject* f, X x) return returning::call(f, x); } -void apply_void_X_ref(PyObject* f, X x) +void apply_void_X_ref(PyObject* f, X& x) { - returning::call(f, boost::ref(x)); + returning::call(f, boost::ref(x)); +} + +void apply_void_X_cref(PyObject* f, X const& x) +{ + returning::call(f, boost::cref(x)); +} + +void apply_void_X_ptr(PyObject* f, X* x) +{ + returning::call(f, ptr(x)); +} + +void apply_void_X_deep_ptr(PyObject* f, X* x) +{ + returning::call(f, x); } int X::counter; @@ -56,6 +72,9 @@ BOOST_PYTHON_MODULE_INIT(callbacks_ext) .def("apply_void_int", apply_void_int) .def("apply_X_X", apply_X_X) .def("apply_void_X_ref", apply_void_X_ref) + .def("apply_void_X_cref", apply_void_X_cref) + .def("apply_void_X_ptr", apply_void_X_ptr) + .def("apply_void_X_deep_ptr", apply_void_X_deep_ptr) .add( class_("X") .def_init(args()) @@ -67,5 +86,4 @@ BOOST_PYTHON_MODULE_INIT(callbacks_ext) ; } - - +#include "module_tail.cpp" diff --git a/test/callbacks.py b/test/callbacks.py index 16c5be94..810aad53 100644 --- a/test/callbacks.py +++ b/test/callbacks.py @@ -27,6 +27,45 @@ >>> apply_void_X_ref(increment, x) >>> x.value() 43 + +>>> apply_void_X_cref(increment, x) +>>> x.value() # const-ness is not respected, sorry! +44 + +>>> last_x = 1 +>>> def decrement(x): +... global last_x +... last_x = x +... if x is not None: +... x.set(x.value() - 1) + +>>> apply_void_X_ptr(decrement, x) +>>> x.value() +43 +>>> last_x.value() +43 +>>> increment(last_x) +>>> x.value() +44 +>>> last_x.value() +44 + +>>> apply_void_X_ptr(decrement, None) +>>> assert last_x is None +>>> x.value() +44 + +>>> last_x = 1 +>>> apply_void_X_deep_ptr(decrement, None) +>>> assert last_x is None +>>> x.value() +44 + +>>> apply_void_X_deep_ptr(decrement, x) +>>> x.value() +44 +>>> last_x.value() +43 ''' def run(args = None): From 5da8206915a4d4fabc0659f88c8b1a620eef85d7 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 9 Mar 2002 21:13:26 +0000 Subject: [PATCH 340/369] initial checkin [SVN r13153] --- include/boost/python/ptr.hpp | 127 +++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 include/boost/python/ptr.hpp diff --git a/include/boost/python/ptr.hpp b/include/boost/python/ptr.hpp new file mode 100644 index 00000000..4e0f067e --- /dev/null +++ b/include/boost/python/ptr.hpp @@ -0,0 +1,127 @@ +#ifndef BOOST_PTR_HPP_INCLUDED +# define BOOST_PTR_HPP_INCLUDED +// Copyright David Abrahams 2002. 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. +// +// Based on boost/ref.hpp, thus: +// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi) +// Copyright (C) 2001 Peter Dimov + +# if _MSC_VER+0 >= 1020 +# pragma once +# endif + +# include + +namespace boost { namespace python { + +template class pointer_wrapper +{ + public: + typedef Ptr type; + + explicit pointer_wrapper(Ptr x): p_(x) {} + operator Ptr() const { return p_; } + Ptr get() const { return p_; } + private: + Ptr p_; +}; + +template +inline pointer_wrapper ptr(T t) +{ + return pointer_wrapper(t); +} + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +class is_pointer_wrapper +{ + public: + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +template +class is_pointer_wrapper > +{ + public: + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +template +class unwrap_pointer +{ + public: + typedef T type; +}; + +template +class unwrap_pointer > +{ + public: + typedef T type; +}; +# else // no partial specialization + +}} // namespace boost::python + +#include + +namespace boost { namespace python { + +namespace detail +{ + typedef char (&yes_pointer_wrapper_t)[1]; + typedef char (&no_pointer_wrapper_t)[2]; + + no_pointer_wrapper_t is_pointer_wrapper_test(...); + + template + yes_pointer_wrapper_t is_pointer_wrapper_test(type< pointer_wrapper >); + + template + struct pointer_unwrapper + { + template + struct apply + { + typedef T type; + }; + }; + + template<> + struct pointer_unwrapper + { + template + struct apply + { + typedef typename T::type type; + }; + }; +} + +template +class is_pointer_wrapper +{ + public: + BOOST_STATIC_CONSTANT( + bool, value = ( + sizeof(detail::is_pointer_wrapper_test(type())) + == sizeof(detail::yes_pointer_wrapper_t))); +}; + +template +class unwrap_pointer + : public detail::pointer_unwrapper< + is_pointer_wrapper::value + >::template apply +{}; + +# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +}} // namespace boost::python + +#endif // #ifndef BOOST_PTR_HPP_INCLUDED From 74078552df235f7adf34d8f397387d072bd2608b Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 9 Mar 2002 23:59:04 +0000 Subject: [PATCH 341/369] Improved error messages Added support for pointer/reference returns [SVN r13154] --- src/converter/callback.cpp | 43 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/src/converter/callback.cpp b/src/converter/callback.cpp index a248f1ad..68ea32f1 100644 --- a/src/converter/callback.cpp +++ b/src/converter/callback.cpp @@ -45,11 +45,50 @@ namespace detail { PyErr_SetString( PyExc_TypeError - , const_cast("no from_python (by-value) converters found for type")); + , const_cast("no from_python rvalue or lvalue converters found for type")); throw error_already_set(); } } + BOOST_PYTHON_DECL void throw_if_not_registered(lvalue_from_python_registration*const& x) + { + if (!x) + { + PyErr_SetString( + PyExc_TypeError + , const_cast("no from_python lvalue converters found for type")); + throw error_already_set(); + } + } + + BOOST_PYTHON_DECL void* callback_convert_reference( + PyObject* source + , lvalue_from_python_registration*const& converters) + { + ref holder(source); + void* result = find(source, converters); + if (!result) + { + PyErr_SetString( + PyExc_TypeError + , const_cast("no registered from_python lvalue converter was able to convert object")); + throw error_already_set(); + } + return result; + } + + BOOST_PYTHON_DECL void* callback_convert_pointer( + PyObject* source + , lvalue_from_python_registration*const& converters) + { + if (source == Py_None) + { + Py_DECREF(source); + return 0; + } + return callback_convert_reference(source, converters); + } + BOOST_PYTHON_DECL void throw_no_class_registered() { PyErr_SetString( @@ -68,7 +107,7 @@ namespace detail { PyErr_SetString( PyExc_TypeError - , const_cast("no registered from_python (by-value) converter was able to convert type")); + , const_cast("no registered from_python lvalue or rvalue converter was able to convert object")); throw error_already_set(); } if (data.construct != 0) From ae1c1b3a47e7a76d572ce13e8aa473d5c8ff9e06 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 10 Mar 2002 06:25:09 +0000 Subject: [PATCH 342/369] Improved None <==> NULL correspondence [SVN r13155] --- include/boost/python/to_python_indirect.hpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/include/boost/python/to_python_indirect.hpp b/include/boost/python/to_python_indirect.hpp index fbbfc6f7..a636ff66 100644 --- a/include/boost/python/to_python_indirect.hpp +++ b/include/boost/python/to_python_indirect.hpp @@ -67,6 +67,22 @@ namespace detail return python::objects::class_object::reference; } }; + + // null_pointer_to_none -- return none() for null pointers and 0 for all other types/values + // + // Uses simulated partial ordering + template + inline PyObject* null_pointer_to_none(T&, int) + { + return 0; + } + + // overload for pointers + template + inline PyObject* null_pointer_to_none(T* x, long) + { + return x == 0 ? python::detail::none() : 0; + } } template @@ -79,6 +95,10 @@ inline bool to_python_indirect::convertible() template inline PyObject* to_python_indirect::operator()(T x) const { + PyObject* const null_result = detail::null_pointer_to_none(x, 1L); + if (null_result != 0) + return null_result; + PyObject* raw_result = type()->tp_alloc(type(), 0); if (raw_result == 0) From 7eb42dc36b02149979fac59a28a3477b758cae51 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 10 Mar 2002 06:26:11 +0000 Subject: [PATCH 343/369] factored out void_ptr manipulations [SVN r13156] --- include/boost/python/type_from_python.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/boost/python/type_from_python.hpp b/include/boost/python/type_from_python.hpp index 16b8da81..d5b9faed 100644 --- a/include/boost/python/type_from_python.hpp +++ b/include/boost/python/type_from_python.hpp @@ -7,6 +7,7 @@ # define TYPE_FROM_PYTHON_DWA2002130_HPP # include +# include namespace boost { namespace python { @@ -31,7 +32,7 @@ namespace detail { typedef typename boost::add_reference::type param; return &Extractor::execute( - boost::python::converter::detail::void_ptr_to_reference( + boost::python::detail::void_ptr_to_reference( op, (param(*)())0 ) ); } From 688c64ce2118e2231a93adbfe75a8c8cf81a644f Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 10 Mar 2002 06:29:05 +0000 Subject: [PATCH 344/369] char conversions Handle dangling references [SVN r13157] --- .../python/converter/builtin_converters.hpp | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/include/boost/python/converter/builtin_converters.hpp b/include/boost/python/converter/builtin_converters.hpp index 4db0eb9c..c0d2ba09 100644 --- a/include/boost/python/converter/builtin_converters.hpp +++ b/include/boost/python/converter/builtin_converters.hpp @@ -27,9 +27,13 @@ namespace detail namespace converter { template struct callback_to_python; + BOOST_PYTHON_DECL PyObject* do_call_to_python(char); + BOOST_PYTHON_DECL PyObject* do_call_to_python(char const*); + BOOST_PYTHON_DECL PyObject* do_call_to_python(PyObject*); + BOOST_PYTHON_DECL PyObject* do_callback_to_python(PyObject*); } -# define BOOST_PYTHON_TO_PYTHON_BY_VALUE(T, expr) \ +# define BOOST_PYTHON_CALL_TO_PYTHON_BY_VALUE(T, expr) \ template <> struct to_python_value \ : detail::builtin_to_python \ { \ @@ -45,7 +49,9 @@ namespace converter { \ return (expr); \ } \ - }; \ + }; + +# define BOOST_PYTHON_CALLBACK_TO_PYTHON_BY_VALUE(T, expr) \ namespace converter \ { \ template <> struct callback_to_python< T > \ @@ -57,8 +63,11 @@ namespace converter private: \ ref m_held; \ }; \ - } + } +# define BOOST_PYTHON_TO_PYTHON_BY_VALUE(T, expr) \ + BOOST_PYTHON_CALL_TO_PYTHON_BY_VALUE(T,expr) \ + BOOST_PYTHON_CALLBACK_TO_PYTHON_BY_VALUE(T,expr) # define BOOST_PYTHON_TO_INT(T) \ BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, PyInt_FromLong(x)) \ @@ -71,12 +80,14 @@ BOOST_PYTHON_TO_INT(int) BOOST_PYTHON_TO_INT(long) # undef BOOST_TO_PYTHON_INT -BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, x ? PyString_FromString(x) : boost::python::detail::none()) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(char, converter::do_call_to_python(x)) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, converter::do_call_to_python(x)) BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, PyString_FromString(x.c_str())) BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, PyFloat_FromDouble(x)) BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, PyFloat_FromDouble(x)) BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, PyFloat_FromDouble(x)) -BOOST_PYTHON_TO_PYTHON_BY_VALUE(PyObject*, (x ? x : boost::python::detail::none())) +BOOST_PYTHON_CALL_TO_PYTHON_BY_VALUE(PyObject*, converter::do_call_to_python(x)) +BOOST_PYTHON_CALLBACK_TO_PYTHON_BY_VALUE(PyObject*, converter::do_callback_to_python(x)) BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, PyComplex_FromDoubles(x.real(), x.imag())) BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, PyComplex_FromDoubles(x.real(), x.imag())) BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, PyComplex_FromDoubles(x.real(), x.imag())) From 3447aaa8c67c3a648f2af72473bd2ac7c7f542df Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 10 Mar 2002 06:32:07 +0000 Subject: [PATCH 345/369] Pointer/reference from_python callback conversions [SVN r13158] --- include/boost/python/converter/callback.hpp | 26 +++++++++++++++++++ .../converter/callback_from_python_base.hpp | 5 ++++ 2 files changed, 31 insertions(+) diff --git a/include/boost/python/converter/callback.hpp b/include/boost/python/converter/callback.hpp index 756466e3..a8fceb53 100644 --- a/include/boost/python/converter/callback.hpp +++ b/include/boost/python/converter/callback.hpp @@ -164,6 +164,32 @@ namespace detail BOOST_PYTHON_DECL void throw_no_class_registered(); + template + inline reference_callback_from_python::reference_callback_from_python() + { + detail::throw_if_not_registered(lvalue_from_python_chain::value); + } + + template + inline T reference_callback_from_python::operator()(PyObject* obj) const + { + return python::detail::void_ptr_to_reference( + callback_convert_reference(obj, lvalue_from_python_chain::value) + , (T(*)())0); + } + + template + inline pointer_callback_from_python::pointer_callback_from_python() + { + detail::throw_if_not_registered(lvalue_from_python_chain::value); + } + + template + inline T pointer_callback_from_python::operator()(PyObject* obj) const + { + return T(callback_convert_pointer(obj, lvalue_from_python_chain::value)); + } + template inline value_callback_to_python::value_callback_to_python(T const& x) : callback_to_python_base(&x, to_python_function::value) diff --git a/include/boost/python/converter/callback_from_python_base.hpp b/include/boost/python/converter/callback_from_python_base.hpp index 0eeccb0e..117ba145 100644 --- a/include/boost/python/converter/callback_from_python_base.hpp +++ b/include/boost/python/converter/callback_from_python_base.hpp @@ -10,9 +10,14 @@ namespace boost { namespace python { namespace converter { namespace detail { + // Throw an exception BOOST_PYTHON_DECL void throw_if_not_registered(rvalue_stage1_data const&); BOOST_PYTHON_DECL void* convert_rvalue(PyObject*, rvalue_stage1_data& data, void* storage); + + BOOST_PYTHON_DECL void throw_if_not_registered(lvalue_from_python_registration*const&); + BOOST_PYTHON_DECL void* callback_convert_reference(PyObject*, lvalue_from_python_registration*const&); + BOOST_PYTHON_DECL void* callback_convert_pointer(PyObject*, lvalue_from_python_registration*const&); } }}} // namespace boost::python::converter From 948cde1a312e2a777d5fcf2fd1c24f2cfd9cf6fd Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 10 Mar 2002 06:33:13 +0000 Subject: [PATCH 346/369] factored out void_ptr manipulations [SVN r13159] --- .../boost/python/converter/from_python.hpp | 32 ++++--------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/include/boost/python/converter/from_python.hpp b/include/boost/python/converter/from_python.hpp index 03bfcb26..1c6a8b3c 100644 --- a/include/boost/python/converter/from_python.hpp +++ b/include/boost/python/converter/from_python.hpp @@ -15,6 +15,7 @@ # include # include # include +# include namespace boost { namespace python { namespace converter { @@ -143,12 +144,6 @@ inline void*const& from_python_base::result() const namespace detail { - template - inline U& void_ptr_to_reference(void const volatile* p, U&(*)()) - { - return *(U*)p; - } - template struct null_ptr_owner { @@ -161,27 +156,12 @@ namespace detail { return null_ptr_owner::value; } - - template - inline void write_void_ptr(void const volatile* storage, void* ptr, T*) - { - *(T**)storage = (T*)ptr; - } - - // writes U(ptr) into the storage - template - inline void write_void_ptr_reference(void const volatile* storage, void* ptr, U&(*)()) - { - // stripping CV qualification suppresses warnings on older EDGs - typedef typename remove_cv::type u_stripped; - write_void_ptr(storage, ptr, u_stripped(0)); - } } template inline pointer_const_reference_from_python::pointer_const_reference_from_python(PyObject* p) { - detail::write_void_ptr_reference( + python::detail::write_void_ptr_reference( m_result.bytes , p == Py_None ? p : find(p, lvalue_from_python_chain::value) , (T(*)())0); @@ -190,14 +170,14 @@ inline pointer_const_reference_from_python::pointer_const_reference_from_pyth template inline bool pointer_const_reference_from_python::convertible() const { - return detail::void_ptr_to_reference(m_result.bytes, (T(*)())0) != 0; + return python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0) != 0; } template inline T pointer_const_reference_from_python::operator()(PyObject* p) const { return (p == Py_None) ? detail::null_ptr_reference((T(*)())0) - : detail::void_ptr_to_reference(m_result.bytes, (T(*)())0); + : python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0); } // -------- @@ -225,7 +205,7 @@ inline reference_from_python::reference_from_python(PyObject* p) template inline T reference_from_python::operator()(PyObject*) const { - return detail::void_ptr_to_reference(result(), (T(*)())0); + return python::detail::void_ptr_to_reference(result(), (T(*)())0); } // ------- @@ -249,7 +229,7 @@ rvalue_from_python::operator()(PyObject* p) if (m_data.stage1.construct != 0) m_data.stage1.construct(p, &m_data.stage1); - return detail::void_ptr_to_reference(m_data.stage1.convertible, (result_type(*)())0); + return python::detail::void_ptr_to_reference(m_data.stage1.convertible, (result_type(*)())0); } }}} // namespace boost::python::converter From e589d7f1e1a791b2a554b7a6097140f9c4ee89b8 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 10 Mar 2002 06:35:59 +0000 Subject: [PATCH 347/369] adjustments for use with callbacks [SVN r13161] --- .../python/converter/lvalue_from_python_chain.hpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/include/boost/python/converter/lvalue_from_python_chain.hpp b/include/boost/python/converter/lvalue_from_python_chain.hpp index f1417460..2a86bcfa 100644 --- a/include/boost/python/converter/lvalue_from_python_chain.hpp +++ b/include/boost/python/converter/lvalue_from_python_chain.hpp @@ -14,7 +14,9 @@ namespace boost { namespace python { namespace converter { // Given T == U*cv&, T == U*, or T == U&, lvalue_from_python_chain // declares a "templated global reference" to the lvalue from_python -// converter chain for U +// converter chain for U. The optional bool second argument callback, +// when true, removes special treatment for T == U*cv& so that the +// converter for U* is found. namespace detail { template @@ -39,12 +41,13 @@ namespace detail ref_lvalue_from_python_chain::value = registry::lvalue_converters(undecorated_type_id()); - template + template struct select_lvalue_from_python_chain { BOOST_STATIC_CONSTANT( - bool, ptr = boost::python::detail::is_reference_to_pointer::value - || is_pointer::value); + bool, ptr + = !callback && boost::python::detail::is_reference_to_pointer::value + || is_pointer::value); typedef typename add_reference::type>::type normalized; @@ -56,9 +59,9 @@ namespace detail }; } -template +template struct lvalue_from_python_chain - : detail::select_lvalue_from_python_chain::type + : detail::select_lvalue_from_python_chain::type { }; From a56f66e721476e199d917fb1d23d58a795dabddd Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 10 Mar 2002 06:37:58 +0000 Subject: [PATCH 348/369] Factor to_python guts [SVN r13162] --- src/converter/builtin_converters.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/converter/builtin_converters.cpp b/src/converter/builtin_converters.cpp index 87d0d7b4..0ded9c78 100644 --- a/src/converter/builtin_converters.cpp +++ b/src/converter/builtin_converters.cpp @@ -232,6 +232,30 @@ namespace }; } +BOOST_PYTHON_DECL PyObject* do_call_to_python(char x) +{ + return PyString_FromStringAndSize(&x, 1); +} + +BOOST_PYTHON_DECL PyObject* do_call_to_python(char const* x) +{ + return x ? PyString_FromString(x) : boost::python::detail::none(); +} + +BOOST_PYTHON_DECL PyObject* do_call_to_python(PyObject* x) +{ + return x ? x : boost::python::detail::none(); +} + +BOOST_PYTHON_DECL PyObject* do_callback_to_python(PyObject* x) +{ + if (x == 0) + return boost::python::detail::none(); + + Py_INCREF(x); + return x; +} + #define REGISTER_INT_CONVERTERS(U) slot_rvalue_from_python() #define REGISTER_INT_CONVERTERS2(U) REGISTER_INT_CONVERTERS(signed U); REGISTER_INT_CONVERTERS(unsigned U) From be6016a97200d651198a187d1321f16475b907fa Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 10 Mar 2002 06:38:50 +0000 Subject: [PATCH 349/369] Prevent dangling reference returns [SVN r13163] --- src/converter/callback.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/converter/callback.cpp b/src/converter/callback.cpp index 68ea32f1..0ff0c29a 100644 --- a/src/converter/callback.cpp +++ b/src/converter/callback.cpp @@ -66,6 +66,13 @@ namespace detail , lvalue_from_python_registration*const& converters) { ref holder(source); + if (source->ob_refcnt <= 2) + { + PyErr_SetString( + PyExc_ReferenceError + , const_cast("Attempt to return dangling internal reference")); + throw error_already_set(); + } void* result = find(source, converters); if (!result) { From c170b1b83ee11ebc77b54ee2fef01cf98b15e257 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 10 Mar 2002 06:41:04 +0000 Subject: [PATCH 350/369] char conversions Handle dangling references [SVN r13164] --- test/callbacks.cpp | 38 ++++++++++++++++++++++++++++++++++++++ test/callbacks.py | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/test/callbacks.cpp b/test/callbacks.cpp index 2bf285b5..6d1b8fba 100644 --- a/test/callbacks.cpp +++ b/test/callbacks.cpp @@ -8,6 +8,8 @@ #include #include #include +#include +#include using namespace boost::python; @@ -48,6 +50,16 @@ void apply_void_X_ref(PyObject* f, X& x) returning::call(f, boost::ref(x)); } +X& apply_X_ref_pyobject(PyObject* f, PyObject* obj) +{ + return returning::call(f, obj); +} + +X* apply_X_ptr_pyobject(PyObject* f, PyObject* obj) +{ + return returning::call(f, obj); +} + void apply_void_X_cref(PyObject* f, X const& x) { returning::call(f, boost::cref(x)); @@ -63,6 +75,21 @@ void apply_void_X_deep_ptr(PyObject* f, X* x) returning::call(f, x); } +char const* apply_cstring_cstring(PyObject* f, char const* s) +{ + return returning ::call(f, s); +} + +char const* apply_cstring_pyobject(PyObject* f, PyObject* s) +{ + return returning ::call(f, s); +} + +char apply_char_char(PyObject* f, char c) +{ + return returning ::call(f, c); +} + int X::counter; BOOST_PYTHON_MODULE_INIT(callbacks_ext) @@ -75,6 +102,17 @@ BOOST_PYTHON_MODULE_INIT(callbacks_ext) .def("apply_void_X_cref", apply_void_X_cref) .def("apply_void_X_ptr", apply_void_X_ptr) .def("apply_void_X_deep_ptr", apply_void_X_deep_ptr) + + .def("apply_X_ptr_pyobject", apply_X_ptr_pyobject + , return_value_policy()) + + .def("apply_X_ref_pyobject", apply_X_ref_pyobject + , return_value_policy()) + + .def("apply_cstring_cstring", apply_cstring_cstring) + .def("apply_cstring_pyobject", apply_cstring_pyobject) + .def("apply_char_char", apply_char_char) + .add( class_("X") .def_init(args()) diff --git a/test/callbacks.py b/test/callbacks.py index 810aad53..71ad3fb7 100644 --- a/test/callbacks.py +++ b/test/callbacks.py @@ -66,6 +66,46 @@ 44 >>> last_x.value() 43 + +>>> y = apply_X_ref_pyobject(identity, x) +>>> assert y.value() == x.value() +>>> increment(x) +>>> assert y.value() == x.value() + +>>> y = apply_X_ptr_pyobject(identity, x) +>>> assert y.value() == x.value() +>>> increment(x) +>>> assert y.value() == x.value() + +>>> y = apply_X_ptr_pyobject(identity, None) +>>> y + +>>> def new_x(ignored): +... return X(666) +... +>>> try: apply_X_ref_pyobject(new_x, 1) +... except ReferenceError: pass +... else: print 'no error' + +>>> try: apply_X_ptr_pyobject(new_x, 1) +... except ReferenceError: pass +... else: print 'no error' + +>>> try: apply_cstring_cstring(identity, 'hello') +... except ReferenceError: pass +... else: print 'no error' + +>>> apply_char_char(identity, 'x') +'x' + +>>> apply_cstring_pyobject(identity, 'hello') +'hello' + +>>> apply_cstring_pyobject(identity, None) + + +>>> apply_char_char(identity, 'x') +'x' ''' def run(args = None): From 2fa0910547a92a6a1cf0cb7cb11e5b4f6242e3c8 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 10 Mar 2002 06:41:40 +0000 Subject: [PATCH 351/369] initial checkin [SVN r13165] --- include/boost/python/detail/void_ptr.hpp | 34 ++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 include/boost/python/detail/void_ptr.hpp diff --git a/include/boost/python/detail/void_ptr.hpp b/include/boost/python/detail/void_ptr.hpp new file mode 100644 index 00000000..676a5cac --- /dev/null +++ b/include/boost/python/detail/void_ptr.hpp @@ -0,0 +1,34 @@ +// Copyright David Abrahams 2002. 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_PTR_DWA200239_HPP +# define VOID_PTR_DWA200239_HPP + +namespace boost { namespace python { namespace detail { + +template +inline U& void_ptr_to_reference(void const volatile* p, U&(*)()) +{ + return *(U*)p; +} + +template +inline void write_void_ptr(void const volatile* storage, void* ptr, T*) +{ + *(T**)storage = (T*)ptr; +} + +// writes U(ptr) into the storage +template +inline void write_void_ptr_reference(void const volatile* storage, void* ptr, U&(*)()) +{ + // stripping CV qualification suppresses warnings on older EDGs + typedef typename remove_cv::type u_stripped; + write_void_ptr(storage, ptr, u_stripped(0)); +} + +}}} // namespace boost::python::detail + +#endif // VOID_PTR_DWA200239_HPP From bccd85467654e28d29be4427ea94277d52f0f02b Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 11 Mar 2002 18:43:02 +0000 Subject: [PATCH 352/369] Initial work for virtual function support [SVN r13175] --- include/boost/python/class.hpp | 7 +- include/boost/python/class_fwd.hpp | 8 +- include/boost/python/object/class.hpp | 19 -- include/boost/python/object/make_holder.hpp | 14 +- .../boost/python/object/pointer_holder.hpp | 182 +++++++++++++++++- include/boost/python/object/value_holder.hpp | 158 ++++++++++++++- .../boost/python/object/value_holder_fwd.hpp | 17 ++ src/object/class.cpp | 4 +- 8 files changed, 360 insertions(+), 49 deletions(-) create mode 100644 include/boost/python/object/value_holder_fwd.hpp diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index 8dede0e3..7f31df88 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -9,6 +9,7 @@ # include # include # include +# include # include # include # include @@ -32,12 +33,6 @@ namespace // put some convenience classes into the unnamed namespace for the use namespace boost { namespace python { -// Forward declarations -namespace objects -{ - struct value_holder_generator; -} - namespace detail { // This is an mpl BinaryMetaFunction object with a runtime behavior, diff --git a/include/boost/python/class_fwd.hpp b/include/boost/python/class_fwd.hpp index 6faf7aae..bef2e250 100644 --- a/include/boost/python/class_fwd.hpp +++ b/include/boost/python/class_fwd.hpp @@ -5,6 +5,7 @@ // to its suitability for any purpose. #ifndef CLASS_FWD_DWA200222_HPP # define CLASS_FWD_DWA200222_HPP +# include namespace boost { namespace python { @@ -13,15 +14,10 @@ namespace detail struct empty_list; } -namespace objects -{ - struct value_holder_generator; -} - template < class T // class being wrapped , class Bases = detail::empty_list - , class HolderGenerator = objects::value_holder_generator + , class HolderGenerator = objects::value_holder_generator<> > class class_; diff --git a/include/boost/python/object/class.hpp b/include/boost/python/object/class.hpp index 0d5210c7..d453967c 100644 --- a/include/boost/python/object/class.hpp +++ b/include/boost/python/object/class.hpp @@ -11,7 +11,6 @@ # include # include # include -# include # include namespace boost { namespace python { @@ -55,24 +54,6 @@ struct BOOST_PYTHON_DECL instance_holder : private noncopyable virtual void* holds(converter::undecorated_type_id_t) = 0; void install(PyObject* inst) throw(); - - struct iterator_policies : default_iterator_policies - { - template - void increment(Iterator& p) - { - p.base() = p.base()->next(); - } - }; - - typedef iterator_adaptor< - instance_holder* - , iterator_policies - , value_type_is - , reference_is - , pointer_is - , iterator_category_is > iterator; - private: instance_holder* m_next; }; diff --git a/include/boost/python/object/make_holder.hpp b/include/boost/python/object/make_holder.hpp index 825e02b0..1ba6f932 100644 --- a/include/boost/python/object/make_holder.hpp +++ b/include/boost/python/object/make_holder.hpp @@ -22,7 +22,7 @@ struct make_holder<0> template struct apply { - typedef typename detail::eval::type holder; + typedef typename python::detail::eval::type holder; static void execute( PyObject* p) { @@ -38,7 +38,7 @@ struct make_holder<1> template struct apply { - typedef typename detail::eval::type holder; + typedef typename python::detail::eval::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; @@ -57,7 +57,7 @@ struct make_holder<2> template struct apply { - typedef typename detail::eval::type holder; + typedef typename python::detail::eval::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; typedef typename mpl::at<1,ArgList>::type t1; @@ -77,7 +77,7 @@ struct make_holder<3> template struct apply { - typedef typename detail::eval::type holder; + typedef typename python::detail::eval::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; typedef typename mpl::at<1,ArgList>::type t1; @@ -99,7 +99,7 @@ struct make_holder<4> template struct apply { - typedef typename detail::eval::type holder; + typedef typename python::detail::eval::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; typedef typename mpl::at<1,ArgList>::type t1; @@ -123,7 +123,7 @@ struct make_holder<5> template struct apply { - typedef typename detail::eval::type holder; + typedef typename python::detail::eval::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; typedef typename mpl::at<1,ArgList>::type t1; @@ -149,7 +149,7 @@ struct make_holder<6> template struct apply { - typedef typename detail::eval::type holder; + typedef typename python::detail::eval::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; typedef typename mpl::at<1,ArgList>::type t1; diff --git a/include/boost/python/object/pointer_holder.hpp b/include/boost/python/object/pointer_holder.hpp index c307f019..2722ae85 100644 --- a/include/boost/python/object/pointer_holder.hpp +++ b/include/boost/python/object/pointer_holder.hpp @@ -12,6 +12,7 @@ # include # include # include +# include namespace boost { namespace python { namespace objects { @@ -145,7 +146,137 @@ struct pointer_holder : instance_holder Pointer m_p; }; -}}} +template +struct pointer_holder_back_reference : instance_holder +{ + pointer_holder_back_reference(Pointer); + + // Forward construction to the held object + pointer_holder_back_reference(PyObject* p) + : m_p(new Value(p)) {} + + + template + pointer_holder_back_reference(PyObject* p, A1 a1) + : m_p(new Value(p + , (typename unwrap_reference::type&)(a1) + )) + {} + + template + pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2) + : m_p(new Value(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + )) + {} + + template + pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3) + : m_p(new Value(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + )) + {} + + template + pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4) + : m_p(new Value(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + )) + {} + + template + pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) + : m_p(new Value(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + )) {} + + template + pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) + : m_p(new Value(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + )) {} + + template + pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) + : m_p(new Value(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) + )) + {} + + template + pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) + : m_p(new Value(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) + , (typename unwrap_reference::type&)(a8) + )) + {} + + template + pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) + : m_p(new Value(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) + , (typename unwrap_reference::type&)(a8) + , (typename unwrap_reference::type&)(a9) + )) + {} + + template + pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) + : m_p(new Value(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) + , (typename unwrap_reference::type&)(a8) + , (typename unwrap_reference::type&)(a9) + , (typename unwrap_reference::type&)(a10) + )) + {} + + private: // required holder implementation + void* holds(converter::undecorated_type_id_t); + + private: // data members + Pointer m_p; +}; + +}}} // namespace boost::python::objects // back to namespace boost for this forward declaration namespace boost @@ -164,19 +295,54 @@ struct shared_ptr_generator }; }; +struct no_back_reference; + +// Workaround lack of partial specialization +namespace detail +{ + template + struct pointer_holder_back_reference_generator + { + template + struct apply + { + typedef typename boost::python::detail::eval< + PointerGenerator,BackReferenceType + >::type pointer; + + typedef pointer_holder_back_reference type; + }; + }; + + template + struct plain_pointer_holder_generator + { + template + struct apply + { + typedef typename boost::python::detail::eval< + PointerGenerator,Held + >::type pointer; + + typedef pointer_holder type; + }; + }; +} + // A generator metafunction which can be passed to make_holder // PointerGenerator should be another generator metafunction which // makes the appropriate (smart) pointer type to hold the argument to // pointer_holder_generator. -template +template struct pointer_holder_generator + : mpl::select_type< + is_same::value + , detail::plain_pointer_holder_generator< + PointerGenerator> + , detail::pointer_holder_back_reference_generator< + BackReferenceType,PointerGenerator> + >::type { - template - struct apply - { - typedef typename detail::eval::type pointer; - typedef pointer_holder type; - }; }; template diff --git a/include/boost/python/object/value_holder.hpp b/include/boost/python/object/value_holder.hpp index 6533bc39..62222a23 100644 --- a/include/boost/python/object/value_holder.hpp +++ b/include/boost/python/object/value_holder.hpp @@ -6,6 +6,7 @@ #ifndef VALUE_HOLDER_DWA20011215_HPP # define VALUE_HOLDER_DWA20011215_HPP +# include # include # include # include @@ -140,8 +141,136 @@ struct value_holder : instance_holder Held m_held; }; +template +struct value_holder_back_reference : instance_holder +{ + // Forward construction to the held object + value_holder_back_reference(PyObject* p) + : m_held() {} + + template + value_holder_back_reference(PyObject* p, A1 a1) + : m_held(p + , (typename unwrap_reference::type&)(a1) + ) + {} + + template + value_holder_back_reference(PyObject* p, A1 a1, A2 a2) + : m_held(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + ) + {} + + template + value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3) + : m_held(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + ) + {} + + template + value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4) + : m_held(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + ) + {} + + template + value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) + : m_held(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + ) {} + + template + value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) + : m_held(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + ) {} + + template + value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) + : m_held(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) + ) + {} + + template + value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) + : m_held(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) + , (typename unwrap_reference::type&)(a8) + ) + {} + + template + value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) + : m_held(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) + , (typename unwrap_reference::type&)(a8) + , (typename unwrap_reference::type&)(a9) + ) + {} + + template + value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) + : m_held(p + , (typename unwrap_reference::type&)(a1) + , (typename unwrap_reference::type&)(a2) + , (typename unwrap_reference::type&)(a3) + , (typename unwrap_reference::type&)(a4) + , (typename unwrap_reference::type&)(a5) + , (typename unwrap_reference::type&)(a6) + , (typename unwrap_reference::type&)(a7) + , (typename unwrap_reference::type&)(a8) + , (typename unwrap_reference::type&)(a9) + , (typename unwrap_reference::type&)(a10) + ) + {} + + private: // required holder implementation + void* holds(converter::undecorated_type_id_t); + + private: // data members + BackReferenceType m_held; +}; + // A generator metafunction which can be passed to make_holder -struct value_holder_generator +template <> +struct value_holder_generator { template struct apply @@ -150,6 +279,16 @@ struct value_holder_generator }; }; +template +struct value_holder_generator +{ + template + struct apply + { + typedef value_holder_back_reference type; + }; +}; + template void* value_holder::holds(converter::undecorated_type_id_t dst_t) { @@ -158,6 +297,23 @@ void* value_holder::holds(converter::undecorated_type_id_t dst_t) : find_static_type(&m_held, src_t, dst_t); } +template +void* value_holder_back_reference::holds( + converter::undecorated_type_id_t dst_t) +{ + converter::undecorated_type_id_t src_t = converter::undecorated_type_id(); + if (src_t == dst_t) + { + Held* x = &m_held; + return x; + } + + src_t = converter::undecorated_type_id(); + return src_t == dst_t + ? &m_held + : find_static_type(&m_held, src_t, dst_t); +} + }}} // namespace boost::python::objects #endif // VALUE_HOLDER_DWA20011215_HPP diff --git a/include/boost/python/object/value_holder_fwd.hpp b/include/boost/python/object/value_holder_fwd.hpp new file mode 100644 index 00000000..6cb2a0f5 --- /dev/null +++ b/include/boost/python/object/value_holder_fwd.hpp @@ -0,0 +1,17 @@ +// Copyright David Abrahams 2002. 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 VALUE_HOLDER_FWD_DWA2002311_HPP +# define VALUE_HOLDER_FWD_DWA2002311_HPP + +namespace boost { namespace python { namespace objects { + +struct no_back_reference; + +template struct value_holder_generator; + +}}} // namespace boost::python::object + +#endif // VALUE_HOLDER_FWD_DWA2002311_HPP diff --git a/src/object/class.cpp b/src/object/class.cpp index b9deb98f..dc3a42af 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -169,9 +169,9 @@ find_instance_impl(PyObject* inst, converter::undecorated_type_id_t type) instance* self = reinterpret_cast(inst); - for (instance_holder::iterator match(self->objects), end(0); match != end; ++match) + for (instance_holder* match = self->objects; match != 0; match = match->next()) { - void* const found = (*match).holds(type); + void* const found = match->holds(type); if (found) return found; } From 23769371bc8bd2baa16c6fb5ef14f37ad18cb05d Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 11 Mar 2002 18:57:45 +0000 Subject: [PATCH 353/369] Elimination of boost/python/detail/eval.hpp; using mpl::apply instead [SVN r13176] --- include/boost/python/detail/caller.hpp | 1 - include/boost/python/detail/eval.hpp | 40 ------------ include/boost/python/detail/returning.hpp | 63 ++++++++++--------- include/boost/python/object/make_holder.hpp | 16 ++--- .../boost/python/object/pointer_holder.hpp | 6 +- 5 files changed, 43 insertions(+), 83 deletions(-) delete mode 100644 include/boost/python/detail/eval.hpp diff --git a/include/boost/python/detail/caller.hpp b/include/boost/python/detail/caller.hpp index d0b01b6e..68da40e6 100644 --- a/include/boost/python/detail/caller.hpp +++ b/include/boost/python/detail/caller.hpp @@ -7,7 +7,6 @@ # define CALLER_DWA20011214_HPP # include -# include # include # include # include diff --git a/include/boost/python/detail/eval.hpp b/include/boost/python/detail/eval.hpp deleted file mode 100644 index 8699f701..00000000 --- a/include/boost/python/detail/eval.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright David Abrahams 2002. 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 EVAL_DWA2002124_HPP -# define EVAL_DWA2002124_HPP - -# include - -namespace boost { namespace python { namespace detail { - -template struct undefined; -template -struct eval -{ -# if defined(BOOST_MSVC) && BOOST_MSVC <= 1200 - // based on the (non-conforming) MSVC trick from MPL - template - struct unarymetafunction_vc : UnaryMetaFunction {}; - - // illegal C++ which causes VC to admit that unarymetafunction_vc - // can have a nested template: - template<> - struct unarymetafunction_vc - { - template struct apply; - }; - - typedef typename unarymetafunction_vc< - ::boost::mpl::detail::msvc_never_true::value - >::template apply::type type; -# else - typedef typename UnaryMetaFunction::template apply::type type; -# endif -}; - -}}} // namespace boost::python::detail - -#endif // EVAL_DWA2002124_HPP diff --git a/include/boost/python/detail/returning.hpp b/include/boost/python/detail/returning.hpp index d7e98cd8..2c5d8c4f 100644 --- a/include/boost/python/detail/returning.hpp +++ b/include/boost/python/detail/returning.hpp @@ -15,6 +15,7 @@ # include # include # include +# include namespace boost { namespace python { namespace detail { @@ -31,7 +32,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -52,7 +53,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -75,7 +76,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -101,7 +102,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -130,7 +131,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -162,7 +163,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -186,7 +187,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -207,7 +208,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -230,7 +231,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -256,7 +257,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -285,7 +286,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -317,7 +318,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -341,7 +342,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -362,7 +363,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -385,7 +386,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -411,7 +412,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -440,7 +441,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -472,7 +473,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -499,7 +500,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -520,7 +521,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -543,7 +544,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -569,7 +570,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -598,7 +599,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -630,7 +631,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -652,7 +653,7 @@ struct returning { // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -671,7 +672,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -692,7 +693,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -716,7 +717,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -743,7 +744,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -773,7 +774,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; @@ -806,7 +807,7 @@ struct returning // find the result converter typedef typename P::result_converter result_converter; - typename eval::type cr; + typename mpl::apply1::type cr; if (!cr.convertible()) return 0; if (!policies.precall(args_)) return 0; diff --git a/include/boost/python/object/make_holder.hpp b/include/boost/python/object/make_holder.hpp index 1ba6f932..871ed059 100644 --- a/include/boost/python/object/make_holder.hpp +++ b/include/boost/python/object/make_holder.hpp @@ -10,7 +10,7 @@ # include # include # include -# include +# include namespace boost { namespace python { namespace objects { @@ -22,7 +22,7 @@ struct make_holder<0> template struct apply { - typedef typename python::detail::eval::type holder; + typedef typename mpl::apply1::type holder; static void execute( PyObject* p) { @@ -38,7 +38,7 @@ struct make_holder<1> template struct apply { - typedef typename python::detail::eval::type holder; + typedef typename mpl::apply1::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; @@ -57,7 +57,7 @@ struct make_holder<2> template struct apply { - typedef typename python::detail::eval::type holder; + typedef typename mpl::apply1::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; typedef typename mpl::at<1,ArgList>::type t1; @@ -77,7 +77,7 @@ struct make_holder<3> template struct apply { - typedef typename python::detail::eval::type holder; + typedef typename mpl::apply1::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; typedef typename mpl::at<1,ArgList>::type t1; @@ -99,7 +99,7 @@ struct make_holder<4> template struct apply { - typedef typename python::detail::eval::type holder; + typedef typename mpl::apply1::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; typedef typename mpl::at<1,ArgList>::type t1; @@ -123,7 +123,7 @@ struct make_holder<5> template struct apply { - typedef typename python::detail::eval::type holder; + typedef typename mpl::apply1::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; typedef typename mpl::at<1,ArgList>::type t1; @@ -149,7 +149,7 @@ struct make_holder<6> template struct apply { - typedef typename python::detail::eval::type holder; + typedef typename mpl::apply1::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; typedef typename mpl::at<1,ArgList>::type t1; diff --git a/include/boost/python/object/pointer_holder.hpp b/include/boost/python/object/pointer_holder.hpp index 2722ae85..57cb6b47 100644 --- a/include/boost/python/object/pointer_holder.hpp +++ b/include/boost/python/object/pointer_holder.hpp @@ -9,10 +9,10 @@ # include # include # include -# include # include # include # include +# include namespace boost { namespace python { namespace objects { @@ -306,7 +306,7 @@ namespace detail template struct apply { - typedef typename boost::python::detail::eval< + typedef typename mpl::apply1< PointerGenerator,BackReferenceType >::type pointer; @@ -320,7 +320,7 @@ namespace detail template struct apply { - typedef typename boost::python::detail::eval< + typedef typename mpl::apply1< PointerGenerator,Held >::type pointer; From 0bdf3542e451e1e4d5725cfb7b616956b27c53cd Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 12 Mar 2002 20:43:42 +0000 Subject: [PATCH 354/369] factored out find_instance [SVN r13181] --- include/boost/python/object/class.hpp | 14 -------------- include/boost/python/object/class_converters.hpp | 5 ++--- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/include/boost/python/object/class.hpp b/include/boost/python/object/class.hpp index d453967c..468240c0 100644 --- a/include/boost/python/object/class.hpp +++ b/include/boost/python/object/class.hpp @@ -65,20 +65,6 @@ struct instance instance_holder* objects; }; -// Given an undecorated type_id, find the instance data which -// corresponds to it, or return 0 in case no such type is held. -BOOST_PYTHON_DECL void* find_instance_impl(PyObject*, converter::undecorated_type_id_t); - -// This produces a function with the right signature for use in from_python conversions -template -struct instance_finder -{ - static inline void* execute(PyObject* p) - { - return find_instance_impl(p, converter::undecorated_type_id()); - } -}; - BOOST_PYTHON_DECL ref class_metatype(); BOOST_PYTHON_DECL ref class_type(); diff --git a/include/boost/python/object/class_converters.hpp b/include/boost/python/object/class_converters.hpp index 540565bf..5c2a35ae 100644 --- a/include/boost/python/object/class_converters.hpp +++ b/include/boost/python/object/class_converters.hpp @@ -10,6 +10,7 @@ # include # include # include +# include namespace boost { namespace python { namespace objects { @@ -89,9 +90,7 @@ template class_converters::class_converters(ref const& type_object) : m_wrapper(type_object) { - converter::registry::insert( - &instance_finder::execute - , converter::undecorated_type_id()); + (void)instance_finder::registration; // register all up/downcasts here register_dynamic_id(); From 3caa91cc36bc04cf1bbe0726a6d8b2fdf20949d9 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 12 Mar 2002 21:07:26 +0000 Subject: [PATCH 355/369] More fixes [SVN r13182] --- include/boost/python/class.hpp | 15 +++- include/boost/python/object/find_instance.hpp | 37 +++++++++ .../boost/python/object/pointer_holder.hpp | 76 ++++++++++++++----- include/boost/python/object/value_holder.hpp | 55 +++++++++++--- test/Jamfile | 1 + 5 files changed, 150 insertions(+), 34 deletions(-) create mode 100644 include/boost/python/object/find_instance.hpp diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index 7f31df88..0a9c5d87 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -12,6 +12,7 @@ # include # include # include +# include # include # include # include @@ -103,14 +104,24 @@ class class_ : private objects::class_base // Use function::add_to_namespace to achieve overloading if // appropriate. objects::function::add_to_namespace( - this->object(), name, ref(detail::wrap_function(f))); + this->object(), name, + ref(detail::wrap_function( + // This bit of nastiness casts F to a member function of T if possible. + detail::member_function_cast::stage1(f).stage2((T*)0).stage3(f) + ))); return *this; } template self& def(char const* name, Fn fn, CallPolicy policy) { - this->def(name, boost::python::make_function(fn, policy)); + this->def(name + , boost::python::make_function( + // This bit of nastiness casts F to a member function of T if possible. + detail::member_function_cast::stage1(fn).stage2((T*)0).stage3(fn) + , policy) + ); + return *this; } diff --git a/include/boost/python/object/find_instance.hpp b/include/boost/python/object/find_instance.hpp new file mode 100644 index 00000000..c60a82f7 --- /dev/null +++ b/include/boost/python/object/find_instance.hpp @@ -0,0 +1,37 @@ +// Copyright David Abrahams 2002. 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 FIND_INSTANCE_DWA2002312_HPP +# define FIND_INSTANCE_DWA2002312_HPP + +namespace boost { namespace python { namespace objects { + +// Given an undecorated type_id, find the instance data which +// corresponds to it, or return 0 in case no such type is held. +BOOST_PYTHON_DECL void* find_instance_impl(PyObject*, converter::undecorated_type_id_t); + +// This produces a function with the right signature for use in from_python conversions +template +struct instance_finder +{ + instance_finder() + { + converter::registry::insert(&execute, converter::undecorated_type_id()); + } + + static instance_finder const registration; + private: + static inline void* execute(PyObject* p) + { + return find_instance_impl(p, converter::undecorated_type_id()); + } +}; + +template +instance_finder const instance_finder::registration; + +}}} // namespace boost::python::objects + +#endif // FIND_INSTANCE_DWA2002312_HPP diff --git a/include/boost/python/object/pointer_holder.hpp b/include/boost/python/object/pointer_holder.hpp index 57cb6b47..84700299 100644 --- a/include/boost/python/object/pointer_holder.hpp +++ b/include/boost/python/object/pointer_holder.hpp @@ -9,6 +9,7 @@ # include # include # include +# include # include # include # include @@ -153,67 +154,88 @@ struct pointer_holder_back_reference : instance_holder // Forward construction to the held object pointer_holder_back_reference(PyObject* p) - : m_p(new Value(p)) {} + : m_p(new BackReferenceType(p)) { + (void)instance_finder::registration; + } + template pointer_holder_back_reference(PyObject* p, A1 a1) - : m_p(new Value(p + : m_p(new BackReferenceType(p , (typename unwrap_reference::type&)(a1) )) - {} + { + (void)instance_finder::registration; + } + template pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2) - : m_p(new Value(p + : m_p(new BackReferenceType(p , (typename unwrap_reference::type&)(a1) , (typename unwrap_reference::type&)(a2) )) - {} + { + (void)instance_finder::registration; + } + template pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3) - : m_p(new Value(p + : m_p(new BackReferenceType(p , (typename unwrap_reference::type&)(a1) , (typename unwrap_reference::type&)(a2) , (typename unwrap_reference::type&)(a3) )) - {} + { + (void)instance_finder::registration; + } + template pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4) - : m_p(new Value(p + : m_p(new BackReferenceType(p , (typename unwrap_reference::type&)(a1) , (typename unwrap_reference::type&)(a2) , (typename unwrap_reference::type&)(a3) , (typename unwrap_reference::type&)(a4) )) - {} + { + (void)instance_finder::registration; + } + template pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) - : m_p(new Value(p + : m_p(new BackReferenceType(p , (typename unwrap_reference::type&)(a1) , (typename unwrap_reference::type&)(a2) , (typename unwrap_reference::type&)(a3) , (typename unwrap_reference::type&)(a4) , (typename unwrap_reference::type&)(a5) - )) {} + )) { + (void)instance_finder::registration; + } + template pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) - : m_p(new Value(p + : m_p(new BackReferenceType(p , (typename unwrap_reference::type&)(a1) , (typename unwrap_reference::type&)(a2) , (typename unwrap_reference::type&)(a3) , (typename unwrap_reference::type&)(a4) , (typename unwrap_reference::type&)(a5) , (typename unwrap_reference::type&)(a6) - )) {} + )) { + (void)instance_finder::registration; + } + template pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) - : m_p(new Value(p + : m_p(new BackReferenceType(p , (typename unwrap_reference::type&)(a1) , (typename unwrap_reference::type&)(a2) , (typename unwrap_reference::type&)(a3) @@ -222,11 +244,14 @@ struct pointer_holder_back_reference : instance_holder , (typename unwrap_reference::type&)(a6) , (typename unwrap_reference::type&)(a7) )) - {} + { + (void)instance_finder::registration; + } + template pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) - : m_p(new Value(p + : m_p(new BackReferenceType(p , (typename unwrap_reference::type&)(a1) , (typename unwrap_reference::type&)(a2) , (typename unwrap_reference::type&)(a3) @@ -236,11 +261,14 @@ struct pointer_holder_back_reference : instance_holder , (typename unwrap_reference::type&)(a7) , (typename unwrap_reference::type&)(a8) )) - {} + { + (void)instance_finder::registration; + } + template pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) - : m_p(new Value(p + : m_p(new BackReferenceType(p , (typename unwrap_reference::type&)(a1) , (typename unwrap_reference::type&)(a2) , (typename unwrap_reference::type&)(a3) @@ -251,11 +279,14 @@ struct pointer_holder_back_reference : instance_holder , (typename unwrap_reference::type&)(a8) , (typename unwrap_reference::type&)(a9) )) - {} + { + (void)instance_finder::registration; + } + template pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) - : m_p(new Value(p + : m_p(new BackReferenceType(p , (typename unwrap_reference::type&)(a1) , (typename unwrap_reference::type&)(a2) , (typename unwrap_reference::type&)(a3) @@ -267,7 +298,10 @@ struct pointer_holder_back_reference : instance_holder , (typename unwrap_reference::type&)(a9) , (typename unwrap_reference::type&)(a10) )) - {} + { + (void)instance_finder::registration; + } + private: // required holder implementation void* holds(converter::undecorated_type_id_t); diff --git a/include/boost/python/object/value_holder.hpp b/include/boost/python/object/value_holder.hpp index 62222a23..c0a5c580 100644 --- a/include/boost/python/object/value_holder.hpp +++ b/include/boost/python/object/value_holder.hpp @@ -10,6 +10,7 @@ # include # include # include +# include # include namespace boost { namespace python { namespace objects { @@ -146,14 +147,20 @@ struct value_holder_back_reference : instance_holder { // Forward construction to the held object value_holder_back_reference(PyObject* p) - : m_held() {} + : m_held() { + (void)instance_finder::registration; + } + template value_holder_back_reference(PyObject* p, A1 a1) : m_held(p , (typename unwrap_reference::type&)(a1) ) - {} + { + (void)instance_finder::registration; + } + template value_holder_back_reference(PyObject* p, A1 a1, A2 a2) @@ -161,7 +168,10 @@ struct value_holder_back_reference : instance_holder , (typename unwrap_reference::type&)(a1) , (typename unwrap_reference::type&)(a2) ) - {} + { + (void)instance_finder::registration; + } + template value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3) @@ -170,7 +180,10 @@ struct value_holder_back_reference : instance_holder , (typename unwrap_reference::type&)(a2) , (typename unwrap_reference::type&)(a3) ) - {} + { + (void)instance_finder::registration; + } + template value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4) @@ -180,7 +193,10 @@ struct value_holder_back_reference : instance_holder , (typename unwrap_reference::type&)(a3) , (typename unwrap_reference::type&)(a4) ) - {} + { + (void)instance_finder::registration; + } + template value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) @@ -190,7 +206,10 @@ struct value_holder_back_reference : instance_holder , (typename unwrap_reference::type&)(a3) , (typename unwrap_reference::type&)(a4) , (typename unwrap_reference::type&)(a5) - ) {} + ) { + (void)instance_finder::registration; + } + template value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) @@ -201,7 +220,10 @@ struct value_holder_back_reference : instance_holder , (typename unwrap_reference::type&)(a4) , (typename unwrap_reference::type&)(a5) , (typename unwrap_reference::type&)(a6) - ) {} + ) { + (void)instance_finder::registration; + } + template value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) @@ -214,7 +236,10 @@ struct value_holder_back_reference : instance_holder , (typename unwrap_reference::type&)(a6) , (typename unwrap_reference::type&)(a7) ) - {} + { + (void)instance_finder::registration; + } + template value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) @@ -228,7 +253,10 @@ struct value_holder_back_reference : instance_holder , (typename unwrap_reference::type&)(a7) , (typename unwrap_reference::type&)(a8) ) - {} + { + (void)instance_finder::registration; + } + template value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) @@ -243,7 +271,10 @@ struct value_holder_back_reference : instance_holder , (typename unwrap_reference::type&)(a8) , (typename unwrap_reference::type&)(a9) ) - {} + { + (void)instance_finder::registration; + } + template value_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) @@ -259,7 +290,9 @@ struct value_holder_back_reference : instance_holder , (typename unwrap_reference::type&)(a9) , (typename unwrap_reference::type&)(a10) ) - {} + { + (void)instance_finder::registration; + } private: // required holder implementation void* holds(converter::undecorated_type_id_t); diff --git a/test/Jamfile b/test/Jamfile index 767b07e6..1f5de1e9 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -55,6 +55,7 @@ bpl-test try : newtest.py m1.cpp m2.cpp ; bpl-test builtin_converters : test_builtin_converters.py test_builtin_converters.cpp ; bpl-test test_pointer_adoption ; bpl-test callbacks ; +bpl-test virtual_functions ; # --- unit tests of library components --- unit-test indirect_traits_test From c18d8fa9677dfde9501bd01f2dabd4827705973c Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 12 Mar 2002 21:14:03 +0000 Subject: [PATCH 356/369] added first virtual function tests [SVN r13183] --- test/virtual_functions.cpp | 118 +++++++++++++++++++++++++++++++++++++ test/virtual_functions.py | 100 +++++++++++++++++++++++++++++++ 2 files changed, 218 insertions(+) create mode 100644 test/virtual_functions.cpp create mode 100644 test/virtual_functions.py diff --git a/test/virtual_functions.cpp b/test/virtual_functions.cpp new file mode 100644 index 00000000..ab05fe3c --- /dev/null +++ b/test/virtual_functions.cpp @@ -0,0 +1,118 @@ +// Copyright David Abrahams 2002. 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. +#include +#include +#include +#include + +using namespace boost::python; + +struct X +{ + explicit X(int x) : x(x), magic(7654321) { ++counter; } + X(X const& rhs) : x(rhs.x), magic(7654321) { ++counter; } + virtual ~X() { assert(magic == 7654321); magic = 6666666; x = 9999; --counter; } + + void set(int x) { assert(magic == 7654321); this->x = x; } + int value() const { assert(magic == 7654321); return x; } + static int count() { return counter; } + private: + void operator=(X const&); + private: + int x; + long magic; + static int counter; +}; + +struct Y : X +{ + Y(int x) : X(x) {}; +}; + +struct abstract : X +{ + abstract(int x) : X(x) {}; + int call_f(Y const& y) { return f(y); } + virtual int f(Y const& y) = 0; +}; + +struct concrete : X +{ + concrete(int x) : X(x) {}; + int call_f(Y const& y) { return f(y); } + virtual int f(Y const& y) { set(y.value()); return y.value(); } +}; + +struct abstract_callback : abstract +{ + abstract_callback(PyObject* p, int x) + : abstract(x), self(p) + {} + + int f(Y const& y) + { + return returning::call_method(self, "f", boost::ref(y)); + } + + PyObject* self; +}; + +struct concrete_callback : concrete +{ + concrete_callback(PyObject* p, int x) + : concrete(x), self(p) + {} + + int f(Y const& y) + { + return returning::call_method(self, "f", boost::ref(y)); + } + + int f_impl(Y const& y) + { + return this->concrete::f(y); + } + + PyObject* self; +}; + +int X::counter; + +BOOST_PYTHON_MODULE_INIT(virtual_functions_ext) +{ + module("virtual_functions_ext") + .add( + class_, objects::value_holder_generator >("concrete") + .def_init(args()) + .def("value", &concrete::value) + .def("set", &concrete::set) + .def("call_f", &concrete::call_f) + .def("f", &concrete_callback::f_impl)) + +#if 0 + .add( + class_ + , objects::pointer_holder_generator< + boost::python::objects::shared_ptr_generator + , abstract_callback> + >("abstract") + + .def_init(args()) + .def("value", &abstract::value) + .def("call_f", &abstract::call_f) + .def("set", &abstract::set)) +#endif + + .add( + class_("Y") + .def_init(args()) + .def("value", &Y::value) + .def("set", &Y::set) + ) + ; +} + +#include "module_tail.cpp" diff --git a/test/virtual_functions.py b/test/virtual_functions.py new file mode 100644 index 00000000..8ea992c5 --- /dev/null +++ b/test/virtual_functions.py @@ -0,0 +1,100 @@ +''' +>>> from virtual_functions_ext import * + +>>> class C1(concrete): +... def f(self, y): +... return concrete.f(self, Y(-y.value())) + +>>> class C2(concrete): +... pass + +<<<>>> class A1(abstract): +<<<... def f(self, y): +<<<... return abstract.f(self, Y(-y.value())) +<<< +<<<>>> class A2(abstract): +<<<... pass +<<< + +>>> y1 = Y(16) +>>> y2 = Y(17) + + + +# +# Test abstract with f overridden +# +<<<>>> a1 = A1(42) +<<<>>> a1.value() +<<<42 +<<< +<<<# Call f indirectly from C++ +<<<>>> a1.call_f(y1) +<<<-16 +<<< +<<<# Call f directly from Python +<<<>>> a1.f(y2) +<<<-17 +<<< +<<<# +<<<# Test abstract with f not overridden +<<<# +<<<>>> a2 = A2(42) +<<<>>> A2.value() +<<<42 +<<< +<<<# Call f indirectly from C++ +<<<>>> c1.call_f(y1) +<<<16 +<<< +<<<# Call f directly from Python +<<<>>> c1.f(y2) +<<<17 +<<< +############# Concrete Tests ############ + +# +# Test concrete with f overridden +# +>>> c1 = C1(42) +>>> c1.value() +42 + +# Call f indirectly from C++ +>>> c1.call_f(y1) +-16 + +# Call f directly from Python +>>> c1.f(y2) +-17 + +# +# Test concrete with f not overridden +# +>>> c2 = C2(42) +>>> c2.value() +42 + +# Call f indirectly from C++ +>>> c2.call_f(y1) +16 + +# Call f directly from Python +>>> c2.f(y2) +17 + + +''' + +def run(args = None): + import sys + import doctest + + if args is not None: + sys.argv = args + return doctest.testmod(sys.modules.get(__name__)) + +if __name__ == '__main__': + print "running..." + import sys + sys.exit(run()[0]) From 81a07899ae2451bcb7cd2cc677e76444990f2f9b Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 12 Mar 2002 21:15:28 +0000 Subject: [PATCH 357/369] initial checkin [SVN r13184] --- .../python/detail/member_function_cast.hpp | 231 ++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 include/boost/python/detail/member_function_cast.hpp diff --git a/include/boost/python/detail/member_function_cast.hpp b/include/boost/python/detail/member_function_cast.hpp new file mode 100644 index 00000000..3d965021 --- /dev/null +++ b/include/boost/python/detail/member_function_cast.hpp @@ -0,0 +1,231 @@ +// Copyright David Abrahams 2002. 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 MEMBER_FUNCTION_CAST_DWA2002311_HPP +# define MEMBER_FUNCTION_CAST_DWA2002311_HPP +# include +# include + +namespace boost { namespace python { namespace detail { + +template +struct cast_helper +{ + struct yes_helper + { + static FT stage3(FT x) { return x; } + }; + + struct no_helper + { + template + static T stage3(T x) { return x; } + }; + + static yes_helper stage2(S*) { return yes_helper(); } + static no_helper stage2(void*) { return no_helper(); } +}; + +struct non_member_function_cast_impl +{ + template + static non_member_function_cast_impl stage1(T) { return non_member_function_cast_impl(); } + + template + static non_member_function_cast_impl stage2(T) { return non_member_function_cast_impl(); } + + template + T stage3(T x) { return x; } +}; + +template +struct member_function_cast_impl +{ + template + static cast_helper stage1(R (S::*)()) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0)) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0,A1)) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0,A1,A2)) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0,A1,A2,A3)) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0,A1,A2,A3,A4)) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0,A1,A2,A3,A4,A5)) + { + return cast_helper(); + } + +# if 1 + template + static cast_helper stage1(R (S::*)()const) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0)const) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0,A1)const) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0,A1,A2)const) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0,A1,A2,A3)const) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0,A1,A2,A3,A4)const) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0,A1,A2,A3,A4,A5)const) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)()volatile) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0)volatile) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0,A1)volatile) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0,A1,A2)volatile) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0,A1,A2,A3)volatile) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0,A1,A2,A3,A4)volatile) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0,A1,A2,A3,A4,A5)volatile) + { + return cast_helper(); + } + +// # ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + static cast_helper stage1(R (S::*)()const volatile) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0)const volatile) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0,A1)const volatile) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0,A1,A2)const volatile) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0,A1,A2,A3)const volatile) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0,A1,A2,A3,A4)const volatile) + { + return cast_helper(); + } + + template + static cast_helper stage1(R (S::*)(A0,A1,A2,A3,A4,A5)const volatile) + { + return cast_helper(); + } +# endif +}; + + +template +struct member_function_cast + : mpl::select_type< + is_member_function_pointer::value + , member_function_cast_impl + , non_member_function_cast_impl + >::type +{ +}; + +}}} // namespace boost::python::detail + +#endif // MEMBER_FUNCTION_CAST_DWA2002311_HPP From 6528bd0e4fa0f22368e08ef2b4152056e8504ef4 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 14 Mar 2002 18:43:36 +0000 Subject: [PATCH 358/369] Fixes for VC7 [SVN r13194] --- src/object/inheritance.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/object/inheritance.cpp b/src/object/inheritance.cpp index 7efc980c..5b95e478 100644 --- a/src/object/inheritance.cpp +++ b/src/object/inheritance.cpp @@ -109,7 +109,7 @@ namespace make_iterator_property_map( to_target , get(vertex_index, reverse_topology) -# ifdef BOOST_MSVC_STD_ITERATOR +# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION , *to_target # endif ) From fbbc1981cabf54cdb37b15c15b119365b009d578 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 15 Mar 2002 00:25:26 +0000 Subject: [PATCH 359/369] Bug fix (thanks, VC7!) [SVN r13200] --- include/boost/python/detail/member_function_cast.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/python/detail/member_function_cast.hpp b/include/boost/python/detail/member_function_cast.hpp index 3d965021..52718390 100644 --- a/include/boost/python/detail/member_function_cast.hpp +++ b/include/boost/python/detail/member_function_cast.hpp @@ -56,13 +56,13 @@ struct member_function_cast_impl } template - static cast_helper stage1(R (S::*)(A0,A1)) + static cast_helper stage1(R (S::*)(A0,A1)) { return cast_helper(); } template - static cast_helper stage1(R (S::*)(A0,A1,A2)) + static cast_helper stage1(R (S::*)(A0,A1,A2)) { return cast_helper(); } From aa705b07f3f7812a6ebc2a2b3eae92a57758d4ea Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 15 Mar 2002 00:25:43 +0000 Subject: [PATCH 360/369] VC7 workaround [SVN r13201] --- include/boost/python/object/make_holder.hpp | 58 +++++++++++++-------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/include/boost/python/object/make_holder.hpp b/include/boost/python/object/make_holder.hpp index 871ed059..5268bde4 100644 --- a/include/boost/python/object/make_holder.hpp +++ b/include/boost/python/object/make_holder.hpp @@ -14,6 +14,22 @@ namespace boost { namespace python { namespace objects { +namespace detail +{ + // Use of this workaround as opposed to straightforward mpl::at + // needed for vc7, for some reason. + template + struct at + { + private: + typedef typename mpl::at_algorithm_traits< + typename mpl::sequence_traits::sequence_category + >::template algorithm::type base; + public: + typedef typename base::type type; + }; +} + template struct make_holder; template <> @@ -39,7 +55,7 @@ struct make_holder<1> struct apply { typedef typename mpl::apply1::type holder; - typedef typename mpl::at<0,ArgList>::type t0; + typedef typename detail::at<0,ArgList>::type t0; typedef typename forward::type f0; static void execute( @@ -58,9 +74,9 @@ struct make_holder<2> struct apply { typedef typename mpl::apply1::type holder; - typedef typename mpl::at<0,ArgList>::type t0; + typedef typename detail::at<0,ArgList>::type t0; typedef typename forward::type f0; - typedef typename mpl::at<1,ArgList>::type t1; + typedef typename detail::at<1,ArgList>::type t1; typedef typename forward::type f1; static void execute( @@ -78,11 +94,11 @@ struct make_holder<3> struct apply { typedef typename mpl::apply1::type holder; - typedef typename mpl::at<0,ArgList>::type t0; + typedef typename detail::at<0,ArgList>::type t0; typedef typename forward::type f0; - typedef typename mpl::at<1,ArgList>::type t1; + typedef typename detail::at<1,ArgList>::type t1; typedef typename forward::type f1; - typedef typename mpl::at<2,ArgList>::type t2; + typedef typename detail::at<2,ArgList>::type t2; typedef typename forward::type f2; static void execute( @@ -100,13 +116,13 @@ struct make_holder<4> struct apply { typedef typename mpl::apply1::type holder; - typedef typename mpl::at<0,ArgList>::type t0; + typedef typename detail::at<0,ArgList>::type t0; typedef typename forward::type f0; - typedef typename mpl::at<1,ArgList>::type t1; + typedef typename detail::at<1,ArgList>::type t1; typedef typename forward::type f1; - typedef typename mpl::at<2,ArgList>::type t2; + typedef typename detail::at<2,ArgList>::type t2; typedef typename forward::type f2; - typedef typename mpl::at<3,ArgList>::type t3; + typedef typename detail::at<3,ArgList>::type t3; typedef typename forward::type f3; static void execute( @@ -124,15 +140,15 @@ struct make_holder<5> struct apply { typedef typename mpl::apply1::type holder; - typedef typename mpl::at<0,ArgList>::type t0; + typedef typename detail::at<0,ArgList>::type t0; typedef typename forward::type f0; - typedef typename mpl::at<1,ArgList>::type t1; + typedef typename detail::at<1,ArgList>::type t1; typedef typename forward::type f1; - typedef typename mpl::at<2,ArgList>::type t2; + typedef typename detail::at<2,ArgList>::type t2; typedef typename forward::type f2; - typedef typename mpl::at<3,ArgList>::type t3; + typedef typename detail::at<3,ArgList>::type t3; typedef typename forward::type f3; - typedef typename mpl::at<4,ArgList>::type t4; + typedef typename detail::at<4,ArgList>::type t4; typedef typename forward::type f4; static void execute( @@ -150,17 +166,17 @@ struct make_holder<6> struct apply { typedef typename mpl::apply1::type holder; - typedef typename mpl::at<0,ArgList>::type t0; + typedef typename detail::at<0,ArgList>::type t0; typedef typename forward::type f0; - typedef typename mpl::at<1,ArgList>::type t1; + typedef typename detail::at<1,ArgList>::type t1; typedef typename forward::type f1; - typedef typename mpl::at<2,ArgList>::type t2; + typedef typename detail::at<2,ArgList>::type t2; typedef typename forward::type f2; - typedef typename mpl::at<3,ArgList>::type t3; + typedef typename detail::at<3,ArgList>::type t3; typedef typename forward::type f3; - typedef typename mpl::at<4,ArgList>::type t4; + typedef typename detail::at<4,ArgList>::type t4; typedef typename forward::type f4; - typedef typename mpl::at<5,ArgList>::type t5; + typedef typename detail::at<5,ArgList>::type t5; typedef typename forward::type f5; static void execute( From a2071feeb11685a4aed5a67c042edb70fbe6b174 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 15 Mar 2002 12:47:04 +0000 Subject: [PATCH 361/369] Roll back vc7 workarounds; Aleksey has folded them into the MPL code [SVN r13207] --- include/boost/python/object/make_holder.hpp | 58 ++++++++------------- 1 file changed, 21 insertions(+), 37 deletions(-) diff --git a/include/boost/python/object/make_holder.hpp b/include/boost/python/object/make_holder.hpp index 5268bde4..871ed059 100644 --- a/include/boost/python/object/make_holder.hpp +++ b/include/boost/python/object/make_holder.hpp @@ -14,22 +14,6 @@ namespace boost { namespace python { namespace objects { -namespace detail -{ - // Use of this workaround as opposed to straightforward mpl::at - // needed for vc7, for some reason. - template - struct at - { - private: - typedef typename mpl::at_algorithm_traits< - typename mpl::sequence_traits::sequence_category - >::template algorithm::type base; - public: - typedef typename base::type type; - }; -} - template struct make_holder; template <> @@ -55,7 +39,7 @@ struct make_holder<1> struct apply { typedef typename mpl::apply1::type holder; - typedef typename detail::at<0,ArgList>::type t0; + typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; static void execute( @@ -74,9 +58,9 @@ struct make_holder<2> struct apply { typedef typename mpl::apply1::type holder; - typedef typename detail::at<0,ArgList>::type t0; + typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; - typedef typename detail::at<1,ArgList>::type t1; + typedef typename mpl::at<1,ArgList>::type t1; typedef typename forward::type f1; static void execute( @@ -94,11 +78,11 @@ struct make_holder<3> struct apply { typedef typename mpl::apply1::type holder; - typedef typename detail::at<0,ArgList>::type t0; + typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; - typedef typename detail::at<1,ArgList>::type t1; + typedef typename mpl::at<1,ArgList>::type t1; typedef typename forward::type f1; - typedef typename detail::at<2,ArgList>::type t2; + typedef typename mpl::at<2,ArgList>::type t2; typedef typename forward::type f2; static void execute( @@ -116,13 +100,13 @@ struct make_holder<4> struct apply { typedef typename mpl::apply1::type holder; - typedef typename detail::at<0,ArgList>::type t0; + typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; - typedef typename detail::at<1,ArgList>::type t1; + typedef typename mpl::at<1,ArgList>::type t1; typedef typename forward::type f1; - typedef typename detail::at<2,ArgList>::type t2; + typedef typename mpl::at<2,ArgList>::type t2; typedef typename forward::type f2; - typedef typename detail::at<3,ArgList>::type t3; + typedef typename mpl::at<3,ArgList>::type t3; typedef typename forward::type f3; static void execute( @@ -140,15 +124,15 @@ struct make_holder<5> struct apply { typedef typename mpl::apply1::type holder; - typedef typename detail::at<0,ArgList>::type t0; + typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; - typedef typename detail::at<1,ArgList>::type t1; + typedef typename mpl::at<1,ArgList>::type t1; typedef typename forward::type f1; - typedef typename detail::at<2,ArgList>::type t2; + typedef typename mpl::at<2,ArgList>::type t2; typedef typename forward::type f2; - typedef typename detail::at<3,ArgList>::type t3; + typedef typename mpl::at<3,ArgList>::type t3; typedef typename forward::type f3; - typedef typename detail::at<4,ArgList>::type t4; + typedef typename mpl::at<4,ArgList>::type t4; typedef typename forward::type f4; static void execute( @@ -166,17 +150,17 @@ struct make_holder<6> struct apply { typedef typename mpl::apply1::type holder; - typedef typename detail::at<0,ArgList>::type t0; + typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; - typedef typename detail::at<1,ArgList>::type t1; + typedef typename mpl::at<1,ArgList>::type t1; typedef typename forward::type f1; - typedef typename detail::at<2,ArgList>::type t2; + typedef typename mpl::at<2,ArgList>::type t2; typedef typename forward::type f2; - typedef typename detail::at<3,ArgList>::type t3; + typedef typename mpl::at<3,ArgList>::type t3; typedef typename forward::type f3; - typedef typename detail::at<4,ArgList>::type t4; + typedef typename mpl::at<4,ArgList>::type t4; typedef typename forward::type f4; - typedef typename detail::at<5,ArgList>::type t5; + typedef typename mpl::at<5,ArgList>::type t5; typedef typename forward::type f5; static void execute( From a8d6f40794fee484ec07f1d13c2514a687889779 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 15 Mar 2002 14:16:31 +0000 Subject: [PATCH 362/369] *** empty log message *** [SVN r13210] --- .../python/detail/member_function_cast.hpp | 14 ++++- include/boost/python/detail/wrap_function.hpp | 5 ++ src/object/inheritance.cpp | 2 +- test/Jamfile | 7 ++- test/member_function_cast.cpp | 55 +++++++++++++++++++ test/module_tail.cpp | 3 + 6 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 test/member_function_cast.cpp diff --git a/include/boost/python/detail/member_function_cast.hpp b/include/boost/python/detail/member_function_cast.hpp index 52718390..6e3f18c4 100644 --- a/include/boost/python/detail/member_function_cast.hpp +++ b/include/boost/python/detail/member_function_cast.hpp @@ -43,6 +43,13 @@ struct non_member_function_cast_impl template struct member_function_cast_impl { +# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + template + static non_member_function_cast_impl stage1(U) + { + return non_member_function_cast_impl(); + } +# endif template static cast_helper stage1(R (S::*)()) { @@ -85,7 +92,6 @@ struct member_function_cast_impl return cast_helper(); } -# if 1 template static cast_helper stage1(R (S::*)()const) { @@ -170,7 +176,6 @@ struct member_function_cast_impl return cast_helper(); } -// # ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template static cast_helper stage1(R (S::*)()const volatile) { @@ -212,17 +217,20 @@ struct member_function_cast_impl { return cast_helper(); } -# endif }; template struct member_function_cast +# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + : member_function_cast_impl +# else : mpl::select_type< is_member_function_pointer::value , member_function_cast_impl , non_member_function_cast_impl >::type +# endif { }; diff --git a/include/boost/python/detail/wrap_function.hpp b/include/boost/python/detail/wrap_function.hpp index 0424183d..682b3e89 100644 --- a/include/boost/python/detail/wrap_function.hpp +++ b/include/boost/python/detail/wrap_function.hpp @@ -45,9 +45,14 @@ template PyObject* wrap_function(F f) { return wrap_function_select< +# if 1 + type_traits::ice_not< + is_pointer::value +# else type_traits::ice_or< is_function::value , is_member_function_pointer::value +# endif >::value >::execute(f); } diff --git a/src/object/inheritance.cpp b/src/object/inheritance.cpp index 5b95e478..91a37f02 100644 --- a/src/object/inheritance.cpp +++ b/src/object/inheritance.cpp @@ -109,7 +109,7 @@ namespace make_iterator_property_map( to_target , get(vertex_index, reverse_topology) -# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +# ifdef BOOST_NO_STD_ITERATOR_TRAITS , *to_target # endif ) diff --git a/test/Jamfile b/test/Jamfile index 1f5de1e9..a01efdde 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -59,11 +59,14 @@ bpl-test virtual_functions ; # --- unit tests of library components --- unit-test indirect_traits_test - : indirect_traits_test.cpp : $(BOOST_ROOT) ; + : indirect_traits_test.cpp : $(BOOST_ROOT) ; unit-test destroy_test : destroy_test.cpp : $(BOOST_ROOT) ; unit-test pointer_type_id_test - : pointer_type_id_test.cpp : $(BOOST_ROOT) ; + : pointer_type_id_test.cpp : $(BOOST_ROOT) ; + +unit-test member_function_cast + : member_function_cast.cpp : $(BOOST_ROOT) ; unit-test select_from_python_test : select_from_python_test.cpp diff --git a/test/member_function_cast.cpp b/test/member_function_cast.cpp new file mode 100644 index 00000000..986d87b5 --- /dev/null +++ b/test/member_function_cast.cpp @@ -0,0 +1,55 @@ +// Copyright David Abrahams 2002. 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. +#include +#include +#include +#include + +using namespace boost; + +template +void assert_same(S, type* = 0) +{ + BOOST_STATIC_ASSERT((is_same::value)); +} + +template +void assert_mf_cast(F f, type* = 0, type* = 0) +{ + assert_same( + python::detail::member_function_cast::stage1(f).stage2((Target*)0).stage3(f) + ); +} + +struct X +{ + int f() const { return 0; } + void g(char*) {} +}; + +struct Y : X +{ + +}; + +struct Z : Y +{ + int f() const { return 0; } + void g(char*) {} +}; + +int main() +{ + assert_mf_cast(&X::f); + assert_mf_cast(&X::g); + + assert_mf_cast(&Z::f); + assert_mf_cast(&Z::g); + + assert_mf_cast(3); + assert_mf_cast(X()); + return 0; +}; diff --git a/test/module_tail.cpp b/test/module_tail.cpp index 6849bf83..763e7dff 100644 --- a/test/module_tail.cpp +++ b/test/module_tail.cpp @@ -16,10 +16,13 @@ extern "C" BOOL WINAPI DllMain ( HINSTANCE hInst, DWORD wDataSeg, LPVOID lpvReserved ); # ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable:4297) extern "C" void structured_exception_translator(unsigned int, EXCEPTION_POINTERS*) { throw; } +# pragma warning(pop) # endif BOOL WINAPI DllMain( From 08ac2877261938a38136c4f1edd087e560e63a0b Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 20 Mar 2002 07:04:28 +0000 Subject: [PATCH 363/369] warning suppression for vc7 [SVN r13229] --- test/comprehensive.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/comprehensive.cpp b/test/comprehensive.cpp index 6c7cc4d3..d4617181 100644 --- a/test/comprehensive.cpp +++ b/test/comprehensive.cpp @@ -1225,6 +1225,9 @@ extern "C" BOOL WINAPI DllMain ( HINSTANCE hInst, DWORD wDataSeg, LPVOID lpvRese # ifdef BOOST_MSVC extern "C" void structured_exception_translator(unsigned int, EXCEPTION_POINTERS*) +# if BOOST_MSVC > 1200 + throw(...) +# endif { throw; } From 3b8dc924c3c0aae4b066c9254685b3bd4cb1c81c Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 20 Mar 2002 07:06:09 +0000 Subject: [PATCH 364/369] Removed defunct workarounds [SVN r13230] --- src/conversions.cpp | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/src/conversions.cpp b/src/conversions.cpp index e6b6161a..e180af67 100644 --- a/src/conversions.cpp +++ b/src/conversions.cpp @@ -19,9 +19,7 @@ #include #include #include -#ifndef BOOST_NO_LIMITS -# include -#endif +#include BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE @@ -53,19 +51,11 @@ T integer_from_python(PyObject* p, boost::python::type) { const long long_result = from_python(p, boost::python::type()); -#ifndef BOOST_NO_LIMITS try { return boost::numeric_cast(long_result); } catch(const boost::bad_numeric_cast&) -#else - if (static_cast(long_result) == long_result) - { - return static_cast(long_result); - } - else -#endif { char buffer[256]; const char message[] = "%ld out of range for %s"; @@ -73,7 +63,7 @@ T integer_from_python(PyObject* p, boost::python::type) PyErr_SetString(PyExc_ValueError, buffer); throw boost::python::argument_error(); } -#if defined(__MWERKS__) && __MWERKS__ <= 0x2406 +#if defined(__MWERKS__) && __MWERKS__ <= 0x2407 return 0; // Not smart enough to know that the catch clause always rethrows #endif } @@ -83,16 +73,11 @@ PyObject* integer_to_python(T value) { long value_as_long; -#ifndef BOOST_NO_LIMITS try { value_as_long = boost::numeric_cast(value); } catch(const boost::bad_numeric_cast&) -#else - value_as_long = static_cast(value); - if (value_as_long != value) -#endif { const char message[] = "value out of range for Python int"; PyErr_SetString(PyExc_ValueError, message); From d72128107ee45312b23c18bb32b0b59ad3dcc7ab Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 20 Mar 2002 07:16:06 +0000 Subject: [PATCH 365/369] no comment [SVN r13231] --- include/boost/python/conversions.hpp | 7 +++---- include/boost/python/detail/init_function.hpp | 6 ++++++ src/extension_class.cpp | 3 +-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/include/boost/python/conversions.hpp b/include/boost/python/conversions.hpp index 24ac5614..f328981e 100644 --- a/include/boost/python/conversions.hpp +++ b/include/boost/python/conversions.hpp @@ -157,16 +157,15 @@ BOOST_PYTHON_DECL PyObject* to_python(unsigned char); BOOST_PYTHON_DECL unsigned char from_python(PyObject*, boost::python::type); unsigned char from_python(PyObject*, boost::python::type); +BOOST_PYTHON_DECL float from_python(PyObject*, boost::python::type); +BOOST_PYTHON_DECL double from_python(PyObject*, boost::python::type); + # ifndef BOOST_MSVC6_OR_EARLIER PyObject* to_python(float); -float from_python(PyObject*, boost::python::type); PyObject* to_python(double); -double from_python(PyObject*, boost::python::type); # else BOOST_PYTHON_DECL PyObject* to_python(float); -BOOST_PYTHON_DECL float from_python(PyObject*, boost::python::type); BOOST_PYTHON_DECL PyObject* to_python(double); -BOOST_PYTHON_DECL double from_python(PyObject*, boost::python::type); # endif float from_python(PyObject*, boost::python::type); diff --git a/include/boost/python/detail/init_function.hpp b/include/boost/python/detail/init_function.hpp index 3c6f2380..048c90dd 100644 --- a/include/boost/python/detail/init_function.hpp +++ b/include/boost/python/detail/init_function.hpp @@ -168,6 +168,9 @@ template struct init_function { +# ifdef BOOST_MSVC6_OR_EARLIER +# define typename +# endif static init* create(signature0) { return new init0; } @@ -276,6 +279,9 @@ struct init_function typename detail::parameter_traits::const_reference, typename detail::parameter_traits::const_reference>; } +#ifdef BOOST_MSVC6_OR_EARLIER +# undef typename +#endif }; class BOOST_PYTHON_DECL init : public function diff --git a/src/extension_class.cpp b/src/extension_class.cpp index cc784ca6..98505347 100644 --- a/src/extension_class.cpp +++ b/src/extension_class.cpp @@ -11,7 +11,6 @@ #define BOOST_PYTHON_SOURCE -#include #include #include #include @@ -178,7 +177,7 @@ extension_instance::~extension_instance() } } -meta_class* extension_meta_class() +BOOST_PYTHON_DECL meta_class* extension_meta_class() { static meta_class result; return &result; From 0ce8ab7bcec74ee7f0ed19079e511445dfe18099 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 24 Mar 2002 14:52:30 +0000 Subject: [PATCH 366/369] Full virtual function and abstract base support; new class interface. [SVN r13253] --- include/boost/python/class.hpp | 190 +++++++++++------- include/boost/python/class_fwd.hpp | 7 +- .../boost/python/detail/arg_tuple_size.hpp | 2 +- include/boost/python/detail/msvc_typeinfo.hpp | 31 +-- include/boost/python/make_function.hpp | 6 +- .../boost/python/object/class_converters.hpp | 25 +-- include/boost/python/object/class_wrapper.hpp | 11 +- include/boost/python/object/find_instance.hpp | 3 + include/boost/python/object/make_holder.hpp | 36 ++-- .../boost/python/object/pointer_holder.hpp | 142 +++++-------- include/boost/python/object/select_holder.hpp | 70 +++++++ include/boost/python/object/value_holder.hpp | 23 +-- test/Jamfile | 15 ++ test/m1.cpp | 13 +- test/select_holder.cpp | 77 +++++++ test/virtual_functions.cpp | 14 +- test/virtual_functions.py | 70 +++---- 17 files changed, 430 insertions(+), 305 deletions(-) create mode 100644 include/boost/python/object/select_holder.hpp create mode 100644 test/select_holder.cpp diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index 0a9c5d87..cff0adf9 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -7,55 +7,50 @@ # define CLASS_DWA200216_HPP # include +# include +# include # include # include -# include # include # include # include -# include # include +# include +# include # include # include -# include - -namespace // put some convenience classes into the unnamed namespace for the user -{ - // A type list for specifying bases - template < BOOST_MPL_LIST_DEFAULT_PARAMETERS(typename B, ::boost::mpl::null_argument) > - struct bases : ::boost::mpl::type_list< BOOST_MPL_LIST_PARAMETERS(B) >::type - {}; - - // A type list for specifying arguments - template < BOOST_MPL_LIST_DEFAULT_PARAMETERS(typename A, ::boost::mpl::null_argument) > - struct args : ::boost::mpl::type_list< BOOST_MPL_LIST_PARAMETERS(A) >::type - {}; -} +# include +# include +# include +# include namespace boost { namespace python { namespace detail { - // This is an mpl BinaryMetaFunction object with a runtime behavior, - // which is to write the id of the type which is passed as its 2nd - // compile-time argument into the iterator pointed to by its runtime - // argument - struct write_type_id - { - // The first argument is Ignored because mpl::for_each is still - // currently an accumulate (reduce) implementation. - template struct apply - { - // also an artifact of accumulate-based for_each - typedef void type; + struct write_type_id; + + template + struct select_held_type; + + template + struct has_noncopyable; - // Here's the runtime behavior - static void execute(converter::undecorated_type_id_t** p) - { - *(*p)++ = converter::undecorated_type_id(); - } - }; - }; + // Register a to_python converter for a class T, depending on the + // type of the first (tag) argument. The 2nd argument is a pointer + // to the type of holder that must be created. The 3rd argument is a + // reference to the Python type object to be created. + template + static inline void register_copy_constructor(mpl::bool_t const&, Holder*, ref const& obj, T* = 0) + { + objects::class_wrapper x(obj); + } + + // Tag dispatched to have no effect. + template + static inline void register_copy_constructor(mpl::bool_t const&, Holder*, ref const&, T* = 0) + { + } } // @@ -64,27 +59,24 @@ namespace detail // This is the primary mechanism through which users will expose // C++ classes to Python. The three template arguments are: // -// T - The class being exposed to Python -// -// Bases - An MPL sequence of base classes -// -// HolderGenerator - -// An optional type generator for the "holder" which -// maintains the C++ object inside the Python instance. The -// default just holds the object "by-value", but other -// holders can be substituted which will hold the C++ object -// by smart pointer, for example. -// template < class T // class being wrapped - , class Bases - , class HolderGenerator + , class X1 // = detail::not_specified + , class X2 // = detail::not_specified + , class X3 // = detail::not_specified > class class_ : private objects::class_base { - typedef class_ self; + typedef class_ self; + BOOST_STATIC_CONSTANT(bool, is_copyable = (!detail::has_noncopyable::value)); + + typedef typename detail::select_held_type< + X1, typename detail::select_held_type< + X2, typename detail::select_held_type< + X3 + >::type>::type>::type held_type; + public: - // Automatically derive the class name - only works on some // compilers because type_info::name is sometimes mangled (gcc) class_(); @@ -130,7 +122,12 @@ class class_ : private objects::class_base template self& def_init(Args const&) { - def("__init__", make_constructor()); + def("__init__", + make_constructor( + // Using runtime type selection works around a CWPro7 bug. + objects::select_holder((held_type*)0).get() + ) + ); return *this; } @@ -147,6 +144,12 @@ class class_ : private objects::class_base private: // types typedef objects::class_id class_id; + typedef typename detail::select_bases::type + >::type + >::type bases; + // A helper class which will contain an array of id objects to be // passed to the base class constructor struct id_vector @@ -159,50 +162,97 @@ class class_ : private objects::class_base // Write the rest of the elements into succeeding positions. class_id* p = ids + 1; - mpl::for_each::execute(&p); + mpl::for_each::execute(&p); } BOOST_STATIC_CONSTANT( - std::size_t, size = mpl::size::value + 1); + std::size_t, size = mpl::size::value + 1); class_id ids[size]; }; - - private: // helper functions - void initialize_converters(); }; // // implementations // -template -inline class_::class_() +template +inline class_::class_() : class_base(typeid(T).name(), id_vector::size, id_vector().ids) { - // Bring the class converters into existence. This static object - // will survive until the shared library this module lives in is - // unloaded (that doesn't happen until Python terminates). - static objects::class_converters converters(object()); + // register converters + objects::register_class_from_python(); + + detail::register_copy_constructor( + mpl::bool_t() + , objects::select_holder((held_type*)0).get() + , this->object()); } -template -inline class_::class_(char const* name) +template +inline class_::class_(char const* name) : class_base(name, id_vector::size, id_vector().ids) { - // Bring the class converters into existence. This static object - // will survive until the shared library this module lives in is - // unloaded (that doesn't happen until Python terminates). - static objects::class_converters converters(object()); + // register converters + objects::register_class_from_python(); + + detail::register_copy_constructor( + mpl::bool_t() + , objects::select_holder((held_type*)0).get() + , this->object()); } -template -inline ref class_::object() const +template +inline ref class_::object() const { typedef objects::class_base base; return this->base::object(); } +namespace detail +{ + // This is an mpl BinaryMetaFunction object with a runtime behavior, + // which is to write the id of the type which is passed as its 2nd + // compile-time argument into the iterator pointed to by its runtime + // argument + struct write_type_id + { + // The first argument is Ignored because mpl::for_each is still + // currently an accumulate (reduce) implementation. + template struct apply + { + // also an artifact of accumulate-based for_each + typedef void type; + + // Here's the runtime behavior + static void execute(converter::undecorated_type_id_t** p) + { + *(*p)++ = converter::undecorated_type_id(); + } + }; + }; + + + template + struct has_noncopyable + : type_traits::ice_or< + is_same::value + , is_same::value + , is_same::value> + {}; + + + template + struct select_held_type + : mpl::select_type< + !(specifies_bases::value | is_same::value) + , T + , Prev + > + { + }; +} + }} // namespace boost::python #endif // CLASS_DWA200216_HPP diff --git a/include/boost/python/class_fwd.hpp b/include/boost/python/class_fwd.hpp index bef2e250..1ef941aa 100644 --- a/include/boost/python/class_fwd.hpp +++ b/include/boost/python/class_fwd.hpp @@ -5,7 +5,7 @@ // to its suitability for any purpose. #ifndef CLASS_FWD_DWA200222_HPP # define CLASS_FWD_DWA200222_HPP -# include +# include namespace boost { namespace python { @@ -16,8 +16,9 @@ namespace detail template < class T // class being wrapped - , class Bases = detail::empty_list - , class HolderGenerator = objects::value_holder_generator<> + , class X1 = detail::not_specified + , class X2 = detail::not_specified + , class X3 = detail::not_specified > class class_; diff --git a/include/boost/python/detail/arg_tuple_size.hpp b/include/boost/python/detail/arg_tuple_size.hpp index 04bca0af..fa38a4a9 100644 --- a/include/boost/python/detail/arg_tuple_size.hpp +++ b/include/boost/python/detail/arg_tuple_size.hpp @@ -103,7 +103,7 @@ struct arg_tuple_size // Metrowerks thinks this creates ambiguities -# if !defined(__MWERKS__) || __MWERKS__ > 0x2406 +# if !defined(__MWERKS__) || __MWERKS__ > 0x2407 template struct arg_tuple_size diff --git a/include/boost/python/detail/msvc_typeinfo.hpp b/include/boost/python/detail/msvc_typeinfo.hpp index 2473023a..3da411f0 100644 --- a/include/boost/python/detail/msvc_typeinfo.hpp +++ b/include/boost/python/detail/msvc_typeinfo.hpp @@ -8,7 +8,8 @@ #include #include - +#include +#include // // Fix for MSVC's broken typeid() implementation which doesn't strip // decoration. This fix doesn't handle cv-qualified array types. It @@ -62,35 +63,35 @@ inline typeinfo typeid_nonref(boost::type* = 0) } template -inline typeinfo typeid_ref(boost::type*, ...) -{ - return typeid_nonref(); -} - -template -inline typeinfo typeid_ref(boost::type*, T& (*)()) +inline typeinfo typeid_ref(T&(*)()) { return typeid_nonref(); } template -inline typeinfo typeid_array(bool_t, boost::type* = 0) +inline typeinfo array_ref_typeid(bool_t, bool_t, boost::type* = 0) { - typedef T (*x)(); - return typeid_ref((boost::type*)0, x(0)); + return typeid_ref((T&(*)())0); } template -inline typeinfo typeid_array(bool_t, boost::type* = 0) +inline typeinfo array_ref_typeid(bool_t, bool_t, boost::type* = 0) { - return typeid_nonref(); + return typeid_ref((T(*)())0); +} + +template +inline typeinfo array_ref_typeid(bool_t, bool_t, boost::type* = 0) +{ + return typeid_ref((T&(*)())0); } template inline typeinfo msvc_typeid(boost::type* = 0) { - typedef bool_t::value> tag; - return typeid_array(tag(), (boost::type*)0); + typedef bool_t::value> array_tag; + typedef bool_t::value> ref_tag; + return array_ref_typeid(array_tag(), ref_tag(), (boost::type*)0); } }}} // namespace boost::python::detail diff --git a/include/boost/python/make_function.hpp b/include/boost/python/make_function.hpp index 2943d96c..6e7f1661 100644 --- a/include/boost/python/make_function.hpp +++ b/include/boost/python/make_function.hpp @@ -35,8 +35,8 @@ objects::function* make_function(F f, Policies const& policies) , detail::arg_tuple_size::value); } -template -objects::function* make_constructor(T* = 0, ArgList* = 0, Generator* = 0) +template +objects::function* make_constructor(Holder* = 0, ArgList* = 0) { enum { nargs = mpl::size::value }; @@ -44,7 +44,7 @@ objects::function* make_constructor(T* = 0, ArgList* = 0, Generator* = 0) objects::py_function( ::boost::bind(detail::caller(), objects::make_holder - ::template apply::execute + ::template apply::execute , _1, _2, default_call_policies())) , nargs + 1); } diff --git a/include/boost/python/object/class_converters.hpp b/include/boost/python/object/class_converters.hpp index 5c2a35ae..8f2786f3 100644 --- a/include/boost/python/object/class_converters.hpp +++ b/include/boost/python/object/class_converters.hpp @@ -11,27 +11,10 @@ # include # include # include +# include namespace boost { namespace python { namespace objects { -// Instantiating this class brings into existence all converters -// associated with a class Bases is expected to be an mpl sequence of -// base types. -template -struct class_converters -{ - public: // member functions - // Constructor takes the python class object associated with T - class_converters(ref const& python_class); - - private: // data members - class_wrapper m_wrapper; -}; - -// -// Implementation details -// - ////////////////////////////////////////////////////////////////////// // // register_base_of - @@ -86,9 +69,11 @@ struct register_base_of }; }; + +// Brings into existence all converters associated with a class Bases +// is expected to be an mpl sequence of base types. template -class_converters::class_converters(ref const& type_object) - : m_wrapper(type_object) +inline void register_class_from_python(Derived* = 0, Bases* = 0) { (void)instance_finder::registration; diff --git a/include/boost/python/object/class_wrapper.hpp b/include/boost/python/object/class_wrapper.hpp index f8702205..577d1012 100644 --- a/include/boost/python/object/class_wrapper.hpp +++ b/include/boost/python/object/class_wrapper.hpp @@ -6,15 +6,14 @@ #ifndef CLASS_WRAPPER_DWA20011221_HPP # define CLASS_WRAPPER_DWA20011221_HPP -# include # include # include namespace boost { namespace python { namespace objects { -template +template struct class_wrapper - : to_python_converter > + : to_python_converter > { class_wrapper(ref const& type_) : m_class_object_keeper(type_) @@ -39,7 +38,7 @@ struct class_wrapper // Build a value_holder to contain the object using the copy // constructor - value_holder* p = new value_holder(raw_result, cref(x)); + Holder* p = new Holder(raw_result, cref(x)); // Install it in the instance p->install(raw_result); @@ -53,8 +52,8 @@ struct class_wrapper static PyTypeObject* m_class_object; }; -template -PyTypeObject* class_wrapper::m_class_object; +template +PyTypeObject* class_wrapper::m_class_object; }}} // namespace boost::python::objects diff --git a/include/boost/python/object/find_instance.hpp b/include/boost/python/object/find_instance.hpp index c60a82f7..3db670fc 100644 --- a/include/boost/python/object/find_instance.hpp +++ b/include/boost/python/object/find_instance.hpp @@ -6,6 +6,9 @@ #ifndef FIND_INSTANCE_DWA2002312_HPP # define FIND_INSTANCE_DWA2002312_HPP +# include +# include + namespace boost { namespace python { namespace objects { // Given an undecorated type_id, find the instance data which diff --git a/include/boost/python/object/make_holder.hpp b/include/boost/python/object/make_holder.hpp index 871ed059..59043317 100644 --- a/include/boost/python/object/make_holder.hpp +++ b/include/boost/python/object/make_holder.hpp @@ -10,7 +10,6 @@ # include # include # include -# include namespace boost { namespace python { namespace objects { @@ -19,14 +18,13 @@ template struct make_holder; template <> struct make_holder<0> { - template + template struct apply { - typedef typename mpl::apply1::type holder; static void execute( PyObject* p) { - (new holder(p))->install(p); + (new Holder(p))->install(p); } }; }; @@ -35,10 +33,9 @@ struct make_holder<0> template <> struct make_holder<1> { - template + template struct apply { - typedef typename mpl::apply1::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; @@ -46,7 +43,7 @@ struct make_holder<1> PyObject* p , t0 a0) { - (new holder(p, f0(a0)))->install(p); + (new Holder(p, f0(a0)))->install(p); } }; }; @@ -54,10 +51,9 @@ struct make_holder<1> template <> struct make_holder<2> { - template + template struct apply { - typedef typename mpl::apply1::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; typedef typename mpl::at<1,ArgList>::type t1; @@ -66,7 +62,7 @@ struct make_holder<2> static void execute( PyObject* p, t0 a0, t1 a1) { - (new holder(p, f0(a0), f1(a1)))->install(p); + (new Holder(p, f0(a0), f1(a1)))->install(p); } }; }; @@ -74,10 +70,9 @@ struct make_holder<2> template <> struct make_holder<3> { - template + template struct apply { - typedef typename mpl::apply1::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; typedef typename mpl::at<1,ArgList>::type t1; @@ -88,7 +83,7 @@ struct make_holder<3> static void execute( PyObject* p, t0 a0, t1 a1, t2 a2) { - (new holder(p, f0(a0), f1(a1), f2(a2)))->install(p); + (new Holder(p, f0(a0), f1(a1), f2(a2)))->install(p); } }; }; @@ -96,10 +91,9 @@ struct make_holder<3> template <> struct make_holder<4> { - template + template struct apply { - typedef typename mpl::apply1::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; typedef typename mpl::at<1,ArgList>::type t1; @@ -112,7 +106,7 @@ struct make_holder<4> static void execute( PyObject* p, t0 a0, t1 a1, t2 a2, t3 a3) { - (new holder(p, f0(a0), f1(a1), f2(a2), f3(a3)))->install(p); + (new Holder(p, f0(a0), f1(a1), f2(a2), f3(a3)))->install(p); } }; }; @@ -120,10 +114,9 @@ struct make_holder<4> template <> struct make_holder<5> { - template + template struct apply { - typedef typename mpl::apply1::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; typedef typename mpl::at<1,ArgList>::type t1; @@ -138,7 +131,7 @@ struct make_holder<5> static void execute( PyObject* p, t0 a0, t1 a1, t2 a2, t3 a3, t4 a4) { - (new holder(p, f0(a0), f1(a1), f2(a2), f3(a3), f4(a4)))->install(p); + (new Holder(p, f0(a0), f1(a1), f2(a2), f3(a3), f4(a4)))->install(p); } }; }; @@ -146,10 +139,9 @@ struct make_holder<5> template <> struct make_holder<6> { - template + template struct apply { - typedef typename mpl::apply1::type holder; typedef typename mpl::at<0,ArgList>::type t0; typedef typename forward::type f0; typedef typename mpl::at<1,ArgList>::type t1; @@ -166,7 +158,7 @@ struct make_holder<6> static void execute( PyObject* p, t0 a0, t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) { - (new holder(p, f0(a0), f1(a1), f2(a2), f3(a3), f4(a4), f5(a5)))->install(p); + (new Holder(p, f0(a0), f1(a1), f2(a2), f3(a3), f4(a4), f5(a5)))->install(p); } }; }; diff --git a/include/boost/python/object/pointer_holder.hpp b/include/boost/python/object/pointer_holder.hpp index 84700299..8bce39bd 100644 --- a/include/boost/python/object/pointer_holder.hpp +++ b/include/boost/python/object/pointer_holder.hpp @@ -14,6 +14,7 @@ # include # include # include +# include namespace boost { namespace python { namespace objects { @@ -147,81 +148,83 @@ struct pointer_holder : instance_holder Pointer m_p; }; -template +template struct pointer_holder_back_reference : instance_holder { + private: + typedef typename python::detail::pointee::type held_type; + public: + pointer_holder_back_reference(Pointer); // Forward construction to the held object pointer_holder_back_reference(PyObject* p) - : m_p(new BackReferenceType(p)) { - (void)instance_finder::registration; + : m_p(new held_type(p)) { + (void)instance_finder::registration; } - - template pointer_holder_back_reference(PyObject* p, A1 a1) - : m_p(new BackReferenceType(p + : m_p(new held_type(p , (typename unwrap_reference::type&)(a1) )) { - (void)instance_finder::registration; + (void)instance_finder::registration; } template pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2) - : m_p(new BackReferenceType(p + : m_p(new held_type(p , (typename unwrap_reference::type&)(a1) , (typename unwrap_reference::type&)(a2) )) { - (void)instance_finder::registration; + (void)instance_finder::registration; } template pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3) - : m_p(new BackReferenceType(p + : m_p(new held_type(p , (typename unwrap_reference::type&)(a1) , (typename unwrap_reference::type&)(a2) , (typename unwrap_reference::type&)(a3) )) { - (void)instance_finder::registration; + (void)instance_finder::registration; } template pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4) - : m_p(new BackReferenceType(p + : m_p(new held_type(p , (typename unwrap_reference::type&)(a1) , (typename unwrap_reference::type&)(a2) , (typename unwrap_reference::type&)(a3) , (typename unwrap_reference::type&)(a4) )) { - (void)instance_finder::registration; + (void)instance_finder::registration; } template pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) - : m_p(new BackReferenceType(p + : m_p(new held_type(p , (typename unwrap_reference::type&)(a1) , (typename unwrap_reference::type&)(a2) , (typename unwrap_reference::type&)(a3) , (typename unwrap_reference::type&)(a4) , (typename unwrap_reference::type&)(a5) )) { - (void)instance_finder::registration; + (void)instance_finder::registration; } template pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) - : m_p(new BackReferenceType(p + : m_p(new held_type(p , (typename unwrap_reference::type&)(a1) , (typename unwrap_reference::type&)(a2) , (typename unwrap_reference::type&)(a3) @@ -229,13 +232,13 @@ struct pointer_holder_back_reference : instance_holder , (typename unwrap_reference::type&)(a5) , (typename unwrap_reference::type&)(a6) )) { - (void)instance_finder::registration; + (void)instance_finder::registration; } template pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) - : m_p(new BackReferenceType(p + : m_p(new held_type(p , (typename unwrap_reference::type&)(a1) , (typename unwrap_reference::type&)(a2) , (typename unwrap_reference::type&)(a3) @@ -245,13 +248,13 @@ struct pointer_holder_back_reference : instance_holder , (typename unwrap_reference::type&)(a7) )) { - (void)instance_finder::registration; + (void)instance_finder::registration; } template pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) - : m_p(new BackReferenceType(p + : m_p(new held_type(p , (typename unwrap_reference::type&)(a1) , (typename unwrap_reference::type&)(a2) , (typename unwrap_reference::type&)(a3) @@ -262,13 +265,13 @@ struct pointer_holder_back_reference : instance_holder , (typename unwrap_reference::type&)(a8) )) { - (void)instance_finder::registration; + (void)instance_finder::registration; } template pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) - : m_p(new BackReferenceType(p + : m_p(new held_type(p , (typename unwrap_reference::type&)(a1) , (typename unwrap_reference::type&)(a2) , (typename unwrap_reference::type&)(a3) @@ -280,13 +283,13 @@ struct pointer_holder_back_reference : instance_holder , (typename unwrap_reference::type&)(a9) )) { - (void)instance_finder::registration; + (void)instance_finder::registration; } template pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) - : m_p(new BackReferenceType(p + : m_p(new held_type(p , (typename unwrap_reference::type&)(a1) , (typename unwrap_reference::type&)(a2) , (typename unwrap_reference::type&)(a3) @@ -299,7 +302,7 @@ struct pointer_holder_back_reference : instance_holder , (typename unwrap_reference::type&)(a10) )) { - (void)instance_finder::registration; + (void)instance_finder::registration; } @@ -310,81 +313,18 @@ struct pointer_holder_back_reference : instance_holder Pointer m_p; }; -}}} // namespace boost::python::objects - -// back to namespace boost for this forward declaration -namespace boost -{ - template class shared_ptr; -} - -namespace boost { namespace python { namespace objects { - -struct shared_ptr_generator -{ - template - struct apply - { - typedef boost::shared_ptr type; - }; -}; - -struct no_back_reference; - -// Workaround lack of partial specialization -namespace detail -{ - template - struct pointer_holder_back_reference_generator - { - template - struct apply - { - typedef typename mpl::apply1< - PointerGenerator,BackReferenceType - >::type pointer; - - typedef pointer_holder_back_reference type; - }; - }; - - template - struct plain_pointer_holder_generator - { - template - struct apply - { - typedef typename mpl::apply1< - PointerGenerator,Held - >::type pointer; - - typedef pointer_holder type; - }; - }; -} - -// A generator metafunction which can be passed to make_holder -// PointerGenerator should be another generator metafunction which -// makes the appropriate (smart) pointer type to hold the argument to -// pointer_holder_generator. -template -struct pointer_holder_generator - : mpl::select_type< - is_same::value - , detail::plain_pointer_holder_generator< - PointerGenerator> - , detail::pointer_holder_back_reference_generator< - BackReferenceType,PointerGenerator> - >::type -{ -}; - template pointer_holder::pointer_holder(Pointer p) : m_p(p) { } +template +pointer_holder_back_reference::pointer_holder_back_reference(Pointer p) + : m_p(p) +{ +} + template void* pointer_holder::holds(converter::undecorated_type_id_t dst_t) { @@ -396,6 +336,20 @@ void* pointer_holder::holds(converter::undecorated_type_id_t dst : find_dynamic_type(&*this->m_p, src_t, dst_t); } +template +void* pointer_holder_back_reference::holds(converter::undecorated_type_id_t dst_t) +{ + if (dst_t == converter::undecorated_type_id()) + return &this->m_p; + + if (dst_t == converter::undecorated_type_id()) + return &*this->m_p; + + converter::type_id_t src_t = converter::undecorated_type_id(); + Value* p = &*this->m_p; + return src_t == dst_t ? p : find_dynamic_type(p, src_t, dst_t); +} + }}} // namespace boost::python::objects #endif // POINTER_HOLDER_DWA20011215_HPP diff --git a/include/boost/python/object/select_holder.hpp b/include/boost/python/object/select_holder.hpp new file mode 100644 index 00000000..39d50c0a --- /dev/null +++ b/include/boost/python/object/select_holder.hpp @@ -0,0 +1,70 @@ +// Copyright David Abrahams 2002. 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 SELECT_HOLDER_DWA2002322_HPP +# define SELECT_HOLDER_DWA2002322_HPP + +# include +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace objects { + +namespace detail +{ + template + struct select_value_holder + { + typedef typename mpl::select_type< + (!is_same::value) | has_back_reference::value + , value_holder_back_reference + , value_holder + >::type holder; + + static holder* get() { return 0; } + }; + + template + struct select_pointer_holder + { + typedef typename python::detail::pointee::type pointee; + + typedef typename mpl::select_type< + (!is_same::value) | has_back_reference::value + , pointer_holder_back_reference + , pointer_holder + >::type holder; + + static holder* get() { return 0; } + }; +} + +template +inline detail::select_value_holder select_holder(python::detail::not_specified*, T* = 0, NotSpecified* = 0) +{ + return detail::select_value_holder(); +} + +template +inline detail::select_value_holder select_holder(T*, Held* = 0) +{ + return detail::select_value_holder(); +} + + +template +detail::select_pointer_holder select_holder(void*, Ptr* = 0, T* = 0) +{ + return detail::select_pointer_holder(); +} + +}}} // namespace boost::python::objects + +#endif // SELECT_HOLDER_DWA2002322_HPP diff --git a/include/boost/python/object/value_holder.hpp b/include/boost/python/object/value_holder.hpp index c0a5c580..4154a7e8 100644 --- a/include/boost/python/object/value_holder.hpp +++ b/include/boost/python/object/value_holder.hpp @@ -142,7 +142,7 @@ struct value_holder : instance_holder Held m_held; }; -template +template struct value_holder_back_reference : instance_holder { // Forward construction to the held object @@ -301,27 +301,6 @@ struct value_holder_back_reference : instance_holder BackReferenceType m_held; }; -// A generator metafunction which can be passed to make_holder -template <> -struct value_holder_generator -{ - template - struct apply - { - typedef value_holder type; - }; -}; - -template -struct value_holder_generator -{ - template - struct apply - { - typedef value_holder_back_reference type; - }; -}; - template void* value_holder::holds(converter::undecorated_type_id_t dst_t) { diff --git a/test/Jamfile b/test/Jamfile index a01efdde..6db104fb 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -68,6 +68,20 @@ unit-test pointer_type_id_test unit-test member_function_cast : member_function_cast.cpp : $(BOOST_ROOT) ; +unit-test bases + : bases.cpp : $(BOOST_ROOT) ; + +unit-test if_else + : if_else.cpp : $(BOOST_ROOT) ; + +unit-test pointee + : pointee.cpp : $(BOOST_ROOT) ; + +unit-test select_holder + : select_holder.cpp + : $(BOOST_ROOT) BOOST_PYTHON_STATIC_LIB $(PYTHON_PROPERTIES) +; + unit-test select_from_python_test : select_from_python_test.cpp ../src/converter/type_id.cpp @@ -77,3 +91,4 @@ unit-test select_from_python_test $(PYTHON_V1_PROPERTIES) ; + diff --git a/test/m1.cpp b/test/m1.cpp index 439d58e2..cbaaf8db 100644 --- a/test/m1.cpp +++ b/test/m1.cpp @@ -201,6 +201,7 @@ BOOST_PYTHON_MODULE_INIT(m1) { using namespace boost::python; using boost::mpl::type_list; + using boost::shared_ptr; simple_to_python(); @@ -219,10 +220,6 @@ BOOST_PYTHON_MODULE_INIT(m1) module m1("m1"); - typedef boost::python::objects::pointer_holder_generator< - boost::python::objects::shared_ptr_generator - > use_shared_ptr; - m1 // Insert the metaclass for all extension classes .setattr("xclass", boost::python::objects::class_metatype()) @@ -251,7 +248,7 @@ BOOST_PYTHON_MODULE_INIT(m1) .def("take_d", take_d) .add( - class_, use_shared_ptr>("A") + class_ >("A") .def_init() .def("name", &A::name) ) @@ -262,13 +259,13 @@ BOOST_PYTHON_MODULE_INIT(m1) // or "C" below if we make them part of the same chain m1 .add( - class_, use_shared_ptr>("B") + class_, shared_ptr >("B") .def_init() .def("name", &B::name) ) .add( - class_, use_shared_ptr>("C") + class_, shared_ptr >("C") .def_init() .def("name", &C::name) ) @@ -276,7 +273,7 @@ BOOST_PYTHON_MODULE_INIT(m1) m1 .add( - class_, use_shared_ptr>("D") + class_, bases >("D") .def_init() .def("name", &D::name) ) diff --git a/test/select_holder.cpp b/test/select_holder.cpp new file mode 100644 index 00000000..cb8fd640 --- /dev/null +++ b/test/select_holder.cpp @@ -0,0 +1,77 @@ +// Copyright David Abrahams 2002. 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. +#include +#include +#include +#include +#include +#include + +#define BOOST_INCLUDE_MAIN +#include + +struct BR {}; + +struct Base {}; +struct Derived : Base {}; + +namespace boost { namespace python +{ + // specialization + template <> + struct has_back_reference
    + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; +}} // namespace boost::python + +template +void assert_same(U* = 0, T* = 0) +{ + BOOST_TEST((boost::is_same::value)); + BOOST_STATIC_ASSERT((boost::is_same::value)); + +} + +template +void assert_holder(T* = 0, Held* = 0, Holder* = 0) +{ + assert_same(boost::python::objects::select_holder((Held*)0).get()); +} + +int test_main(int, char * []) +{ + using namespace boost::python::detail; + using namespace boost::python::objects; + + assert_holder >(); + + assert_holder >(); + assert_holder >(); + assert_holder >(); + + assert_holder >(); + + assert_holder + ,pointer_holder,Base> >(); + + assert_holder + ,pointer_holder_back_reference,Base> >(); + + assert_holder + ,pointer_holder_back_reference,BR> > (); + + return 0; +} + +#if defined(__GNUC__) && __GNUC__ <= 3 +// This definition is needed for MinGW 2.95.2 for some reason +namespace boost { namespace python +{ + bool handle_exception_impl(boost::function0) { return false; } +}} +#endif diff --git a/test/virtual_functions.cpp b/test/virtual_functions.cpp index ab05fe3c..586048d5 100644 --- a/test/virtual_functions.cpp +++ b/test/virtual_functions.cpp @@ -7,6 +7,7 @@ #include #include #include +#include using namespace boost::python; @@ -66,6 +67,10 @@ struct concrete_callback : concrete : concrete(x), self(p) {} + concrete_callback(PyObject* p, concrete const& x) + : concrete(x), self(p) + {} + int f(Y const& y) { return returning::call_method(self, "f", boost::ref(y)); @@ -85,26 +90,21 @@ BOOST_PYTHON_MODULE_INIT(virtual_functions_ext) { module("virtual_functions_ext") .add( - class_, objects::value_holder_generator >("concrete") + class_("concrete") .def_init(args()) .def("value", &concrete::value) .def("set", &concrete::set) .def("call_f", &concrete::call_f) .def("f", &concrete_callback::f_impl)) -#if 0 .add( - class_ - , objects::pointer_holder_generator< - boost::python::objects::shared_ptr_generator - , abstract_callback> + class_ >("abstract") .def_init(args()) .def("value", &abstract::value) .def("call_f", &abstract::call_f) .def("set", &abstract::set)) -#endif .add( class_("Y") diff --git a/test/virtual_functions.py b/test/virtual_functions.py index 8ea992c5..9b074b1a 100644 --- a/test/virtual_functions.py +++ b/test/virtual_functions.py @@ -8,13 +8,13 @@ >>> class C2(concrete): ... pass -<<<>>> class A1(abstract): -<<<... def f(self, y): -<<<... return abstract.f(self, Y(-y.value())) -<<< -<<<>>> class A2(abstract): -<<<... pass -<<< +>>> class A1(abstract): +... def f(self, y): +... return y.value() * 2 + +>>> class A2(abstract): +... pass + >>> y1 = Y(16) >>> y2 = Y(17) @@ -24,33 +24,35 @@ # # Test abstract with f overridden # -<<<>>> a1 = A1(42) -<<<>>> a1.value() -<<<42 -<<< -<<<# Call f indirectly from C++ -<<<>>> a1.call_f(y1) -<<<-16 -<<< -<<<# Call f directly from Python -<<<>>> a1.f(y2) -<<<-17 -<<< -<<<# -<<<# Test abstract with f not overridden -<<<# -<<<>>> a2 = A2(42) -<<<>>> A2.value() -<<<42 -<<< -<<<# Call f indirectly from C++ -<<<>>> c1.call_f(y1) -<<<16 -<<< -<<<# Call f directly from Python -<<<>>> c1.f(y2) -<<<17 -<<< +>>> a1 = A1(42) +>>> a1.value() +42 + +# Call f indirectly from C++ +>>> a1.call_f(y1) +32 + +# Call f directly from Python +>>> a1.f(y2) +34 + +# +# Test abstract with f not overridden +# +>>> a2 = A2(42) +>>> a2.value() +42 + +# Call f indirectly from C++ +>>> try: a2.call_f(y1) +... except AttributeError: pass +... else: print 'no exception' + +# Call f directly from Python +>>> try: a2.call_f(y2) +... except AttributeError: pass +... else: print 'no exception' + ############# Concrete Tests ############ # From 453fbbed1bf3ece47d97e3b2fd903b5e0bb186e5 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 24 Mar 2002 15:05:58 +0000 Subject: [PATCH 367/369] initial checkin [SVN r13255] --- include/boost/python/detail/not_specified.hpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 include/boost/python/detail/not_specified.hpp diff --git a/include/boost/python/detail/not_specified.hpp b/include/boost/python/detail/not_specified.hpp new file mode 100644 index 00000000..ce1b280d --- /dev/null +++ b/include/boost/python/detail/not_specified.hpp @@ -0,0 +1,15 @@ +// Copyright David Abrahams 2002. 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 NOT_SPECIFIED_DWA2002321_HPP +# define NOT_SPECIFIED_DWA2002321_HPP + +namespace boost { namespace python { namespace detail { + + struct not_specified {}; + +}}} // namespace boost::python::detail + +#endif // NOT_SPECIFIED_DWA2002321_HPP From 9d3d50c654f7a976cbcd9d2ad9543271a8ae6b79 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 24 Mar 2002 15:19:56 +0000 Subject: [PATCH 368/369] initial checkin [SVN r13256] --- include/boost/python/args.hpp | 19 ++++ include/boost/python/bases.hpp | 58 ++++++++++ include/boost/python/detail/if_else.hpp | 117 ++++++++++++++++++++ include/boost/python/detail/pointee.hpp | 36 ++++++ include/boost/python/has_back_reference.hpp | 22 ++++ test/bases.cpp | 63 +++++++++++ test/if_else.cpp | 61 ++++++++++ test/pointee.cpp | 35 ++++++ 8 files changed, 411 insertions(+) create mode 100644 include/boost/python/args.hpp create mode 100644 include/boost/python/bases.hpp create mode 100644 include/boost/python/detail/if_else.hpp create mode 100644 include/boost/python/detail/pointee.hpp create mode 100644 include/boost/python/has_back_reference.hpp create mode 100644 test/bases.cpp create mode 100644 test/if_else.cpp create mode 100644 test/pointee.cpp diff --git a/include/boost/python/args.hpp b/include/boost/python/args.hpp new file mode 100644 index 00000000..b584506b --- /dev/null +++ b/include/boost/python/args.hpp @@ -0,0 +1,19 @@ +// Copyright David Abrahams 2002. 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 ARGS_DWA2002323_HPP +# define ARGS_DWA2002323_HPP +# include + +namespace boost { namespace python { + +// A type list for specifying arguments +template < BOOST_MPL_LIST_DEFAULT_PARAMETERS(typename A, ::boost::mpl::null_argument) > +struct args : ::boost::mpl::type_list< BOOST_MPL_LIST_PARAMETERS(A) >::type +{}; + +}} // namespace boost::python + +#endif // ARGS_DWA2002323_HPP diff --git a/include/boost/python/bases.hpp b/include/boost/python/bases.hpp new file mode 100644 index 00000000..468c6744 --- /dev/null +++ b/include/boost/python/bases.hpp @@ -0,0 +1,58 @@ +// Copyright David Abrahams 2002. 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 BASES_DWA2002321_HPP +# define BASES_DWA2002321_HPP +# include +# include +# include +# include + +namespace boost { namespace python { + // A type list for specifying bases + template < BOOST_MPL_LIST_DEFAULT_PARAMETERS(typename B, ::boost::mpl::null_argument) > + struct bases : ::boost::mpl::type_list< BOOST_MPL_LIST_PARAMETERS(B) >::type + {}; + + namespace detail + { +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template struct specifies_bases + { + BOOST_STATIC_CONSTANT(bool, value = false); + }; + template < BOOST_MPL_LIST_PARAMETERS(class B) > + struct specifies_bases< bases< BOOST_MPL_LIST_PARAMETERS(B) > > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; +# else + template < BOOST_MPL_LIST_PARAMETERS(class B) > + static char is_bases_helper(bases< BOOST_MPL_LIST_PARAMETERS(B) > const&); + + static char (& is_bases_helper(...) )[256]; + + template struct specifies_bases + { + private: + static typename add_reference::type make(); + BOOST_STATIC_CONSTANT(bool, non_ref = !is_reference::value); + public: + BOOST_STATIC_CONSTANT(bool, value = non_ref & (sizeof(is_bases_helper(make())) == 1)); + }; +# endif + template > + struct select_bases + : mpl::select_type< + specifies_bases::value + , T + , Prev + > + { + }; + } +}} // namespace boost::python + +#endif // BASES_DWA2002321_HPP diff --git a/include/boost/python/detail/if_else.hpp b/include/boost/python/detail/if_else.hpp new file mode 100644 index 00000000..6668617c --- /dev/null +++ b/include/boost/python/detail/if_else.hpp @@ -0,0 +1,117 @@ +// Copyright David Abrahams 2002. 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 IF_ELSE_DWA2002322_HPP +# define IF_ELSE_DWA2002322_HPP +# include + +namespace boost { namespace python { namespace detail { + +template struct elif_selected; + +template +struct if_selected +{ + template + struct elif : elif_selected + { + }; + + template + struct else_ + { + typedef T type; + }; +}; + +# if defined(BOOST_MSVC) && (BOOST_MSVC == 1300) +namespace msvc70_aux { + +template< bool > struct inherit_from +{ + template< typename T > struct result + { + typedef T type; + }; +}; + +template<> struct inherit_from +{ + template< typename T > struct result + { + struct type {}; + }; +}; + +template< typename T > +struct never_true +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +} // namespace msvc70_aux + +#endif // # if defined(BOOST_MSVC) && (BOOST_MSVC == 1300) + +template +struct elif_selected +{ +# if !(defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__MWERKS__) && __MWERKS__ <= 0x2407) + template class then; +# elif defined(BOOST_MSVC) && (BOOST_MSVC == 1300) + template + struct then : msvc70_aux::inherit_from< msvc70_aux::never_true::value > + ::template result< if_selected >::type + { + }; +# else + template + struct then : if_selected + { + }; +# endif +}; + +# if !(defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__MWERKS__) && __MWERKS__ <= 0x2407) +template +template +class elif_selected::then : public if_selected +{ +}; +# endif + +template struct if_ +{ + template + struct then : if_selected + { + }; +}; + +struct if_unselected +{ + template struct elif : if_ + { + }; + + template + struct else_ + { + typedef U type; + }; +}; + +template <> +struct if_ +{ + template + struct then : if_unselected + { + }; +}; + +}}} // namespace boost::python::detail + +#endif // IF_ELSE_DWA2002322_HPP diff --git a/include/boost/python/detail/pointee.hpp b/include/boost/python/detail/pointee.hpp new file mode 100644 index 00000000..2af1535f --- /dev/null +++ b/include/boost/python/detail/pointee.hpp @@ -0,0 +1,36 @@ +// Copyright David Abrahams 2002. 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 POINTEE_DWA2002323_HPP +# define POINTEE_DWA2002323_HPP + +# include + +namespace boost { namespace python { namespace detail { + +template +struct pointee_impl +{ + template struct apply : remove_pointer {}; +}; + +template <> +struct pointee_impl +{ + template struct apply + { + typedef typename T::element_type type; + }; +}; + +template +struct pointee + : pointee_impl::value>::template apply +{ +}; + +}}} // namespace boost::python::detail + +#endif // POINTEE_DWA2002323_HPP diff --git a/include/boost/python/has_back_reference.hpp b/include/boost/python/has_back_reference.hpp new file mode 100644 index 00000000..95a3ae9a --- /dev/null +++ b/include/boost/python/has_back_reference.hpp @@ -0,0 +1,22 @@ +// Copyright David Abrahams 2002. 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 HAS_BACK_REFERENCE_DWA2002323_HPP +# define HAS_BACK_REFERENCE_DWA2002323_HPP + +namespace boost { namespace python { + +// traits class which users can specialize to indicate that a class +// contains a back-reference to its owning PyObject* +template +struct has_back_reference +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; + + +}} // namespace boost::python + +#endif // HAS_BACK_REFERENCE_DWA2002323_HPP diff --git a/test/bases.cpp b/test/bases.cpp new file mode 100644 index 00000000..e4f91990 --- /dev/null +++ b/test/bases.cpp @@ -0,0 +1,63 @@ +// Copyright David Abrahams 2002. 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. +#include +#include +#include + +struct A; +struct B; + +template +struct choose_bases + : boost::python::detail::select_bases< + X + , typename boost::python::detail::select_bases< + Y + , typename boost::python::detail::select_bases::type + >::type> +{ + +}; + +int main() +{ + BOOST_STATIC_ASSERT((boost::python::detail::specifies_bases< + boost::python::bases >::value)); + + BOOST_STATIC_ASSERT((!boost::python::detail::specifies_bases< + boost::python::bases& >::value)); + + BOOST_STATIC_ASSERT((!boost::python::detail::specifies_bases< + void* >::value)); + + BOOST_STATIC_ASSERT((!boost::python::detail::specifies_bases< + int >::value)); + + BOOST_STATIC_ASSERT((!boost::python::detail::specifies_bases< + int[5] >::value)); + + typedef boost::python::detail::select_bases< + int + , boost::python::detail::select_bases::type > collected1; + + BOOST_STATIC_ASSERT((boost::is_same >::value)); + BOOST_STATIC_ASSERT((boost::is_same::type,boost::python::bases<> >::value)); + + typedef boost::python::detail::select_bases< + int + , boost::python::detail::select_bases< + boost::python::bases + , boost::python::detail::select_bases< + A + >::type + >::type + > collected2; + + BOOST_STATIC_ASSERT((boost::is_same >::value)); + BOOST_STATIC_ASSERT((boost::is_same,long>::type,boost::python::bases >::value)); + + return 0; +} diff --git a/test/if_else.cpp b/test/if_else.cpp new file mode 100644 index 00000000..d8bd34ca --- /dev/null +++ b/test/if_else.cpp @@ -0,0 +1,61 @@ +// Copyright David Abrahams 2002. 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. +#include +#include +#include + + typedef char c1; + typedef char c2[2]; + typedef char c3[3]; + typedef char c4[4]; + +template +struct choose +{ +#if 1 + typedef typename boost::python::detail::if_< + (sizeof(c1) == size) + >::template then< + c1 + >::template elif< + (sizeof(c2) == size) + >::template then< + c2 + >::template elif< + (sizeof(c3) == size) + >::template then< + c3 + >::template elif< + (sizeof(c4) == size) + >::template then< + c4 + >::template else_::type type; +#else + typedef typename boost::python::detail::if_< + (sizeof(c1) == size) + , c1 + >::template elif< + (sizeof(c2) == size) + , c2 + >::template elif< + (sizeof(c3) == size) + , c3 + >::template elif< + (sizeof(c4) == size) + , c4 + >::template else_::type type; +#endif +}; + +int main() +{ + BOOST_STATIC_ASSERT((boost::is_same::type,c1>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type,c2>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type,c3>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type,c4>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type,void*>::value)); + return 0; +} diff --git a/test/pointee.cpp b/test/pointee.cpp new file mode 100644 index 00000000..7935e897 --- /dev/null +++ b/test/pointee.cpp @@ -0,0 +1,35 @@ +// Copyright David Abrahams 2002. 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. +#include +#include +#include +#include +#include + +struct A; + +int main() +{ + BOOST_STATIC_ASSERT( + (boost::is_same< + boost::python::detail::pointee >::type + , char** + >::value)); + + BOOST_STATIC_ASSERT( + (boost::is_same< + boost::python::detail::pointee >::type + , A>::value)); + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + BOOST_STATIC_ASSERT( + (boost::is_same< + boost::python::detail::pointee::type + , char + >::value)); +#endif + return 0; +} From 516f30a307f5b4785e1a45cd619339d55a487035 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 24 Mar 2002 15:51:50 +0000 Subject: [PATCH 369/369] fixes for older KCCs [SVN r13258] --- include/boost/python/class.hpp | 9 ++++++--- include/boost/python/object/select_holder.hpp | 7 +++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index cff0adf9..166ced73 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -245,9 +245,12 @@ namespace detail template struct select_held_type : mpl::select_type< - !(specifies_bases::value | is_same::value) - , T - , Prev + type_traits::ice_or< + type_traits::ice_not::value>::value + , is_same::value + >::value + , T + , Prev > { }; diff --git a/include/boost/python/object/select_holder.hpp b/include/boost/python/object/select_holder.hpp index 39d50c0a..72446358 100644 --- a/include/boost/python/object/select_holder.hpp +++ b/include/boost/python/object/select_holder.hpp @@ -22,8 +22,10 @@ namespace detail template struct select_value_holder { + BOOST_STATIC_CONSTANT(bool, selector = (!is_same::value) | has_back_reference::value); + typedef typename mpl::select_type< - (!is_same::value) | has_back_reference::value + selector , value_holder_back_reference , value_holder >::type holder; @@ -35,9 +37,10 @@ namespace detail struct select_pointer_holder { typedef typename python::detail::pointee::type pointee; + BOOST_STATIC_CONSTANT(bool, selector = (!is_same::value) | has_back_reference::value); typedef typename mpl::select_type< - (!is_same::value) | has_back_reference::value + selector , pointer_holder_back_reference , pointer_holder >::type holder;