From 12c798145089290c17f101e7de8e028f8a025f48 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 14 Feb 2002 15:57:40 +0000 Subject: [PATCH] *** 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();
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)