diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index a924b8fd..0045138a 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -131,17 +131,33 @@ class class_ : public objects::class_base return this->def(op.name(), &op_t::template apply::execute); } - template - self& def(detail::func_stubs_base const& stubs, signature sig) + self& def_generator( + char const* name, + detail::func_stubs_base const& stubs, + SigT sig, char const* doc = 0) { - // convert sig to a type_list (see signature.hpp) and call - // detail::define_with_defaults passing in the stubs (see defaults_gen.hpp), - // this instance, and the converted sig type_list. - detail::define_with_defaults(stubs.derived(), *this, detail::get_signature(sig)); + // convert sig to a type_list (see detail::get_signature in signature.hpp) and + // call detail::define_with_defaults passing in the stubs (see defaults_gen.hpp), + // this class_ instance, and the converted sig type_list. + detail::define_with_defaults(name, stubs.derived(), *this, detail::get_signature(sig), doc); return *this; } +// template +// self& def(detail::func_stubs_base const& stubs, F) +// { +// // convert signature to a type_list (see signature.hpp) and call +// // detail::define_with_defaults passing in the stubs (see defaults_gen.hpp), +// // this class_ instance, and the converted signature type_list. +// detail::define_with_defaults( +// stubs.derived(), +// *this, +// detail::get_signature(signature()) +// ); +// 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/defaults_def.hpp b/include/boost/python/detail/defaults_def.hpp index 5f2e7d11..44a1939b 100644 --- a/include/boost/python/detail/defaults_def.hpp +++ b/include/boost/python/detail/defaults_def.hpp @@ -37,11 +37,12 @@ namespace detail { // // The set of overloaded functions (define_stub_function) expects: // -// 1. char const* name: a python function name +// 1. char const* name: function name that will be visible to python // 2. StubsT: a function stubs struct (see defaults_gen.hpp) // 3. HolderT& holder: a python::class_ or python::module instance // 4. int_t: the Nth overloaded function (StubsT::func_N) // (see defaults_gen.hpp) +// 5. char const* name: doc string // /////////////////////////////////////////////////////////////////////////////// #define BPL_IMPL_STUB_FUNC_DEF(INDEX, DATA) \ @@ -53,10 +54,15 @@ namespace detail { char const* name, \ StubsT, \ HolderT& holder, \ - boost::mpl::int_t \ + boost::mpl::int_t, \ + char const* doc \ ) \ { \ - holder.def(name, &StubsT::BOOST_PP_CAT(func_, INDEX)); \ + holder.def( \ + name, \ + &StubsT::BOOST_PP_CAT(func_, INDEX), \ + default_call_policies(), \ + doc); \ } \ BOOST_PP_REPEAT(BOOST_PYTHON_MAX_ARITY, BPL_IMPL_STUB_FUNC_DEF, BOOST_PP_EMPTY) @@ -71,9 +77,10 @@ BOOST_PP_REPEAT(BOOST_PYTHON_MAX_ARITY, BPL_IMPL_STUB_FUNC_DEF, BOOST_PP_EMPTY) // terminal case define_with_defaults_helper<0>. The struct and its // specialization has a sole static member function def that expects: // -// 1. char const* name: a python function name +// 1. char const* name: function name that will be visible to python // 2. StubsT: a function stubs struct (see defaults_gen.hpp) // 3. HolderT& holder: a python::class_ or python::module instance +// 4. char const* name: doc string // // The def static member function calls a corresponding // define_stub_function. The general case recursively calls @@ -86,12 +93,12 @@ BOOST_PP_REPEAT(BOOST_PYTHON_MAX_ARITY, BPL_IMPL_STUB_FUNC_DEF, BOOST_PP_EMPTY) template static void - def(char const* name, StubsT stubs, HolderT& holder) + def(char const* name, StubsT stubs, HolderT& holder, char const* doc) { // define the NTH stub function of stubs - define_stub_function(name, stubs, holder, boost::mpl::int_t()); + define_stub_function(name, stubs, holder, boost::mpl::int_t(), doc); // call the next define_with_defaults_helper - define_with_defaults_helper::def(name, stubs, holder); + define_with_defaults_helper::def(name, stubs, holder, doc); } }; @@ -101,10 +108,10 @@ BOOST_PP_REPEAT(BOOST_PYTHON_MAX_ARITY, BPL_IMPL_STUB_FUNC_DEF, BOOST_PP_EMPTY) template static void - def(char const* name, StubsT stubs, HolderT& holder) + def(char const* name, StubsT stubs, HolderT& holder, char const* doc) { // define the Oth stub function of stubs - define_stub_function(name, stubs, holder, boost::mpl::int_t<0>()); + define_stub_function(name, stubs, holder, boost::mpl::int_t<0>(), doc); // return } }; @@ -113,6 +120,12 @@ BOOST_PP_REPEAT(BOOST_PYTHON_MAX_ARITY, BPL_IMPL_STUB_FUNC_DEF, BOOST_PP_EMPTY) // // define_with_defaults // +// 1. char const* name: function name that will be visible to python +// 2. StubsT: a function stubs struct (see defaults_gen.hpp) +// 3. HolderT& holder: a python::class_ or python::module instance +// 4. SigT sig: Function signature typelist (see defaults_gen.hpp) +// 5. char const* name: doc string +// // This is the main entry point. This function recursively defines all // stub functions of StubT (see defaults_gen.hpp) in HolderT holder which // can be either a python::class_ or a python::module. The sig argument @@ -126,7 +139,12 @@ BOOST_PP_REPEAT(BOOST_PYTHON_MAX_ARITY, BPL_IMPL_STUB_FUNC_DEF, BOOST_PP_EMPTY) /////////////////////////////////////////////////////////////////////////////// template inline void - define_with_defaults(StubsT, HolderT& holder, SigT sig) + define_with_defaults( + char const* name, + StubsT, + HolderT& holder, + SigT sig, + char const* doc) { typedef typename mpl::select_type < @@ -137,11 +155,11 @@ BOOST_PP_REPEAT(BOOST_PYTHON_MAX_ARITY, BPL_IMPL_STUB_FUNC_DEF, BOOST_PP_EMPTY) ::type stubs_type; BOOST_STATIC_ASSERT( - (stubs_type::max_args + 1) == boost::mpl::size::value); + (stubs_type::max_args + 1) <= boost::mpl::size::value); typedef stubs_type::template gen gen_type; define_with_defaults_helper::def - (stubs_type::name(), gen_type(), holder); + (name, gen_type(), holder, doc); } } // namespace detail diff --git a/include/boost/python/detail/defaults_gen.hpp b/include/boost/python/detail/defaults_gen.hpp index e807fe52..0f580d94 100644 --- a/include/boost/python/detail/defaults_gen.hpp +++ b/include/boost/python/detail/defaults_gen.hpp @@ -99,9 +99,6 @@ struct func_stubs_base { BOOST_STATIC_CONSTANT(int, n_funcs = BOOST_PP_INC(N_DFLTS)); \ BOOST_STATIC_CONSTANT(int, max_args = n_funcs); \ \ - static char const* \ - name() { return BOOST_PP_STRINGIZE(FNAME); } \ - \ template \ struct gen { \ \ @@ -153,9 +150,6 @@ struct func_stubs_base { BOOST_STATIC_CONSTANT(int, n_funcs = BOOST_PP_INC(N_DFLTS)); \ BOOST_STATIC_CONSTANT(int, max_args = n_funcs + 1); \ \ - static char const* \ - name() { return BOOST_PP_STRINGIZE(FNAME); } \ - \ template \ struct gen { \ \ @@ -267,8 +261,6 @@ struct func_stubs_base { // static const int n_funcs = 4; // static const int max_args = n_funcs; // -// static char const* name() { return "foo"; } -// // template // struct gen { // diff --git a/include/boost/python/module.hpp b/include/boost/python/module.hpp index b477b91d..48822d08 100644 --- a/include/boost/python/module.hpp +++ b/include/boost/python/module.hpp @@ -72,12 +72,15 @@ class module : public detail::module_base } template - module& def(detail::func_stubs_base const& stubs, signature sig) + module& def_generator( + char const* name, + detail::func_stubs_base const& stubs, + SigT sig, char const* doc = 0) { - // convert sig to a type_list (see signature.hpp) and call - // detail::define_with_defaults passing in the stubs (see defaults_gen.hpp), - // this instance, and the converted sig type_list. - detail::define_with_defaults(stubs.derived(), *this, detail::get_signature(sig)); + // convert sig to a type_list (see detail::get_signature in signature.hpp) and + // call detail::define_with_defaults passing in the stubs (see defaults_gen.hpp), + // this module instance, and the converted sig type_list. + detail::define_with_defaults(name, stubs.derived(), *this, detail::get_signature(sig), doc); return *this; } }; diff --git a/include/boost/python/signature.hpp b/include/boost/python/signature.hpp index 87b8695f..af452b1f 100644 --- a/include/boost/python/signature.hpp +++ b/include/boost/python/signature.hpp @@ -59,6 +59,13 @@ namespace detail { // return boost::mpl::type_list(); // } // +// template +// inline boost::mpl::type_list +// get_signature(RT(*)(T0...TN)) +// { +// return boost::mpl::type_list(); +// } +// // template // inline boost::mpl::type_list // get_signature(signature) @@ -66,6 +73,20 @@ namespace detail { // return boost::mpl::type_list(); // } // +// template +// inline boost::mpl::type_list +// get_signature(RT(ClassT::*)(T0...TN))) +// { +// return boost::mpl::type_list(); +// } +// +// template +// inline boost::mpl::type_list +// get_signature(RT(ClassT::*)(T0...TN) const)) +// { +// return boost::mpl::type_list(); +// } +// // These functions extract the return type, class (for member functions) // and arguments of the input signature and stuffs them in an mpl::type_list. // @@ -90,6 +111,26 @@ namespace detail { RT BOOST_PP_COMMA_IF(INDEX) BOOST_PP_ENUM_PARAMS(INDEX, T) \ > \ get_signature(signature) \ + { \ + return boost::mpl::type_list \ + (); \ + } \ + \ + template \ + < \ + typename RT BOOST_PP_COMMA_IF(INDEX) \ + BOOST_PP_ENUM \ + ( \ + INDEX, \ + BPL_IMPL_TEMPLATE_GEN, \ + BOOST_PP_EMPTY \ + ) \ + > \ + inline boost::mpl::type_list \ + < \ + RT BOOST_PP_COMMA_IF(INDEX) BOOST_PP_ENUM_PARAMS(INDEX, T) \ + > \ + get_signature(RT(*)(BOOST_PP_ENUM_PARAMS(INDEX, T))) \ { \ return boost::mpl::type_list \ (); \ @@ -117,6 +158,51 @@ namespace detail { return boost::mpl::type_list \ \ (); \ + } \ + \ + template \ + < \ + typename RT, typename ClassT BOOST_PP_COMMA_IF(INDEX) \ + BOOST_PP_ENUM \ + ( \ + INDEX, \ + BPL_IMPL_TEMPLATE_GEN, \ + BOOST_PP_EMPTY \ + ) \ + > \ + inline boost::mpl::type_list \ + < \ + RT, ClassT BOOST_PP_COMMA_IF(INDEX) BOOST_PP_ENUM_PARAMS(INDEX, T) \ + > \ + get_signature(RT(ClassT::*)(BOOST_PP_ENUM_PARAMS(INDEX, T))) \ + { \ + return boost::mpl::type_list \ + \ + (); \ + } \ + \ + template \ + < \ + typename RT, typename ClassT BOOST_PP_COMMA_IF(INDEX) \ + BOOST_PP_ENUM \ + ( \ + INDEX, \ + BPL_IMPL_TEMPLATE_GEN, \ + BOOST_PP_EMPTY \ + ) \ + > \ + inline boost::mpl::type_list \ + < \ + RT, ClassT const \ + BOOST_PP_COMMA_IF(INDEX) BOOST_PP_ENUM_PARAMS(INDEX, T) \ + > \ + get_signature(RT(ClassT::*)(BOOST_PP_ENUM_PARAMS(INDEX, T)) const) \ + { \ + return boost::mpl::type_list \ + < \ + RT, ClassT const \ + BOOST_PP_COMMA_IF(INDEX) BOOST_PP_ENUM_PARAMS(INDEX, T) \ + >(); \ } \ /////////////////////////////////////////////////////////////////////////////// diff --git a/test/defaults.cpp b/test/defaults.cpp index c49ed91d..7d617c00 100644 --- a/test/defaults.cpp +++ b/test/defaults.cpp @@ -5,7 +5,7 @@ // to its suitability for any purpose. #include #include -#include +#include #if defined(_AIX) && defined(__EDG_VERSION__) && __EDG_VERSION__ < 245 # include // works around a KCC intermediate code generation bug @@ -15,50 +15,97 @@ using namespace boost::python; using namespace std; /////////////////////////////////////////////////////////////////////////////// - -std::string -foo(int a, char b = 'D', std::string c = "default", double d = 0.0) +object +bar(int a, char b, std::string c, double d) { - std::stringstream stream; - stream << "int(" << a << "); "; - stream << "char(" << b << "); "; - stream << "string(" << c << "); "; - stream << "double(" << d << "); "; - return stream.str(); + list abcd; + abcd.append(a); + abcd.append(b); + abcd.append(c); + abcd.append(d); + return "int(%s); char(%s); string(%s); double(%s); " % tuple(abcd); } -BOOST_PYTHON_FUNCTION_GEN(foo_stubs, foo, 1, 4) +object +bar(int a, char b, std::string c) +{ + list abcd; + abcd.append(a); + abcd.append(b); + abcd.append(c); + abcd.append(0.0); + return "int(%s); char(%s); string(%s); double(%s); " % tuple(abcd); +} + +object +bar(int a, char b) +{ + list abcd; + abcd.append(a); + abcd.append(b); + abcd.append("default"); + abcd.append(0.0); + return "int(%s); char(%s); string(%s); double(%s); " % tuple(abcd); +} + +object +bar(int a) +{ + list abcd; + abcd.append(a); + abcd.append('D'); + abcd.append("default"); + abcd.append(0.0); + return "int(%s); char(%s); string(%s); double(%s); " % tuple(abcd); +} + +BOOST_PYTHON_FUNCTION_GENERATOR(bar_stubs, bar, 1, 4) + +/////////////////////////////////////////////////////////////////////////////// +object +foo(int a, char b = 'D', std::string c = "default", double d = 0.0) +{ + list abcd; + abcd.append(a); + abcd.append(b); + abcd.append(c); + abcd.append(d); + return "int(%s); char(%s); string(%s); double(%s); " % tuple(abcd); +} + +BOOST_PYTHON_FUNCTION_GENERATOR(foo_stubs, foo, 1, 4) /////////////////////////////////////////////////////////////////////////////// struct X { - std::string + object bar(int a, char b = 'D', std::string c = "default", double d = 0.0) const { - std::stringstream stream; - stream << "int(" << a << "); "; - stream << "char(" << b << "); "; - stream << "string(" << c << "); "; - stream << "double(" << d << "); "; - return stream.str(); + list abcd; + abcd.append(a); + abcd.append(b); + abcd.append(c); + abcd.append(d); + return "int(%s); char(%s); string(%s); double(%s); " % tuple(abcd); } }; -BOOST_PYTHON_MEMBER_FUNCTION_GEN(X_bar_stubs, bar, 1, 4) +BOOST_PYTHON_MEM_FUN_GENERATOR(X_bar_stubs, bar, 1, 4) /////////////////////////////////////////////////////////////////////////////// BOOST_PYTHON_MODULE_INIT(defaults_ext) { module m("defaults_ext"); - m.def(foo_stubs(), signature()); + m.def_generator("foo", foo_stubs(), foo); + m.def_generator("bar", bar_stubs(), signature()); class_ xc("X"); m.add(xc); xc.def_init(); - xc.def(X_bar_stubs(), signature()); + xc.def_generator("bar", X_bar_stubs(), X::bar); } #include "module_tail.cpp" diff --git a/test/defaults.py b/test/defaults.py index 1261453a..b72cea4f 100644 --- a/test/defaults.py +++ b/test/defaults.py @@ -1,21 +1,29 @@ """ >>> from defaults_ext import * +>>> bar(1) +'int(1); char(D); string(default); double(0.0); ' +>>> bar(2, 'X') +'int(2); char(X); string(default); double(0.0); ' +>>> bar(3, 'Y', "Hello World") +'int(3); char(Y); string(Hello World); double(0.0); ' +>>> bar(4, 'Z', "Hi There", 3.3) +'int(4); char(Z); string(Hi There); double(3.3); ' >>> foo(1) -'int(1); char(D); string(default); double(0); ' +'int(1); char(D); string(default); double(0.0); ' >>> foo(2, 'X') -'int(2); char(X); string(default); double(0); ' +'int(2); char(X); string(default); double(0.0); ' >>> foo(3, 'Y', "Hello World") -'int(3); char(Y); string(Hello World); double(0); ' +'int(3); char(Y); string(Hello World); double(0.0); ' >>> foo(4, 'Z', "Hi There", 3.3) 'int(4); char(Z); string(Hi There); double(3.3); ' >>> x = X() >>> x.bar(1) -'int(1); char(D); string(default); double(0); ' +'int(1); char(D); string(default); double(0.0); ' >>> x.bar(2, 'X') -'int(2); char(X); string(default); double(0); ' +'int(2); char(X); string(default); double(0.0); ' >>> x.bar(3, 'Y', "Hello World") -'int(3); char(Y); string(Hello World); double(0); ' +'int(3); char(Y); string(Hello World); double(0.0); ' >>> x.bar(4, 'Z', "Hi There", 3.3) 'int(4); char(Z); string(Hi There); double(3.3); ' >>>