From 0dbb780a2f8b6e52100a201ff10e41ac9fa5db57 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 15 Nov 2001 05:29:22 +0000 Subject: [PATCH] * 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") {