From 1b3917fb08dded36d2bab1e3a5f3666c7cbec18f Mon Sep 17 00:00:00 2001 From: Travis CI Date: Fri, 7 Oct 2016 15:41:33 +0000 Subject: [PATCH] Deploy to GitHub Pages: 5b416c8a83d7d3962aa1412fe06f2af173f28b5a --- develop/doc/html/HTML.manifest | 30 + develop/doc/html/article.html | 929 ++++++++++ develop/doc/html/boostbook.css | 716 ++++++++ develop/doc/html/building.html | 98 ++ develop/doc/html/building/background.html | 70 + .../choosing_a_boost_python_library_.html | 128 ++ .../building/configuring_boost_build.html | 252 +++ develop/doc/html/building/include_issues.html | 53 + .../installing_boost_python_on_your_.html | 52 + .../html/building/no_install_quickstart.html | 318 ++++ .../notes_for_mingw_and_cygwin_with_.html | 47 + .../building/python_debugging_builds.html | 78 + .../html/building/testing_boost_python.html | 42 + develop/doc/html/configuration.html | 350 ++++ develop/doc/html/faq.html | 116 ++ .../faq/compilation_takes_too_much_time_.html | 42 + .../faq/does_boost_python_work_with_mac_.html | 93 + .../faq/error_c2064_term_does_not_evalua.html | 77 + .../faq/fatal_error_c1204_compiler_limit.html | 94 + .../faq/how_can_i_automatically_convert_.html | 146 ++ .../faq/how_can_i_find_the_existing_pyob.html | 103 ++ .../faq/how_can_i_wrap_a_function_which0.html | 86 + .../faq/how_can_i_wrap_functions_which_t.html | 120 ++ .../faq/how_do_i_create_sub_packages_usi.html | 41 + .../faq/how_do_i_debug_my_python_extensi.html | 151 ++ .../faq/i_m_getting_the_attempt_to_retur.html | 67 + .../faq/is_boost_python_thread_aware_com.html | 60 + .../faq/is_return_internal_reference_eff.html | 62 + .../faq/why_doesn_t_my_operator_work.html | 63 + .../faq/why_is_my_automatic_to_python_co.html | 67 + develop/doc/html/glossary.html | 81 + develop/doc/html/images/alert.png | Bin 0 -> 603 bytes develop/doc/html/images/blank.png | Bin 0 -> 374 bytes develop/doc/html/images/boost.png | Bin 0 -> 6308 bytes develop/doc/html/images/bpl.png | Bin 0 -> 21289 bytes develop/doc/html/images/bpl.svg | 224 +++ develop/doc/html/images/callouts/1.png | Bin 0 -> 391 bytes develop/doc/html/images/callouts/1.svg | 15 + develop/doc/html/images/callouts/10.png | Bin 0 -> 485 bytes develop/doc/html/images/callouts/10.svg | 18 + develop/doc/html/images/callouts/11.png | Bin 0 -> 410 bytes develop/doc/html/images/callouts/11.svg | 16 + develop/doc/html/images/callouts/12.png | Bin 0 -> 488 bytes develop/doc/html/images/callouts/12.svg | 18 + develop/doc/html/images/callouts/13.png | Bin 0 -> 509 bytes develop/doc/html/images/callouts/13.svg | 20 + develop/doc/html/images/callouts/14.png | Bin 0 -> 499 bytes develop/doc/html/images/callouts/14.svg | 17 + develop/doc/html/images/callouts/15.png | Bin 0 -> 507 bytes develop/doc/html/images/callouts/15.svg | 19 + develop/doc/html/images/callouts/16.svg | 20 + develop/doc/html/images/callouts/17.svg | 17 + develop/doc/html/images/callouts/18.svg | 21 + develop/doc/html/images/callouts/19.svg | 20 + develop/doc/html/images/callouts/2.png | Bin 0 -> 446 bytes develop/doc/html/images/callouts/2.svg | 17 + develop/doc/html/images/callouts/20.svg | 20 + develop/doc/html/images/callouts/21.svg | 18 + develop/doc/html/images/callouts/22.svg | 20 + develop/doc/html/images/callouts/23.svg | 22 + develop/doc/html/images/callouts/24.svg | 19 + develop/doc/html/images/callouts/25.svg | 21 + develop/doc/html/images/callouts/26.svg | 22 + develop/doc/html/images/callouts/27.svg | 19 + develop/doc/html/images/callouts/28.svg | 23 + develop/doc/html/images/callouts/29.svg | 22 + develop/doc/html/images/callouts/3.png | Bin 0 -> 431 bytes develop/doc/html/images/callouts/3.svg | 19 + develop/doc/html/images/callouts/30.svg | 22 + develop/doc/html/images/callouts/4.png | Bin 0 -> 441 bytes develop/doc/html/images/callouts/4.svg | 16 + develop/doc/html/images/callouts/5.png | Bin 0 -> 423 bytes develop/doc/html/images/callouts/5.svg | 18 + develop/doc/html/images/callouts/6.png | Bin 0 -> 431 bytes develop/doc/html/images/callouts/6.svg | 19 + develop/doc/html/images/callouts/7.png | Bin 0 -> 397 bytes develop/doc/html/images/callouts/7.svg | 16 + develop/doc/html/images/callouts/8.png | Bin 0 -> 434 bytes develop/doc/html/images/callouts/8.svg | 20 + develop/doc/html/images/callouts/9.png | Bin 0 -> 420 bytes develop/doc/html/images/callouts/9.svg | 19 + develop/doc/html/images/caution.png | Bin 0 -> 1250 bytes develop/doc/html/images/caution.svg | 68 + develop/doc/html/images/draft.png | Bin 0 -> 17454 bytes develop/doc/html/images/home.png | Bin 0 -> 358 bytes develop/doc/html/images/home.svg | 26 + develop/doc/html/images/important.png | Bin 0 -> 722 bytes develop/doc/html/images/important.svg | 25 + develop/doc/html/images/next.png | Bin 0 -> 336 bytes develop/doc/html/images/next.svg | 19 + develop/doc/html/images/next_disabled.png | Bin 0 -> 1110 bytes develop/doc/html/images/note.png | Bin 0 -> 490 bytes develop/doc/html/images/note.svg | 33 + develop/doc/html/images/prev.png | Bin 0 -> 334 bytes develop/doc/html/images/prev.svg | 19 + develop/doc/html/images/prev_disabled.png | Bin 0 -> 1109 bytes develop/doc/html/images/smiley.png | Bin 0 -> 867 bytes develop/doc/html/images/tip.png | Bin 0 -> 449 bytes develop/doc/html/images/tip.svg | 84 + develop/doc/html/images/toc-blank.png | Bin 0 -> 318 bytes develop/doc/html/images/toc-minus.png | Bin 0 -> 259 bytes develop/doc/html/images/toc-plus.png | Bin 0 -> 264 bytes develop/doc/html/images/up.png | Bin 0 -> 370 bytes develop/doc/html/images/up.svg | 19 + develop/doc/html/images/up_disabled.png | Bin 0 -> 1115 bytes develop/doc/html/images/warning.png | Bin 0 -> 1241 bytes develop/doc/html/images/warning.svg | 23 + develop/doc/html/index.html | 129 ++ develop/doc/html/reference/HTML.manifest | 59 + develop/doc/html/reference/concepts.html | 261 +++ .../reference/concepts/dereferenceable.html | 104 ++ .../html/reference/concepts/extractor.html | 135 ++ .../reference/concepts/holdergenerator.html | 92 + .../reference/concepts/objectwrapper.html | 132 ++ .../reference/concepts/resultconverter.html | 210 +++ develop/doc/html/reference/embedding.html | 205 +++ .../embedding/boost_python_import_hpp.html | 94 + .../function_invocation_and_creation.html | 287 +++ .../boost_python_call_hpp.html | 96 + .../boost_python_call_method_hpp.html | 156 ++ .../boost_python_data_members_hpp.html | 215 +++ .../boost_python_make_function_hpp.html | 186 ++ .../boost_python_overloads_hpp.html | 208 +++ .../boost_python_ptr_hpp.html | 287 +++ .../boost_python_raw_function_hpp.html | 111 ++ .../function_documentation.html | 458 +++++ .../models_of_callpolicies.html | 1098 ++++++++++++ .../models_of_resultconverter.html | 308 ++++ .../models_of_resultconvertergenerat.html | 683 ++++++++ develop/doc/html/reference/glossary.html | 80 + .../html/reference/high_level_components.html | 1072 ++++++++++++ .../boost_python_def_hpp.html | 212 +++ .../boost_python_def_visitor_hpp.html | 208 +++ .../boost_python_docstring_options_h.html | 363 ++++ .../boost_python_enum_hpp.html | 217 +++ .../boost_python_errors_hpp.html | 278 +++ .../boost_python_exception_translato.html | 130 ++ .../boost_python_init_hpp.html | 233 +++ .../boost_python_iterator_hpp.html | 391 +++++ .../boost_python_module_hpp.html | 111 ++ .../boost_python_operators_hpp.html | 1558 +++++++++++++++++ .../boost_python_scope_hpp.html | 160 ++ .../boost_python_stl_iterator_hpp.html | 311 ++++ .../boost_python_wrapper_hpp.html | 222 +++ develop/doc/html/reference/index.html | 137 ++ .../doc/html/reference/object_wrappers.html | 260 +++ .../boost_python_list_hpp.html | 120 ++ .../boost_python_long_hpp.html | 97 + .../boost_python_numeric_hpp.html | 259 +++ .../boost_python_object_hpp.html | 1148 ++++++++++++ .../boost_python_slice_hpp.html | 305 ++++ .../object_wrappers/boost_python_str_hpp.html | 211 +++ .../boost_python_tuple_hpp.html | 119 ++ .../to_from_python_type_conversion.html | 287 +++ .../boost_python_implicit_hpp.html | 181 ++ .../boost_python_lvalue_from_pytype_.html | 305 ++++ .../boost_python_opaque_pointer_conv.html | 113 ++ .../boost_python_register_ptr_to_pyt.html | 166 ++ .../boost_python_to_python_converter.html | 252 +++ develop/doc/html/reference/topics.html | 332 ++++ .../reference/topics/indexing_support.html | 830 +++++++++ .../html/reference/topics/pickle_support.html | 356 ++++ .../reference/utility_and_infrastructure.html | 240 +++ .../boost_python_handle_hpp.html | 363 ++++ .../boost_python_instance_holder_hpp.html | 212 +++ .../boost_python_pointee_hpp.html | 106 ++ .../boost_python_ssize_t_hpp.html | 90 + .../boost_python_type_id_hpp.html | 234 +++ develop/doc/html/rst.css | 149 ++ develop/doc/html/support.html | 85 + develop/doc/html/tutorial/HTML.manifest | 9 + develop/doc/html/tutorial/index.html | 149 ++ .../doc/html/tutorial/tutorial/embedding.html | 268 +++ .../doc/html/tutorial/tutorial/exception.html | 56 + .../doc/html/tutorial/tutorial/exposing.html | 601 +++++++ .../doc/html/tutorial/tutorial/functions.html | 587 +++++++ develop/doc/html/tutorial/tutorial/hello.html | 191 ++ .../doc/html/tutorial/tutorial/iterators.html | 180 ++ .../doc/html/tutorial/tutorial/object.html | 366 ++++ .../html/tutorial/tutorial/techniques.html | 429 +++++ develop/doc/index.html | 13 + 181 files changed, 26611 insertions(+) create mode 100644 develop/doc/html/HTML.manifest create mode 100644 develop/doc/html/article.html create mode 100644 develop/doc/html/boostbook.css create mode 100644 develop/doc/html/building.html create mode 100644 develop/doc/html/building/background.html create mode 100644 develop/doc/html/building/choosing_a_boost_python_library_.html create mode 100644 develop/doc/html/building/configuring_boost_build.html create mode 100644 develop/doc/html/building/include_issues.html create mode 100644 develop/doc/html/building/installing_boost_python_on_your_.html create mode 100644 develop/doc/html/building/no_install_quickstart.html create mode 100644 develop/doc/html/building/notes_for_mingw_and_cygwin_with_.html create mode 100644 develop/doc/html/building/python_debugging_builds.html create mode 100644 develop/doc/html/building/testing_boost_python.html create mode 100644 develop/doc/html/configuration.html create mode 100644 develop/doc/html/faq.html create mode 100644 develop/doc/html/faq/compilation_takes_too_much_time_.html create mode 100644 develop/doc/html/faq/does_boost_python_work_with_mac_.html create mode 100644 develop/doc/html/faq/error_c2064_term_does_not_evalua.html create mode 100644 develop/doc/html/faq/fatal_error_c1204_compiler_limit.html create mode 100644 develop/doc/html/faq/how_can_i_automatically_convert_.html create mode 100644 develop/doc/html/faq/how_can_i_find_the_existing_pyob.html create mode 100644 develop/doc/html/faq/how_can_i_wrap_a_function_which0.html create mode 100644 develop/doc/html/faq/how_can_i_wrap_functions_which_t.html create mode 100644 develop/doc/html/faq/how_do_i_create_sub_packages_usi.html create mode 100644 develop/doc/html/faq/how_do_i_debug_my_python_extensi.html create mode 100644 develop/doc/html/faq/i_m_getting_the_attempt_to_retur.html create mode 100644 develop/doc/html/faq/is_boost_python_thread_aware_com.html create mode 100644 develop/doc/html/faq/is_return_internal_reference_eff.html create mode 100644 develop/doc/html/faq/why_doesn_t_my_operator_work.html create mode 100644 develop/doc/html/faq/why_is_my_automatic_to_python_co.html create mode 100644 develop/doc/html/glossary.html create mode 100644 develop/doc/html/images/alert.png create mode 100644 develop/doc/html/images/blank.png create mode 100644 develop/doc/html/images/boost.png create mode 100644 develop/doc/html/images/bpl.png create mode 100644 develop/doc/html/images/bpl.svg create mode 100644 develop/doc/html/images/callouts/1.png create mode 100644 develop/doc/html/images/callouts/1.svg create mode 100644 develop/doc/html/images/callouts/10.png create mode 100644 develop/doc/html/images/callouts/10.svg create mode 100644 develop/doc/html/images/callouts/11.png create mode 100644 develop/doc/html/images/callouts/11.svg create mode 100644 develop/doc/html/images/callouts/12.png create mode 100644 develop/doc/html/images/callouts/12.svg create mode 100644 develop/doc/html/images/callouts/13.png create mode 100644 develop/doc/html/images/callouts/13.svg create mode 100644 develop/doc/html/images/callouts/14.png create mode 100644 develop/doc/html/images/callouts/14.svg create mode 100644 develop/doc/html/images/callouts/15.png create mode 100644 develop/doc/html/images/callouts/15.svg create mode 100644 develop/doc/html/images/callouts/16.svg create mode 100644 develop/doc/html/images/callouts/17.svg create mode 100644 develop/doc/html/images/callouts/18.svg create mode 100644 develop/doc/html/images/callouts/19.svg create mode 100644 develop/doc/html/images/callouts/2.png create mode 100644 develop/doc/html/images/callouts/2.svg create mode 100644 develop/doc/html/images/callouts/20.svg create mode 100644 develop/doc/html/images/callouts/21.svg create mode 100644 develop/doc/html/images/callouts/22.svg create mode 100644 develop/doc/html/images/callouts/23.svg create mode 100644 develop/doc/html/images/callouts/24.svg create mode 100644 develop/doc/html/images/callouts/25.svg create mode 100644 develop/doc/html/images/callouts/26.svg create mode 100644 develop/doc/html/images/callouts/27.svg create mode 100644 develop/doc/html/images/callouts/28.svg create mode 100644 develop/doc/html/images/callouts/29.svg create mode 100644 develop/doc/html/images/callouts/3.png create mode 100644 develop/doc/html/images/callouts/3.svg create mode 100644 develop/doc/html/images/callouts/30.svg create mode 100644 develop/doc/html/images/callouts/4.png create mode 100644 develop/doc/html/images/callouts/4.svg create mode 100644 develop/doc/html/images/callouts/5.png create mode 100644 develop/doc/html/images/callouts/5.svg create mode 100644 develop/doc/html/images/callouts/6.png create mode 100644 develop/doc/html/images/callouts/6.svg create mode 100644 develop/doc/html/images/callouts/7.png create mode 100644 develop/doc/html/images/callouts/7.svg create mode 100644 develop/doc/html/images/callouts/8.png create mode 100644 develop/doc/html/images/callouts/8.svg create mode 100644 develop/doc/html/images/callouts/9.png create mode 100644 develop/doc/html/images/callouts/9.svg create mode 100644 develop/doc/html/images/caution.png create mode 100644 develop/doc/html/images/caution.svg create mode 100644 develop/doc/html/images/draft.png create mode 100644 develop/doc/html/images/home.png create mode 100644 develop/doc/html/images/home.svg create mode 100644 develop/doc/html/images/important.png create mode 100644 develop/doc/html/images/important.svg create mode 100644 develop/doc/html/images/next.png create mode 100644 develop/doc/html/images/next.svg create mode 100644 develop/doc/html/images/next_disabled.png create mode 100644 develop/doc/html/images/note.png create mode 100644 develop/doc/html/images/note.svg create mode 100644 develop/doc/html/images/prev.png create mode 100644 develop/doc/html/images/prev.svg create mode 100644 develop/doc/html/images/prev_disabled.png create mode 100644 develop/doc/html/images/smiley.png create mode 100644 develop/doc/html/images/tip.png create mode 100644 develop/doc/html/images/tip.svg create mode 100644 develop/doc/html/images/toc-blank.png create mode 100644 develop/doc/html/images/toc-minus.png create mode 100644 develop/doc/html/images/toc-plus.png create mode 100644 develop/doc/html/images/up.png create mode 100644 develop/doc/html/images/up.svg create mode 100644 develop/doc/html/images/up_disabled.png create mode 100644 develop/doc/html/images/warning.png create mode 100644 develop/doc/html/images/warning.svg create mode 100644 develop/doc/html/index.html create mode 100644 develop/doc/html/reference/HTML.manifest create mode 100644 develop/doc/html/reference/concepts.html create mode 100644 develop/doc/html/reference/concepts/dereferenceable.html create mode 100644 develop/doc/html/reference/concepts/extractor.html create mode 100644 develop/doc/html/reference/concepts/holdergenerator.html create mode 100644 develop/doc/html/reference/concepts/objectwrapper.html create mode 100644 develop/doc/html/reference/concepts/resultconverter.html create mode 100644 develop/doc/html/reference/embedding.html create mode 100644 develop/doc/html/reference/embedding/boost_python_import_hpp.html create mode 100644 develop/doc/html/reference/function_invocation_and_creation.html create mode 100644 develop/doc/html/reference/function_invocation_and_creation/boost_python_call_hpp.html create mode 100644 develop/doc/html/reference/function_invocation_and_creation/boost_python_call_method_hpp.html create mode 100644 develop/doc/html/reference/function_invocation_and_creation/boost_python_data_members_hpp.html create mode 100644 develop/doc/html/reference/function_invocation_and_creation/boost_python_make_function_hpp.html create mode 100644 develop/doc/html/reference/function_invocation_and_creation/boost_python_overloads_hpp.html create mode 100644 develop/doc/html/reference/function_invocation_and_creation/boost_python_ptr_hpp.html create mode 100644 develop/doc/html/reference/function_invocation_and_creation/boost_python_raw_function_hpp.html create mode 100644 develop/doc/html/reference/function_invocation_and_creation/function_documentation.html create mode 100644 develop/doc/html/reference/function_invocation_and_creation/models_of_callpolicies.html create mode 100644 develop/doc/html/reference/function_invocation_and_creation/models_of_resultconverter.html create mode 100644 develop/doc/html/reference/function_invocation_and_creation/models_of_resultconvertergenerat.html create mode 100644 develop/doc/html/reference/glossary.html create mode 100644 develop/doc/html/reference/high_level_components.html create mode 100644 develop/doc/html/reference/high_level_components/boost_python_def_hpp.html create mode 100644 develop/doc/html/reference/high_level_components/boost_python_def_visitor_hpp.html create mode 100644 develop/doc/html/reference/high_level_components/boost_python_docstring_options_h.html create mode 100644 develop/doc/html/reference/high_level_components/boost_python_enum_hpp.html create mode 100644 develop/doc/html/reference/high_level_components/boost_python_errors_hpp.html create mode 100644 develop/doc/html/reference/high_level_components/boost_python_exception_translato.html create mode 100644 develop/doc/html/reference/high_level_components/boost_python_init_hpp.html create mode 100644 develop/doc/html/reference/high_level_components/boost_python_iterator_hpp.html create mode 100644 develop/doc/html/reference/high_level_components/boost_python_module_hpp.html create mode 100644 develop/doc/html/reference/high_level_components/boost_python_operators_hpp.html create mode 100644 develop/doc/html/reference/high_level_components/boost_python_scope_hpp.html create mode 100644 develop/doc/html/reference/high_level_components/boost_python_stl_iterator_hpp.html create mode 100644 develop/doc/html/reference/high_level_components/boost_python_wrapper_hpp.html create mode 100644 develop/doc/html/reference/index.html create mode 100644 develop/doc/html/reference/object_wrappers.html create mode 100644 develop/doc/html/reference/object_wrappers/boost_python_list_hpp.html create mode 100644 develop/doc/html/reference/object_wrappers/boost_python_long_hpp.html create mode 100644 develop/doc/html/reference/object_wrappers/boost_python_numeric_hpp.html create mode 100644 develop/doc/html/reference/object_wrappers/boost_python_object_hpp.html create mode 100644 develop/doc/html/reference/object_wrappers/boost_python_slice_hpp.html create mode 100644 develop/doc/html/reference/object_wrappers/boost_python_str_hpp.html create mode 100644 develop/doc/html/reference/object_wrappers/boost_python_tuple_hpp.html create mode 100644 develop/doc/html/reference/to_from_python_type_conversion.html create mode 100644 develop/doc/html/reference/to_from_python_type_conversion/boost_python_implicit_hpp.html create mode 100644 develop/doc/html/reference/to_from_python_type_conversion/boost_python_lvalue_from_pytype_.html create mode 100644 develop/doc/html/reference/to_from_python_type_conversion/boost_python_opaque_pointer_conv.html create mode 100644 develop/doc/html/reference/to_from_python_type_conversion/boost_python_register_ptr_to_pyt.html create mode 100644 develop/doc/html/reference/to_from_python_type_conversion/boost_python_to_python_converter.html create mode 100644 develop/doc/html/reference/topics.html create mode 100644 develop/doc/html/reference/topics/indexing_support.html create mode 100644 develop/doc/html/reference/topics/pickle_support.html create mode 100644 develop/doc/html/reference/utility_and_infrastructure.html create mode 100644 develop/doc/html/reference/utility_and_infrastructure/boost_python_handle_hpp.html create mode 100644 develop/doc/html/reference/utility_and_infrastructure/boost_python_instance_holder_hpp.html create mode 100644 develop/doc/html/reference/utility_and_infrastructure/boost_python_pointee_hpp.html create mode 100644 develop/doc/html/reference/utility_and_infrastructure/boost_python_ssize_t_hpp.html create mode 100644 develop/doc/html/reference/utility_and_infrastructure/boost_python_type_id_hpp.html create mode 100644 develop/doc/html/rst.css create mode 100644 develop/doc/html/support.html create mode 100644 develop/doc/html/tutorial/HTML.manifest create mode 100644 develop/doc/html/tutorial/index.html create mode 100644 develop/doc/html/tutorial/tutorial/embedding.html create mode 100644 develop/doc/html/tutorial/tutorial/exception.html create mode 100644 develop/doc/html/tutorial/tutorial/exposing.html create mode 100644 develop/doc/html/tutorial/tutorial/functions.html create mode 100644 develop/doc/html/tutorial/tutorial/hello.html create mode 100644 develop/doc/html/tutorial/tutorial/iterators.html create mode 100644 develop/doc/html/tutorial/tutorial/object.html create mode 100644 develop/doc/html/tutorial/tutorial/techniques.html create mode 100644 develop/doc/index.html diff --git a/develop/doc/html/HTML.manifest b/develop/doc/html/HTML.manifest new file mode 100644 index 00000000..375d3832 --- /dev/null +++ b/develop/doc/html/HTML.manifest @@ -0,0 +1,30 @@ +index.html +building.html +building/background.html +building/no_install_quickstart.html +building/installing_boost_python_on_your_.html +building/configuring_boost_build.html +building/choosing_a_boost_python_library_.html +building/include_issues.html +building/python_debugging_builds.html +building/testing_boost_python.html +building/notes_for_mingw_and_cygwin_with_.html +configuration.html +support.html +faq.html +faq/i_m_getting_the_attempt_to_retur.html +faq/is_return_internal_reference_eff.html +faq/how_can_i_wrap_functions_which_t.html +faq/fatal_error_c1204_compiler_limit.html +faq/how_do_i_debug_my_python_extensi.html +faq/why_doesn_t_my_operator_work.html +faq/does_boost_python_work_with_mac_.html +faq/how_can_i_find_the_existing_pyob.html +faq/how_can_i_wrap_a_function_which0.html +faq/compilation_takes_too_much_time_.html +faq/how_do_i_create_sub_packages_usi.html +faq/error_c2064_term_does_not_evalua.html +faq/how_can_i_automatically_convert_.html +faq/why_is_my_automatic_to_python_co.html +faq/is_boost_python_thread_aware_com.html +glossary.html diff --git a/develop/doc/html/article.html b/develop/doc/html/article.html new file mode 100644 index 00000000..6a9126dc --- /dev/null +++ b/develop/doc/html/article.html @@ -0,0 +1,929 @@ + + + + + + +Building Hybrid Systems with Boost.Python + + + + + + + + +
+

Building Hybrid Systems with Boost.Python

+ +++ + + + + + + + + + + + + + +
Author:David Abrahams
Contact:dave@boost-consulting.com
Organization:Boost Consulting
Date:2003-05-14
Author:Ralf W. Grosse-Kunstleve
Copyright:Copyright David Abrahams and Ralf W. Grosse-Kunstleve 2003. All rights reserved
+ +
+

Abstract

+

Boost.Python is an open source C++ library which provides a concise +IDL-like interface for binding C++ classes and functions to +Python. Leveraging the full power of C++ compile-time introspection +and of recently developed metaprogramming techniques, this is achieved +entirely in pure C++, without introducing a new syntax. +Boost.Python's rich set of features and high-level interface make it +possible to engineer packages from the ground up as hybrid systems, +giving programmers easy and coherent access to both the efficient +compile-time polymorphism of C++ and the extremely convenient run-time +polymorphism of Python.

+
+
+

Introduction

+

Python and C++ are in many ways as different as two languages could +be: while C++ is usually compiled to machine-code, Python is +interpreted. Python's dynamic type system is often cited as the +foundation of its flexibility, while in C++ static typing is the +cornerstone of its efficiency. C++ has an intricate and difficult +compile-time meta-language, while in Python, practically everything +happens at runtime.

+

Yet for many programmers, these very differences mean that Python and +C++ complement one another perfectly. Performance bottlenecks in +Python programs can be rewritten in C++ for maximal speed, and +authors of powerful C++ libraries choose Python as a middleware +language for its flexible system integration capabilities. +Furthermore, the surface differences mask some strong similarities:

+
    +
  • 'C'-family control structures (if, while, for...)
  • +
  • Support for object-orientation, functional programming, and generic +programming (these are both multi-paradigm programming languages.)
  • +
  • Comprehensive operator overloading facilities, recognizing the +importance of syntactic variability for readability and +expressivity.
  • +
  • High-level concepts such as collections and iterators.
  • +
  • High-level encapsulation facilities (C++: namespaces, Python: modules) +to support the design of re-usable libraries.
  • +
  • Exception-handling for effective management of error conditions.
  • +
  • C++ idioms in common use, such as handle/body classes and +reference-counted smart pointers mirror Python reference semantics.
  • +
+

Given Python's rich 'C' interoperability API, it should in principle +be possible to expose C++ type and function interfaces to Python with +an analogous interface to their C++ counterparts. However, the +facilities provided by Python alone for integration with C++ are +relatively meager. Compared to C++ and Python, 'C' has only very +rudimentary abstraction facilities, and support for exception-handling +is completely missing. 'C' extension module writers are required to +manually manage Python reference counts, which is both annoyingly +tedious and extremely error-prone. Traditional extension modules also +tend to contain a great deal of boilerplate code repetition which +makes them difficult to maintain, especially when wrapping an evolving +API.

+

These limitations have lead to the development of a variety of wrapping +systems. SWIG is probably the most popular package for the +integration of C/C++ and Python. A more recent development is SIP, +which was specifically designed for interfacing Python with the Qt +graphical user interface library. Both SWIG and SIP introduce their +own specialized languages for customizing inter-language bindings. +This has certain advantages, but having to deal with three different +languages (Python, C/C++ and the interface language) also introduces +practical and mental difficulties. The CXX package demonstrates an +interesting alternative. It shows that at least some parts of +Python's 'C' API can be wrapped and presented through a much more +user-friendly C++ interface. However, unlike SWIG and SIP, CXX does +not include support for wrapping C++ classes as new Python types.

+

The features and goals of Boost.Python overlap significantly with +many of these other systems. That said, Boost.Python attempts to +maximize convenience and flexibility without introducing a separate +wrapping language. Instead, it presents the user with a high-level +C++ interface for wrapping C++ classes and functions, managing much of +the complexity behind-the-scenes with static metaprogramming. +Boost.Python also goes beyond the scope of earlier systems by +providing:

+
    +
  • Support for C++ virtual functions that can be overridden in Python.
  • +
  • Comprehensive lifetime management facilities for low-level C++ +pointers and references.
  • +
  • Support for organizing extensions as Python packages, +with a central registry for inter-language type conversions.
  • +
  • A safe and convenient mechanism for tying into Python's powerful +serialization engine (pickle).
  • +
  • Coherence with the rules for handling C++ lvalues and rvalues that +can only come from a deep understanding of both the Python and C++ +type systems.
  • +
+

The key insight that sparked the development of Boost.Python is that +much of the boilerplate code in traditional extension modules could be +eliminated using C++ compile-time introspection. Each argument of a +wrapped C++ function must be extracted from a Python object using a +procedure that depends on the argument type. Similarly the function's +return type determines how the return value will be converted from C++ +to Python. Of course argument and return types are part of each +function's type, and this is exactly the source from which +Boost.Python deduces most of the information required.

+

This approach leads to user guided wrapping: as much information is +extracted directly from the source code to be wrapped as is possible +within the framework of pure C++, and some additional information is +supplied explicitly by the user. Mostly the guidance is mechanical +and little real intervention is required. Because the interface +specification is written in the same full-featured language as the +code being exposed, the user has unprecedented power available when +she does need to take control.

+
+
+

Boost.Python Design Goals

+

The primary goal of Boost.Python is to allow users to expose C++ +classes and functions to Python using nothing more than a C++ +compiler. In broad strokes, the user experience should be one of +directly manipulating C++ objects from Python.

+

However, it's also important not to translate all interfaces too +literally: the idioms of each language must be respected. For +example, though C++ and Python both have an iterator concept, they are +expressed very differently. Boost.Python has to be able to bridge the +interface gap.

+

It must be possible to insulate Python users from crashes resulting +from trivial misuses of C++ interfaces, such as accessing +already-deleted objects. By the same token the library should +insulate C++ users from low-level Python 'C' API, replacing +error-prone 'C' interfaces like manual reference-count management and +raw PyObject pointers with more-robust alternatives.

+

Support for component-based development is crucial, so that C++ types +exposed in one extension module can be passed to functions exposed in +another without loss of crucial information like C++ inheritance +relationships.

+

Finally, all wrapping must be non-intrusive, without modifying or +even seeing the original C++ source code. Existing C++ libraries have +to be wrappable by third parties who only have access to header files +and binaries.

+
+
+

Hello Boost.Python World

+

And now for a preview of Boost.Python, and how it improves on the raw +facilities offered by Python. Here's a function we might want to +expose:

+
+char const* greet(unsigned x)
+{
+   static char const* const msgs[] = { "hello", "Boost.Python", "world!" };
+
+   if (x > 2)
+       throw std::range_error("greet: index out of range");
+
+   return msgs[x];
+}
+
+

To wrap this function in standard C++ using the Python 'C' API, we'd +need something like this:

+
+extern "C" // all Python interactions use 'C' linkage and calling convention
+{
+    // Wrapper to handle argument/result conversion and checking
+    PyObject* greet_wrap(PyObject* args, PyObject * keywords)
+    {
+         int x;
+         if (PyArg_ParseTuple(args, "i", &x))    // extract/check arguments
+         {
+             char const* result = greet(x);      // invoke wrapped function
+             return PyString_FromString(result); // convert result to Python
+         }
+         return 0;                               // error occurred
+    }
+
+    // Table of wrapped functions to be exposed by the module
+    static PyMethodDef methods[] = {
+        { "greet", greet_wrap, METH_VARARGS, "return one of 3 parts of a greeting" }
+        , { NULL, NULL, 0, NULL } // sentinel
+    };
+
+    // module initialization function
+    DL_EXPORT init_hello()
+    {
+        (void) Py_InitModule("hello", methods); // add the methods to the module
+    }
+}
+
+

Now here's the wrapping code we'd use to expose it with Boost.Python:

+
+#include <boost/python.hpp>
+using namespace boost::python;
+BOOST_PYTHON_MODULE(hello)
+{
+    def("greet", greet, "return one of 3 parts of a greeting");
+}
+
+

and here it is in action:

+
+>>> import hello
+>>> for x in range(3):
+...     print hello.greet(x)
+...
+hello
+Boost.Python
+world!
+
+

Aside from the fact that the 'C' API version is much more verbose, +it's worth noting a few things that it doesn't handle correctly:

+
    +
  • The original function accepts an unsigned integer, and the Python +'C' API only gives us a way of extracting signed integers. The +Boost.Python version will raise a Python exception if we try to pass +a negative number to hello.greet, but the other one will proceed +to do whatever the C++ implementation does when converting an +negative integer to unsigned (usually wrapping to some very large +number), and pass the incorrect translation on to the wrapped +function.
  • +
  • That brings us to the second problem: if the C++ greet() +function is called with a number greater than 2, it will throw an +exception. Typically, if a C++ exception propagates across the +boundary with code generated by a 'C' compiler, it will cause a +crash. As you can see in the first version, there's no C++ +scaffolding there to prevent this from happening. Functions wrapped +by Boost.Python automatically include an exception-handling layer +which protects Python users by translating unhandled C++ exceptions +into a corresponding Python exception.
  • +
  • A slightly more-subtle limitation is that the argument conversion +used in the Python 'C' API case can only get that integer x in +one way. PyArg_ParseTuple can't convert Python long objects +(arbitrary-precision integers) which happen to fit in an unsigned +int but not in a signed long, nor will it ever handle a +wrapped C++ class with a user-defined implicit operator unsigned +int() conversion. Boost.Python's dynamic type conversion +registry allows users to add arbitrary conversion methods.
  • +
+
+
+

Library Overview

+

This section outlines some of the library's major features. Except as +neccessary to avoid confusion, details of library implementation are +omitted.

+
+

Exposing Classes

+

C++ classes and structs are exposed with a similarly-terse interface. +Given:

+
+struct World
+{
+    void set(std::string msg) { this->msg = msg; }
+    std::string greet() { return msg; }
+    std::string msg;
+};
+
+

The following code will expose it in our extension module:

+
+#include <boost/python.hpp>
+BOOST_PYTHON_MODULE(hello)
+{
+    class_<World>("World")
+        .def("greet", &World::greet)
+        .def("set", &World::set)
+    ;
+}
+
+

Although this code has a certain pythonic familiarity, people +sometimes find the syntax bit confusing because it doesn't look like +most of the C++ code they're used to. All the same, this is just +standard C++. Because of their flexible syntax and operator +overloading, C++ and Python are great for defining domain-specific +(sub)languages +(DSLs), and that's what we've done in Boost.Python. To break it down:

+
+class_<World>("World")
+
+

constructs an unnamed object of type class_<World> and passes +"World" to its constructor. This creates a new-style Python class +called World in the extension module, and associates it with the +C++ type World in the Boost.Python type conversion registry. We +might have also written:

+
+class_<World> w("World");
+
+

but that would've been more verbose, since we'd have to name w +again to invoke its def() member function:

+
+w.def("greet", &World::greet)
+
+

There's nothing special about the location of the dot for member +access in the original example: C++ allows any amount of whitespace on +either side of a token, and placing the dot at the beginning of each +line allows us to chain as many successive calls to member functions +as we like with a uniform syntax. The other key fact that allows +chaining is that class_<> member functions all return a reference +to *this.

+

So the example is equivalent to:

+
+class_<World> w("World");
+w.def("greet", &World::greet);
+w.def("set", &World::set);
+
+

It's occasionally useful to be able to break down the components of a +Boost.Python class wrapper in this way, but the rest of this article +will stick to the terse syntax.

+

For completeness, here's the wrapped class in use:

+
+>>> import hello
+>>> planet = hello.World()
+>>> planet.set('howdy')
+>>> planet.greet()
+'howdy'
+
+
+

Constructors

+

Since our World class is just a plain struct, it has an +implicit no-argument (nullary) constructor. Boost.Python exposes the +nullary constructor by default, which is why we were able to write:

+
+>>> planet = hello.World()
+
+

However, well-designed classes in any language may require constructor +arguments in order to establish their invariants. Unlike Python, +where __init__ is just a specially-named method, In C++ +constructors cannot be handled like ordinary member functions. In +particular, we can't take their address: &World::World is an +error. The library provides a different interface for specifying +constructors. Given:

+
+struct World
+{
+    World(std::string msg); // added constructor
+    ...
+
+

we can modify our wrapping code as follows:

+
+class_<World>("World", init<std::string>())
+    ...
+
+

of course, a C++ class may have additional constructors, and we can +expose those as well by passing more instances of init<...> to +def():

+
+class_<World>("World", init<std::string>())
+    .def(init<double, double>())
+    ...
+
+

Boost.Python allows wrapped functions, member functions, and +constructors to be overloaded to mirror C++ overloading.

+
+
+

Data Members and Properties

+

Any publicly-accessible data members in a C++ class can be easily +exposed as either readonly or readwrite attributes:

+
+class_<World>("World", init<std::string>())
+    .def_readonly("msg", &World::msg)
+    ...
+
+

and can be used directly in Python:

+
+>>> planet = hello.World('howdy')
+>>> planet.msg
+'howdy'
+
+

This does not result in adding attributes to the World instance +__dict__, which can result in substantial memory savings when +wrapping large data structures. In fact, no instance __dict__ +will be created at all unless attributes are explicitly added from +Python. Boost.Python owes this capability to the new Python 2.2 type +system, in particular the descriptor interface and property type.

+

In C++, publicly-accessible data members are considered a sign of poor +design because they break encapsulation, and style guides usually +dictate the use of "getter" and "setter" functions instead. In +Python, however, __getattr__, __setattr__, and since 2.2, +property mean that attribute access is just one more +well-encapsulated syntactic tool at the programmer's disposal. +Boost.Python bridges this idiomatic gap by making Python property +creation directly available to users. If msg were private, we +could still expose it as attribute in Python as follows:

+
+class_<World>("World", init<std::string>())
+    .add_property("msg", &World::greet, &World::set)
+    ...
+
+

The example above mirrors the familiar usage of properties in Python +2.2+:

+
+>>> class World(object):
+...     __init__(self, msg):
+...         self.__msg = msg
+...     def greet(self):
+...         return self.__msg
+...     def set(self, msg):
+...         self.__msg = msg
+...     msg = property(greet, set)
+
+
+
+

Operator Overloading

+

The ability to write arithmetic operators for user-defined types has +been a major factor in the success of both languages for numerical +computation, and the success of packages like NumPy attests to the +power of exposing operators in extension modules. Boost.Python +provides a concise mechanism for wrapping operator overloads. The +example below shows a fragment from a wrapper for the Boost rational +number library:

+
+class_<rational<int> >("rational_int")
+  .def(init<int, int>()) // constructor, e.g. rational_int(3,4)
+  .def("numerator", &rational<int>::numerator)
+  .def("denominator", &rational<int>::denominator)
+  .def(-self)        // __neg__ (unary minus)
+  .def(self + self)  // __add__ (homogeneous)
+  .def(self * self)  // __mul__
+  .def(self + int()) // __add__ (heterogenous)
+  .def(int() + self) // __radd__
+  ...
+
+

The magic is performed using a simplified application of "expression +templates" [VELD1995], a technique originally developed for +optimization of high-performance matrix algebra expressions. The +essence is that instead of performing the computation immediately, +operators are overloaded to construct a type representing the +computation. In matrix algebra, dramatic optimizations are often +available when the structure of an entire expression can be taken into +account, rather than evaluating each operation "greedily". +Boost.Python uses the same technique to build an appropriate Python +method object based on expressions involving self.

+
+
+

Inheritance

+

C++ inheritance relationships can be represented to Boost.Python by adding +an optional bases<...> argument to the class_<...> template +parameter list as follows:

+
+class_<Derived, bases<Base1,Base2> >("Derived")
+     ...
+
+

This has two effects:

+
    +
  1. When the class_<...> is created, Python type objects +corresponding to Base1 and Base2 are looked up in +Boost.Python's registry, and are used as bases for the new Python +Derived type object, so methods exposed for the Python Base1 +and Base2 types are automatically members of the Derived +type. Because the registry is global, this works correctly even if +Derived is exposed in a different module from either of its +bases.
  2. +
  3. C++ conversions from Derived to its bases are added to the +Boost.Python registry. Thus wrapped C++ methods expecting (a +pointer or reference to) an object of either base type can be +called with an object wrapping a Derived instance. Wrapped +member functions of class T are treated as though they have an +implicit first argument of T&, so these conversions are +neccessary to allow the base class methods to be called for derived +objects.
  4. +
+

Of course it's possible to derive new Python classes from wrapped C++ +class instances. Because Boost.Python uses the new-style class +system, that works very much as for the Python built-in types. There +is one significant detail in which it differs: the built-in types +generally establish their invariants in their __new__ function, so +that derived classes do not need to call __init__ on the base +class before invoking its methods :

+
+>>> class L(list):
+...      def __init__(self):
+...          pass
+...
+>>> L().reverse()
+>>>
+
+

Because C++ object construction is a one-step operation, C++ instance +data cannot be constructed until the arguments are available, in the +__init__ function:

+
+>>> class D(SomeBoostPythonClass):
+...      def __init__(self):
+...          pass
+...
+>>> D().some_boost_python_method()
+Traceback (most recent call last):
+  File "<stdin>", line 1, in ?
+TypeError: bad argument type for built-in operation
+
+

This happened because Boost.Python couldn't find instance data of type +SomeBoostPythonClass within the D instance; D's __init__ +function masked construction of the base class. It could be corrected +by either removing D's __init__ function or having it call +SomeBoostPythonClass.__init__(...) explicitly.

+
+
+

Virtual Functions

+

Deriving new types in Python from extension classes is not very +interesting unless they can be used polymorphically from C++. In +other words, Python method implementations should appear to override +the implementation of C++ virtual functions when called through base +class pointers/references from C++. Since the only way to alter the +behavior of a virtual function is to override it in a derived class, +the user must build a special derived class to dispatch a polymorphic +class' virtual functions:

+
+//
+// interface to wrap:
+//
+class Base
+{
+ public:
+    virtual int f(std::string x) { return 42; }
+    virtual ~Base();
+};
+
+int calls_f(Base const& b, std::string x) { return b.f(x); }
+
+//
+// Wrapping Code
+//
+
+// Dispatcher class
+struct BaseWrap : Base
+{
+    // Store a pointer to the Python object
+    BaseWrap(PyObject* self_) : self(self_) {}
+    PyObject* self;
+
+    // Default implementation, for when f is not overridden
+    int f_default(std::string x) { return this->Base::f(x); }
+    // Dispatch implementation
+    int f(std::string x) { return call_method<int>(self, "f", x); }
+};
+
+...
+    def("calls_f", calls_f);
+    class_<Base, BaseWrap>("Base")
+        .def("f", &Base::f, &BaseWrap::f_default)
+        ;
+
+

Now here's some Python code which demonstrates:

+
+>>> class Derived(Base):
+...     def f(self, s):
+...          return len(s)
+...
+>>> calls_f(Base(), 'foo')
+42
+>>> calls_f(Derived(), 'forty-two')
+9
+
+

Things to notice about the dispatcher class:

+
    +
  • The key element which allows overriding in Python is the +call_method invocation, which uses the same global type +conversion registry as the C++ function wrapping does to convert its +arguments from C++ to Python and its return type from Python to C++.
  • +
  • Any constructor signatures you wish to wrap must be replicated with +an initial PyObject* argument
  • +
  • The dispatcher must store this argument so that it can be used to +invoke call_method
  • +
  • The f_default member function is needed when the function being +exposed is not pure virtual; there's no other way Base::f can be +called on an object of type BaseWrap, since it overrides f.
  • +
+
+
+

Deeper Reflection on the Horizon?

+

Admittedly, this formula is tedious to repeat, especially on a project +with many polymorphic classes. That it is neccessary reflects some +limitations in C++'s compile-time introspection capabilities: there's +no way to enumerate the members of a class and find out which are +virtual functions. At least one very promising project has been +started to write a front-end which can generate these dispatchers (and +other wrapping code) automatically from C++ headers.

+

Pyste is being developed by Bruno da Silva de Oliveira. It builds on +GCC_XML, which generates an XML version of GCC's internal program +representation. Since GCC is a highly-conformant C++ compiler, this +ensures correct handling of the most-sophisticated template code and +full access to the underlying type system. In keeping with the +Boost.Python philosophy, a Pyste interface description is neither +intrusive on the code being wrapped, nor expressed in some unfamiliar +language: instead it is a 100% pure Python script. If Pyste is +successful it will mark a move away from wrapping everything directly +in C++ for many of our users. It will also allow us the choice to +shift some of the metaprogram code from C++ to Python. We expect that +soon, not only our users but the Boost.Python developers themselves +will be "thinking hybrid" about their own code.

+
+
+
+

Serialization

+

Serialization is the process of converting objects in memory to a +form that can be stored on disk or sent over a network connection. The +serialized object (most often a plain string) can be retrieved and +converted back to the original object. A good serialization system will +automatically convert entire object hierarchies. Python's standard +pickle module is just such a system. It leverages the language's strong +runtime introspection facilities for serializing practically arbitrary +user-defined objects. With a few simple and unintrusive provisions this +powerful machinery can be extended to also work for wrapped C++ objects. +Here is an example:

+
+#include <string>
+
+struct World
+{
+    World(std::string a_msg) : msg(a_msg) {}
+    std::string greet() const { return msg; }
+    std::string msg;
+};
+
+#include <boost/python.hpp>
+using namespace boost::python;
+
+struct World_picklers : pickle_suite
+{
+  static tuple
+  getinitargs(World const& w) { return make_tuple(w.greet()); }
+};
+
+BOOST_PYTHON_MODULE(hello)
+{
+    class_<World>("World", init<std::string>())
+        .def("greet", &World::greet)
+        .def_pickle(World_picklers())
+    ;
+}
+
+

Now let's create a World object and put it to rest on disk:

+
+>>> import hello
+>>> import pickle
+>>> a_world = hello.World("howdy")
+>>> pickle.dump(a_world, open("my_world", "w"))
+
+

In a potentially different script on a potentially different +computer with a potentially different operating system:

+
+>>> import pickle
+>>> resurrected_world = pickle.load(open("my_world", "r"))
+>>> resurrected_world.greet()
+'howdy'
+
+

Of course the cPickle module can also be used for faster +processing.

+

Boost.Python's pickle_suite fully supports the pickle protocol +defined in the standard Python documentation. Like a __getinitargs__ +function in Python, the pickle_suite's getinitargs() is responsible for +creating the argument tuple that will be use to reconstruct the pickled +object. The other elements of the Python pickling protocol, +__getstate__ and __setstate__ can be optionally provided via C++ +getstate and setstate functions. C++'s static type system allows the +library to ensure at compile-time that nonsensical combinations of +functions (e.g. getstate without setstate) are not used.

+

Enabling serialization of more complex C++ objects requires a little +more work than is shown in the example above. Fortunately the +object interface (see next section) greatly helps in keeping the +code manageable.

+
+
+

Object interface

+

Experienced 'C' language extension module authors will be familiar +with the ubiquitous PyObject*, manual reference-counting, and the +need to remember which API calls return "new" (owned) references or +"borrowed" (raw) references. These constraints are not just +cumbersome but also a major source of errors, especially in the +presence of exceptions.

+

Boost.Python provides a class object which automates reference +counting and provides conversion to Python from C++ objects of +arbitrary type. This significantly reduces the learning effort for +prospective extension module writers.

+

Creating an object from any other type is extremely simple:

+
+object s("hello, world");  // s manages a Python string
+
+

object has templated interactions with all other types, with +automatic to-python conversions. It happens so naturally that it's +easily overlooked:

+
+object ten_Os = 10 * s[4]; // -> "oooooooooo"
+
+

In the example above, 4 and 10 are converted to Python objects +before the indexing and multiplication operations are invoked.

+

The extract<T> class template can be used to convert Python objects +to C++ types:

+
+double x = extract<double>(o);
+
+

If a conversion in either direction cannot be performed, an +appropriate exception is thrown at runtime.

+

The object type is accompanied by a set of derived types +that mirror the Python built-in types such as list, dict, +tuple, etc. as much as possible. This enables convenient +manipulation of these high-level types from C++:

+
+dict d;
+d["some"] = "thing";
+d["lucky_number"] = 13;
+list l = d.keys();
+
+

This almost looks and works like regular Python code, but it is pure +C++. Of course we can wrap C++ functions which accept or return +object instances.

+
+
+
+

Thinking hybrid

+

Because of the practical and mental difficulties of combining +programming languages, it is common to settle a single language at the +outset of any development effort. For many applications, performance +considerations dictate the use of a compiled language for the core +algorithms. Unfortunately, due to the complexity of the static type +system, the price we pay for runtime performance is often a +significant increase in development time. Experience shows that +writing maintainable C++ code usually takes longer and requires far +more hard-earned working experience than developing comparable Python +code. Even when developers are comfortable working exclusively in +compiled languages, they often augment their systems by some type of +ad hoc scripting layer for the benefit of their users without ever +availing themselves of the same advantages.

+

Boost.Python enables us to think hybrid. Python can be used for +rapidly prototyping a new application; its ease of use and the large +pool of standard libraries give us a head start on the way to a +working system. If necessary, the working code can be used to +discover rate-limiting hotspots. To maximize performance these can +be reimplemented in C++, together with the Boost.Python bindings +needed to tie them back into the existing higher-level procedure.

+

Of course, this top-down approach is less attractive if it is clear +from the start that many algorithms will eventually have to be +implemented in C++. Fortunately Boost.Python also enables us to +pursue a bottom-up approach. We have used this approach very +successfully in the development of a toolbox for scientific +applications. The toolbox started out mainly as a library of C++ +classes with Boost.Python bindings, and for a while the growth was +mainly concentrated on the C++ parts. However, as the toolbox is +becoming more complete, more and more newly added functionality can be +implemented in Python.

+images/python_cpp_mix.png +

This figure shows the estimated ratio of newly added C++ and Python +code over time as new algorithms are implemented. We expect this +ratio to level out near 70% Python. Being able to solve new problems +mostly in Python rather than a more difficult statically typed +language is the return on our investment in Boost.Python. The ability +to access all of our code from Python allows a broader group of +developers to use it in the rapid development of new applications.

+
+
+

Development history

+

The first version of Boost.Python was developed in 2000 by Dave +Abrahams at Dragon Systems, where he was privileged to have Tim Peters +as a guide to "The Zen of Python". One of Dave's jobs was to develop +a Python-based natural language processing system. Since it was +eventually going to be targeting embedded hardware, it was always +assumed that the compute-intensive core would be rewritten in C++ to +optimize speed and memory footprint1. The project also wanted to +test all of its C++ code using Python test scripts2. The only +tool we knew of for binding C++ and Python was SWIG, and at the time +its handling of C++ was weak. It would be false to claim any deep +insight into the possible advantages of Boost.Python's approach at +this point. Dave's interest and expertise in fancy C++ template +tricks had just reached the point where he could do some real damage, +and Boost.Python emerged as it did because it filled a need and +because it seemed like a cool thing to try.

+

This early version was aimed at many of the same basic goals we've +described in this paper, differing most-noticeably by having a +slightly more cumbersome syntax and by lack of special support for +operator overloading, pickling, and component-based development. +These last three features were quickly added by Ullrich Koethe and +Ralf Grosse-Kunstleve3, and other enthusiastic contributors arrived +on the scene to contribute enhancements like support for nested +modules and static member functions.

+

By early 2001 development had stabilized and few new features were +being added, however a disturbing new fact came to light: Ralf had +begun testing Boost.Python on pre-release versions of a compiler using +the EDG front-end, and the mechanism at the core of Boost.Python +responsible for handling conversions between Python and C++ types was +failing to compile. As it turned out, we had been exploiting a very +common bug in the implementation of all the C++ compilers we had +tested. We knew that as C++ compilers rapidly became more +standards-compliant, the library would begin failing on more +platforms. Unfortunately, because the mechanism was so central to the +functioning of the library, fixing the problem looked very difficult.

+

Fortunately, later that year Lawrence Berkeley and later Lawrence +Livermore National labs contracted with Boost Consulting for support +and development of Boost.Python, and there was a new opportunity to +address fundamental issues and ensure a future for the library. A +redesign effort began with the low level type conversion architecture, +building in standards-compliance and support for component-based +development (in contrast to version 1 where conversions had to be +explicitly imported and exported across module boundaries). A new +analysis of the relationship between the Python and C++ objects was +done, resulting in more intuitive handling for C++ lvalues and +rvalues.

+

The emergence of a powerful new type system in Python 2.2 made the +choice of whether to maintain compatibility with Python 1.5.2 easy: +the opportunity to throw away a great deal of elaborate code for +emulating classic Python classes alone was too good to pass up. In +addition, Python iterators and descriptors provided crucial and +elegant tools for representing similar C++ constructs. The +development of the generalized object interface allowed us to +further shield C++ programmers from the dangers and syntactic burdens +of the Python 'C' API. A great number of other features including C++ +exception translation, improved support for overloaded functions, and +most significantly, CallPolicies for handling pointers and +references, were added during this period.

+

In October 2002, version 2 of Boost.Python was released. Development +since then has concentrated on improved support for C++ runtime +polymorphism and smart pointers. Peter Dimov's ingenious +boost::shared_ptr design in particular has allowed us to give the +hybrid developer a consistent interface for moving objects back and +forth across the language barrier without loss of information. At +first, we were concerned that the sophistication and complexity of the +Boost.Python v2 implementation might discourage contributors, but the +emergence of Pyste and several other significant feature +contributions have laid those fears to rest. Daily questions on the +Python C++-sig and a backlog of desired improvements show that the +library is getting used. To us, the future looks bright.

+
+
+

Conclusions

+

Boost.Python achieves seamless interoperability between two rich and +complimentary language environments. Because it leverages template +metaprogramming to introspect about types and functions, the user +never has to learn a third syntax: the interface definitions are +written in concise and maintainable C++. Also, the wrapping system +doesn't have to parse C++ headers or represent the type system: the +compiler does that work for us.

+

Computationally intensive tasks play to the strengths of C++ and are +often impossible to implement efficiently in pure Python, while jobs +like serialization that are trivial in Python can be very difficult in +pure C++. Given the luxury of building a hybrid software system from +the ground up, we can approach design with new confidence and power.

+
+
+

Citations

+ + + + + +
[VELD1995]T. Veldhuizen, "Expression Templates," C++ Report, +Vol. 7 No. 5 June 1995, pp. 26-31. +http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html
+
+
+

Footnotes

+ + + + + +
[1]In retrospect, it seems that "thinking hybrid" from the +ground up might have been better for the NLP system: the +natural component boundaries defined by the pure python +prototype turned out to be inappropriate for getting the +desired performance and memory footprint out of the C++ core, +which eventually caused some redesign overhead on the Python +side when the core was moved to C++.
+ + + + + +
[2]We also have some reservations about driving all C++ +testing through a Python interface, unless that's the only way +it will be ultimately used. Any transition across language +boundaries with such different object models can inevitably +mask bugs.
+ + + + + +
[3]These features were expressed very differently in v1 of +Boost.Python
+
+
+ + diff --git a/develop/doc/html/boostbook.css b/develop/doc/html/boostbook.css new file mode 100644 index 00000000..28f89359 --- /dev/null +++ b/develop/doc/html/boostbook.css @@ -0,0 +1,716 @@ + +/*============================================================================= +Copyright (c) 2004 Joel de Guzman +http://spirit.sourceforge.net/ + +Copyright 2013 Niall Douglas additions for colors and alignment. +Copyright 2013 Paul A. Bristow additions for more colors and alignments. + +Distributed under the Boost Software License, Version 1.0. (See accompany- +ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ + +/*============================================================================= +Body defaults +=============================================================================*/ + + body + { + margin: 1em; + font-family: sans-serif; + } + +/*============================================================================= +Paragraphs +=============================================================================*/ + + p + { + text-align: left; + font-size: 10pt; + line-height: 1.15; + } + +/*============================================================================= +Program listings +=============================================================================*/ + + /* Code on paragraphs */ + p tt.computeroutput + { + font-size: 9pt; + } + + pre.synopsis + { + font-size: 9pt; + margin: 1pc 4% 0pc 4%; + padding: 0.5pc 0.5pc 0.5pc 0.5pc; + } + + .programlisting, + .screen + { + font-size: 9pt; + display: block; + margin: 1pc 4% 0pc 4%; + padding: 0.5pc 0.5pc 0.5pc 0.5pc; + } + + /* Program listings in tables don't get borders */ + td .programlisting, + td .screen + { + margin: 0pc 0pc 0pc 0pc; + padding: 0pc 0pc 0pc 0pc; + } + +/*============================================================================= +Headings +=============================================================================*/ + + h1, h2, h3, h4, h5, h6 + { + text-align: left; + margin: 1em 0em 0.5em 0em; + font-weight: bold; + } + + h1 { font-size: 140%; } + h2 { font-weight: bold; font-size: 140%; } + h3 { font-weight: bold; font-size: 130%; } + h4 { font-weight: bold; font-size: 120%; } + h5 { font-weight: normal; font-style: italic; font-size: 110%; } + h6 { font-weight: normal; font-style: italic; font-size: 100%; } + + /* Top page titles */ + title, + h1.title, + h2.title + h3.title, + h4.title, + h5.title, + h6.title, + .refentrytitle + { + font-weight: bold; + margin-bottom: 1pc; + } + + h1.title { font-size: 140% } + h2.title { font-size: 140% } + h3.title { font-size: 130% } + h4.title { font-size: 120% } + h5.title { font-size: 110% } + h6.title { font-size: 100% } + + .section h1 + { + margin: 0em 0em 0.5em 0em; + font-size: 140%; + } + + .section h2 { font-size: 140% } + .section h3 { font-size: 130% } + .section h4 { font-size: 120% } + .section h5 { font-size: 110% } + .section h6 { font-size: 100% } + + /* Code on titles */ + h1 tt.computeroutput { font-size: 140% } + h2 tt.computeroutput { font-size: 140% } + h3 tt.computeroutput { font-size: 130% } + h4 tt.computeroutput { font-size: 130% } + h5 tt.computeroutput { font-size: 130% } + h6 tt.computeroutput { font-size: 130% } + + +/*============================================================================= +Author +=============================================================================*/ + + h3.author + { + font-size: 100% + } + +/*============================================================================= +Lists +=============================================================================*/ + + li + { + font-size: 10pt; + line-height: 1.3; + } + + /* Unordered lists */ + ul + { + text-align: left; + } + + /* Ordered lists */ + ol + { + text-align: left; + } + +/*============================================================================= +Links +=============================================================================*/ + + a + { + text-decoration: none; /* no underline */ + } + + a:hover + { + text-decoration: underline; + } + +/*============================================================================= +Spirit style navigation +=============================================================================*/ + + .spirit-nav + { + text-align: right; + } + + .spirit-nav a + { + color: white; + padding-left: 0.5em; + } + + .spirit-nav img + { + border-width: 0px; + } + +/*============================================================================= +Copyright footer +=============================================================================*/ + .copyright-footer + { + text-align: right; + font-size: 70%; + } + + .copyright-footer p + { + text-align: right; + font-size: 80%; + } + +/*============================================================================= +Table of contents +=============================================================================*/ + + div.toc + { + margin: 1pc 4% 0pc 4%; + padding: 0.1pc 1pc 0.1pc 1pc; + font-size: 80%; + line-height: 1.15; + } + + .boost-toc + { + float: right; + padding: 0.5pc; + } + + /* Code on toc */ + .toc .computeroutput { font-size: 120% } + + /* No margin on nested menus */ + + .toc dl dl { margin: 0; } + +/*============================================================================= +Tables +=============================================================================*/ + + .table-title, + div.table p.title + { + margin-left: 4%; + padding-right: 0.5em; + padding-left: 0.5em; + } + + .informaltable table, + .table table + { + width: 92%; + margin-left: 4%; + margin-right: 4%; + } + + div.informaltable table, + div.table table + { + padding: 4px; + } + + /* Table Cells */ + div.informaltable table tr td, + div.table table tr td + { + padding: 0.5em; + text-align: left; + font-size: 9pt; + } + + div.informaltable table tr th, + div.table table tr th + { + padding: 0.5em 0.5em 0.5em 0.5em; + border: 1pt solid white; + font-size: 80%; + } + + table.simplelist + { + width: auto !important; + margin: 0em !important; + padding: 0em !important; + border: none !important; + } + table.simplelist td + { + margin: 0em !important; + padding: 0em !important; + text-align: left !important; + font-size: 9pt !important; + border: none !important; + } + +/*============================================================================= +Suppress margins in tables +=============================================================================*/ + + table th > *:first-child, + table td > *:first-child + { + margin-top: 0; + } + + table th > *:last-child, + table td > *:last-child + { + margin-bottom: 0; + } + +/*============================================================================= +Blurbs +=============================================================================*/ + + div.note, + div.tip, + div.important, + div.caution, + div.warning, + p.blurb + { + font-size: 9pt; /* A little bit smaller than the main text */ + line-height: 1.2; + display: block; + margin: 1pc 4% 0pc 4%; + padding: 0.5pc 0.5pc 0.5pc 0.5pc; + } + + p.blurb img + { + padding: 1pt; + } + +/*============================================================================= +Variable Lists +=============================================================================*/ + + div.variablelist + { + margin: 1em 0; + } + + /* Make the terms in definition lists bold */ + div.variablelist dl dt, + span.term + { + font-weight: bold; + font-size: 10pt; + } + + div.variablelist table tbody tr td + { + text-align: left; + vertical-align: top; + padding: 0em 2em 0em 0em; + font-size: 10pt; + margin: 0em 0em 0.5em 0em; + line-height: 1; + } + + div.variablelist dl dt + { + margin-bottom: 0.2em; + } + + div.variablelist dl dd + { + margin: 0em 0em 0.5em 2em; + font-size: 10pt; + } + + div.variablelist table tbody tr td p, + div.variablelist dl dd p + { + margin: 0em 0em 0.5em 0em; + line-height: 1; + } + +/*============================================================================= +Misc +=============================================================================*/ + + /* Title of books and articles in bibliographies */ + span.title + { + font-style: italic; + } + + span.underline + { + text-decoration: underline; + } + + span.strikethrough + { + text-decoration: line-through; + } + + /* Copyright, Legal Notice */ + div div.legalnotice p + { + text-align: left + } + +/*============================================================================= +Colors +=============================================================================*/ + + @media screen + { + body { + background-color: #FFFFFF; + color: #000000; + } + + /* Syntax Highlighting */ + .keyword { color: #0000AA; } + .identifier { color: #000000; } + .special { color: #707070; } + .preprocessor { color: #402080; } + .char { color: teal; } + .comment { color: #800000; } + .string { color: teal; } + .number { color: teal; } + .white_bkd { background-color: #FFFFFF; } + .dk_grey_bkd { background-color: #999999; } + + /* Links */ + a, a .keyword, a .identifier, a .special, a .preprocessor + a .char, a .comment, a .string, a .number + { + color: #005a9c; + } + + a:visited, a:visited .keyword, a:visited .identifier, + a:visited .special, a:visited .preprocessor a:visited .char, + a:visited .comment, a:visited .string, a:visited .number + { + color: #9c5a9c; + } + + h1 a, h2 a, h3 a, h4 a, h5 a, h6 a, + h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover, + h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited + { + text-decoration: none; /* no underline */ + color: #000000; + } + + /* Copyright, Legal Notice */ + .copyright + { + color: #666666; + font-size: small; + } + + div div.legalnotice p + { + color: #666666; + } + + /* Program listing */ + pre.synopsis + { + border: 1px solid #DCDCDC; + } + + .programlisting, + .screen + { + border: 1px solid #DCDCDC; + } + + td .programlisting, + td .screen + { + border: 0px solid #DCDCDC; + } + + /* Blurbs */ + div.note, + div.tip, + div.important, + div.caution, + div.warning, + p.blurb + { + border: 1px solid #DCDCDC; + } + + /* Table of contents */ + div.toc + { + border: 1px solid #DCDCDC; + } + + /* Tables */ + div.informaltable table tr td, + div.table table tr td + { + border: 1px solid #DCDCDC; + } + + div.informaltable table tr th, + div.table table tr th + { + background-color: #F0F0F0; + border: 1px solid #DCDCDC; + } + + .copyright-footer + { + color: #8F8F8F; + } + + /* Misc */ + span.highlight + { + color: #00A000; + } + } + + @media print + { + /* Links */ + a + { + color: black; + } + + a:visited + { + color: black; + } + + .spirit-nav + { + display: none; + } + + /* Program listing */ + pre.synopsis + { + border: 1px solid gray; + } + + .programlisting, + .screen + { + border: 1px solid gray; + } + + td .programlisting, + td .screen + { + border: 0px solid #DCDCDC; + } + + /* Table of contents */ + div.toc + { + border: 1px solid gray; + } + + .informaltable table, + .table table + { + border: 1px solid gray; + border-collapse: collapse; + } + + /* Tables */ + div.informaltable table tr td, + div.table table tr td + { + border: 1px solid gray; + } + + div.informaltable table tr th, + div.table table tr th + { + border: 1px solid gray; + } + + table.simplelist tr td + { + border: none !important; + } + + /* Misc */ + span.highlight + { + font-weight: bold; + } + } + +/*============================================================================= +Images +=============================================================================*/ + + span.inlinemediaobject img + { + vertical-align: middle; + } + +/*============================================================================== +Super and Subscript: style so that line spacing isn't effected, see +http://www.adobe.com/cfusion/communityengine/index.cfm?event=showdetails&productId=1&postId=5341 +==============================================================================*/ + +sup, +sub { +height: 0; +line-height: 1; +vertical-align: baseline; +position: relative; + +} + +/* For internet explorer: */ + +* html sup, +* html sub { +vertical-align: bottom; +} + +sup { +bottom: 1ex; +} + +sub { +top: .5ex; +} + +/*============================================================================== +Indexes: pretty much the same as the TOC. +==============================================================================*/ + + .index + { + font-size: 80%; + padding-top: 0px; + padding-bottom: 0px; + margin-top: 0px; + margin-bottom: 0px; + margin-left: 0px; + } + + .index ul + { + padding-left: 3em; + } + + .index p + { + padding: 2px; + margin: 2px; + } + + .index-entry-level-0 + { + font-weight: bold; + } + + .index em + { + font-weight: bold; + } + + +/*============================================================================== +Alignment and coloring use 'role' feature, available from Quickbook 1.6 up. +Added from Niall Douglas for role color and alignment. +http://article.gmane.org/gmane.comp.lib.boost.devel/243318 +*/ + +/* Add text alignment (see http://www.w3schools.com/cssref/pr_text_text-align.asp) */ +span.aligncenter +{ + display: inline-block; width: 100%; text-align: center; +} +span.alignright +{ + display: inline-block; width: 100%; text-align: right; +} +/* alignleft is the default. */ +span.alignleft +{ + display: inline-block; width: 100%; text-align: left; +} + +/* alignjustify stretches the word spacing so that each line has equal width +within a chosen fraction of page width (here arbitrarily 20%). +*Not* useful inside table items as the column width remains the total string width. +Nor very useful, except to temporarily restrict the width. +*/ +span.alignjustify +{ + display: inline-block; width: 20%; text-align: justify; +} + +/* Text colors. +Names at http://www.w3.org/TR/2002/WD-css3-color-20020219/ 4.3. X11 color keywords. +Quickbook Usage: [role red Some red text] + +*/ +span.red { inline-block; color: red; } +span.green { color: green; } +span.lime { color: #00FF00; } +span.blue { color: blue; } +span.navy { color: navy; } +span.yellow { color: yellow; } +span.magenta { color: magenta; } +span.indigo { color: #4B0082; } +span.cyan { color: cyan; } +span.purple { color: purple; } +span.gold { color: gold; } +span.silver { color: silver; } /* lighter gray */ +span.gray { color: #808080; } /* light gray */ diff --git a/develop/doc/html/building.html b/develop/doc/html/building.html new file mode 100644 index 00000000..15d1cf03 --- /dev/null +++ b/develop/doc/html/building.html @@ -0,0 +1,98 @@ + + + +Chapter 1. Building and Testing + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+
+

+Chapter 1. Building and Testing

+

+David Abrahams +

+
+
+ +
+ +

+ Boost.Python requires Python 2.2 + [1] or newer. +

+
+
+

+

[1] + Note that although we tested earlier versions of Boost.Python with Python + 2.2, and we don't think we've done anything + to break compatibility, this release of Boost.Python may not have been + tested with versions of Python earlier than 2.4, so we're not 100% sure + that python 2.2 and 2.3 are supported. +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/building/background.html b/develop/doc/html/building/background.html new file mode 100644 index 00000000..6c571bf6 --- /dev/null +++ b/develop/doc/html/building/background.html @@ -0,0 +1,70 @@ + + + +Background + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ There are two basic models for combining C++ and Python: +

+
    +
  • + extending, + in which the end-user launches the Python interpreter executable and + imports Python “extension modules” written in C++. Think of taking + a library written in C++ and giving it a Python interface so Python programmers + can use it. From Python, these modules look just like regular Python + modules. +
  • +
  • + embedding, + in which the end-user launches a program written in C++ that in turn + invokes the Python interpreter as a library subroutine. Think of adding + scriptability to an existing application. +
  • +
+

+ The key distinction between extending and embedding is the location of the + C++ main() + function: in the Python interpreter executable, or in some other program, + respectively. Note that even when embedding Python in another program, extension + modules are often the best way to make C/C++ functionality accessible to + Python code, so the use of extension modules is really at the heart + of both models. +

+

+ Except in rare cases, extension modules are built as dynamically-loaded libraries + with a single entry point, which means you can change them without rebuilding + either the other extension modules or the executable containing main(). +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/building/choosing_a_boost_python_library_.html b/develop/doc/html/building/choosing_a_boost_python_library_.html new file mode 100644 index 00000000..6cf068e3 --- /dev/null +++ b/develop/doc/html/building/choosing_a_boost_python_library_.html @@ -0,0 +1,128 @@ + + + +Choosing a Boost.Python Library Binary + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +

+ If—instead of letting Boost.Build construct and link with the right libraries + automatically—you choose to use a pre-built Boost.Python library, you'll + need to think about which one to link with. The Boost.Python binary comes + in both static and dynamic flavors. Take care to choose the right flavor + for your application. [3] +

+
+ +

+ The dynamic library is the safest and most-versatile choice: +

+
    +
  • + A single copy of the library code is used by all extension modules + built with a given toolset. [4] +
  • +
  • + The library contains a type conversion registry. Because one registry + is shared among all extension modules, instances of a class exposed + to Python in one dynamically-loaded extension module can be passed + to functions exposed in another such module. +
  • +
+
+
+ +

+ It might be appropriate to use the static Boost.Python library in any of + the following cases: +

+
    +
  • + You are extending + python and the types exposed in your dynamically-loaded extension module + don't need to be used by any other Boost.Python extension modules, + and you don't care if the core library code is duplicated among them. +
  • +
  • + You are embedding + python in your application and either: +
      +
    • + You are targeting a Unix variant OS other than MacOS or AIX, + where the dynamically-loaded extension modules can “see” + the Boost.Python library symbols that are part of the executable. +
    • +
    • + Or, you have statically linked some Boost.Python extension modules + into your application and you don't care if any dynamically-loaded + Boost.Python extension modules are able to use the types exposed + by your statically-linked extension modules (and vice-versa). +
    • +
    +
  • +
+
+
+

+

[3] + Information about how to identify the static and dynamic builds of Boost.Python + on Windows + / Unix + variants +

+

[4] + Because of the way most *nix platforms share symbols among dynamically-loaded + objects, I'm not certain that extension modules built with different + compiler toolsets will always use different copies of the Boost.Python + library when loaded into the same Python instance. Not using different + libraries could be a good thing if the compilers have compatible + ABIs, because extension modules built with the two libraries would + be interoperable. Otherwise, it could spell disaster, since an extension + module and the Boost.Python library would have different ideas of + such things as class layout. I would appreciate someone doing the + experiment to find out what happens. +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/building/configuring_boost_build.html b/develop/doc/html/building/configuring_boost_build.html new file mode 100644 index 00000000..d92a827d --- /dev/null +++ b/develop/doc/html/building/configuring_boost_build.html @@ -0,0 +1,252 @@ + + + +Configuring Boost.Build + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +

+ As described in the Boost.Build + Reference Manual, a file called user-config.jam in + your home directory is used to specify the tools and libraries available + to the build system. You may need to create or edit user-config.jam to + tell Boost.Build how to invoke Python, #include + its headers, and link with its libraries. +

+
+ + + + + +
[Note]Note

+ If you are using a unix-variant OS and you ran Boost's configure + script, it may have generated a user-config.jam + for you. [2] If your configure/make sequence was successful and Boost.Python + binaries were built, your user-config.jam + file is probably already correct. +

+

+ If you have one fairly “standard” python installation for your platform, + you might not need to do anything special to describe it. If you haven't + configured python in user-config.jam (and + you don't specify --without-python + on the Boost.Build command line), Boost.Build will automatically execute + the equivalent of +

+
import toolset : using ;
+using python ;
+
+

+ which automatically looks for Python in the most likely places. However, + that only happens when using the Boost.Python project file (e.g. when referred + to by another project as in the quickstart method). If instead you are linking + against separately-compiled Boost.Python binaries, you should set up a user-config.jam file + with at least the minimal incantation above. +

+
+ +

+ If you have several versions of Python installed, or Python is installed + in an unusual way, you may want to supply any or all of the following optional + parameters to using python. +

+
+

+
+
version
+

+ the version of Python to use. Should be in Major.Minor format, for + example, 2.3. Do not + include the subminor version (i.e. not + 2.5.1). If you have multiple Python versions + installed, the version will usually be the only configuration argument + required. +

+
cmd-or-prefix
+

+ preferably, a command that invokes a Python interpreter. Alternatively, + the installation prefix for Python libraries and header files. Only + use the alternative formulation if there is no appropriate Python + executable available. +

+
includes
+

+ the #include paths + for Python headers. Normally the correct path(s) will be automatically + deduced from version + and/or cmd-or-prefix. +

+
libraries
+

+ the path to Python library binaries. On MacOS/Darwin, you can also + pass the path of the Python framework. Normally the correct path(s) + will be automatically deduced from version + and/or cmd-or-prefix. +

+
condition
+

+ if specified, should be a set of Boost.Build properties that are + matched against the build configuration when Boost.Build selects + a Python configuration to use. See examples below for details. +

+
extension-suffix
+

+ A string to append to the name of extension modules before the true + filename extension. You almost certainly don't need to use this. + Usually this suffix is only used when targeting a Windows debug build + of Python, and will be set automatically for you based on the value + of the <python-debugging> + feature. However, at least one Linux distribution (Ubuntu Feisty + Fawn) has a specially configured <python-dbg> + package that claims to use such a suffix. +

+
+
+
+
+ +

+ Note that in the examples below, case and especially + whitespace are significant. +

+
    +
  • + If you have both python 2.5 and python 2.4 installed, user-config.jam might contain +
    using python : 2.5 ;  # Make both versions of Python available
    +using python : 2.4 ;  # To build with python 2.4, add python=2.4
    +                      # to your command line.
    +
    +

    + The first version configured (2.5) becomes the default. To build + against python 2.4, add python=2.4 + to the bjam command + line. +

    +
  • +
  • + If you have python installed in an unusual location, you might supply + the path to the interpreter in the cmd-or-prefix + parameter: +
    using python : : /usr/local/python-2.6-beta/bin/python ;
    +
    +
  • +
  • + If you have a separate build of Python for use with a particular toolset, + you might supply that toolset in the condition + parameter: +
    using python ;  # use for most toolsets
    +
    +# Use with Intel C++ toolset
    +using python
    +     : # version
    +     : c:\\Devel\\Python-2.5-IntelBuild\\PCBuild\\python # cmd-or-prefix
    +     : # includes
    +     : # libraries
    +     : <toolset>intel # condition
    +     ;
    +
    +
  • +
  • + If you have downloaded the Python sources and built both the normal + and the "python + debugging" builds from source on Windows, you might see: +
    using python : 2.5 : C:\\src\\Python-2.5\\PCBuild\\python ;
    +using python : 2.5 : C:\\src\\Python-2.5\\PCBuild\\python_d
    +  : # includes
    +  : # libs
    +  : <python-debugging>on ;
    +
    +
  • +
  • + You can set up your user-config.jam so a bjam built under Windows can + build/test both Windows and Cygwin_ python extensions. Just pass <target-os>cygwin + in the condition parameter + for the cygwin python installation: +
    # windows installation
    +using python ;
    +
    +# cygwin installation
    +using python : : c:\\cygwin\\bin\\python2.5 : : : <target-os>cygwin ;
    +
    +

    + when you put target-os=cygwin in your build request, it should build + with the cygwin version of python: _ +

    +
    bjam target-os=cygwin toolset=gcc
    +
    +

    + This is supposed to work the other way, too (targeting windows python + with a Cygwin bjam) but it + seems as though the support in Boost.Build's toolsets for building + that way is broken at the time of this writing. +

    +
  • +
  • + Note that because of the + way Boost.Build currently selects target alternatives, you + might have be very explicit in your build requests. For example, given: +
    using python : 2.5 ; # a regular windows build
    +using python : 2.4 : : : : <target-os>cygwin ;
    +
    +

    + building with +

    +
    bjam target-os=cygwin
    +
    +

    + will yield an error. Instead, you'll need to write +

    +
    bjam target-os=cygwin/python=2.4
    +
    +
  • +
+
+
+

+

[2] + configure overwrites + the existing user-config.jam in your home directory (if any) + after making a backup of the old version. +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/building/include_issues.html b/develop/doc/html/building/include_issues.html new file mode 100644 index 00000000..9630fe2f --- /dev/null +++ b/develop/doc/html/building/include_issues.html @@ -0,0 +1,53 @@ + + + +#include Issues + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ 1. If you should ever have occasion to #include + "python.h" directly in a + translation unit of a program using Boost.Python, use #include + "boost/python/detail/wrap_python.hpp" + instead. It handles several issues necessary for use with Boost.Python, one + of which is mentioned in the next section. +

+

+ 2. Be sure not to #include + any system headers before wrap_python.hpp. This + restriction is actually imposed by Python, or more properly, by Python's + interaction with your operating system. See http://docs.python.org/ext/simpleExample.html + for details. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/building/installing_boost_python_on_your_.html b/develop/doc/html/building/installing_boost_python_on_your_.html new file mode 100644 index 00000000..944943a9 --- /dev/null +++ b/develop/doc/html/building/installing_boost_python_on_your_.html @@ -0,0 +1,52 @@ + + + +Installing Boost.Python on your System + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ Since Boost.Python is a separately-compiled (as opposed to header-only) library, its user relies on the services + of a Boost.Python library binary. +

+

+ If you need a regular installation of the Boost.Python library binaries on + your system, the Boost Getting + Started Guide will walk you through the steps of creating one. If + building binaries from source, you might want to supply the --with-python + argument to bjam (or the + --with-libraries=python + argument to configure), so + only the Boost.Python binary will be built, rather than all the Boost binaries. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/building/no_install_quickstart.html b/develop/doc/html/building/no_install_quickstart.html new file mode 100644 index 00000000..f3d28d5e --- /dev/null +++ b/develop/doc/html/building/no_install_quickstart.html @@ -0,0 +1,318 @@ + + + +No-Install Quickstart + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +

+ There is no need to “install Boost” in order to get started using Boost.Python. + These instructions use Boost.Build + projects, which will build those binaries as soon as they're needed. Your + first tests may take a little longer while you wait for Boost.Python to build, + but doing things this way will save you from worrying about build intricacies + like which library binaries to use for a specific compiler configuration + and figuring out the right compiler options to use yourself. +

+
+ + + + + +
[Note]Note
+

+ Of course it's possible to use other build systems to build Boost.Python + and its extensions, but they are not officially supported by Boost. Moreover + 99% of all “I can't build Boost.Python” problems + come from trying to use another build system without first following + these instructions. +

+

+ If you want to use another system anyway, we suggest that you follow these + instructions, and then invoke bjam + with the +

+

+ -a + -ofilename +

+

+ options to dump the build commands it executes to a file, so you can see + what your alternate build system needs to do. +

+
+
+ +

+ 1. Get Boost; see sections 1 and 2 of the Boost Getting + Started Guide. +

+

+ 2. Get the bjam build driver. + See section 5 of the Boost Getting + Started Guide. +

+

+ 3. cd into the example/quickstart/ directory of your Boost.Python installation, + which contains a small example project. +

+

+ 4. Invoke bjam. Replace + the “stage“ argument + from the example invocation from section 5 of the Boost Getting + Started Guide with “test,“ + to build all the test targets. Also add the argument “--verbose-test” to see the output generated by + the tests when they are run. On Windows, your bjam + invocation might look something like: +

+
C:\\...\\quickstart> bjam toolset=msvc --verbose-test test
+
+

+ and on Unix variants, perhaps, +

+
.../quickstart$ bjam toolset=gcc --verbose-test test
+
+
+ + + + + +
[Note]Note

+ For the sake of concision, the rest of this guide will use unix-style + forward slashes in pathnames instead of the backslashes with which Windows + users may be more familiar. The forward slashes should work everywhere + except in Command + Prompt windows, where you should use backslashes. +

+

+ If you followed this procedure successfully, you will have built an extension + module called extending + and tested it by running a Python script called test_extending.py. + You will also have built and run a simple application called embedding that embeds python. +

+
+
+ +

+ If you're seeing lots of compiler and/or linker error messages, it's probably + because Boost.Build is having trouble finding your Python installation. + You might want to pass the --debug-configuration option to bjam the first few times you invoke it, + to make sure that Boost.Build is correctly locating all the parts of your + Python installation. If it isn't, consider Configuring + Boost.Build as detailed below. +

+

+ If you're still having trouble, Someone on one of the following mailing + lists may be able to help: +

+
+
+
+ +

+ Rejoice! If you're new to Boost.Python, at this point it might be a good + idea to ignore build issues for a while and concentrate on learning the + library by going through the Tutorial + and perhaps some of the Reference Manual, + trying out what you've learned about the API by modifying the quickstart + project. +

+
+
+ + +

+ If you're content to keep your extension module forever in one source file + called extending.cpp, inside your Boost.Python distribution, + and import it forever as extending, + then you can stop here. However, it's likely that you will want to make + a few changes. There are a few things you can do without having to learn + Boost.Build in depth. +

+

+ The project you just built is specified in two files in the current directory: + boost-build.jam, which tells bjam + where it can find the interpreted code of the Boost build system, and + Jamroot, which describes + the targets you just built. These files are heavily commented, so they + should be easy to modify. Take care, however, to preserve whitespace. Punctuation + such as ; will not be recognized + as intended by bjam if + it is not surrounded by whitespace. +

+
+ +

+ You'll probably want to copy this project elsewhere so you can change + it without modifying your Boost distribution. To do that, simply +

+

+ a. copy the entire example/quickstart/ directory into a new directory. +

+

+ b. In the new copies of boost-build.jam + and Jamroot, locate the + relative path near the top of the file that is clearly marked by a comment, + and edit that path so that it refers to the same directory your Boost + distribution as it referred to when the file was in its original location + in the example/quickstart/ + directory. +

+

+ For example, if you moved the project from /home/dave/boost_1_34_0/libs/python/example/quickstart to /home/dave/my-project, you could change the first + path in boost-build.jam from +

+
../../../../tools/build/src
+
+

+ to +

+
/home/dave/boost_1_34_0/tools/build/src
+
+

+ and change the first path in Jamroot + from +

+
../../../..
+
+

+ to +

+
/home/dave/boost_1_34_0
+
+
+
+ +

+ The names of additional source files involved in building your extension + module or embedding application can be listed in Jamroot + right alongside extending.cpp + or embedding.cpp respectively. Just be sure to leave + whitespace around each filename: +

+
 file1.cpp file2.cpp file3.cpp 
+
+

+ Naturally, if you want to change the name of a source file you can tell + Boost.Build about it by editing the name in Jamroot. +

+
+
+ +

+ The name of the extension module is determined by two things: +

+
    +
  1. + the name in Jamroot + immediately following python-extension, + and +
  2. +
  3. + the name passed to BOOST_PYTHON_MODULE + in extending.cpp. +
  4. +
+

+ To change the name of the extension module from extending + to hello, you'd edit + Jamroot, changing +

+
python-extension extending : extending.cpp ;
+
+

+ to +

+
python-extension hello : extending.cpp ;
+
+

+ and you'd edit extending.cpp, changing +

+
BOOST_PYTHON_MODULE(extending)
+
+

+ to +

+
BOOST_PYTHON_MODULE(hello)
+
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/building/notes_for_mingw_and_cygwin_with_.html b/develop/doc/html/building/notes_for_mingw_and_cygwin_with_.html new file mode 100644 index 00000000..58f4f4db --- /dev/null +++ b/develop/doc/html/building/notes_for_mingw_and_cygwin_with_.html @@ -0,0 +1,47 @@ + + + +Notes for MinGW (and Cygwin with -mno-cygwin) GCC Users + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ If you are using a version of Python prior to 2.4.1 with a MinGW prior to + 3.0.0 (with binutils-2.13.90-20030111-1), you will need to create a MinGW-compatible + version of the Python library; the one shipped with Python will only work + with a Microsoft-compatible linker. Follow the instructions in the “Non-Microsoft” + section of the “Building Extensions: Tips And Tricks” chapter in Installing Python Modules + to create libpythonXX.a, where XX + corresponds to the major and minor version numbers of your Python installation. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/building/python_debugging_builds.html b/develop/doc/html/building/python_debugging_builds.html new file mode 100644 index 00000000..840990d2 --- /dev/null +++ b/develop/doc/html/building/python_debugging_builds.html @@ -0,0 +1,78 @@ + + + +Python Debugging Builds + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ Python can be built in a special “python debugging” configuration that + adds extra checks and instrumentation that can be very useful for developers + of extension modules. The data structures used by the debugging configuration + contain additional members, so a Python executable + built with python debugging enabled cannot be used with an extension module + or library compiled without it, and vice-versa. +

+

+ Since pre-built “python debugging” versions of the Python executable + and libraries are not supplied with most distributions of Python, [5] and we didn't want to force our users to build them, Boost.Build + does not automatically enable python debugging in its debug + build variant (which is the default). Instead there is a special build property + called python-debugging that, when used as a build property, + will define the right preprocessor symbols and select the right libraries + to link with. +

+

+ On unix-variant platforms, the debugging versions of Python's data structures + will only be used if the symbol Py_DEBUG + is defined. On many windows compilers, when extension modules are built with + the preprocessor symbol _DEBUG, + Python defaults to force linking with a special debugging version of the + Python DLL. Since that symbol is very commonly used even when Python is not + present, Boost.Python temporarily undefines _DEBUG + when Python.h is #included from boost/python/detail/wrap_python.hpp - + unless BOOST_DEBUG_PYTHON + is defined. The upshot is that if you want “python debugging”and you + aren't using Boost.Build, you should make sure BOOST_DEBUG_PYTHON + is defined, or python debugging will be suppressed. +

+
+

+

[5] + On Unix and similar platforms, a debugging python and associated libraries + are built by adding --with-pydebug when configuring the Python build. On + Windows, the debugging version of Python is generated by the "Win32 + Debug" target of the Visual Studio project in the PCBuild subdirectory + of a full Python source code distribution. +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/building/testing_boost_python.html b/develop/doc/html/building/testing_boost_python.html new file mode 100644 index 00000000..28cce0e3 --- /dev/null +++ b/develop/doc/html/building/testing_boost_python.html @@ -0,0 +1,42 @@ + + + +Testing Boost.Python + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ To run the full test suite for Boost.Python, invoke bjam + in the test subdirectory + of your Boost.Python distribution. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/configuration.html b/develop/doc/html/configuration.html new file mode 100644 index 00000000..cf86c1b1 --- /dev/null +++ b/develop/doc/html/configuration.html @@ -0,0 +1,350 @@ + + + +Chapter 2. Configuration + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+
+

+Chapter 2. Configuration

+

+David Abrahams +

+
+
+ +
+ + +
+ +

+ 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. +

+
+
+ +

+ These are the macros that may be defined by an application using Boost.Python. + Note that if you extend a strict interpretation of the C++ standard to + cover dynamic libraries, using different values of these macros when compiling + different libraries (including extension modules and the Boost.Python library + itself) is a violation of the ODR. However, + we know of no C++ implementations on which this particular violation is + detectable or causes any problems. +

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Macro +

+
+

+ Default +

+
+

+ Meaning +

+
+

+ BOOST_PYTHON_MAX_ARITY +

+
+

+ 15 +

+
+

+ The maximum arity of any function, member function, or constructor + to be wrapped, invocation of a Boost.Python function wich is + specified as taking arguments x1, x2,...Xn. This includes, in + particular, callback mechanisms such as object::operator()(...) + or call_method<R>(... ). +

+
+

+ BOOST_PYTHON_MAX_BASES +

+
+

+ 10 +

+
+

+ The maximum number of template arguments to the bases<...> + class template, which is used to specify the bases of a wrapped + C++ class.. +

+
+

+ BOOST_PYTHON_STATIC_MODULE +

+
+

+ not defined +

+
+

+ If defined, prevents your module initialization function from + being treated as an exported symbol on platforms which support + that distinction in-code +

+
+

+ BOOST_PYTHON_ENABLE_CDECL +

+
+

+ not defined +

+
+

+ If defined, allows functions using the __cdecl + calling convention to be wrapped. +

+
+

+ BOOST_PYTHON_ENABLE_STDCALL +

+
+

+ not defined +

+
+

+ If defined, allows functions using the __stdcall + calling convention to be wrapped. +

+
+

+ BOOST_PYTHON_ENABLE_FASTCALL +

+
+

+ not defined +

+
+

+ If defined, allows functions using the __fastcall + calling convention to be wrapped. +

+
+
+
+ +

+ These macros are defined by Boost.Python + and are implementation details of interest only to implementors and those + porting to new platforms. +

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Macro +

+
+

+ Default +

+
+

+ Meaning +

+
+

+ BOOST_PYTHON_TYPE_ID_NAME +

+
+

+ not defined +

+
+

+ If defined, this indicates that the type_info comparison across + shared library boundaries does not work on this platform. In + other words, if shared-lib-1 passes typeid(T) to a function in shared-lib-2 + which compares it to typeid(T), that comparison may return + false. If this macro + is #defined, Boost.Python uses and compares typeid(T).name() instead of using and comparing + the std::type_info objects directly. +

+
+

+ BOOST_PYTHON_NO_PY_SIGNATURES +

+
+

+ not defined +

+
+

+ If defined for a module no pythonic signatures are generated + for the docstrings of the module functions, and no python type + is associated with any of the converters registered by the module. + This also reduces the binary size of the module by about 14% + (gcc compiled). If defined for the boost_python runtime library, + the default for the docstring_options.enable_py_signatures() is set to false. +

+
+

+ BOOST_PYTHON_SUPPORTS_PY_SIGNATURES +

+
+

+ defined if BOOST_PYTHON_NO_PY_SIGNATURES + is undefined +

+
+

+ This macro is defined to enable a smooth transition from older + Boost.Python versions which do not support pythonic signatures. + For example usage see here. +

+
+

+ BOOST_PYTHON_PY_SIGNATURES_PROPER_INIT_SELF_TYPE +

+
+

+ not defined +

+
+

+ If defined the python type of __init__ + method "self" parameters is properly generated, otherwise + object is used. It is undefined by default because it increases + the binary size of the module by about 14% (gcc compiled). +

+
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/faq.html b/develop/doc/html/faq.html new file mode 100644 index 00000000..7129047c --- /dev/null +++ b/develop/doc/html/faq.html @@ -0,0 +1,116 @@ + + + +Chapter 4. Frequently Asked Questions (FAQs) + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+

+Chapter 4. Frequently Asked Questions (FAQs)

+ +
+ +

+ If what you're trying to do is something like this: +

+
typedef boost::function<void (string s) > funcptr;
+
+void foo(funcptr fp)
+{
+  fp("hello,world!");
+}
+
+BOOST_PYTHON_MODULE(test)
+{
+  def("foo",foo);
+}
+
+

+ And then: +

+
>>> def hello(s):
+...    print s
+...
+>>> foo(hello)
+hello, world!
+
+

+ The short answer is: "you can't". This is not a Boost.Python limitation + so much as a limitation of C++. The problem is that a Python function is + actually data, and the only way of associating data with a C++ function pointer + is to store it in a static variable of the function. The problem with that + is that you can only associate one piece of data with every C++ function, + and we have no way of compiling a new C++ function on-the-fly for every Python + function you decide to pass to foo. + In other words, this could work if the C++ function is always going to invoke + the same Python function, but you probably don't want + that. +

+

+ If you have the luxury of changing the C++ code you're wrapping, pass it + an object instead and call + that; the overloaded function call operator will invoke the Python function + you pass it behind the object. +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/faq/compilation_takes_too_much_time_.html b/develop/doc/html/faq/compilation_takes_too_much_time_.html new file mode 100644 index 00000000..d0967099 --- /dev/null +++ b/develop/doc/html/faq/compilation_takes_too_much_time_.html @@ -0,0 +1,42 @@ + + + +Compilation takes too much time and eats too much memory! What can I do to make it faster? + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ Please refer to the Reducing Compiling Time + section in the Tutorial. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/faq/does_boost_python_work_with_mac_.html b/develop/doc/html/faq/does_boost_python_work_with_mac_.html new file mode 100644 index 00000000..94d2901e --- /dev/null +++ b/develop/doc/html/faq/does_boost_python_work_with_mac_.html @@ -0,0 +1,93 @@ + + + +Does Boost.Python work with Mac OS X? + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ It is known to work under 10.2.8 and 10.3 using Apple's gcc 3.3 compiler: +

+
gcc (GCC) 3.3 20030304 (Apple Computer, Inc. build 1493)
+

+ Under 10.2.8 get the August 2003 gcc update (free at http://connect.apple.com). + Under 10.3 get the Xcode Tools v1.0 (also free). +

+

+ Python 2.3 is required. The Python that ships with 10.3 is fine. Under 10.2.8 + use these commands to install Python as a framework: +

+
./configure --enable-framework
+make
+make frameworkinstall
+

+ The last command requires root privileges because the target directory is + /Library/Frameworks/Python.framework/Versions/2.3. However, + the installation does not interfere with the Python version that ships with + 10.2.8. +

+

+ It is also crucial to increase the stacksize + before starting compilations, e.g.: +

+
limit stacksize 8192k
+

+ If the stacksize is too small + the build might crash with internal compiler errors. +

+

+ Sometimes Apple's compiler exhibits a bug by printing an error like the following + while compiling a boost::python::class_<your_type> + template instantiation: +

+
.../inheritance.hpp:44: error: cannot
+  dynamic_cast `p' (of type `struct cctbx::boost_python::<unnamed>::add_pair*
+  ') to type `void*' (source type is not polymorphic)
+
+

+ We do not know a general workaround, but if the definition of your_type can be modified the following + was found to work in all cases encountered so far: +

+
struct your_type
+{
+  // before defining any member data
+#if defined(__MACH__) &amp;&amp; defined(__APPLE_CC__) &amp;&amp; __APPLE_CC__ == 1493
+  bool dummy_;
+#endif
+  // now your member data, e.g.
+  double x;
+  int j;
+  // etc.
+};
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/faq/error_c2064_term_does_not_evalua.html b/develop/doc/html/faq/error_c2064_term_does_not_evalua.html new file mode 100644 index 00000000..d59cc03d --- /dev/null +++ b/develop/doc/html/faq/error_c2064_term_does_not_evalua.html @@ -0,0 +1,77 @@ + + + +error C2064: term does not evaluate to a function taking 2 arguments + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ Niall Douglas provides these notes: +

+

+ If you see Microsoft Visual C++ 7.1 (MS Visual Studio .NET 2003) issue an + error message like the following it is most likely due to a bug in the compiler: +

+
boost\boost\python\detail\invoke.hpp(76):
+error C2064: term does not evaluate to a function taking 2 arguments"
+
+

+ This message is triggered by code like the following: +

+
#include <boost/python.hpp>
+
+using namespace boost::python;
+
+class FXThread
+{
+public:
+  bool setAutoDelete(bool doso) throw();
+};
+
+void Export_FXThread()
+{
+  class_< FXThread >("FXThread")
+      .def("setAutoDelete", &amp;FXThread::setAutoDelete)
+  ;
+}
+
+

+ The bug is related to the throw() modifier. As a workaround cast off the + modifier. E.g.: +

+
.def("setAutoDelete", (bool (FXThread::*)(bool)) &FXThread::setAutoDelete)
+
+

+ (The bug has been reported to Microsoft.) +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/faq/fatal_error_c1204_compiler_limit.html b/develop/doc/html/faq/fatal_error_c1204_compiler_limit.html new file mode 100644 index 00000000..192920af --- /dev/null +++ b/develop/doc/html/faq/fatal_error_c1204_compiler_limit.html @@ -0,0 +1,94 @@ + + + +fatal error C1204:Compiler limit:internal structure overflow + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ Q: I get this error message when + compiling a large source file. What can I do? +

+

+ A: You have two choices: +

+
    +
  1. + Upgrade your compiler (preferred) +
  2. +
  3. + Break your source file up into multiple translation units. +

    + my_module.cpp: +

    +
    ...
    +void more_of_my_module();
    +BOOST_PYTHON_MODULE(my_module)
    +{
    +  def("foo", foo);
    +  def("bar", bar);
    +  ...
    +  more_of_my_module();
    +}
    +
    +

    + more_of_my_module.cpp: +

    +
    void more_of_my_module()
    +{
    +  def("baz", baz);
    +  ...
    +}
    +
    +

    + If you find that a class_<...> declaration can't fit in + a single source file without triggering the error, you can always pass + a reference to the class_ + object to a function in another source file, and call some of its member + functions (e.g. .def(...)) in the auxilliary source file: +

    +

    + more_of_my_class.cpp: +

    +
    void more_of_my_class(class&lt;my_class&gt;&amp; x)
    +{
    +  x
    +   .def("baz", baz)
    +   .add_property("xx", &my_class::get_xx, &my_class::set_xx)
    +   ;
    +  ...
    +}
    +
    +
  4. +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/faq/how_can_i_automatically_convert_.html b/develop/doc/html/faq/how_can_i_automatically_convert_.html new file mode 100644 index 00000000..bb435b77 --- /dev/null +++ b/develop/doc/html/faq/how_can_i_automatically_convert_.html @@ -0,0 +1,146 @@ + + + +How can I automatically convert my custom string type to and from a Python string? + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ Ralf W. Grosse-Kunstleve provides these notes: +

+

+ Below is a small, self-contained demo extension module that shows how to + do this. Here is the corresponding trivial test: +

+
import custom_string
+assert custom_string.hello() == "Hello world."
+assert custom_string.size("california") == 10
+
+

+ If you look at the code you will find: +

+
    +
  • + A custom to_python converter + (easy): custom_string_to_python_str +
  • +
  • + A custom lvalue converter (needs more code): custom_string_from_python_str +
  • +
+

+ The custom converters are registered in the global Boost.Python registry + near the top of the module initialization function. Once flow control has + passed through the registration code the automatic conversions from and to + Python strings will work in any module imported in the same process. +

+
#include <boost/python/module.hpp>
+#include <boost/python/def.hpp>
+#include <boost/python/to_python_converter.hpp>
+
+namespace sandbox { namespace {
+
+class custom_string
+{
+  public:
+    custom_string() {}
+    custom_string(std::string const &value) : value_(value) {}
+    std::string const &value() const { return value_; }
+  private:
+    std::string value_;
+};
+
+struct custom_string_to_python_str
+{
+  static PyObject* convert(custom_string const &s)
+  {
+    return boost::python::incref(boost::python::object(s.value()).ptr());
+  }
+};
+
+struct custom_string_from_python_str
+{
+  custom_string_from_python_str()
+  {
+    boost::python::converter::registry::push_back(
+      &convertible,
+      &construct,
+      boost::python::type_id<custom_string>());
+  }
+
+  static void* convertible(PyObject* obj_ptr)
+  {
+    if (!PyString_Check(obj_ptr)) return 0;
+    return obj_ptr;
+  }
+
+  static void construct(
+    PyObject* obj_ptr,
+    boost::python::converter::rvalue_from_python_stage1_data* data)
+  {
+    const char* value = PyString_AsString(obj_ptr);
+    if (value == 0) boost::python::throw_error_already_set();
+    void* storage = (
+      (boost::python::converter::rvalue_from_python_storage<custom_string>*)
+        data)->storage.bytes;
+    new (storage) custom_string(value);
+    data->convertible = storage;
+  }
+};
+
+custom_string hello() { return custom_string("Hello world."); }
+
+std::size_t size(custom_string const &s) { return s.value().size(); }
+
+void init_module()
+{
+  using namespace boost::python;
+
+  boost::python::to_python_converter<
+    custom_string,
+    custom_string_to_python_str>();
+
+  custom_string_from_python_str();
+
+  def("hello", hello);
+  def("size", size);
+}
+
+}} // namespace sandbox::<anonymous>
+
+BOOST_PYTHON_MODULE(custom_string)
+{
+  sandbox::init_module();
+}
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/faq/how_can_i_find_the_existing_pyob.html b/develop/doc/html/faq/how_can_i_find_the_existing_pyob.html new file mode 100644 index 00000000..8bcf55d3 --- /dev/null +++ b/develop/doc/html/faq/how_can_i_find_the_existing_pyob.html @@ -0,0 +1,103 @@ + + + +How can I find the existing PyObject that holds a C++ object? + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ "I am wrapping a function that always returns a pointer to an already-held + C++ object." +

+

+ One way to do that is to hijack the mechanisms used for wrapping a class + with virtual functions. If you make a wrapper class with an initial PyObject* + constructor argument and store that PyObject* as "self", you can + get back to it by casting down to that wrapper type in a thin wrapper function. + For example: +

+
class X { X(int); virtual ~X(); ... };
+X* f();  // known to return Xs that are managed by Python objects
+
+
+// wrapping code
+
+struct X_wrap : X
+{
+  X_wrap(PyObject* self, int v) : self(self), X(v) {}
+  PyObject* self;
+};
+
+handle<> f_wrap()
+{
+  X_wrap* xw = dynamic_cast<X_wrap*>(f());
+  assert(xw != 0);
+  return handle<>(borrowed(xw->self));
+}
+
+...
+
+def("f", f_wrap());
+class_<X,X_wrap,boost::noncopyable>("X", init<int>())
+ ...
+ ;
+
+

+ Of course, if X has no virtual functions you'll have to use static_cast instead of dynamic_cast + with no runtime check that it's valid. This approach also only works if the + X object was constructed + from Python, because Xs constructed + from C++ are of course never X_wrap + objects. +

+

+ Another approach to this requires you to change your C++ code a bit; if that's + an option for you it might be a better way to go. work we've been meaning + to get to anyway. When a shared_ptr<X> + is converted from Python, the shared_ptr actually manages a reference to + the containing Python object. When a shared_ptr<X> is converted back + to Python, the library checks to see if it's one of those "Python object + managers" and if so just returns the original Python object. So you + could just write object(p) to get + the Python object back. To exploit this you'd have to be able to change the + C++ code you're wrapping so that it deals with shared_ptr instead of raw + pointers. +

+

+ There are other approaches too. The functions that receive the Python object + that you eventually want to return could be wrapped with a thin wrapper that + records the correspondence between the object address and its containing + Python object, and you could have your f_wrap function look in that mapping + to get the Python object out. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/faq/how_can_i_wrap_a_function_which0.html b/develop/doc/html/faq/how_can_i_wrap_a_function_which0.html new file mode 100644 index 00000000..fccd1e4f --- /dev/null +++ b/develop/doc/html/faq/how_can_i_wrap_a_function_which0.html @@ -0,0 +1,86 @@ + + + +How can I wrap a function which needs to take ownership of a raw pointer? + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ Q: Part of an API that I'm wrapping goes + something like this: +

+
struct A {}; struct B { void add( A* ); }
+where B::add() takes ownership of the pointer passed to it.
+
+

+ However: +

+
a = mod.A()
+b = mod.B()
+b.add( a )
+del a
+del b
+# python interpreter crashes
+# later due to memory corruption.
+
+

+ Even binding the lifetime of a to b via with_custodian_and_ward + doesn't prevent the python object a from ultimately trying to delete the + object it's pointing to. Is there a way to accomplish a 'transfer-of-ownership' + of a wrapped C++ object? +

+

+ --Bruce Lowery +

+

+ Yes: Make sure the C++ object is held by auto_ptr: +

+
class_<A, std::auto_ptr<A> >("A")
+  ...
+  ;
+
+

+ Then make a thin wrapper function which takes an auto_ptr parameter: +

+
void b_insert(B &b, std::auto_ptr<A> a)
+{
+  b.insert(a.get());
+  a.release();
+}
+
+

+ Wrap that as B.add. Note that pointers returned via manage_new_object + will also be held by auto_ptr, + so this transfer-of-ownership will also work correctly. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/faq/how_can_i_wrap_functions_which_t.html b/develop/doc/html/faq/how_can_i_wrap_functions_which_t.html new file mode 100644 index 00000000..30c8d102 --- /dev/null +++ b/develop/doc/html/faq/how_can_i_wrap_functions_which_t.html @@ -0,0 +1,120 @@ + + + +How can I wrap functions which take C++ containers as arguments? + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ Ralf W. Grosse-Kunstleve provides these notes: +

+
    +
  1. +

    + Using the regular class_<> wrapper: +

    +
    class_<std::vector<double> >("std_vector_double")
    +  .def(...)
    +  ...
    +;
    +
    + This can be moved to a template so that several types (double, int, + long, etc.) can be wrapped + with the same code. This technique is used in the file scitbx/include/scitbx/array_family/boost_python/flex_wrapper.h in the "scitbx" package. + The file could easily be modified for wrapping std::vector<> instantiations. This type of + C++/Python binding is most suitable for containers that may contain a + large number of elements (>10000). +
  2. +
  3. +

    + Using custom rvalue converters. Boost.Python "rvalue converters" + match function signatures such as: +

    +
    void foo(std::vector<double> const &array); // pass by const-reference
    +void foo(std::vector<double> array); // pass by value
    +
    + Some custom rvalue converters are implemented in the file scitbx/include/scitbx/boost_python/container_conversions.h This code can be used to convert + from C++ container types such as std::vector<> or std::list<> to Python tuples and vice versa. + A few simple examples can be found in the file scitbx/array_family/boost_python/regression_test_module.cpp + Automatic C++ container <-> Python tuple conversions are most suitable + for containers of moderate size. These converters generate significantly + less object code compared to alternative 1 above. +
  4. +
+

+ A disadvantage of using alternative 2 is that operators such as arithmetic + +,-,*,/,% are not available. It would be useful to have custom rvalue converters + that convert to a "math_array" type instead of tuples. This is + currently not implemented but is possible within the framework of Boost.Python + V2 as it will be released in the next couple of weeks. [ed.: this was posted + on 2002/03/10] +

+

+ It would also be useful to also have "custom lvalue converters" + such as std::vector<> + <-> Python list. These converters would support the modification of + the Python list from C++. For example: +

+

+ C++: +

+
void foo(std::vector<double> &array)
+{
+  for(std::size_t i=0;i&lt;array.size();i++) {
+    array[i] *= 2;
+  }
+}
+
+

+ Python: +

+
>>> l = [1, 2, 3]
+>>> foo(l)
+>>> print l
+[2, 4, 6]
+
+

+ Custom lvalue converters require changes to the Boost.Python core library + and are currently not available. +

+

+ P.S.: +

+

+ The "scitbx" files referenced above are available via anonymous + CVS: +

+
cvs -d:pserver:anonymous@cvs.cctbx.sourceforge.net:/cvsroot/cctbx login
+cvs -d:pserver:anonymous@cvs.cctbx.sourceforge.net:/cvsroot/cctbx co scitbx
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/faq/how_do_i_create_sub_packages_usi.html b/develop/doc/html/faq/how_do_i_create_sub_packages_usi.html new file mode 100644 index 00000000..94e5d67e --- /dev/null +++ b/develop/doc/html/faq/how_do_i_create_sub_packages_usi.html @@ -0,0 +1,41 @@ + + + +How do I create sub-packages using Boost.Python? + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ Please refer to the Creating Packages section in the Tutorial. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/faq/how_do_i_debug_my_python_extensi.html b/develop/doc/html/faq/how_do_i_debug_my_python_extensi.html new file mode 100644 index 00000000..0269072b --- /dev/null +++ b/develop/doc/html/faq/how_do_i_debug_my_python_extensi.html @@ -0,0 +1,151 @@ + + + +How do I debug my Python extensions? + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ Greg Burley gives the following answer for Unix GCC users: +

+
+

+ Once you have created a boost python extension for your c++ library or + class, you may need to debug the code. Afterall this is one of the reasons + for wrapping the library in python. An expected side-effect or benefit + of using BPL is that debugging should be isolated to the c++ library that + is under test, given that python code is minimal and boost::python either + works or it doesn't. (ie. While errors can occur when the wrapping method + is invalid, most errors are caught by the compiler ;-). +

+

+ The basic steps required to initiate a gdb session to debug a c++ library + via python are shown here. Note, however that you should start the gdb + session in the directory that contains your BPL my_ext.so module. +

+
(gdb) target exec python
+(gdb) run
+>>> from my_ext import *
+>>> [C-c]
+(gdb) break MyClass::MyBuggyFunction
+(gdb) cont
+>>> pyobj = MyClass()
+>>> pyobj.MyBuggyFunction()
+Breakpoint 1, MyClass::MyBuggyFunction ...
+Current language:  auto; currently c++
+(gdb) do debugging stuff
+
+
+

+ Greg's approach works even better using Emacs' "gdb" command, since + it will show you each line of source as you step through it. +

+

+ On Windows, my favorite debugging solution + is the debugger that comes with Microsoft Visual C++ 7. This debugger seems + to work with code generated by all versions of Microsoft and Metrowerks toolsets; + it's rock solid and "just works" without requiring any special + tricks from the user. +

+

+ Raoul Gough has provided the following for gdb on Windows: +

+
+

+ gdb support for Windows DLLs has improved lately, so it is now possible + to debug Python extensions using a few tricks. Firstly, you will need an + up-to-date gdb with support for minimal symbol extraction from a DLL. Any + gdb from version 6 onwards, or Cygwin gdb-20030214-1 and onwards should + do. A suitable release will have a section in the gdb.info file under Configuration + - Native - Cygwin Native - Non-debug DLL symbols. Refer to that info section + for more details of the procedures outlined here. +

+

+ Secondly, it seems necessary to set a breakpoint in the Python interpreter, + rather than using ^C to break execution. A good place to set this breakpoint + is PyOS_Readline, which will stop execution immediately before reading + each interactive Python command. You have to let Python start once under + the debugger, so that it loads its own DLL, before you can set the breakpoint: +

+
$ gdb python
+GNU gdb 2003-09-02-cvs (cygwin-special)
+[...]
+
+(gdb) run
+Starting program: /cygdrive/c/Python22/python.exe
+Python 2.2.2 (#37, Oct 14 2002, 17:02:34) [MSC 32 bit (Intel)] on win32
+Type "help", "copyright", "credits" or "license" for more information.
+>>> ^Z
+
+
+Program exited normally.
+(gdb) break *&PyOS_Readline
+Breakpoint 1 at 0x1e04eff0
+(gdb) run
+Starting program: /cygdrive/c/Python22/python.exe
+Python 2.2.2 (#37, Oct 14 2002, 17:02:34) [MSC 32 bit (Intel)] on win32
+Type "help", "copyright", "credits" or "license" for more information.
+
+Breakpoint 1, 0x1e04eff0 in python22!PyOS_Readline ()
+   from /cygdrive/c/WINNT/system32/python22.dll
+(gdb) cont
+Continuing.
+>>> from my_ext import *
+
+Breakpoint 1, 0x1e04eff0 in python22!PyOS_Readline ()
+   from /cygdrive/c/WINNT/system32/python22.dll
+(gdb) # my_ext now loaded (with any debugging symbols it contains)
+
+
+

+ + Debugging + extensions through Boost.Build +

+

+ If you are launching your extension module tests with Boost.Build + using the boost-python-runtest rule, you can ask it to launch + your debugger for you by adding "--debugger=debugger" + to your bjam command-line: +

+
bjam -sTOOLS=vc7.1 "--debugger=devenv /debugexe" test
+bjam -sTOOLS=gcc -sPYTHON_LAUNCH=gdb test
+
+

+ It can also be extremely useful to add the -d+2 + option when you run your test, because Boost.Build will then show you the + exact commands it uses to invoke it. This will invariably involve setting + up PYTHONPATH and other important environment variables such as LD_LIBRARY_PATH + which may be needed by your debugger in order to get things to work right. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/faq/i_m_getting_the_attempt_to_retur.html b/develop/doc/html/faq/i_m_getting_the_attempt_to_retur.html new file mode 100644 index 00000000..0d8593aa --- /dev/null +++ b/develop/doc/html/faq/i_m_getting_the_attempt_to_retur.html @@ -0,0 +1,67 @@ + + + +I'm getting the "attempt to return dangling reference" error. What am I doing wrong? + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ That exception is protecting you from causing a nasty crash. It usually happens + in response to some code like this: +

+
period const &get_floating_frequency() const
+{
+  return boost::python::call_method<period const &>(
+    m_self,"get_floating_frequency");
+}
+
+

+ And you get: +

+
ReferenceError: Attempt to return dangling reference to object of type:
+class period
+
+

+ In this case, the Python method invoked by call_method + constructs a new Python object. You're trying to return a reference to a + C++ object (an instance of class period) contained within and owned by that + Python object. Because the called method handed back a brand new object, + the only reference to it is held for the duration of get_floating_frequency() above. When the function returns, the Python + object will be destroyed, destroying the instance of class + period, and leaving the returned + reference dangling. That's already undefined behavior, and if you try to + do anything with that reference you're likely to cause a crash. Boost.Python + detects this situation at runtime and helpfully throws an exception instead + of letting you do that. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/faq/is_boost_python_thread_aware_com.html b/develop/doc/html/faq/is_boost_python_thread_aware_com.html new file mode 100644 index 00000000..dd5cba66 --- /dev/null +++ b/develop/doc/html/faq/is_boost_python_thread_aware_com.html @@ -0,0 +1,60 @@ + + + +Is Boost.Python thread-aware/compatible with multiple interpreters? + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ Niall Douglas provides these notes: +

+

+ The quick answer to this is: no. +

+

+ The longer answer is that it can be patched to be so, but it's complex. You + will need to add custom lock/unlock wrapping of every time your code enters + Boost.Python (particularly every virtual function override) plus heavily + modify boost/python/detail/invoke.hpp with custom unlock/lock wrapping of + every time Boost.Python enters your code. You must furthermore take care + to not unlock/lock when Boost.Python is invoking iterator + changes via invoke.hpp. +

+

+ There is a patched invoke.hpp posted + on the C++-SIG mailing list archives and you can find a real implementation + of all the machinery necessary to fully implement this in the TnFOX project + at this SourceForge + project location. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/faq/is_return_internal_reference_eff.html b/develop/doc/html/faq/is_return_internal_reference_eff.html new file mode 100644 index 00000000..52e80222 --- /dev/null +++ b/develop/doc/html/faq/is_return_internal_reference_eff.html @@ -0,0 +1,62 @@ + + + +Is return_internal_reference efficient? + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ Q: /I have an object composed of 12 doubles. + A const& + to this object is returned by a member function of another class. From the + viewpoint of using the returned object in Python I do not care if I get a + copy or a reference to the returned object. In Boost.Python I have the choice + of using copy_const_reference + or return_internal_reference. + Are there considerations that would lead me to prefer one over the other, + such as size of generated code or memory overhead?/ +

+

+ A: copy_const_reference + will make an instance with storage for one of your objects, size = base_size + 12 * sizeof(double). + return_internal_reference + will make an instance with storage for a pointer to one of your objects, + size = + base_size + + sizeof(void*). However, + it will also create a weak reference object which goes in the source object's + weakreflist and a special callback object to manage the lifetime of the internally-referenced + object. My guess? copy_const_reference + is your friend here, resulting in less overall memory use and less fragmentation, + also probably fewer total cycles. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/faq/why_doesn_t_my_operator_work.html b/develop/doc/html/faq/why_doesn_t_my_operator_work.html new file mode 100644 index 00000000..34b31e11 --- /dev/null +++ b/develop/doc/html/faq/why_doesn_t_my_operator_work.html @@ -0,0 +1,63 @@ + + + +Why doesn't my *= operator work? + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ Q: I have exported my class to + python, with many overloaded operators. it works fine for me except the + *= operator. It always tells + me "can't multiply sequence with non int type". If I use p1.__imul__(p2) + instead of p1 *= + p2, it successfully executes my + code. What's wrong with me? +

+

+ A: There's nothing wrong with you. This + is a bug in Python 2.2. You can see the same effect in Pure Python (you can + learn a lot about what's happening in Boost.Python by playing with new-style + classes in Pure Python). +

+
>>> class X(object):
+...     def __imul__(self, x):
+...         print 'imul'
+...
+>>> x = X()
+>>> x *= 1
+
+

+ To cure this problem, all you need to do is upgrade your Python to version + 2.2.1 or later. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/faq/why_is_my_automatic_to_python_co.html b/develop/doc/html/faq/why_is_my_automatic_to_python_co.html new file mode 100644 index 00000000..9e1367a2 --- /dev/null +++ b/develop/doc/html/faq/why_is_my_automatic_to_python_co.html @@ -0,0 +1,67 @@ + + + +Why is my automatic to-python conversion not being found? + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ Niall Douglas provides these notes: +

+

+ If you define custom converters similar to the ones shown above the def_readonly() + and def_readwrite() + member functions provided by boost::python::class_ + for direct access to your member data will not work as expected. This is + because def_readonly("bar",&foo::bar) is equivalent to: +

+
.add_property("bar", make_getter(&foo::bar, return_internal_reference()))
+
+

+ Similarly, def_readwrite("bar",&foo::bar) + is equivalent to: +

+
.add_property("bar", make_getter(&foo::bar, return_internal_reference()),
+                   make_setter(&foo::bar, return_internal_reference())
+
+

+ In order to define return value policies compatible with the custom conversions + replace def_readonly() + and def_readwrite() + by add_property(). + E.g.: +

+
.add_property("bar", make_getter(&foo::bar, return_value_policy<return_by_value>()),
+                   make_setter(&foo::bar, return_value_policy<return_by_value>()))
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/glossary.html b/develop/doc/html/glossary.html new file mode 100644 index 00000000..02d033e6 --- /dev/null +++ b/develop/doc/html/glossary.html @@ -0,0 +1,81 @@ + + + +Chapter 5. Glossary + + + + + + + +
+
+
+PrevUpHome +
+
+

+Chapter 5. Glossary

+
+

+
+
arity
+

+ The number of argumnts accepted by a function or member function. Unless + otherwise specified, the hidden this + argument to member functions is not counted when specifying arity. +

+
ntbs
+

+ Null-Terminated Byte String, or 'C'-string. C++ string literals are + ntbses. An ntbs + must never be null. +

+
raise
+

+ Exceptions in Python are "raised", not "thrown", + as they are in C++. When this documentation says that some Python exception + is "raised" in the context of C++ code, it means that the corresponding + Python exception is set via the Python/'C' + API, and throw_error_already_set() is called. +

+
POD
+

+ A technical term from the C++ standard. Short for "Plain Ol'Data": + A POD-struct is an aggregate class that has no non-static data members + of type pointer to member, non-POD-struct, non-POD-union (or array of + such types) or reference, and has no user-defined copy assign- ment operator + and no user-defined destructor. Similarly, a POD-union is an aggregate + union that has no non-static data members of type pointer to member, + non-POD-struct, non-POD-union (or array of such types) or reference, + and has no user-defined copy assignment operator and no user-defined + destructor. A POD class is a class that is either a POD-struct or a POD-union. + An aggregate is an array or a class (clause 9) with no user-declared + constructors (12.1), no private or protected non-static data members + (clause 11), no base classes (clause 10), and no virtual functions (10.3). +

+
ODR
+

+ The "One Definition Rule", which says that any entity in a + C++ program must have the same definition in all translation units (object + files) which make up a program. +

+
+
+
+ + + +
+
+
+PrevUpHome +
+ + diff --git a/develop/doc/html/images/alert.png b/develop/doc/html/images/alert.png new file mode 100644 index 0000000000000000000000000000000000000000..b4645bc7e7cd81f2818bf22aa898e95f89f7b154 GIT binary patch literal 603 zcmeAS@N?(olHy`uVBq!ia0y~yV31^BU=ZVAW?*1oN<7}ez`(#Bl2vQw%VQUVy#($c(b7<_!Z&&*`7 zwYIFTuIA!kP?6(!`t<3^g$y0J3{Q73WQH(YSjJ#(AQj-}VXe>LZ_gkv$q?hiVP&Xj ztS4or%^)MjpsB?1|Nnp9pi5p13=F0vL4Lvi$p8#BTQ7jZgtNdSvY3H^>jMZgI;}C8 z!N9FSxfgB=H7N+NC77H_+N#nawR{=RqTMBX)(LXL|IjinhDSdCyWWZ3S$0kBOZbahGm>{cU3L4X z*xaKNrl+L*2&>`tT{GF}sK6TCoSy58@94C>csZ@3se0z)OD!J`ePg?KNk!eRu!nuZ zwIuy5g5`UyU*2!`JMiPV^UIVvmW1t{f1*^~1#9h_jDIZO*R6JmbN8&QBXd?)zY=(& z`HG+Mis#k2-hNM1nwI_8efYU@yAuCZhY42|Be;Juo!svFUA16}A_D^hgQu&X%Q~lo FCIA+53ZVc1 literal 0 HcmV?d00001 diff --git a/develop/doc/html/images/blank.png b/develop/doc/html/images/blank.png new file mode 100644 index 0000000000000000000000000000000000000000..764bf4f0c3bb4a09960b04b6fa9c9024bca703bc GIT binary patch literal 374 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 literal 0 HcmV?d00001 diff --git a/develop/doc/html/images/bpl.png b/develop/doc/html/images/bpl.png new file mode 100644 index 0000000000000000000000000000000000000000..c2d8c69e00ca3aada62024809e20d138a8906875 GIT binary patch literal 21289 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 +image/svg+xmlBoost.Python + \ No newline at end of file diff --git a/develop/doc/html/images/callouts/1.png b/develop/doc/html/images/callouts/1.png new file mode 100644 index 0000000000000000000000000000000000000000..6003ad3af44ecde89a963d5af6a4180217319dfb GIT binary patch literal 391 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`*F|>EaktF{gKeVcsDJ z0oVU;*6~a;Smx2ZrsEQ?ZxM&ygvBnFE?nmtg94rky>!~x8m)3j$<^(USQPg)>&zq; zMi;kRX=V2=&tIr>`d!)XyUpL@9=UmHetuZ+!_#HmOU>-J$pS3-bN!ardIyAF-G1#? z>&)f7E`k#|4sWoP;JM|(l6I_WZ`%~1y>agujE%b%?TB9+mb}(fsxyPFgQGMy*=%;A z(aZyu>`GQPiY$*T-1gu1pAwY3_N%b5cB#xoiRPn8jf*q{Trb|_a%sui&dtzin6_r? zu}%d~p(mAmOGTO#c2u;xJ(}Y^?ex>t7XL(?7U+1p1hOa|ab;w%c)sCoo@_(^WX<=s zr#89B91nl^w~jx#=XQ?S<*?OXYm`>JmO9g8;`^U+STt2<{M7jt yFTo&UT%Db3I{*CoWB+`guig6oxB + + + +]> + + + + + + + + diff --git a/develop/doc/html/images/callouts/10.png b/develop/doc/html/images/callouts/10.png new file mode 100644 index 0000000000000000000000000000000000000000..0426f516a497db7f9a989ae412c381123c882a59 GIT binary patch literal 485 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`(f1)5S5QVovKM!_~JE zMB47_a|Rw%VTn}{6Ibo_{>?on>HF_suX>mE-_|+p)}_VbyG%XWRxDs!Bbdb`rSkCf z_opQpQ)e&z9?Q3;X^2drllMU70&71c8CwuJm{abIp zeHPuYNTZJ3@x#oHxOW1*hRe1@t$mhYkYRMp!NudU$f{L`HtEbcpPpkT-Q%WwW82?% zC04fVjt$l>J1E5m&cv;Mo-ym249h`b!OT;yI|^kU z7g#)~+Iz@=rzNo?Z+rL2lqSFB&0ni{FPmfwyfr;gD5K)Z38R1FYejhuGSfQP|hTIvQJ?m5M8zE|_KJ2Ny0Fm1o>%kU%6J0MhalaBNL z`|XP~Ht29?&a!*3EqAew_mM&!z3HdD7hn7l!t9~x=u!|XzH8m#&o*bC7c(?GuT1E< zIxY74U)KBI?en(Zj`8vg@_IC9@{~!dRw-$!in=2h%i uo%h^T#Pz@K#3`Fjeg5 + + + +]> + + + + + + + + + diff --git a/develop/doc/html/images/callouts/11.png b/develop/doc/html/images/callouts/11.png new file mode 100644 index 0000000000000000000000000000000000000000..821afc4fa84787cc97485b71e9f2078f45c93dca GIT binary patch literal 410 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`&U3>EaktF{gFX#;)5A z0&V{%irr-ME}D3(<3UjG?A^;f=DTxNc8JvRJ?~omN$9208L_ft0gE{24F|>2&Q_(X zyZRk}S@Y!IJLwtuX$cuSW9kad-E9>}+B4ar@B8JKU&IA}ZdvzvdHazWz|5Z1g ze)`Eh`){a=Ty&?>q6`CxFY1#$=XWS5S;+8pJeF8|am8VmFNNE0pWSjTLp3m4UCF?B z)v7}^cJ1H)wSBfZUSXp*CCGT~*L1 z!O^woK;8cKATG~IcM5iAPD}l8PyF`VZ_(}ou7b0cInG+vv8ev~-ZX{}_a4{SRWsNx zp57$DG;5jTyyy8w3^D7&C6fPqtf+bOwJP3 + + + +]> + + + + + + + + + diff --git a/develop/doc/html/images/callouts/12.png b/develop/doc/html/images/callouts/12.png new file mode 100644 index 0000000000000000000000000000000000000000..7cec72720fa9bb6f49fc4b405f7e36f20abe7fbd GIT binary patch literal 488 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`(fP)5S5QVovKM+tara zMB3h~S9S>cC`GVy&NA$7e!FZ3*ZX_(gMKMn{jgqg*t>n5-mVwdc+LxmI|e9UlrZu5 zQ({_ROHtjRNV$1z%lk=bT+YJ`-QVnLY|jT_oBf)`qRPnx(gN%Xx|4tEMdaVwoi3 z8lgAcLau*<4)^ratatOor+TqI{wNVS?clathJwW!uZ)j$%&5q+Ew{P&-MZ_q|3(_ifRH$!b{%@XfPPgvO) wR!x~yId8sr_tEzopr0G&e8k^lez literal 0 HcmV?d00001 diff --git a/develop/doc/html/images/callouts/12.svg b/develop/doc/html/images/callouts/12.svg new file mode 100644 index 00000000..9794044c --- /dev/null +++ b/develop/doc/html/images/callouts/12.svg @@ -0,0 +1,18 @@ + + + + +]> + + + + + + + + + diff --git a/develop/doc/html/images/callouts/13.png b/develop/doc/html/images/callouts/13.png new file mode 100644 index 0000000000000000000000000000000000000000..5b41e02a670f020ae62b7854482c4ba1980d73cf GIT binary patch literal 509 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`%IK)5S5QVovKN`}4B` zMA$w&XL9s;aOlF(1%)YvneO4jm-o(&U;MKD#e?Mq8+>b)^R3G((>5$`ILflv=tsMT zqri^uWh?XJrteF)Ir(#L@uYSZ#}5m2PWL-;h`yh)YSr?%_21hCg6ylJ<~^TZ68k@M z*0PUs0U}2m4Zrz%{ru!$;?!{|$E-JRd$xd+!qOu@YuZ+=+K?-K{IOu7#Gy?(C029K zJuHwgKK8+3O1mEi<8zsP?~|?OE?SqZ;@R}Hh*OcJN#Q`=cIVYsi%fl`jgRf~&@_Gf zwzE(sdH3B%ReKL@(z)}#{LAm!8Ou74CNVNBn8MT`ef;AL!#4E;rLlAT)H7zW#a>U8 zU^AP|o3>d}=J>$`0|rHwDM43C-@g0)`~9hChd_}fnOvtgEzsbyc%HHSwnVR+$0Qaf z4hDzV>nAp?Vf*l#Q@}~VH~7Z3-c_p%=AWOKD!ECAd8tU(q6Mq8jughk>rJ2Tw)o@M zm#pV3mrVI!!@p|Pp+XrSHQ@j+Lm56tj!LO-Hu>!LzuT|B{(4Tap5^mRI^HKOr#o>( zhECmcH*b>$SLC#%J&RUEtqrq3WKa^{tg=+3a-Mjg$X|1pImHv7|6G6l?EhE#0)GDv Vq@B#jVqjok@O1TaS?83{1OO3{ + + + +]> + + + + + + + + + diff --git a/develop/doc/html/images/callouts/14.png b/develop/doc/html/images/callouts/14.png new file mode 100644 index 0000000000000000000000000000000000000000..de5bdbd3eb8be01d27b6f1a345d586d0c4d61b2a GIT binary patch literal 499 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`(f6)5S5QVovL&ji+t} zh_HY7zn8PK$&+QbhfZH4OXk6oR~J^xFa4ru^@GK(LHCDmEpzN0DV1hDCj-+7ZjQ+v zYTxf&UV7^JrT0DT=ibj@uHP27{{Ga|pN^VKANF1{d3)jY*E+*vNA@lkcl~(Lphv#f zZSgm;g1vG7SsXu1?TCBVaZcj#*Q&kO-j-$e7zzmX9alE-b>4iFg+V~@k_l_W_wBcH zWmp*BaqNHHW9Xsz@VDKv%bG0$2|bO5Z6>~kGkrGPetRKrdu;6W&)@+-S^-5e@qWpx=%~ppu-*HbtcU?B((KtQse2TO*ZEl8Jswt zRO&J4%x73CvPq};vBd=w-op^F6<=oH98=hD0fB5^~^0#Ht9-5wBo~e + + + +]> + + + + + + + + + diff --git a/develop/doc/html/images/callouts/15.png b/develop/doc/html/images/callouts/15.png new file mode 100644 index 0000000000000000000000000000000000000000..3fd6ac38603390bf6f9bbfdb85ddb203e2edc421 GIT binary patch literal 507 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`%IO)5S5QVovL&-F>$L z1lS(@e{k6MP=#(Q)65P&Df1-{87Bltt+Mf&((ZAvc!Ef@>!Js&9H9b5iNOkrjBYL6 zJ*_!sB>iV?h@ACiit<@=<+J)R*K4P%cxw9w^X5-kmdSp5TRo@ZmA&eVHGWMv{dC`S zuce2g9b}I0mp%UT(3$h)E?kO6N0T-NtiR6f#9?6EcU;-Tw>eSb#{2IdZ1@=hR$sjr zzyA8Z#}+%3XYST(VGvBTnww-G;h@R7RHW^&qTY1wDM1E2%vZCnP73-ad;I5-GeP_8 zE`G0F6Q(`qeEN%Bd`m@QuDc4b82Acr%ROx3%dny5{(I}bX7&S{bY%G0Jv1kte!3xU z{l(W`FJx^snCW9M|9s%ekN~~u3#V){n|<~=yTas?3Ovp)cJVPNC~di&>!G + + + +]> + + + + + + + + + diff --git a/develop/doc/html/images/callouts/16.svg b/develop/doc/html/images/callouts/16.svg new file mode 100644 index 00000000..01d6bf81 --- /dev/null +++ b/develop/doc/html/images/callouts/16.svg @@ -0,0 +1,20 @@ + + + + +]> + + + + + + + + + diff --git a/develop/doc/html/images/callouts/17.svg b/develop/doc/html/images/callouts/17.svg new file mode 100644 index 00000000..0a04c556 --- /dev/null +++ b/develop/doc/html/images/callouts/17.svg @@ -0,0 +1,17 @@ + + + + +]> + + + + + + + + + diff --git a/develop/doc/html/images/callouts/18.svg b/develop/doc/html/images/callouts/18.svg new file mode 100644 index 00000000..1cb891b3 --- /dev/null +++ b/develop/doc/html/images/callouts/18.svg @@ -0,0 +1,21 @@ + + + + +]> + + + + + + + + + diff --git a/develop/doc/html/images/callouts/19.svg b/develop/doc/html/images/callouts/19.svg new file mode 100644 index 00000000..e6fbb179 --- /dev/null +++ b/develop/doc/html/images/callouts/19.svg @@ -0,0 +1,20 @@ + + + + +]> + + + + + + + + + diff --git a/develop/doc/html/images/callouts/2.png b/develop/doc/html/images/callouts/2.png new file mode 100644 index 0000000000000000000000000000000000000000..f7c1578846cd7e67f148e7bbe3178ec170050e48 GIT binary patch literal 446 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`)q*>EaktF{gFH!7eFB zfwuoy?SYP89?67Uc^u>7$ueKD;_TuU8yCKP?%y^nk6}6Q`Xb ztf|`>GH3mp6jYb?>^RdSfr%@^R!^go|6uIuQi$NDW>upBo%&=x}fma9VINW5Ly|Qkmm3JvHr(Hb1rr&)I%k zqW}1XsO0Up4@Uid#O=~jwU>`!u0>yZkk=jF7J(OKyBQi3I1HqEAMAR!+FC^5{Aa5( zf1b8B8nUgv%H`5>GKER;h_=JWcU60(815ha{H$oF%dBM*eC_{b&TZl;l$m|{>8A+2 z>GpSd7ik$I?GB%onzMHA^lP*F zk0)=tnX|7g@rLFCKI7=6AyTdvVl+z`(%Z>FVdQ I&MBb@0M`i8D*ylh literal 0 HcmV?d00001 diff --git a/develop/doc/html/images/callouts/2.svg b/develop/doc/html/images/callouts/2.svg new file mode 100644 index 00000000..07d03395 --- /dev/null +++ b/develop/doc/html/images/callouts/2.svg @@ -0,0 +1,17 @@ + + + + +]> + + + + + + + + diff --git a/develop/doc/html/images/callouts/20.svg b/develop/doc/html/images/callouts/20.svg new file mode 100644 index 00000000..ccbfd403 --- /dev/null +++ b/develop/doc/html/images/callouts/20.svg @@ -0,0 +1,20 @@ + + + + +]> + + + + + + + + + diff --git a/develop/doc/html/images/callouts/21.svg b/develop/doc/html/images/callouts/21.svg new file mode 100644 index 00000000..93ec53fd --- /dev/null +++ b/develop/doc/html/images/callouts/21.svg @@ -0,0 +1,18 @@ + + + + +]> + + + + + + + + + diff --git a/develop/doc/html/images/callouts/22.svg b/develop/doc/html/images/callouts/22.svg new file mode 100644 index 00000000..f48c5f3f --- /dev/null +++ b/develop/doc/html/images/callouts/22.svg @@ -0,0 +1,20 @@ + + + + +]> + + + + + + + + + diff --git a/develop/doc/html/images/callouts/23.svg b/develop/doc/html/images/callouts/23.svg new file mode 100644 index 00000000..66242129 --- /dev/null +++ b/develop/doc/html/images/callouts/23.svg @@ -0,0 +1,22 @@ + + + + +]> + + + + + + + + + diff --git a/develop/doc/html/images/callouts/24.svg b/develop/doc/html/images/callouts/24.svg new file mode 100644 index 00000000..a3d55253 --- /dev/null +++ b/develop/doc/html/images/callouts/24.svg @@ -0,0 +1,19 @@ + + + + +]> + + + + + + + + + diff --git a/develop/doc/html/images/callouts/25.svg b/develop/doc/html/images/callouts/25.svg new file mode 100644 index 00000000..56614a97 --- /dev/null +++ b/develop/doc/html/images/callouts/25.svg @@ -0,0 +1,21 @@ + + + + +]> + + + + + + + + + diff --git a/develop/doc/html/images/callouts/26.svg b/develop/doc/html/images/callouts/26.svg new file mode 100644 index 00000000..56faeaca --- /dev/null +++ b/develop/doc/html/images/callouts/26.svg @@ -0,0 +1,22 @@ + + + + +]> + + + + + + + + + diff --git a/develop/doc/html/images/callouts/27.svg b/develop/doc/html/images/callouts/27.svg new file mode 100644 index 00000000..a75c8121 --- /dev/null +++ b/develop/doc/html/images/callouts/27.svg @@ -0,0 +1,19 @@ + + + + +]> + + + + + + + + + diff --git a/develop/doc/html/images/callouts/28.svg b/develop/doc/html/images/callouts/28.svg new file mode 100644 index 00000000..7f8cf1a3 --- /dev/null +++ b/develop/doc/html/images/callouts/28.svg @@ -0,0 +1,23 @@ + + + + +]> + + + + + + + + + diff --git a/develop/doc/html/images/callouts/29.svg b/develop/doc/html/images/callouts/29.svg new file mode 100644 index 00000000..cb63adf1 --- /dev/null +++ b/develop/doc/html/images/callouts/29.svg @@ -0,0 +1,22 @@ + + + + +]> + + + + + + + + + diff --git a/develop/doc/html/images/callouts/3.png b/develop/doc/html/images/callouts/3.png new file mode 100644 index 0000000000000000000000000000000000000000..3ff0a93931515bb97a045dfa61a8530d87e458fd GIT binary patch literal 431 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`$7M>EaktF{gFH*{(+p zB5wOOu6l7m)8 z=-oKUH}V^&iJyB|uo8LF()AHB5)-MfO`N3nt zvX}OXM~sd8*9*0GtV!A!kzpdmy4F;zn{|?kqeR<^5G@5I1_ong&q>Sg=9!B)JHv7pU)=hauMINB3;oaL&ye>}mU!H{id4Bxig=9%^>^=*s?64R8I`k2o? pd-p8Ef~{sjr?y8+Fx+F*x_2OD_kw447#J8BJYD@<);T3K0RY@Tw*mkF literal 0 HcmV?d00001 diff --git a/develop/doc/html/images/callouts/3.svg b/develop/doc/html/images/callouts/3.svg new file mode 100644 index 00000000..918be806 --- /dev/null +++ b/develop/doc/html/images/callouts/3.svg @@ -0,0 +1,19 @@ + + + + +]> + + + + + + + + diff --git a/develop/doc/html/images/callouts/30.svg b/develop/doc/html/images/callouts/30.svg new file mode 100644 index 00000000..dc43ba1e --- /dev/null +++ b/develop/doc/html/images/callouts/30.svg @@ -0,0 +1,22 @@ + + + + +]> + + + + + + + + + diff --git a/develop/doc/html/images/callouts/4.png b/develop/doc/html/images/callouts/4.png new file mode 100644 index 0000000000000000000000000000000000000000..6aa29fc0b48c17aa6ce5540e1af5c00510c33ff7 GIT binary patch literal 441 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`)qx>EaktF{gFH#x5mC zfwup%GG$o)=ergqP)_hu?Cbmc-FuV6=PTSkE z?z;W`K`XyJWKnY38^_LI-}iXo6rn{K^Ugm{NGsVLTQQIQc;ScrMIF~}*~{?xZ|}UC z)%voeOU2Vbu7Bb(%{5!g=daxAHc3V5z+>?E76HlSc>&q{{ zJgU5>EY^K=``x_dYqp*_vnNK+lE-=9auZ+6u0=XLho7HKd(8afJ98Qv1B>H_g?h*I z^7xt(_!*jJt_^x6<$Ce%iJd)$VVYl~OqdVEFZF#=7-s1t%fP_E;OXk;vd$@?2>|9n B#bp2h literal 0 HcmV?d00001 diff --git a/develop/doc/html/images/callouts/4.svg b/develop/doc/html/images/callouts/4.svg new file mode 100644 index 00000000..8eb6a53b --- /dev/null +++ b/develop/doc/html/images/callouts/4.svg @@ -0,0 +1,16 @@ + + + + +]> + + + + + + + + diff --git a/develop/doc/html/images/callouts/5.png b/develop/doc/html/images/callouts/5.png new file mode 100644 index 0000000000000000000000000000000000000000..36e785867ad9b06bb5da296fee61b67cd8159ded GIT binary patch literal 423 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`&U2>EaktF{gFn*{nkj zBCY4o9LZ47@QCRUnZAf+N!}-g*k62kUh<2$=N}3cU-wJsu7~Tf`D?j51GwEfg_G2_ zuV#t97&qf=>*tSit#h_USr*FJFU!>WaGpbPU+ne2DLtw;&jomW^|@TLId}ILd4;Y; z`kGI<1$&J<4oW?f4p9*ch$x|rP+;KqSwET0Ksa~vKtM(>J91HOJ>EhB>xN^tsw+8di7uv`rMqUeL zJtlGLsS$%o&3$<<&56<(YY$o;PcU%UfB(F1o@3V5sOFBi;${Vo2fOrSjvstkva9-x zil;zZBGUt9^BXy4GknxI4hvj-p!#HTV6S6ePsEk3N^VkheYYwwc>v z!48gj&!5^CXy3`&YF5dr$YOKedHr?gg#ir$OfFx%f9Fdu@F;mr4Z2vhci-*k?73P? f@97_A_`n?SY~RWh)zCHu1_lOCS3j3^P6 + + + +]> + + + + + + + + diff --git a/develop/doc/html/images/callouts/6.png b/develop/doc/html/images/callouts/6.png new file mode 100644 index 0000000000000000000000000000000000000000..c943676beafa0562916b058c169951febcd3cddb GIT binary patch literal 431 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`$7M>EaktF{gFH{#8D;%7vjax1W#KXIAnv(J`n z&5VyM+63~m6_r{NIT!+`rAn_gmE-I&+!3QUA?T1q^ClfZ7RG!2%96cqg2wgyaq?lS zMX$X!U8LbO@45W6mvfv$L-`J@Z+FmS&DLGD$|-VMfY)E~efQs=*mUM;<-bcWOZM5Z zTz)B%D3P@Lt`d*4kJ{wr1(Q_j + + + +]> + + + + + + + + diff --git a/develop/doc/html/images/callouts/7.png b/develop/doc/html/images/callouts/7.png new file mode 100644 index 0000000000000000000000000000000000000000..20940de30d2146b73118a08905955162fe985f68 GIT binary patch literal 397 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`z*d>EaktF{gLJ{wyX( zf%f{%yMM5|1Qs>DxO#n#YtRpleGYL4%{eMNMC?4cR!{jhN$+gat*(bhBwQW8eR)?F zba$a+^0L_vzt^7O@l~6=`|-z${Iyee1O}bTzyIC7L&Goql*H!=r=P}oFAaJ)O@ZgI z{@Sm`#{5B@N=kt`V%+OqiyeDxcc)!#?*L7k5+eADVIg?*L>hpfK3x*)1hCVBt; z;|%wV8@Gym{wcFIjN7SWb%BU0N0Y+6yzR|3cK@fSPF7(wKKyx4{o#4fYt#Iv1TDJ# z*2#-AZQqV>`4S8w#?i?>7PHU(+hgr1l-*Nl-OBiY{af+c^=0Sh`7 + + + +]> + + + + + + + + diff --git a/develop/doc/html/images/callouts/8.png b/develop/doc/html/images/callouts/8.png new file mode 100644 index 0000000000000000000000000000000000000000..d8e34d4a09f6dca4f9c22e626d9f9d82b969b02c GIT binary patch literal 434 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`$7P>EaktF{kyy#=ct) z0&EZJryZ5xyvdOv(510`p{HDvlxC~E$|>iVgULHQ3PYvrom?h2P4(>+k=FEToVfLb z-1}ul4-dV}J2m&O{aGGazV^u2>+);2+U^P78~6Tv*4AI1E_e2NCZAD1|9M}poAQ6# z2UUCjU5lzOJ!f0qp`v6c!}s@T(aY_*-6p<)(^RJf%{ZH;pv2Hn%$FKjXEE0=dabFI zOUbTczTJ2ED(5xNoT$P%L(+vssY!q-Q6kB1zW$Oa(QCh^Kc6#2_JRrTx8JslG@1mM zBBvdU`kln8=_3m^%&og1Cq^RrH#tzmz{IfafeFfcH9y85}Sb4q9e0BP^KrT_o{ literal 0 HcmV?d00001 diff --git a/develop/doc/html/images/callouts/8.svg b/develop/doc/html/images/callouts/8.svg new file mode 100644 index 00000000..c1803a3c --- /dev/null +++ b/develop/doc/html/images/callouts/8.svg @@ -0,0 +1,20 @@ + + + + +]> + + + + + + + + diff --git a/develop/doc/html/images/callouts/9.png b/develop/doc/html/images/callouts/9.png new file mode 100644 index 0000000000000000000000000000000000000000..abe636072b61306fbcd6157b95dfdf7e86a77e5d GIT binary patch literal 420 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`&U8>EaktF{gEcf7T%f znb!OIl8YM`EC?0g)MK6LySsR*bBW@-#a{$sD|jaA?Rq5|BVw*<(2>_Fw2;L_Ls+eT z*=m-pP5G8*zMrjje*N{AqvqEc&v$lO8~PeQnNu$u7&XUG^XcT&$oGAZue{@YWbseb zX;0Q#doE68rNi6aM(w}9J~guKY8ESl1YdhX&(saqqyj~D?!KF+)#9L-_*{J2Y1Ks< zObjyp?mceG5^anO3Q8tYyaIvx98EzeZXaKe_`Z|7b6wRX+{3FhZAn{V<2dEM9+du_kptYsE+ z{WKfa2W_~S^T2{nZ8E1=H*3uG*3`)V4^%t_SRAV?Wb9U5edYbrW%=bs0jAGCWzMDv z&-uLjLxRB%P3bLBx;@8}pH%jFEoHiFvT*CZ6}7y~440#x2c4?eefQp-XqD5OV!VD< d@-ZKf|NC_Jf+y*vd<+Z>44$rjF6*2UngH>Mv>N~b literal 0 HcmV?d00001 diff --git a/develop/doc/html/images/callouts/9.svg b/develop/doc/html/images/callouts/9.svg new file mode 100644 index 00000000..bc149d3c --- /dev/null +++ b/develop/doc/html/images/callouts/9.svg @@ -0,0 +1,19 @@ + + + + +]> + + + + + + + + diff --git a/develop/doc/html/images/caution.png b/develop/doc/html/images/caution.png new file mode 100644 index 0000000000000000000000000000000000000000..5b7809ca4a9c8d778087522e5ce04b6e90099595 GIT binary patch literal 1250 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4rT@hhU+WOo?>8NW(e>Jab;j&;NV~o5MYpy zU{F+KFf?Rva$<;zVn|MA$j)XcE@r5%W@u?)XlW_#>0#*UDemd%nKFf8%9P?MQ>y38 zVVEwkZjIWyHF@jSt$X(}?A@Du?i|Cp zbLXyIW4Lzh+_h`h?%iX!chB(NJdh*`E$$X&!4}4&+z{J`|sZwzJC|^ z{$1kxcf;@BzyJTw@c+NS|Nj#IN5NBISn~R-X--a%afBxQ|J!3zMjr_SU zk_iHr)f*lf{$5^Qz}I)@3FlWvw(w~u=1P@VsTP+$RNGvxbHL-(%M6nc6`{zlU zjGQJeveps+!&Jb&mD)L@hA} z1_tL6*NBqf{Irtt#G+IN2MuLS&)mfHRNut(%;anZ6Fnn63k6F{eFF=914D)6qRirw zN{8Ia;*!i{z0_j8l+uFyyb`_S{M?DV6n8K%Fld2|%S_KpEGaEYWk@zRFt#waFg8d` zG)YZPF-fe)lBATd3a!N{b-$VA&f+n^|#(~yCI Ofx*+&&t;ucLK6T%G-N*j literal 0 HcmV?d00001 diff --git a/develop/doc/html/images/caution.svg b/develop/doc/html/images/caution.svg new file mode 100644 index 00000000..4bd586a0 --- /dev/null +++ b/develop/doc/html/images/caution.svg @@ -0,0 +1,68 @@ + + + + + + Attenzione + + + + pulsante + + + + + Open Clip Art Library + + + + + Architetto Francesco Rollandin + + + + + Architetto Francesco Rollandin + + + + image/svg+xml + + + en + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/develop/doc/html/images/draft.png b/develop/doc/html/images/draft.png new file mode 100644 index 0000000000000000000000000000000000000000..0084708c9b8287c51efa6b40b8d492854191455e GIT binary patch literal 17454 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 YsPxZ;53A2HFfcH9y85}Sb4q9e0Fi|iga7~l literal 0 HcmV?d00001 diff --git a/develop/doc/html/images/home.png b/develop/doc/html/images/home.png new file mode 100644 index 0000000000000000000000000000000000000000..5584aacb097a80e66a5320312b6e4eb017af1a06 GIT binary patch literal 358 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj7G?$phK4%r{|pQa%*9TgAsieWw;%dHU|?WS z3GfMV6&Dfg?(A@OuseF>a6(*+nzF*onKLh6zO-%YmOy{sw6wJU|Nk%gvq74Hfq|za z$S?Rm0x$^OKX;CSfq}EYBeIx*fm;ZK886+f`@_J%pjzS@Q4*Y=R#Ki=l*-_nm|T>f zo0^iDsNj}alvU8YOY t9}F9JU6`43jMG5vNQA& + + + + + + + +]> + + + + + + + + + + + + + + diff --git a/develop/doc/html/images/important.png b/develop/doc/html/images/important.png new file mode 100644 index 0000000000000000000000000000000000000000..12c90f607a1b27ddde0a7d922ae255e8c90e883e GIT binary patch literal 722 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4rT@hhU+WOo?>8NcoN_f;wr$vARr(hAt9lu zscC6x>EvV>6{VS+EaBwj6ciMco$ZvI98_E!l$@NLot<4>UER|o(bHqOcQ41TYc{y!?kM?_wFg)yJvXsp5^oB z9Pi&Vyniq7|3Ab3{~Z7S3p{_W`TV)z`}cpO z$(;G%_wGG* z?AW<;=dNA5cJJQ3=g*(NfB*jb_wWDz|6hCQ@I3|w2F4_BcNgdM3%p4T42R|DNig) zWpL0?*7VFxOi%SqOwUZtRxr^s(z8&owA44S&^IttNG{4OE~#|Ltt>9dOx8;+)=McZ z$j>X$OU}=oxJz*d0|SE=*tpE}yu^~yqEv=t literal 0 HcmV?d00001 diff --git a/develop/doc/html/images/important.svg b/develop/doc/html/images/important.svg new file mode 100644 index 00000000..dd84f3fe --- /dev/null +++ b/develop/doc/html/images/important.svg @@ -0,0 +1,25 @@ + + + + + + + + +]> + + + + + + + + + + + + + + + diff --git a/develop/doc/html/images/next.png b/develop/doc/html/images/next.png new file mode 100644 index 0000000000000000000000000000000000000000..59800b4e87f60c0e3383ede2b384b9be0f5ffe8d GIT binary patch literal 336 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj7G?$phK4%r{|pQa%*9TgAsieWw;%dHU|?WS z3GfMV6&Dfg?(8r&Hr}>%OQ656nzF)*4nJa0`Jj)#l9-t%+}PK^d+g590~2^trx_V+aGYt)W#Kgko@Q{~>i6>w}LxPb)_bi1gN;4a>^d{wc + + + + + +]> + + + + + + + + + + + diff --git a/develop/doc/html/images/next_disabled.png b/develop/doc/html/images/next_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..10a8c59d7b3741260b7bfe918b62d0670cad8433 GIT binary patch literal 1110 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj4rT@h2G_o0{}>n;SkfJR9T^xl_SO6joXo($ zppfhlZ{Pm>`SaViZ};!tyLt1*|NsBbojZ3P6EBL3=9l=JzX3_ zD&{0TNo#1Z_o+&KnDHU@)Rs;LG+GiER_Ffe$!`njxgN@xNAPfH=1 literal 0 HcmV?d00001 diff --git a/develop/doc/html/images/note.png b/develop/doc/html/images/note.png new file mode 100644 index 0000000000000000000000000000000000000000..d0c3c645ab9af6318035b026dd86944b9ddc9114 GIT binary patch literal 490 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4h9AWhNCh`Dhvz^OiAAEE({E-dXuv&t)U99M06BF~bt=lC3t1z!y3OU-_; z>3=1k>J3(3i_72APIz-IDqpqc+E%+vGv;(%KfZ!%@4A+C&xmZ75-RagX8L}A{%x+r zX<~gz))PX{awr=ezabJ<%O$qq%HpE?3}IarYhrI#g}e)4`)(-lYr?KO{@fm?UzpsD z&F7x?_G;CcbIZ>^o0GCAMe@{JfwtZgS9s0dn=t$|`IrrC3yU6#%a-U6G$wZz0 z>m`@($9HNPdGJ4#pEvb;3eT@>Ck6%v=MvY5lHmNblJdl&R0anPWlhiA#Pn3(#PrPM zYy}fNBRvZROG|wN3w;Aah2)~l;*v^-+{)sT%w)aPV!f2og8aM^z2yAdiMtecFfcG^ zfsM;d&r2*RElOoDPD(L1F;6y4H8Hg?FgGwTOER!DNJ%kHHBU4$OExhPxjgw70|Nse jNLN5&dMbmFNrjP#wt==mQ8cF^C=xwg{an^LB{Ts5w*0vf literal 0 HcmV?d00001 diff --git a/develop/doc/html/images/note.svg b/develop/doc/html/images/note.svg new file mode 100644 index 00000000..648299d2 --- /dev/null +++ b/develop/doc/html/images/note.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + diff --git a/develop/doc/html/images/prev.png b/develop/doc/html/images/prev.png new file mode 100644 index 0000000000000000000000000000000000000000..d88a40f923e3c554125f01cd366707c60cfcad04 GIT binary patch literal 334 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj7G?$phK4%r{|pQa%*9TgAsieWw;%dHU|?WS z3GfMV6&DdqOG`60Hr}>%%ZlYo1O0u~loc*tzSP~>;p||S5Et|R|Noh1c$yg)73T~N2spa`a*~JRJ5eh~I1}5!gYtAz;Fo=OPI2WZRmSpDVDTHL^rZN~B=o=X8 z8<-ql-^0nkz!2u?;uumfC;0|1OPoRyGxLNShYX~Tl_Wf9G1_imu)%RA9}mw<0X2^e zQioc&m}WXSvRw^OFi2qFa&lm1W^U?K=~^Ook|m{hVvche^Q6-g?(V)Vn8U=toEqFE UkjD9gfq{X+)78&qol`;+00?PtqyPW_ literal 0 HcmV?d00001 diff --git a/develop/doc/html/images/prev.svg b/develop/doc/html/images/prev.svg new file mode 100644 index 00000000..6d88ffdd --- /dev/null +++ b/develop/doc/html/images/prev.svg @@ -0,0 +1,19 @@ + + + + + + +]> + + + + + + + + + + + diff --git a/develop/doc/html/images/prev_disabled.png b/develop/doc/html/images/prev_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..ab3c17e02d156e7494dbab2f9cd66af46af2358c GIT binary patch literal 1109 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj4rT@h2G_o0{}>n;SkfJR9T^xl_SO6joXo($ zppfhlO-<`D(~2b}=LHv2RC7dZWAVCrDh<7Ss(U_A1L-MNQRp<#x>RYL|A z0d8w%7gb?npBLs13>ys`SR)0#F|i0-(0!9|ZvFp)$&5@KPtr;p8yJ{=^Qv)(GIJ<+ zNI0-0Zew5(Fj?c!G-tyG77m3Osc(4d6PFVdQ&MBb@ E0L^J1b^rhX literal 0 HcmV?d00001 diff --git a/develop/doc/html/images/smiley.png b/develop/doc/html/images/smiley.png new file mode 100644 index 0000000000000000000000000000000000000000..30a77f71ce16872d046a1a5d6fd698a2f65a3f62 GIT binary patch literal 867 zcmeAS@N?(olHy`uVBq!ia0y~yU=U|uV36QoW?*1YTQtp`fq{X!*vT`5gM;JtL;nX1 z42*&SJ|V8+B7&<|tz5IBw4@*~EXexT*H!m!O?Pp!sH>^CckiyDuKJ|Dl+(w%CQay1 zOYu8%=FGd73zHKgmoF}|u{3I~kKDVXVbQ_`9c`_Fz7{iQrl~4QMTGi1fByW=jcKLD z*?C#s*_rWAAIx@f)c16=+qAB-t1T`u&hzVsWjnTSn>lml<@5cSX&!B@jUfSci{|F_ z_w^KKXB!)+#6)_3`t<4gwQEt~&MzL%J+!ao-_JD<@64PzGws6Z-hv$8-Me=7btN{` zl~t96rKP3$c$&I9TcsogXQl?mL%y{W;-5&-92C)*?h!W?b)Wnj^{5*w_%-mE4Lj!$7BYguC zr{Y6*7#J8-K`Mgt(@M${i&7bU6O)Vbb5m0?6BXPti&D$;i?WLqd?OT$3=B-#%hsG{ zU|`huba4!+n3FrHHoVC|#v<-Y&ynX`2+ z)ci{*-@n^>-frGI_MA-9eHCQCFMs-NiTvCzJ8a&6h<9#D<(d3(^{E}JLTitR9GSK2 z$*O4*8tU!OHS*&Yg~mSMD)7~hd93j+u`cf5MM<4*zJ;yfFKhYEn9bv3Xeg3g;K-G= z;q?Q<5Qk-d*rznCncd{p+umG~t-YZ3L%_f9;YyrSd?k7nE}0j~xg-T!p1r_pXw_8J z^q9XtRP=q)pSk7_!?YePxacL!`8E4~v$oZii_iB4y^t?YSBana!LlH(Q{_whcc+EB z6^^opPM-68`QEg&=hc<^;brIeKBf1+k=uTZ@Aa)4^R8_EExPXM@|~g)-OB%bBP#i` ie0$=QHXfdLO8@!p%oni+1)dBH3=E#GelF{r5}E*N2(Kal literal 0 HcmV?d00001 diff --git a/develop/doc/html/images/tip.png b/develop/doc/html/images/tip.png new file mode 100644 index 0000000000000000000000000000000000000000..5c4aab3bb3543191c360387c4af9a3cbaa051345 GIT binary patch literal 449 zcmeAS@N?(olHy`uVBq!ia0y~yV31^BV36QoU|?X-y2mNSz`($iDJ87yAgr${wU6ATeb^ycE^w7cIp z?_W?xU6%d(bb~@Shbi-aG=ETBbm~(ogOmrW&bwBIxdt+K+A3yD;V_t}R>0LF5GN)x zed{W(mq$!1ciVpPy1}W+9bm)Xrgda~bSbG?a3DdjluYV+O9SdLnMpASqX+9EZY3c7C@7#N&OTq83NAIrA4U>si~GJ7Ut&0mS)MRMrP)TsYwQg=9VeOrfC+2Nk)mu rLdL(;85kJ&K)M1F(^DCYOe>5`v<1B4~iR4S3j3^P6 + + + + + lamp + + + + office + + lamp + + + + + Open Clip Art Library + + + + + Sergio Luiz Araujo Silva + + + + + Public Domain + + + set 2005 + image/svg+xml + + + en + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/develop/doc/html/images/toc-blank.png b/develop/doc/html/images/toc-blank.png new file mode 100644 index 0000000000000000000000000000000000000000..6ffad17a0c7a78deaae58716e8071cc40cb0b8e0 GIT binary patch literal 318 zcmeAS@N?(olHy`uVBq!ia0y~yVBlw9VBln7W?*2DUznZ3z`$S-;1lA?z`)P|#tmSq zfuVt+q2a)R0}Txg{}~t<{xkdsQ~$xN|NsB{3#)lDFfcGCdAqwXbg;^LFfcI4dAc}; zRNPAb@qhn+dx4sSAN-68Y+`}}843&7&M+`cx!`muLvG^(1_lP_64!{5;QX|b^2DN4 z1_upgP0!rK^itl1hi%%HopDWWCg4y_C{| z{JavqiARt`YJFJnVhX)qGzOMplv!L->5yAl zT#}irms+fsQd*FoSE84kpF44v;tmD|1}(60ndy0nC8b5F42emG<`xDZ$;L?r7Ky3J=GDKJX@I;2(iM=Hp2}coT4AYeplx7Y_5oxZgQu&X%Q~lo FCIGT9P(J_w literal 0 HcmV?d00001 diff --git a/develop/doc/html/images/up.png b/develop/doc/html/images/up.png new file mode 100644 index 0000000000000000000000000000000000000000..17d9c3ec491ae1ba22188ce85985623c92ffa9be GIT binary patch literal 370 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj7G?$phK4%r{|pQa%*9TgAsieWw;%dHU|?X- z3h)VW6&DdqOG|Thu-mqE%ZlYoyE{8BU%nLR@2jS)FmvY2qel)W#Kk;%^zi@x|I?Un z*fKCM@RbDl1^-6|46X<6oM2#J;4JWnEM{Qf76M_$OLy!3FfcHvmbgZg1m~xflqVLY zGWaGY7v<-srer26xMdclmgg5`7c2NiC>R+Sn6#IzInThrAO_OlT$Gwvl9`{U5R#dj z%3x@qZ(yu%U~+tY4<`cyLy@P8V@SoEspmFwHW&!FJyeg_(XezvV9WvAI|r@_>dZZG zPW6aiOT!J--9O?NG0%AP;}ge|4lDQN4=-}8`?JGwx}?mMnO)OdyQdu$nQCjPRV}jm z$u!Qa8E-cQ-r3Nz>Y(YPTd#BPEH+&8GWqfD!}4*53%dA!%#3$cIv;a~fq{X+)78&q Iol`;+0POUaApigX literal 0 HcmV?d00001 diff --git a/develop/doc/html/images/up.svg b/develop/doc/html/images/up.svg new file mode 100644 index 00000000..d31aa9c8 --- /dev/null +++ b/develop/doc/html/images/up.svg @@ -0,0 +1,19 @@ + + + + + + +]> + + + + + + + + + + + diff --git a/develop/doc/html/images/up_disabled.png b/develop/doc/html/images/up_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..e22bc8712192df3a8faa3264b0ec71ff3aaaa96c GIT binary patch literal 1115 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj4rT@h2G_o0{}>n;SkfJR9T^xl_SO6joXo($ zppfhl|Nrwy-~uYR zhzc&Dg3GAj3M#mY3a+7o>!{!cD!7RXZlQwPsNfDNxQhzzp@RFU-~lRlhzcH|g2$-f z2`YGs3Z9{Y=cwQXDtL(sUZH~5sNfAMc#8_&p@R3Q-~%f7hzdTTg3qYn3o7`E3cjI& z@2KDhD)@;CexZWjsNfGO_=^hup@RP~@T}IQi-CcGuO!GX7$yd$8C(zCIl;idaKO{W zF{ENn(v#GNhX4QTi=1XMFdktN{`IZ@p>>FWLcsvS9SfKMdlAq$6s7@ONV`8frfZ~QMdG-hBC2vApc;y96* zmcYQFpvLCIAmDK02m=$xYzYU3L}6wQg@_sdlHD~JI1CtW_~{utEVY`?z`(%Z>FVdQ I&MBb@06Fw0-2eap literal 0 HcmV?d00001 diff --git a/develop/doc/html/images/warning.png b/develop/doc/html/images/warning.png new file mode 100644 index 0000000000000000000000000000000000000000..1c33db8f34a8b42b373179b46a2d8d8a10e061a9 GIT binary patch literal 1241 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4rT@hhU+WOo?>8NW(e>JaphoO5CF?5GB9W| zFc>m0I59AIF)#!%FhnshWHT@nGcZ&$Ftji*^e`|?VPKe2T|Fl#Xiikroa*YO3=B&x zEth(EEp2I8I%UezrAyZ`FswB+TsvjTRtAQxnwndCdbZA)vvujxty{P5WnkF5cJ1D+ zTaPg?91{>YCLwX`*s*gA4Ce#{&Phm|)6~4iz;I1d^V+p*_ZS%N-Mjakf#JEL;`8Uv z-!m}0=iqq%{{43bhVS3M|7T$MKMF=efJz}yVEuRs0|NtNlDE4HLkFv@2Ll7c3r`ov zkcwNmlWOyu3izvS7ejxP>R-!INP5f(XN|IS^C^Iyp?`SUk1vQO?s(K&l| zi|Nkt0@~*ymDp65*E-HED6u(s{Mfrxmah{JrgAMTIq)Du?nC5nnYTRgThA|azEdIl zD^uvV>~q(b?>`Fd;xnAbe7so1I$-&keKN}|vNNOCvX<~g{)wp7{&hR__v^cBU*Gq* zV3YS!cBPWsl#eNWc|~nAXWMOB8tQWBuXo=4>}cytyX_5F^Az{bVJ>7~U~n#RjVKAu zPb(=;EJ|f?&`{R&%uP&B^-WCAOwLv?(KFJsP_VSrH?Yt*FjPn`$}BFabjYnNF3C*R zOD)z*DJ{s)E742N&z-nSaR&nfgBIAh%=Em(lG377hGY|?B=Z!b6jL*k#Ka_13kwTN zLrZf@a|7cv1EVApQ-8txlNlHo_&~Y>64O%|j7%zwOtcNO4T_>U4H+017(8A5T-G@y GGywozG)2h( literal 0 HcmV?d00001 diff --git a/develop/doc/html/images/warning.svg b/develop/doc/html/images/warning.svg new file mode 100644 index 00000000..fc8d7484 --- /dev/null +++ b/develop/doc/html/images/warning.svg @@ -0,0 +1,23 @@ + + + + + + + + +]> + + + + + + + + + + + + + diff --git a/develop/doc/html/index.html b/develop/doc/html/index.html new file mode 100644 index 00000000..1d5eac0a --- /dev/null +++ b/develop/doc/html/index.html @@ -0,0 +1,129 @@ + + + +Boost.Python + + + + + + +
+
+
Next
+
+
+
+

+Boost.Python

+
+

+David Abrahams +

+

+Stefan Seefeld +

+
+
+
+

+ Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +

+
+
+
+
+

+ + Synopsis +

+

+ Welcome to Boost.Python, a C++ library which enables seamless interoperability + between C++ and the Python programming language. The library includes support + for: +

+
    +
  • + References and Pointers +
  • +
  • + Globally Registered Type Coercions +
  • +
  • + Automatic Cross-Module Type Conversions +
  • +
  • + Efficient Function Overloading +
  • +
  • + C++ to Python Exception Translation +
  • +
  • + Default Arguments +
  • +
  • + Keyword Arguments +
  • +
  • + Manipulating Python objects in C++ +
  • +
  • + Exporting C++ Iterators as Python Iterators +
  • +
  • + Documentation Strings +
  • +
+

+ The development of these features was funded in part by grants to Boost Consulting + from the Lawrence Livermore National Laboratories + and by the Computational Crystallography Initiative + at Lawrence Berkeley National Laboratories. +

+ +

+ + Articles +

+

+ Building Hybrid Systems With Boost Python, + by Dave Abrahams and Ralf W. Grosse-Kunstleve +

+
+ + + +

Last revised: October 07, 2016 at 15:41:08 GMT

+
+
Next
+ + diff --git a/develop/doc/html/reference/HTML.manifest b/develop/doc/html/reference/HTML.manifest new file mode 100644 index 00000000..5a721513 --- /dev/null +++ b/develop/doc/html/reference/HTML.manifest @@ -0,0 +1,59 @@ +index.html +concepts.html +concepts/dereferenceable.html +concepts/extractor.html +concepts/holdergenerator.html +concepts/resultconverter.html +concepts/objectwrapper.html +high_level_components.html +high_level_components/boost_python_def_hpp.html +high_level_components/boost_python_def_visitor_hpp.html +high_level_components/boost_python_docstring_options_h.html +high_level_components/boost_python_enum_hpp.html +high_level_components/boost_python_errors_hpp.html +high_level_components/boost_python_exception_translato.html +high_level_components/boost_python_init_hpp.html +high_level_components/boost_python_iterator_hpp.html +high_level_components/boost_python_module_hpp.html +high_level_components/boost_python_operators_hpp.html +high_level_components/boost_python_scope_hpp.html +high_level_components/boost_python_stl_iterator_hpp.html +high_level_components/boost_python_wrapper_hpp.html +object_wrappers.html +object_wrappers/boost_python_list_hpp.html +object_wrappers/boost_python_long_hpp.html +object_wrappers/boost_python_numeric_hpp.html +object_wrappers/boost_python_object_hpp.html +object_wrappers/boost_python_str_hpp.html +object_wrappers/boost_python_slice_hpp.html +object_wrappers/boost_python_tuple_hpp.html +function_invocation_and_creation.html +function_invocation_and_creation/boost_python_call_hpp.html +function_invocation_and_creation/boost_python_call_method_hpp.html +function_invocation_and_creation/boost_python_data_members_hpp.html +function_invocation_and_creation/boost_python_make_function_hpp.html +function_invocation_and_creation/boost_python_overloads_hpp.html +function_invocation_and_creation/boost_python_ptr_hpp.html +function_invocation_and_creation/boost_python_raw_function_hpp.html +function_invocation_and_creation/function_documentation.html +function_invocation_and_creation/models_of_callpolicies.html +function_invocation_and_creation/models_of_resultconverter.html +function_invocation_and_creation/models_of_resultconvertergenerat.html +to_from_python_type_conversion.html +to_from_python_type_conversion/boost_python_implicit_hpp.html +to_from_python_type_conversion/boost_python_lvalue_from_pytype_.html +to_from_python_type_conversion/boost_python_opaque_pointer_conv.html +to_from_python_type_conversion/boost_python_to_python_converter.html +to_from_python_type_conversion/boost_python_register_ptr_to_pyt.html +embedding.html +embedding/boost_python_import_hpp.html +utility_and_infrastructure.html +utility_and_infrastructure/boost_python_instance_holder_hpp.html +utility_and_infrastructure/boost_python_pointee_hpp.html +utility_and_infrastructure/boost_python_handle_hpp.html +utility_and_infrastructure/boost_python_type_id_hpp.html +utility_and_infrastructure/boost_python_ssize_t_hpp.html +topics.html +topics/pickle_support.html +topics/indexing_support.html +glossary.html diff --git a/develop/doc/html/reference/concepts.html b/develop/doc/html/reference/concepts.html new file mode 100644 index 00000000..62485678 --- /dev/null +++ b/develop/doc/html/reference/concepts.html @@ -0,0 +1,261 @@ + + + +Chapter 1. Concepts + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+

+Chapter 1. Concepts

+ +
+ + +
+ +

+ Models of the CallPolicies concept are used to specialize the behavior + of Python callable objects generated by Boost.Python to wrapped C++ objects + like function and member function pointers, providing three behaviors: +

+
    +
  1. + precall - Python argument + tuple management before the wrapped object is invoked +
  2. +
  3. + result_converter - + C++ return value handling +
  4. +
  5. + postcall - Python argument + tuple and result management after the wrapped object is invoked +
  6. +
  7. + extract_return_type + - metafunction for extracting the return type from a given signature + type sequence +
  8. +
+
+
+ +

+ In order to allow the use of multiple models of CallPolicies in the same + callable object, Boost.Python's CallPolicies class templates provide a + chaining interface which allows them to be recursively composed. This interface + takes the form of an optional template parameter, Base, + which defaults to default_call_policies. + By convention, the precall + function of the Base is + invoked after the precall + function supplied by the outer + template, and the postcall + function of the Base is + invoked before the postcall + function of the outer template. + If a result_converter is + supplied by the outer template, + it replaces any result_converter + supplied by the Base. For + an example, see return_internal_reference. +

+
+
+ +
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Expression +

+
+

+ Type +

+
+

+ Result/Semantics +

+
+

+ x.precall(a) +

+
+

+ convertible to bool +

+
+

+ returns false and + PyErr_Occurred() != + 0 upon failure, true otherwise. +

+
+

+ P::result_converter +

+
+

+ A model of ResultConverterGenerator. +

+
+

+ An MPL unary Metafunction Class used produce the "preliminary" + result object. +

+
+

+ x.postcall(a, + r) +

+
+

+ convertible to PyObject* +

+
+

+ 0 and PyErr_Occurred() + != 0 + upon failure. Must "conserve references" even in the + event of an exception. In other words, if r + is not returned, its reference count must be decremented; if + another existing object is returned, its reference count must + be incremented. +

+
+

+ P::extract_return_type +

+
+

+ A model of Metafunction. +

+
+

+ An MPL unary Metafunction used extract the return type from a + given signature. By default it is derived from mpl::front. +

+
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/concepts/dereferenceable.html b/develop/doc/html/reference/concepts/dereferenceable.html new file mode 100644 index 00000000..18ea62ae --- /dev/null +++ b/develop/doc/html/reference/concepts/dereferenceable.html @@ -0,0 +1,104 @@ + + + +Dereferenceable + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ Instances of a Dereferenceable + type can be used like a pointer to access an lvalue. +

+
+
+ +

+ In the table below, T is + a model of Dereferenceable, and x + denotes an object of type T. + In addition, all pointers are Dereferenceable. +

+
+++++ + + + + + + + + + + +
+

+ Expression +

+
+

+ Result +

+
+

+ Operational Semantics +

+
+

+ get_pointer(x) +

+
+

+ convertible to pointee<T>::type* +

+
+

+ &*x, + or a null pointer +

+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/concepts/extractor.html b/develop/doc/html/reference/concepts/extractor.html new file mode 100644 index 00000000..5cb4e9c4 --- /dev/null +++ b/develop/doc/html/reference/concepts/extractor.html @@ -0,0 +1,135 @@ + + + +Extractor + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ An Extractor is a class which Boost.Python can use to extract C++ objects + from Python objects, and is typically used by facilities that define from_python conversions for "traditional" + Python extension types. +

+
+
+ +

+ In the table below, X denotes + a model of Extractor and + a denotes an instance of + a Python object type. +

+
+++++ + + + + + + + + + + + + + + + + + +
+

+ Expression +

+
+

+ Type +

+
+

+ Semantics +

+
+

+ X::execute(a) +

+
+

+ non-void +

+
+

+ Returns the C++ object being extracted. The execute function + must not be overloaded. +

+
+

+ &a.ob_type +

+
+

+ PyTypeObject** +

+
+

+ Points to the ob_type + field of an object which is layout-compatible with PyObject +

+
+
+
+

+Notes +

+

+ Informally, an Extractor's execute member must be a non-overloaded static + function whose single argument is a Python object type. Acceptable Python + object types include those publicly (and unambiguously) derived from PyObject, + and POD types which are layout-compatible with PyObject. +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/concepts/holdergenerator.html b/develop/doc/html/reference/concepts/holdergenerator.html new file mode 100644 index 00000000..b3780baf --- /dev/null +++ b/develop/doc/html/reference/concepts/holdergenerator.html @@ -0,0 +1,92 @@ + + + +HolderGenerator + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ A HolderGenerator is a unary metafunction class which returns types suitable + for holding instances of its argument in a wrapped C++ class instance. +

+
+
+ +

+ In the table below, G denotes + an type which models HolderGenerator, + and X denotes a class type. +

+
++++ + + + + + + + + +
+

+ Expression +

+
+

+ Requirements +

+
+

+ G::apply<X>::type +

+
+

+ A concrete subclass of instance_holder + which can hold objects of type X. +

+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/concepts/objectwrapper.html b/develop/doc/html/reference/concepts/objectwrapper.html new file mode 100644 index 00000000..9092fd92 --- /dev/null +++ b/develop/doc/html/reference/concepts/objectwrapper.html @@ -0,0 +1,132 @@ + + + +ObjectWrapper + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ This page defines two concepts used to describe classes which manage a + Python objects, and which are intended to support usage with a Python-like + syntax. +

+
+
+ +

+ Models of the ObjectWrapper concept have object + as a publicly-accessible base class, and are used to supply special construction + behavior and/or additional convenient functionality through (often templated) + member functions. Except when the return type R is itself an TypeWrapper, + a member function invocation of the form +

+
x.some_function(a1, a2,...an)
+

+ always has semantics equivalent to: +

+
extract<R>(x.attr("some_function")(object(a1), object(a2),...object(an)))()
+

+ (see caveat below). +

+
+
+ +

+ TypeWrapper is a refinement of ObjectWrapper + which is associated with a particular Python type X. + For a given TypeWrapper T, + a valid constructor expression +

+
T(a1, a2,...an)
+

+ builds a new T object managing the result of invoking X with arguments + corresponding to +

+
object(a1), object(a2),...object(an)
+

+ . When used as arguments to wrapped C++ functions, or as the template parameter + to extract<>, + only instances of the associated Python type will be considered a match. +

+
+
+

+Caveat +

+

+ The upshot of the special member function invocation rules when the return + type is a TypeWrapper is that it is possible for the returned object to + manage a Python object of an inappropriate type. This is not usually a + serious problem; the worst-case result is that errors will be detected + at runtime a little later than they might otherwise be. For an example + of how this can occur, note that the dict + member function items returns + an object of type list. + Now suppose the user defines this dict + subclass in Python: +

+
>>> class mydict(dict):
+...     def items(self):
+...         return tuple(dict.items(self)) # return a tuple
+
+

+ Since an instance of mydict + is also an instance of dict, + when used as an argument to a wrapped C++ function, boost::python::dict + can accept objects of Python type mydict. + Invoking items() + on this object can result in an instance of boost::python::list + which actually holds a Python tuple. + Subsequent attempts to use list + methods (e.g. append, or + any other mutating operation) on this object will raise the same exception + that would occur if you tried to do it from Python. +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/concepts/resultconverter.html b/develop/doc/html/reference/concepts/resultconverter.html new file mode 100644 index 00000000..790172f6 --- /dev/null +++ b/develop/doc/html/reference/concepts/resultconverter.html @@ -0,0 +1,210 @@ + + + +ResultConverter + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ A ResultConverter for a type T + is a type whose instances can be used to convert C++ return values of type + T to_python. + A ResultConverterGenerator is an MPL unary metafunction class which, given + the return type of a C++ function, returns a ResultConverter for that type. + ResultConverters in Boost.Python generally inspect library's registry of + converters to find a suitable converter, but converters which don't use + the registry are also possible. +

+
+
+ +

+ In the table below, C denotes + a ResultConverter type for a type R, + c denotes an object of + type C, and r denotes an object of type R. +

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Expression +

+
+

+ Type +

+
+

+ Semantics +

+
+

+ C c +

+
+ +

+ Constructs a c + object. +

+
+

+ c.convertible() +

+
+

+ convertible to bool +

+
+

+ false iff no conversion + from any R value + to a Python object is possible. +

+
+

+ c(r) +

+
+

+ convertible to PyObject* +

+
+

+ A pointer to a Python object corresponding to r, + or 0 iff r could not be converted to_python, in which case PyErr_Occurred should return + non-zero. +

+
+

+ c.get_pytype() +

+
+

+ PyTypeObject const * +

+
+

+ A pointer to a Python Type object corresponding to result of + the conversion, or 0. + Used for documentation generation. If 0 + is returned the generated type in the documentation will be object. +

+
+
+
+ +

+ In the table below, G denotes + a ResultConverterGenerator type and R + denotes a possible C++ function return type. +

+
++++ + + + + + + + + +
+

+ Expression +

+
+

+ Requirements +

+
+

+ G::apply<R>::type +

+
+

+ A ResultConverter type for R. +

+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/embedding.html b/develop/doc/html/reference/embedding.html new file mode 100644 index 00000000..4792a6ae --- /dev/null +++ b/develop/doc/html/reference/embedding.html @@ -0,0 +1,205 @@ + + + +Chapter 6. Embedding + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+

+Chapter 6. Embedding

+ +
+ + +
+ +

+ Exposes a mechanism for embedding the python interpreter into C++ code. +

+
+
+ +
object eval(str expression,
+            object globals = object(),
+            object locals = object());
+
+
+

+
+
Effects
+

+ Evaluate Python expression from expression in the context specified + by the dictionaries globals and locals. +

+
Returns
+

+ An instance of object which holds the value of the expression. +

+
+
+
+
+ +
object exec(str code,
+            object globals = object(),
+            object locals = object());
+
+
+

+
+
Effects
+

+ Execute Python source code from code in the context specified by + the dictionaries globals and locals. +

+
Returns
+

+ An instance of object which holds the result of executing the code. +

+
+
+
+
+ +
object exec_file(str filename,
+                 object globals = object(),
+                 object locals = object());
+
+
+

+
+
Effects
+

+ Execute Python source code from the file named by filename in the + context specified by the dictionaries globals and locals. +

+
Returns
+

+ An instance of object which holds the result of executing the code. +

+
+
+
+
+ +

+ The following example demonstrates the use of import and exec to define + a function in python, and later call it from within C++. +

+
#include <iostream>
+#include <string>
+
+using namespace boost::python;
+
+void greet()
+{
+  // Retrieve the main module.
+  object main = import("__main__");
+
+  // Retrieve the main module's namespace
+  object global(main.attr("__dict__"));
+
+  // Define greet function in Python.
+  object result = exec(
+    "def greet():                   \n"
+    "   return 'Hello from Python!' \n",
+    global, global);
+
+  // Create a reference to it.
+  object greet = global["greet"];
+
+  // Call it.
+  std::string message = extract<std::string>(greet());
+  std::cout << message << std::endl;
+}
+
+

+ Instead of embedding the python script into a string, we could also store + it in an a file... +

+
def greet():
+   return 'Hello from Python!'
+
+

+ ... and execute that instead. +

+
  // ...
+  // Load the greet function from a file.
+  object result = exec_file(script, global, global);
+  // ...
+}
+
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/embedding/boost_python_import_hpp.html b/develop/doc/html/reference/embedding/boost_python_import_hpp.html new file mode 100644 index 00000000..7bf7ecbf --- /dev/null +++ b/develop/doc/html/reference/embedding/boost_python_import_hpp.html @@ -0,0 +1,94 @@ + + + +boost/python/import.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ Exposes a mechanism for importing python modules. +

+
+
+ +
object import(str name);
+
+

+
+
Effects
+

+ Imports the module named by name. +

+
Returns
+

+ An instance of object which holds a reference to the imported module. +

+
+
+
+
+ +

+ The following example demonstrates the use of import to access a function + in python, and later call it from within C++. +

+
#include <iostream>
+#include <string>
+
+using namespace boost::python;
+
+void print_python_version()
+{
+  // Load the sys module.
+  object sys = import("sys");
+
+  // Extract the python version.
+  std::string version = extract<std::string>(sys.attr("version"));
+  std::cout << version << std::endl;
+}
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/function_invocation_and_creation.html b/develop/doc/html/reference/function_invocation_and_creation.html new file mode 100644 index 00000000..46ef7635 --- /dev/null +++ b/develop/doc/html/reference/function_invocation_and_creation.html @@ -0,0 +1,287 @@ + + + +Chapter 4. Function Invocation and Creation + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+

+Chapter 4. Function Invocation and Creation

+
+

Table of Contents

+
+
boost/python/args.hpp
+
+
Introduction
+
Class + arg
+
Class + arg constructor
+
Class + arg operator=
+
Keyword-expression + operator,
+
Example
+
+
boost/python/call.hpp
+
+
Introduction
+
Function + call
+
Example
+
+
boost/python/call_method.hpp
+
+
Introduction
+
Function + call_method
+
Example
+
+
boost/python/data_members.hpp
+
+
Introduction
+
Functions
+
Example
+
+
boost/python/make_function.hpp
+
+
Introduction
+
Functions
+
Example
+
+
boost/python/overloads.hpp
+
+
Introduction
+
OverloadDispatcher + Concept
+
Macros
+
Example
+
+
boost/python/ptr.hpp
+
+
Introduction
+
Functions
+
Class + template pointer_wrapper
+
Class + template pointer_wrapper + types
+
Class + template pointer_wrapper + constructors and destructor
+
Class + template pointer_wrapper + observer functions
+
Metafunctions
+
Example
+
+
boost/python/raw_function.hpp
+
+
Introduction
+
Function + raw_function
+
Example
+
+
Function + documentation
+
+
boost/python/function_doc_signature.hpp
+
boost/python/pytype_function.hpp
+
+
Models + of CallPolicies
+
+
boost/python/default_call_policies.hpp
+
boost/python/return_arg.hpp
+
boost/python/return_internal_reference.hpp
+
boost/python/return_value_policy.hpp
+
boost/python/with_custodian_and_ward.hpp
+
+
Models + of ResultConverter
+
+
boost/python/to_python_indirect.hpp
+
boost/python/to_python_value.hpp
+
+
Models + of ResultConverterGenerator
+
+
boost/python/copy_const_reference.hpp
+
boost/python/copy_non_const_reference.hpp
+
boost/python/manage_new_object.hpp
+
boost/python/reference_existing_object.hpp
+
boost/python/return_by_value.hpp
+
boost/python/return_opaque_pointer.hpp
+
+
+
+
+ + +
+ + +

+ Supplies a family of overloaded functions for specifying argument keywords + for wrapped C++ functions. +

+
+ +

+ A keyword-expression results in an object which holds a sequence of + ntbses, and whose type encodes the number + of keywords specified. The keyword-expression may contain default values + for some or all of the keywords it holds +

+
+
+
+ +

+ The objects of class arg are keyword-expressions holding one keyword ( + size one ) +

+
namespace boost { namespace python
+{
+        struct arg
+        {
+          template <class T>
+                  arg &operator = (T const &value);
+          explicit arg (char const *name){elements[0].name = name;}
+        };
+
+}}
+
+
+
+ +
arg(char const* name);
+
+

+
+
Requires
+

+ The argument must be a ntbs. +

+
Effects
+

+ Constructs an arg object holding a keyword with name name. +

+
+
+
+
+ +
template <class T> arg &operator = (T const &value);
+
+

+
+
Requires
+

+ The argument must convertible to python. +

+
Effects
+

+ Assigns default value for the keyword. +

+
Returns
+

+ Reference to this. +

+
+
+
+
+ +
keyword-expression operator , (keyword-expression, const arg &kw) const
+keyword-expression operator , (keyword-expression, const char *name) const;
+
+
+

+
+
Requires
+

+ The argument name must be a ntbs. +

+
Effects
+

+ Extends the keyword-expression argument with one more keyword. +

+
Returns
+

+ The extended keyword-expression. +

+
+
+
+
+ +
#include <boost/python/def.hpp>
+using namespace boost::python;
+
+int f(double x, double y, double z=0.0, double w=1.0);
+
+BOOST_PYTHON_MODULE(xxx)
+{
+  def("f", f, (arg("x"), "y", arg("z")=0.0, arg("w")=1.0));
+}
+
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/function_invocation_and_creation/boost_python_call_hpp.html b/develop/doc/html/reference/function_invocation_and_creation/boost_python_call_hpp.html new file mode 100644 index 00000000..fe0e88d3 --- /dev/null +++ b/develop/doc/html/reference/function_invocation_and_creation/boost_python_call_hpp.html @@ -0,0 +1,96 @@ + + + +boost/python/call.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +
<boost/python/call.hpp> defines the call family of overloaded function templates, used to invoke Python callable objects from C++.
+
+
+
+ +
template <class R, class A1, class A2, ... class An>
+R call(PyObject* callable, A1 const&, A2 const&, ... An const&)
+
+
+

+
+
Requires
+

+ R is a pointer type, reference type, or a complete type with an accessible + copy constructor +

+
Effects
+

+ Invokes callable(a1, a2, ...an) in Python, where a1...an are the + arguments to call(), converted to Python objects. +

+
Returns
+

+ The result of the Python call, converted to the C++ type R. +

+
Rationale
+

+ For a complete semantic description and rationale, see this page. +

+
+
+
+
+ +

+ The following C++ function applies a Python callable object to its two + arguments and returns the result. If a Python exception is raised or the + result can't be converted to a double, an exception is thrown. +

+
double apply2(PyObject* func, double x, double y)
+{
+   return boost::python::call<double>(func, x, y);
+}
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/function_invocation_and_creation/boost_python_call_method_hpp.html b/develop/doc/html/reference/function_invocation_and_creation/boost_python_call_method_hpp.html new file mode 100644 index 00000000..670387f9 --- /dev/null +++ b/develop/doc/html/reference/function_invocation_and_creation/boost_python_call_method_hpp.html @@ -0,0 +1,156 @@ + + + +boost/python/call_method.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ <boost/python/call_method.hpp> defines the call_method family of + overloaded function templates, used to invoke callable attributes of Python + objects from C++. +

+
+
+ +
template <class R, class A1, class A2, ... class An>
+R call_method(PyObject* self, char const* method, A1 const&, A2 const&, ... An const&)
+
+
+

+
+
Requires
+

+ R is a pointer type, + reference type, or a complete type with an accessible copy constructor +

+
Effects
+

+ Invokes self.method(a1, a2, ...an) in Python, where a1...an + are the arguments to call_method(), converted to Python objects. For + a complete semantic description, see this page. +

+
Returns
+

+ The result of the Python call, converted to the C++ type R. +

+
Rationale
+

+ call_method is critical + to implementing C++ virtual functions which are overridable in Python, + as shown by the example below. +

+
+
+
+
+ +

+ The following C++ illustrates the use of call_method + in wrapping a class with a virtual function that can be overridden in Python: + C++ Module Definition +

+
#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+#include <boost/utility.hpp>
+#include <cstring>
+
+// class to be wrapped
+class Base
+{
+ public:
+   virtual char const* class_name() const { return "Base"; }
+   virtual ~Base();
+};
+
+bool is_base(Base* b)
+{
+   return !std::strcmp(b->class_name(), "Base");
+}
+
+// Wrapper code begins here
+using namespace boost::python;
+
+// Callback class
+class Base_callback : public Base
+{
+ public:
+   Base_callback(PyObject* self) : m_self(self) {}
+
+   char const* class_name() const { return call_method<char const*>(m_self, "class_name"); }
+   char const* Base_name() const { return Base::class_name(); }
+ private:
+   PyObject* const m_self;
+};
+
+using namespace boost::python;
+BOOST_PYTHON_MODULE(my_module)
+{
+    def("is_base", is_base);
+
+    class_<Base,Base_callback, noncopyable>("Base")
+        .def("class_name", &Base_callback::Base_name)
+        ;
+
+}
+
+

+ Python code: +

+
>>> from my_module import *
+>>> class Derived(Base):
+...    def __init__(self):
+...       Base.__init__(self)
+...    def class_name(self):
+...       return self.__class__.__name__
+...
+>>> is_base(Base()) # calls the class_name() method from C++
+1
+>>> is_base(Derived())
+0
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/function_invocation_and_creation/boost_python_data_members_hpp.html b/develop/doc/html/reference/function_invocation_and_creation/boost_python_data_members_hpp.html new file mode 100644 index 00000000..fb5bbf54 --- /dev/null +++ b/develop/doc/html/reference/function_invocation_and_creation/boost_python_data_members_hpp.html @@ -0,0 +1,215 @@ + + + +boost/python/data_members.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ make_getter() + and make_setter() + are the functions used internally by class_<>::def_readonly and class_<>::def_readwrite to produce Python + callable objects which wrap C++ data members. +

+
+
+ +
template <class C, class D>
+object make_getter(D C::*pm);
+
+template <class C, class D, class Policies>
+object make_getter(D C::*pm, Policies const& policies);
+
+
+

+
+
Requires
+

+ Policies is a model of CallPolicies. +

+
Effects
+

+ Creates a Python callable object which accepts a single argument + that can be converted from_python to C*, and returns the corresponding + member D member of the C object, converted to_python. If policies + is supplied, it will be applied to the function as described here. + Otherwise, the library attempts to determine whether D is a user-defined + class type, and if so uses return_internal_reference<> for + Policies. Note that this test may inappropriately choose return_internal_reference<> + in some cases when D is a smart pointer type. This is a known defect. +

+
Returns
+

+ An instance of object which holds the new Python callable object. +

+
+
+
template <class D>
+object make_getter(D const& d);
+template <class D, class Policies>
+object make_getter(D const& d, Policies const& policies);
+
+template <class D>
+object make_getter(D const* p);
+template <class D, class Policies>
+object make_getter(D const* p, Policies const& policies);
+
+
+

+
+
Requires
+

+ Policies is a model of CallPolicies. +

+
Effects
+

+ Creates a Python callable object which accepts no arguments and returns + d or *p, converted to_python on demand. If policies is supplied, + it will be applied to the function as described here. Otherwise, + the library attempts to determine whether D is a user-defined class + type, and if so uses reference_existing_object for Policies. +

+
Returns
+

+ An instance of object which holds the new Python callable object. +

+
+
+
template <class C, class D>
+object make_setter(D C::*pm);
+
+template <class C, class D, class Policies>
+object make_setter(D C::*pm, Policies const& policies);
+
+
+

+
+
Requires
+

+ Policies is a model of CallPolicies. +

+
Effects
+

+ Creates a Python callable object which, when called from Python, + expects two arguments which can be converted from_python to C* and + D const&, respectively, and sets the corresponding D member of + the C object. If policies is supplied, it will be applied to the + function as described here. +

+
Returns
+

+ An instance of object which holds the new Python callable object. +

+
+
+
template <class D>
+object make_setter(D& d);
+template <class D, class Policies>
+object make_setter(D& d, Policies const& policies);
+
+template <class D>
+object make_setter(D* p);
+template <class D, class Policies>
+object make_setter(D* p, Policies const& policies);
+
+
+

+
+
Requires
+

+ Policies is a model of CallPolicies. +

+
Effects
+

+ Creates a Python callable object which accepts one argument, which + is converted from Python to D const& and written into d or *p, + respectively. If policies is supplied, it will be applied to the + function as described here. +

+
Returns
+

+ An instance of object which holds the new Python callable object. +

+
+
+
+
+ +

+ The code below uses make_getter and make_setter to expose a data member + as functions: +

+
#include <boost/python/data_members.hpp>
+#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+
+struct X
+{
+    X(int x) : y(x) {}
+    int y;
+};
+
+using namespace boost::python;
+
+BOOST_PYTHON_MODULE_INIT(data_members_example)
+{
+    class_<X>("X", init<int>())
+       .def("get", make_getter(&X::y))
+       .def("set", make_setter(&X::y))
+       ;
+}
+
+

+ It can be used this way in Python: +

+
>>> from data_members_example import *
+>>> x = X(1)
+>>> x.get()
+1
+>>> x.set(2)
+>>> x.get()
+2
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/function_invocation_and_creation/boost_python_make_function_hpp.html b/develop/doc/html/reference/function_invocation_and_creation/boost_python_make_function_hpp.html new file mode 100644 index 00000000..7b658abc --- /dev/null +++ b/develop/doc/html/reference/function_invocation_and_creation/boost_python_make_function_hpp.html @@ -0,0 +1,186 @@ + + + +boost/python/make_function.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

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

+
+
+ +
template <class F>
+object make_function(F f)
+
+template <class F, class Policies>
+object make_function(F f, Policies const& policies)
+
+template <class F, class Policies, class KeywordsOrSignature>
+object make_function(F f, Policies const& policies, KeywordsOrSignature const& ks)
+
+template <class F, class Policies, class Keywords, class Signature>
+object make_function(F f, Policies const& policies, Keywords const& kw, Signature const& sig)
+
+
+

+
+
Requires
+

+ F is a function pointer or member function pointer type. If policies + are supplied, it must be a model of CallPolicies. If kewords are + supplied, it must be the result of a keyword-expression specifying + no more arguments than the arity of f. +

+
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 will be applied to the function as + described here. * If keywords are supplied, the keywords will be + applied in order to the final arguments of the resulting function. + * If Signature is supplied, it should be an instance of an MPL front-extensible + sequence representing the function's return type followed by its + argument types. Pass a Signature when wrapping function object types + whose signatures can't be deduced, or when you wish to override the + types which will be passed to the wrapped function. +

+
+
Returns
+

+ An instance of object which holds the new Python callable object. +

+
Caveats
+

+ An argument of pointer type may be 0 if None is passed from Python. + An argument type which is a constant reference may refer to a temporary + which was created from the Python object for just the duration of + the call to the wrapped function, for example a std::vector conjured + up by the conversion process from a Python list. Use a non-const + reference argument when a persistent lvalue is required. +

+
+
+
template <class F>
+object make_constructor(F f)
+
+template <class F, class Policies>
+object make_constructor(F f, Policies const& policies)
+
+template <class F, class Policies, class KeywordsOrSignature>
+object make_constructor(F f, Policies const& policies, KeywordsOrSignature const& ks)
+
+template <class F, class Policies, class Keywords, class Signature>
+object make_constructor(F f, Policies const& policies, Keywords const& kw, Signature const& sig)
+
+
+

+
+
Requires
+

+ F is a function pointer type. If policies are supplied, it must be + a model of CallPolicies. If kewords are supplied, it must be the + result of a keyword-expression specifying no more arguments than + the arity of f. +

+
Effects
+

+ Creates a Python callable object which, when called from Python, + converts its arguments to C++ and calls f. +

+
Returns
+

+ An instance of object which holds the new Python callable object. +

+
+
+
+
+ +

+ 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"; }
+
+using namespace boost::python;
+object choose_function(bool selector)
+{
+    if (selector)
+        return boost::python::make_function(foo);
+    else
+        return boost::python::make_function(bar);
+}
+
+BOOST_PYTHON_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'
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/function_invocation_and_creation/boost_python_overloads_hpp.html b/develop/doc/html/reference/function_invocation_and_creation/boost_python_overloads_hpp.html new file mode 100644 index 00000000..818c9f7c --- /dev/null +++ b/develop/doc/html/reference/function_invocation_and_creation/boost_python_overloads_hpp.html @@ -0,0 +1,208 @@ + + + +boost/python/overloads.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ + +

+ Defines facilities for generating families of overloaded Python functions + and extension class methods from C++ functions and member functions with + default arguments, or from similar families of C++ overloads +

+
+ +

+ An overload-dispatch-expression is used to describe a family of overloaded + methods to be generated for an extension class. It has the following + properties: +

+
+

+
+
docstring
+

+ An ntbs whose value will bound to the + methods' __doc__ + attribute +

+
keywords
+

+ A keyword-expression + which will be used to name (a trailing subsequence of) the arguments + to the generated methods. +

+
call policies
+

+ An instance of some type which models CallPolicies. +

+
minimum arity
+

+ The minimum number of arguments to be accepted by a generated method + overload. +

+
maximum arity
+

+ The maximum number of arguments to be accepted by a generated method + overload. +

+
+
+
+
+
+ +

+ An OverloadDispatcher X is a class which has a minimum arity and a maximum + arity, and for which the following following are valid overload-dispatch-expressions, + with the same minimum and maximum arity as the OverloadDispatcher. +

+
X()
+X(docstring)
+X(docstring, keywords)
+X(keywords, docstring)
+X()[policies]
+X(docstring)[policies]
+X(docstring, keywords)[policies]
+X(keywords, docstring)[policies]
+
+

+ * If policies are supplied, it must be an instance of a type which models + CallPolicies, and will be + used as the result's call policies. Otherwise the result's call policies + will be an instance of default_call_policies. * If docstring + is supplied it must be an ntbs, and will be + used as the result's docstring. Otherwise the result has an empty docstring. + * If keywords is supplied it must be the result of a keyword-expression + whose length is no greater than X's maximum arity, and will be used as + the result's keywords. Otherwise the result's keywords will be empty. +

+
+
+

+Macros +

+
BOOST_PYTHON_FUNCTION_OVERLOADS(name, func_id, min_args, max_args)
+
+

+ Expands to the definition of an OverloadDispatcher called name in the current + scope which can be used to generate the following function invocation: +

+
func_id(a1, a2,...ai);
+

+ for all min_args <= + i <= + max_args. +

+
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(name, member_name, min_args, max_args)
+
+

+ Expands to the definition of an OverloadDispatcher called name in the current + scope which can be used to generate the following function invocation: +

+
x.member_name(a1, a2,...ai);
+

+ for all min_args <= i <= max_args, where x is a reference to an object + of class type. +

+
+
+ +
#include <boost/python/module.hpp>
+#include <boost/python/def.hpp>
+#include <boost/python/args.hpp>
+#include <boost/python/tuple.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/overloads.hpp>
+#include <boost/python/return_internal_reference.hpp>
+
+using namespace boost::python;
+
+tuple f(int x = 1, double y = 4.25, char const* z = "wow")
+{
+    return make_tuple(x, y, z);
+}
+
+BOOST_PYTHON_FUNCTION_OVERLOADS(f_overloads, f, 0, 3)
+
+struct Y {};
+struct X
+{
+    Y& f(int x, double y = 4.25, char const* z = "wow")
+    {
+        return inner;
+    }
+    Y inner;
+};
+
+BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(f_member_overloads, f, 1, 3)
+
+BOOST_PYTHON_MODULE(args_ext)
+{
+    def("f", f,
+        f_overloads(
+            args("x", "y", "z"), "This is f's docstring"
+        ));
+
+
+    class_<Y>("Y")
+        ;
+
+    class_<X>("X", "This is X's docstring")
+        .def("f1", &X::f,
+                f_member_overloads(
+                    args("x", "y", "z"), "f's docstring"
+                )[return_internal_reference<>()]
+        )
+        ;
+}
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/function_invocation_and_creation/boost_python_ptr_hpp.html b/develop/doc/html/reference/function_invocation_and_creation/boost_python_ptr_hpp.html new file mode 100644 index 00000000..16eacbc3 --- /dev/null +++ b/develop/doc/html/reference/function_invocation_and_creation/boost_python_ptr_hpp.html @@ -0,0 +1,287 @@ + + + +boost/python/ptr.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ <boost/python/ptr.hpp> defines the ptr() function template, which + allows users to specify how to convert C++ pointer values to python in + the context of implementing overridable virtual functions, invoking Python + callable objects, or explicitly converting C++ objects to Python. Normally, + when passing pointers to Python callbacks, the pointee is copied to ensure + that the Python object never holds a dangling reference. To specify that + the new Python object should merely contain a copy of a pointer p, the + user can pass ptr(p) instead of passing p directly. This interface is meant + to mirror the use of boost::ref(), which can be similarly used to prevent + copying of referents. +

+

+ ptr(p) returns an instance of pointer_wrapper<>, + which can be detected using the is_pointer_wrapper<> + metafunction; unwrap_pointer<> + is a metafunction which extracts the original pointer type from a pointer_wrapper<>. + These classes can be thought of as implementation details. +

+
+
+ +
template <class T>
+pointer_wrapper<T> ptr(T x);
+
+
+

+
+
Requires
+

+ T is a pointer type. +

+
Returns
+

+ pointer_wrapper<T>(x) +

+
Throws
+

+ nothing. +

+
+
+
+
+ +

+ A "type envelope" which is returned by ptr(), used to indicate reference semantics + for pointers passed to Python callbacks. +

+
namespace boost { namespace python
+{
+    template<class Ptr> class pointer_wrapper
+    {
+     public:
+        typedef Ptr type;
+
+        explicit pointer_wrapper(Ptr x);
+        operator Ptr() const;
+        Ptr get() const;
+    };
+}}
+
+
+
+ +
typedef Ptr type;
+
+

+ The type of the pointer being wrapped. +

+
+
+ +
explicit pointer_wrapper(Ptr x);
+
+
+

+
+
Requires
+

+ Ptr is a pointer + type +

+
Effects
+

+ Stores x in a the + pointer_wrapper<>. +

+
Throws
+

+ nothing. +

+
+
+
+
+ +
operator Ptr() const;
+Ptr get() const;
+
+
+

+
+
Returns
+

+ a copy of the stored pointer. +

+
Rationale
+

+ pointer_wrapper is intended to be a stand-in for the actual pointer + type, but sometimes it's better to have an explicit way to retrieve + the pointer. +

+
+
+
+
+ + +
+ +

+ A unary metafunction whose value is true iff its argument is a pointer_wrapper<>. +

+
namespace boost { namespace python
+{
+    template<class T> class is_pointer_wrapper
+    {
+        static unspecified value = ...;
+    };
+}}
+
+
+

+
+
Returns
+

+ true iff T is a specialization of pointer_wrapper<>. + value is an integral constant convertible to bool of unspecified + type +

+
+
+
+
+ +

+ A unary metafunction which extracts the wrapped pointer type from a specialization + of pointer_wrapper<>. +

+
namespace boost { namespace python
+{
+    template<class T> class unwrap_pointer
+    {
+        typedef unspecified type;
+    };
+}}
+
+
+

+
+
Returns
+

+ T::type if T + is a specialization of pointer_wrapper<>, T + otherwise +

+
+
+
+
+
+ +

+ This example illustrates the use of ptr() to prevent an object from being + copied: +

+
#include <boost/python/call.hpp>
+#include <boost/python/ptr.hpp>
+
+class expensive_to_copy
+{
+   ...
+};
+
+void pass_as_arg(expensive_to_copy* x, PyObject* f)
+{
+   // call the Python function f, passing a Python object built around
+   // which refers to *x by-pointer.
+   //
+   // *** Note: ensuring that *x outlives the argument to f() is    ***
+   // *** up to the user! Failure to do so could result in a crash! ***
+
+   boost::python::call<void>(f, ptr(x));
+}
+...
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/function_invocation_and_creation/boost_python_raw_function_hpp.html b/develop/doc/html/reference/function_invocation_and_creation/boost_python_raw_function_hpp.html new file mode 100644 index 00000000..75ba9e14 --- /dev/null +++ b/develop/doc/html/reference/function_invocation_and_creation/boost_python_raw_function_hpp.html @@ -0,0 +1,111 @@ + + + +boost/python/raw_function.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ raw_function(...) + is used to convert a function taking a tuple and a dict into a Python callable object + which accepts a variable number of arguments and arbitrary keyword arguments. +

+
+
+ +
template <class F>
+object raw_function(F f, std::size_t min_args = 0);
+
+
+

+
+
Requires
+

+ f(tuple(), dict()) is well-formed. +

+
Returns
+

+ a callable object which requires at least min_args arguments. When + called, the actual non-keyword arguments will be passed in a tuple + as the first argument to f, and the keyword arguments will be passed + in a dict as the second argument to f. +

+
+
+
+
+ +

+ C++: +

+
#include <boost/python/def.hpp>
+#include <boost/python/tuple.hpp>
+#include <boost/python/dict.hpp>
+#include <boost/python/module.hpp>
+#include <boost/python/raw_function.hpp>
+
+using namespace boost::python;
+
+tuple raw(tuple args, dict kw)
+{
+    return make_tuple(args, kw);
+}
+
+BOOST_PYTHON_MODULE(raw_test)
+{
+    def("raw", raw_function(raw));
+}
+
+

+ Python: +

+
>>> from raw_test import *
+
+>>> raw(3, 4, foo = 'bar', baz = 42)
+((3, 4), {'foo': 'bar', 'baz': 42})
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/function_invocation_and_creation/function_documentation.html b/develop/doc/html/reference/function_invocation_and_creation/function_documentation.html new file mode 100644 index 00000000..c48216db --- /dev/null +++ b/develop/doc/html/reference/function_invocation_and_creation/function_documentation.html @@ -0,0 +1,458 @@ + + + +Function documentation + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ + +
+ +

+ Boost.Python supports docstrings with automatic appending of Pythonic + and C++ signatures. This feature is implemented by class function_doc_signature_generator. The + class uses all of the overloads, supplied arg names and default values, + as well as the user-defined docstrings, to generate documentation for + a given function. +

+
+
+ +

+ The class has only one public function which returns a list of strings + documenting the overloads of a function. +

+
namespace boost { namespace python { namespace objects {
+
+    class function_doc_signature_generator
+    {
+      public:
+          static list function_doc_signatures(function const *f);
+    };
+
+}}}
+
+
+
+ +
#include <boost/python/module.hpp>
+#include <boost/python/def.hpp>
+#include <boost/python/args.hpp>
+#include <boost/python/tuple.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/overloads.hpp>
+#include <boost/python/raw_function.hpp>
+
+using namespace boost::python;
+
+tuple f(int x = 1, double y = 4.25, char const* z = "wow")
+{
+    return make_tuple(x, y, z);
+}
+
+BOOST_PYTHON_FUNCTION_OVERLOADS(f_overloads, f, 0, 3)
+
+
+struct X
+{
+    tuple f(int x = 1, double y = 4.25, char const* z = "wow")
+    {
+        return make_tuple(x, y, z);
+    }
+};
+
+BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(X_f_overloads, X::f, 0, 3)
+
+tuple raw_func(tuple args, dict kw)
+{
+    return make_tuple(args, kw);
+}
+
+BOOST_PYTHON_MODULE(args_ext)
+{
+    def("f", f, (arg("x")=1, arg("y")=4.25, arg("z")="wow")
+        , "This is f's docstring"
+        );
+
+    def("raw", raw_function(raw_func));
+
+    def("f1", f, f_overloads("f1's docstring", args("x", "y", "z")));
+
+
+    class_<X>("X", "This is X's docstring", init<>(args("self")))
+        .def("f", &X::f
+             , "This is X.f's docstring"
+             , args("self","x", "y", "z"))
+
+        ;
+
+}
+
+

+ Python code: +

+
>>> import args_ext
+>>> help(args_ext)
+Help on module args_ext:
+
+NAME
+    args_ext
+
+FILE
+    args_ext.pyd
+
+CLASSES
+    Boost.Python.instance(__builtin__.object)
+        X
+
+    class X(Boost.Python.instance)
+     |  This is X's docstring
+     |
+     |  Method resolution order:
+     |      X
+     |      Boost.Python.instance
+     |      __builtin__.object
+     |
+     |  Methods defined here:
+     |
+     |  __init__(...)
+     |      __init__( (object)self) -> None :
+     |       C++ signature:
+     |           void __init__(struct _object *)
+     |
+     |  f(...)
+     |      f( (X)self, (int)x, (float)y, (str)z) -> tuple : This is X.f's docstring
+     |      C++ signature:
+     |          class boost::python::tuple f(struct X {lvalue},int,double,char const *)
+     |
+     |    .................
+     |
+FUNCTIONS
+    f(...)
+        f([ (int)x=1 [, (float)y=4.25 [, (str)z='wow']]]) -> tuple : This is f's docstring
+        C++ signature:
+            class boost::python::tuple f([ int=1 [,double=4.25 [,char const *='wow']]])
+
+    f1(...)
+        f1([ (int)x [, (float)y [, (str)z]]]) -> tuple : f1's docstring
+        C++ signature:
+            class boost::python::tuple f1([ int [,double [,char const *]]])
+
+    raw(...)
+        object raw(tuple args, dict kwds) :
+        C++ signature:
+            object raw(tuple args, dict kwds)
+
+
+
+
+ + +
+ +

+ To support Pythonic signatures the converters should supply a get_pytype function returning a pointer + to the associated PyTypeObject. + See for example ResultConverter or to_python_converter. The classes + in this header file are meant to be used when implmenting get_pytype. There are also _direct versions of the templates of + class T + which should be used with undecorated type parameter, expected to be + in the conversion registry when the module loads. +

+
+
+ +

+ This template generates a static get_pytype + member returning the template parameter. +

+
namespace boost { namespace python { namespace converter{
+
+    template < PyTypeObject const *pytype >
+    class wrap_pytype
+    {
+      public:
+          static PyTypeObject const *get_pytype(){return pytype; }
+    };
+
+}}}
+
+
+
+ +

+ This template should be used with template parameters which are (possibly + decorated) types exported to python using class_. The generated a static + get_pytype member returns + the corresponding python type. +

+
namespace boost { namespace python { namespace converter{
+
+    template < class T >
+    class registered_pytype
+    {
+      public:
+          static PyTypeObject const *get_pytype();
+    };
+
+}}}
+
+
+
+ +

+ This template generates a static get_pytype + member which inspects the registered from_python + converters for the type T + and returns a matching python type. +

+
namespace boost { namespace python { namespace converter{
+
+    template < class T >
+    class expected_from_python_type
+    {
+      public:
+          static PyTypeObject const *get_pytype();
+    };
+
+}}}
+
+
+
+ +

+ This template generates a static get_pytype + member returning the python type to which T + can be converted. +

+
namespace boost { namespace python { namespace converter{
+
+    template < class T >
+    class to_python_target_type
+    {
+      public:
+          static PyTypeObject const *get_pytype();
+    };
+
+}}}
+
+
+
+ +

+ 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
+#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //unnecessary overhead if py signatures are not supported
+: wrap_pytype<&noddy_NoddyType> //inherits get_pytype from wrap_pytype
+#endif
+{
+    static PyObject* convert(tag const& x)
+    {
+        return PyObject_New(noddy_NoddyObject, &noddy_NoddyType);
+    }
+};
+
+BOOST_PYTHON_MODULE(to_python_converter)
+{
+    def("make_tag", make_tag);
+    to_python_converter<tag, tag_to_noddy
+#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported
+          , true
+#endif
+          >(); //"true" because tag_to_noddy has member get_pytype
+}
+
+

+ The following example registers to and from python converters using the + templates expected_from_python_type and to_pyhton_target_type. +

+
#include <boost/python/module.hpp>
+#include <boost/python/def.hpp>
+#include <boost/python/extract.hpp>
+#include <boost/python/to_python_converter.hpp>
+#include <boost/python/class.hpp>
+
+using namespace boost::python;
+
+struct A
+{
+};
+
+struct B
+{
+  A a;
+  B(const A& a_):a(a_){}
+};
+
+// Converter from A to python int
+struct BToPython
+#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //unnecessary overhead if py signatures are not supported
+   : converter::to_python_target_type<A>  //inherits get_pytype
+#endif
+{
+  static PyObject* convert(const B& b)
+  {
+    return incref(object(b.a).ptr());
+  }
+};
+
+// Conversion from python int to A
+struct BFromPython
+{
+  BFromPython()
+  {
+    boost::python::converter::registry::push_back
+        ( &convertible
+        , &construct
+        , type_id< B >()
+#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported
+        , &converter::expected_from_python_type<A>::get_pytype//convertible to A can be converted to B
+#endif
+        );
+  }
+
+  static void* convertible(PyObject* obj_ptr)
+  {
+      extract<const A&> ex(obj_ptr);
+      if (!ex.check()) return 0;
+      return obj_ptr;
+  }
+
+  static void construct(
+      PyObject* obj_ptr,
+      converter::rvalue_from_python_stage1_data* data)
+  {
+    void* storage = (
+        (converter::rvalue_from_python_storage< B >*)data)-> storage.bytes;
+
+    extract<const A&> ex(obj_ptr);
+    new (storage) B(ex());
+    data->convertible = storage;
+  }
+};
+
+
+B func(const B& b) { return b ; }
+
+BOOST_PYTHON_MODULE(pytype_function_ext)
+{
+  to_python_converter< B , BToPython
+#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported
+             ,true
+#endif
+             >(); //has get_pytype
+  BFromPython();
+
+  class_<A>("A") ;
+
+  def("func", &func);
+
+}
+
+
+
+>>> from pytype_function_ext import *
+>>> print func.__doc__
+func( (A)arg1) -> A :
+    C++ signature:
+         struct B func(struct B)
+
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/function_invocation_and_creation/models_of_callpolicies.html b/develop/doc/html/reference/function_invocation_and_creation/models_of_callpolicies.html new file mode 100644 index 00000000..7ee5343d --- /dev/null +++ b/develop/doc/html/reference/function_invocation_and_creation/models_of_callpolicies.html @@ -0,0 +1,1098 @@ + + + +Models of CallPolicies + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ + +
+ +

+ 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. +

+
namespace boost { namespace python
+{
+    struct default_call_policies
+    {
+        static bool precall(PyObject*);
+        static PyObject* postcall(PyObject*, PyObject* result);
+        typedef default_result_converter result_converter;
+        template <class Sig> struct extract_return_type : mpl::front<Sig>{};
+    };
+}}
+
+
+
+ +
bool precall(PyObject*);
+
+

+
+
Returns
+

+ true +

+
Throws
+

+ nothing +

+
+
+
PyObject* postcall(PyObject*, PyObject* result);
+
+

+
+
Returns
+

+ result +

+
Throws
+

+ nothing +

+
+
+
+
+ +

+ 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. +

+
namespace boost { namespace python
+{
+    struct default_result_converter
+    {
+        template <class T> struct apply;
+    };
+}}
+
+
+
+ +
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; +

+
+
+
+
+ +

+ 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;
+};
+
+
+
+
+ + +
+ +

+ return_arg and return_self instantiations are models + of CallPolicies + which return the specified argument parameter (usually *this) + of a wrapped (member) function. +

+
+
+ +
++++++ + + + + + + + + + + + + + + + + + + + + +
+

+ Parameter +

+
+

+ Requirements +

+
+

+ Description +

+
+

+ Default +

+
+

+ arg_pos +

+
+

+ A positive compile-time constant of type std::size_t. +

+
+

+ the position of the argument to be returned. +

+
+

+ 1 +

+
+

+ Base +

+
+

+ A model of CallPolicies +

+
+

+ Used for policy composition. Any result_converter + it supplies will be overridden by return_arg, + but its precall + and postcall + policies are composed as described here CallPolicies. +

+
+

+ default_call_policies +

+
+
namespace boost { namespace python
+{
+   template <size_t arg_pos=1, class Base = default_call_policies>
+   struct return_arg : Base
+   {
+      static PyObject* postcall(PyObject*, PyObject* result);
+      struct result_converter{ template <class T> struct apply; };
+      template <class Sig> struct extract_return_type : mpl::at_c<Sig, arg_pos>{};
+
+   };
+}}
+
+
+
+ +
PyObject* postcall(PyObject* args, PyObject* result);
+
+

+
+
Requires
+

+ PyTuple_Check(args) + != 0 + and PyTuple_Size(args) != 0 +

+
Returns
+

+ PyTuple_GetItem(args,arg_pos-1) +

+
+
+
+
+ +
namespace boost { namespace python
+{
+   template <class Base = default_call_policies>
+   struct return_self
+     : return_arg<1,Base>
+   {};
+}}
+
+
+
+ +

+ C++ module definition: +

+
#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/return_arg.hpp>
+
+struct Widget
+{
+   Widget() :sensitive_(true){}
+   bool get_sensitive() const { return sensitive_; }
+   void set_sensitive(bool s) { this->sensitive_ = s; }
+ private:
+   bool sensitive_;
+};
+
+struct Label : Widget
+{
+   Label() {}
+
+   std::string  get_label() const { return label_; }
+   void set_label(const std::string &l){ label_ = l; }
+
+ private:
+   std::string label_;
+};
+
+using namespace boost::python;
+BOOST_PYTHON_MODULE(return_self_ext)
+{
+   class_<widget>("Widget")
+      .def("sensitive", &Widget::get_sensitive)
+      .def("sensitive", &Widget::set_sensitive, return_self<>())
+      ;
+
+   class_<Label, bases<Widget> >("Label")
+      .def("label", &Label::get_label)
+      .def("label", &Label::set_label, return_self<>())
+      ;
+}
+
+

+ Python code: +

+
>>> from return_self_ext import *
+>>> l1 = Label().label("foo").sensitive(false)
+>>> l2 = Label().sensitive(false).label("foo")
+
+
+
+
+ + +
+ +

+ 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. +

+
+
+ +
++++++ + + + + + + + + + + + + + + + + + + + + +
+

+ 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). + 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. +

+
+
+

+ 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 +

+
+
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;
+   };
+}}
+
+
+
+ +
PyObject* postcall(PyObject* args, PyObject* result);
+
+

+
+
Requires
+

+ PyTuple_Check(args) + != 0 +

+
Returns
+

+ with_custodian_and_ward_postcall::postcall(args, result) +

+
+
+
+
+ +

+ C++ module definition: +

+
#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/return_internal_reference.hpp>
+
+class Bar
+{
+ public:
+   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(internal_refs)
+{
+   class_<Bar>("Bar", init<int>())
+      .def("get_x", &Bar::get_x)
+      .def("set_x", &Bar::set_x)
+      ;
+
+   class_<Foo>("Foo", init<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
+
+
+
+
+ + +
+ +

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

+
+
+ +
+++++ + + + + + + + + + + + + + + + + + +
+

+ Parameter +

+
+

+ Requirements +

+
+

+ Default +

+
+

+ ResultConverterGenerator +

+
+

+ A model of ResultConverterGenerator +

+
+
+

+ Base +

+
+

+ A model of CallPolicies +

+
+

+ default_call_policies +

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

+ 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(my_module)
+{
+   class_<Bar>("Bar");
+
+   class_<Foo>("Foo", init<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
+
+
+
+
+ + +
+ +

+ This header provides facilities for establishing a lifetime dependency + between two of a function's Python argument or result objects. The ward + object will not be destroyed until after the custodian as long as the + custodian object supports weak + references (Boost.Python extension classes all support weak references). + If the custodian object does not support weak references and is not + None, an appropriate + exception will be thrown. The two class templates with_custodian_and_ward + and with_custodian_and_ward_postcall + differ in the point at which they take effect. +

+

+ In order to reduce the chance of inadvertently creating dangling pointers, + the default is to do lifetime binding before the underlying C++ object + is invoked. However, before invocation the result object is not available, + so with_custodian_and_ward_postcall + is provided to bind lifetimes after invocation. Also, if a C++ exception + is thrown after with_custodian_and_ward<>::precall + but before the underlying C++ object actually stores a pointer, the lifetime + of the custodian and ward objects will be artificially bound together, + so one might choose with_custodian_and_ward_postcall + instead, depending on the semantics of the function being wrapped. +

+

+ Please note that this is not the appropriate tool to use when wrapping + functions which transfer ownership of a raw pointer across the function-call + boundary. Please see the FAQ if you want to do that. +

+
+
+ +
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Parameter +

+
+

+ Requirements +

+
+

+ Description +

+
+

+ Default +

+
+

+ custodian +

+
+

+ A positive compile-time constant of type + std::size_t. +

+
+

+ The 1-based index of the parameter which is the dependency + in the lifetime relationship to be established. If used to + wrap a member function, parameter 1 is the target object (*this). + Note that if the target Python object type doesn't support + weak references, a Python TypeError exception will be raised + when the C++ object being wrapped is called. +

+
+
+

+ ward +

+
+

+ A positive compile-time constant of type std::size_t. +

+
+

+ The 1-based index of the parameter which is the dependent in + the lifetime relationship to be established. If used to wrap + a member function, parameter 1 is the target object (*this). +

+
+
+

+ Base +

+
+

+ A model of CallPolicies +

+
+

+ Used for policy composition. +

+
+

+ default_call_policies +

+
+
namespace boost { namespace python
+{
+   template <std::size_t custodian, std::size_t ward, class Base = default_call_policies>
+   struct with_custodian_and_ward : Base
+   {
+      static bool precall(PyObject* args);
+   };
+}}
+
+
+ +
bool precall(PyObject* args);
+
+

+
+
Requires
+

+ PyTuple_Check(args) + != 0 +

+
Effects
+

+ Makes the lifetime of the argument indicated by ward dependent + on the lifetime of the argument indicated by custodian. +

+
Returns
+

+ false and PyErr_Occurred() != 0 upon failure, true otherwise. +

+
+
+
+
+ +
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Parameter +

+
+

+ Requirements +

+
+

+ Description +

+
+

+ Default +

+
+

+ custodian +

+
+

+ A positive compile-time constant of type std::size_t. +

+
+

+ The index of the parameter which is the dependency in the lifetime + relationship to be established. Zero indicates the result object; + 1 indicates the first argument. If used to wrap a member function, + parameter 1 is the target object (*this). Note that if the target + Python object type doesn't support weak references, a Python + TypeError exception will be raised when the C++ object being + wrapped is called. +

+
+
+

+ ward +

+
+

+ A positive compile-time constant of type std::size_t. +

+
+

+ The index of the parameter which is the dependent in the lifetime + relationship to be established. Zero indicates the result object; + 1 indicates the first argument. If used to wrap a member function, + parameter 1 is the target object (*this). +

+
+
+

+ Base +

+
+

+ A model of CallPolicies +

+
+

+ Used for policy composition. +

+
+

+ default_call_policies +

+
+
namespace boost { namespace python
+{
+   template <std::size_t custodian, std::size_t ward, class Base = default_call_policies>
+   struct with_custodian_and_ward_postcall : Base
+   {
+      static PyObject* postcall(PyObject* args, PyObject* result);
+   };
+}}
+
+
+
+ +
PyObject *postcall(PyObject* args, PyObject* result);
+
+

+
+
Requires
+

+ PyTuple_Check(args) + != 0, + result != + 0 +

+
Effects
+

+ Makes the lifetime of the object indicated by ward dependent on + the lifetime of the object indicated by custodian. +

+
Returns
+

+ 0 and PyErr_Occurred() + != 0 + upon failure, true + otherwise. +

+
+
+
+
+ +

+ The following example shows how with_custodian_and_ward_postcall + is used by the library to implement return_internal_reference +

+
template <std::size_t owner_arg = 1, class Base = default_call_policies>
+struct return_internal_reference
+    : with_custodian_and_ward_postcall<0, owner_arg, Base>
+{
+   typedef reference_existing_object result_converter;
+};
+
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/function_invocation_and_creation/models_of_resultconverter.html b/develop/doc/html/reference/function_invocation_and_creation/models_of_resultconverter.html new file mode 100644 index 00000000..ef347171 --- /dev/null +++ b/develop/doc/html/reference/function_invocation_and_creation/models_of_resultconverter.html @@ -0,0 +1,308 @@ + + + +Models of ResultConverter + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ + +
+ + +
<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.
+[endsect]
+
+
+ +

+ 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. +

+
+++++ + + + + + + + + + + + + + + + + + +
+

+ 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. +

+
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();
+  };
+}}
+
+
+
+ +
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. +

+
+
+
+
+ +
bool convertible()
+
+

+
+
Effects
+

+ Returns true iff any module has registered a Python type corresponding + to U. +

+
+
+
+
+
+ +

+ 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;
+   };
+};
+
+
+
+
+ + +
+ +

+ to_python_value is a + model of ResultConverter + which copies its argument into a new Python object. +

+
+
+ +
namespace boost { namespace python
+{
+   template <class T>
+   struct to_python_value
+   {
+      typedef typename add_reference<
+         typename add_const<T>::type
+      >::type argument_type;
+
+      static bool convertible();
+      PyObject* operator()(argument_type) const;
+   };
+}}
+
+
+
+ +
static bool convertible();
+
+

+
+
Returns
+

+ true iff a converter + has been registered which can convert T + to python by-value. +

+
+
+
PyObject* operator()(argument_type x) const;
+
+

+
+
Requires
+

+ convertible() + == true +

+
Effects
+

+ converts x to python +

+
Returns
+

+ the resulting Python object iff a converter for T + has been registered, 0 + otherwise. +

+
+
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/function_invocation_and_creation/models_of_resultconvertergenerat.html b/develop/doc/html/reference/function_invocation_and_creation/models_of_resultconvertergenerat.html new file mode 100644 index 00000000..52557ffe --- /dev/null +++ b/develop/doc/html/reference/function_invocation_and_creation/models_of_resultconvertergenerat.html @@ -0,0 +1,683 @@ + + + +Models of ResultConverterGenerator + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ + +
+ +

+ 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. +

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

+
+
Requires
+

+ T is U const& for some U. +

+
Returns
+

+ typedef to_python_value<T> type; +

+
+
+
+
+ +

+ 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(my_module)
+{
+    class_<Bar>("Bar");
+
+     class_<Foo>("Foo", init<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
+
+
+
+
+ + +
+ +

+ 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. +

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

+
+
Requires
+

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

+
Returns
+

+ typedef to_python_value<T> type; +

+
+
+
+
+ +

+ C++ module definition: +

+
#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(my_module)
+{
+    class_<Bar>("Bar");
+
+     class_<Foo>("Foo", init<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
+
+
+
+
+ + +
+ +

+ 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. +

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

+
+
Requires
+

+ T is U* + for some U. +

+
Returns
+

+ typedef to_python_indirect<T> type; +

+
+
+
+
+ +

+ 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(my_module)
+{
+    def("make_foo", make_foo, return_value_policy<manage_new_object>())
+    class_<Foo>("Foo")
+        .def("get_x", &Foo::get_x)
+        ;
+}
+
+

+ Python code: +

+
>>> from my_module import *
+>>> f = make_foo(3)     # create a Foo object
+>>> f.get_x()
+3
+
+
+
+
+ + +
+ +

+ 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. +

+
namespace boost { namespace python
+{
+    struct reference_existing_object
+    {
+        template <class T> struct apply;
+    };
+}}
+
+
+
+ +
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 class whose static + execute function constructs an instance holder containing an unowned + U* + pointing to the referent of the wrapped function's return value. +

+
+
+
+
+ +

+ 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(singleton)
+{
+    def("get_it", get_it,
+        return_value_policy<reference_existing_object>());
+
+    class_<Singleton>("Singleton")
+       .def("exchange", &Singleton::exchange)
+       ;
+}
+
+

+ Python code: +

+
>>> 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
+
+
+
+
+ + +
+ +

+ return_by_value is a + model of ResultConverterGenerator + which can be used to wrap C++ functions returning any reference or value + type such that the return value is copied into a new Python object. +

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

+
+
Returns
+

+ typedef to_python_value<T> type; +

+
+
+
+
+ +

+ In C++: +

+
#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/return_by_value.hpp>
+#include <boost/python/return_value_policy.hpp>
+
+// classes to wrap
+struct Bar { };
+
+Bar global_bar;
+
+// functions to wrap:
+Bar b1();
+Bar& b2();
+Bar const& b3();
+
+// Wrapper code
+using namespace boost::python;
+template <class R>
+void def_void_function(char const* name, R (*f)())
+{
+   def(name, f, return_value_policy<return_by_value>());
+}
+
+BOOST_PYTHON_MODULE(my_module)
+{
+    class_<Bar>("Bar");
+    def_void_function("b1", b1);
+    def_void_function("b2", b2);
+    def_void_function("b3", b3);
+}
+
+

+ Python code: +

+
>>> from my_module import *
+>>> b = b1() # each of these calls
+>>> b = b2() # creates a brand
+>>> b = b3() # new Bar object
+
+
+
+
+ + +
+ +

+ return_opaque_pointer is a model of ResultConverterGenerator + which can be used to wrap C++ functions returning pointers to undefined + types such that the return value is copied into a new Python object. +

+

+ In addition to specifying the return_opaque_pointer + policy the BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID + macro must be used to define specializations for the type_id function on the type + pointed to by returned pointer. +

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

+
+
Returns
+

+ detail::opaque_conversion_holder<R> + type; +

+
+
+
+
+ +

+ In C++: +

+
# include <boost/python/return_opaque_pointer.hpp>
+# include <boost/python/def.hpp>
+# include <boost/python/module.hpp>
+# include <boost/python/return_value_policy.hpp>
+
+typedef struct opaque_ *opaque;
+
+opaque the_op   = ((opaque) 0x47110815);
+
+opaque get () { return the_op; }
+void use (opaque op) {
+    if (op != the_op)
+	throw std::runtime_error (std::string ("failed"));
+}
+
+void failuse (opaque op) {
+    if (op == the_op)
+	throw std::runtime_error (std::string ("success"));
+}
+
+BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(opaque_)
+
+namespace bpl = boost::python;
+
+BOOST_PYTHON_MODULE(opaque_ext)
+{
+    bpl::def (
+        "get", &::get, bpl::return_value_policy<bpl::return_opaque_pointer>());
+    bpl::def ("use", &::use);
+    bpl::def ("failuse", &::failuse);
+}
+
+

+ Python code: +

+
"""
+>>> from opaque_ext import *
+>>> #
+>>> # Check for correct conversion
+>>> use(get())
+>>> failuse(get())
+Traceback (most recent call last):
+        ...
+RuntimeError: success
+>>> #
+>>> # Check that there is no conversion from integers ...
+>>> use(0)
+Traceback (most recent call last):
+        ...
+TypeError: bad argument type for built-in operation
+>>> #
+>>> # ... and from strings to opaque objects
+>>> use("")
+Traceback (most recent call last):
+        ...
+TypeError: bad argument type for built-in operation
+"""
+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])
+
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/glossary.html b/develop/doc/html/reference/glossary.html new file mode 100644 index 00000000..a085ae86 --- /dev/null +++ b/develop/doc/html/reference/glossary.html @@ -0,0 +1,80 @@ + + + +Chapter 9. Glossary + + + + + + + +
+
+
+PrevUpHome +
+
+

+Chapter 9. Glossary

+
+

+
+
arity
+

+ The number of argumnts accepted by a function or member function. Unless + otherwise specified, the hidden this + argument to member functions is not counted when specifying arity. +

+
ntbs
+

+ Null-Terminated Byte String, or 'C'-string. C++ string literals are + ntbses. An ntbs + must never be null. +

+
raise
+

+ Exceptions in Python are "raised", not "thrown", + as they are in C++. When this documentation says that some Python exception + is "raised" in the context of C++ code, it means that the corresponding + Python exception is set via the Python/'C' + API, and throw_error_already_set() is called. +

+
POD
+

+ A technical term from the C++ standard. Short for "Plain Ol'Data": + A POD-struct is an aggregate class that has no non-static data members + of type pointer to member, non-POD-struct, non-POD-union (or array of + such types) or reference, and has no user-defined copy assign- ment operator + and no user-defined destructor. Similarly, a POD-union is an aggregate + union that has no non-static data members of type pointer to member, + non-POD-struct, non-POD-union (or array of such types) or reference, + and has no user-defined copy assignment operator and no user-defined + destructor. A POD class is a class that is either a POD-struct or a POD-union. + An aggregate is an array or a class (clause 9) with no user-declared + constructors (12.1), no private or protected non-static data members + (clause 11), no base classes (clause 10), and no virtual functions (10.3). +

+
ODR
+

+ The "One Definition Rule", which says that any entity in a + C++ program must have the same definition in all translation units (object + files) which make up a program. +

+
+
+
+ + + +
+
+
+PrevUpHome +
+ + diff --git a/develop/doc/html/reference/high_level_components.html b/develop/doc/html/reference/high_level_components.html new file mode 100644 index 00000000..97492e33 --- /dev/null +++ b/develop/doc/html/reference/high_level_components.html @@ -0,0 +1,1072 @@ + + + +Chapter 2. High Level Components + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+

+Chapter 2. High Level Components

+
+

Table of Contents

+
+
boost/python/class.hpp
+
+
Introduction
+
Class + template class_<T, Bases, HeldType, NonCopyable>
+
Class + template bases<T1, T2, ...TN>
+
Examples
+
+
boost/python/def.hpp
+
+
Introduction
+
Functions
+
Example
+
+
boost/python/def_visitor.hpp
+
+
Introduction
+
Class + def_visitor
+
Example
+
+
boost/python/docstring_options.hpp
+
+
Introduction
+
Class + docstring_options
+
Class + dostring_options constructors
+
Class + docstring_options destructor
+
Class + docstring_options modifier + functions
+
Example
+
+
boost/python/enum.hpp
+
+
Introduction
+
Class + template enum_
+
Class + template enum_ constructors
+
Class + template enum_ modifier functions
+
Example
+
+
boost/python/errors.hpp
+
+
Introduction
+
Class + error_already_set
+
Functions
+
Example
+
+
boost/python/exception_translator.hpp
+
+
Introduction
+
Function + register_exception_translator
+
Example
+
+
boost/python/init.hpp
+
+
Introduction
+
Class + template init
+
Class + template optional
+
Example
+
+
boost/python/iterator.hpp
+
+
Introduction
+
Class + template iterator
+
Class + template iterator constructors
+
Class + template iterators
+
Class + template iterators nested types
+
Class + template iterators static functions
+
Functions
+
Example
+
+
boost/python/module.hpp
+
+
Introduction
+
Macros
+
Examples
+
+
boost/python/operators.hpp
+
+
Introduction
+
Class + self_ns::self_t
+
Class + template other
+
Class + template detail::operator_
+
Object + self
+
Example
+
+
boost/python/scope.hpp
+
+
Introduction
+
Class + scope
+
Class + scope constructors and destructor
+
Example
+
+
boost/python/stl_iterator.hpp
+
+
Introduction
+
Class + template stl_input_iterator
+
Class + template stl_input_iterator + constructors
+
Class + template stl_input_iterator + modifiers
+
Class + template stl_input_iterator + observers
+
Example
+
+
boost/python/wrapper.hpp
+
+
Introduction
+
Class + override
+
Class + override observer functions
+
Class + template wrapper
+
Class + template wrapper observer + functions
+
Example
+
+
+
+
+ + +
+ +

+ <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. + It also exposes the init, + optional and bases utility class templates, which + are used in conjunction with class_. +

+

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

+
+
+ + +

+ Creates a Python class associated with the C++ type passed as its first + parameter. Although it has four template parameters, only the first one + is required. The three optional arguments can actually be supplied in any order; Boost.Python determines the role of + the argument from its type. +

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Template Parameter +

+
+

+ Requirements +

+
+

+ Semantics +

+
+

+ Default +

+
+

+ T +

+
+

+ A class type. +

+
+

+ The class being wrapped +

+
+
+

+ Bases +

+
+

+ A specialization of bases<...> + which specifies previously-exposed C++ base classes of T. +

+
+

+ Registers from_python + conversions from wrapped T + instances to each of its exposed direct and indirect bases. For + each polymorphic base B, + registers conversions from indirectly-held wrapped B instances to T. +

+
+

+ bases<> +

+
+

+ HeldType +

+
+

+ Must be T, a + class derived from T, + or a Dereferenceable + type for which pointee<HeldType>::type + is T or a class + derived from T. +

+
+

+ Specifies the type that is actually embedded in a Python object + wrapping a T + instance when T's + constructor is called or when a T + or T* + is converted to Python without the use of ptr, + ref, or Call Policies such as + return_internal_reference. + More details below. +

+
+

+ T +

+
+

+ NonCopyable +

+
+

+ If supplied, must be boost::noncopyable. +

+
+

+ Suppresses automatic registration of to_python + conversions which copy T + instances. Required when T + has no publicly-accessible copy constructor. +

+
+

+ An unspecified type other than boost::noncopyable. +

+
+
+ +
    +
  1. + If HeldType is derived from T, + its exposed constructor(s) must accept an initial PyObject* argument which refers back to the + Python object that contains the HeldType instance, as shown in this + example. This argument is not included in the init-expression + passed to def(init_expr), + below, nor is it passed explicitly by users when Python instances + of T are created. + This idiom allows C++ virtual functions which will be overridden + in Python to access the Python object so the Python method can be + invoked. Boost.Python automatically registers additional converters + which allow wrapped instances of T + to be passed to wrapped C++ functions expecting HeldType arguments. +
  2. +
  3. + Because Boost.Python will always allow wrapped instances of T to be passed in place of HeldType + arguments, specifying a smart pointer for HeldType allows users to + pass Python T instances + where a smart pointer-to-T is expected. Smart pointers such as std::auto_ptr<> + or boost::shared_ptr<> + which contain a nested type element_type + designating the referent type are automatically supported; additional + smart pointer types can be supported by specializing pointee<HeldType>. +
  4. +
  5. + As in case 1 above, when HeldType is a smart pointer to a class derived + from T, the initial + PyObject* + argument must be supplied by all of HeldType's exposed constructors. +
  6. +
  7. + Except in cases 1 and 3, users may optionally specify that T itself + gets initialized with a similar initial PyObject* argument by specializing has_back_reference<T>. +
  8. +
+
+
+ +
namespace boost { namespace python
+{
+template <class T
+    , class Bases = bases<>
+          , class HeldType = T
+          , class NonCopyable = unspecified
+         >
+class class_ : public object
+{
+  // Constructors with default __init__
+  class_(char const* name);
+  class_(char const* name, char const* docstring);
+
+  // Constructors, specifying non-default __init__
+  template <class Init>
+  class_(char const* name, Init);
+  template <class Init>
+  class_(char const* name, char const* docstring, Init);
+
+  // Exposing additional __init__ functions
+  template <class Init>
+  class_& def(Init);
+
+  // defining methods
+  template <class F>
+  class_& def(char const* name, F f);
+  template <class Fn, class A1>
+  class_& def(char const* name, Fn fn, A1 const&);
+  template <class Fn, class A1, class A2>
+  class_& def(char const* name, Fn fn, A1 const&, A2 const&);
+  template <class Fn, class A1, class A2, class A3>
+  class_& def(char const* name, Fn fn, A1 const&, A2 const&, A3 const&);
+
+  // declaring method as static
+  class_& staticmethod(char const* name);
+
+  // exposing operators
+  template <unspecified>
+  class_& def(detail::operator_<unspecified>);
+
+  // Raw attribute modification
+  template <class U>
+  class_& setattr(char const* name, U const&);
+
+  // exposing data members
+  template <class D>
+  class_& def_readonly(char const* name, D T::*pm);
+
+  template <class D>
+  class_& def_readwrite(char const* name, D T::*pm);
+
+  // exposing static data members
+  template <class D>
+  class_& def_readonly(char const* name, D const& d);
+  template <class D>
+  class_& def_readwrite(char const* name, D& d);
+
+  // property creation
+  template <class Get>
+  void add_property(char const* name, Get const& fget, char const* doc=0);
+  template <class Get, class Set>
+  void add_property(
+      char const* name, Get const& fget, Set const& fset, char const* doc=0);
+
+  template <class Get>
+  void add_static_property(char const* name, Get const& fget);
+  template <class Get, class Set>
+  void add_static_property(char const* name, Get const& fget, Set const& fset);
+
+  // pickle support
+  template <typename PickleSuite>
+  self& def_pickle(PickleSuite const&);
+  self& enable_pickling();
+};
+}}
+
+
+
+ +
class_(char const* name);
+class_(char const* name, char const* docstring);
+template <class Init>
+class_(char const* name, Init init_spec);
+template <class Init>
+class_(char const* name, char const* docstring, Init init_spec);
+
+
+

+
+
Requires
+

+ name is an ntbs which conforms to Python's + identifier + naming rules. If docstring is supplied, it must be an + ntbs. If init_spec + is supplied, it must be either the special enumeration constant + no_init or an + init-expression + compatible with T. +

+
Effects
+
+

+ Constructs a class_ + object holding a Boost.Python extension class named name. The named + attribute of the current + scope is bound to the new extension class. +

+

+ * If supplied, the value of docstring is bound to the __doc__ attribute of the extension + class. * If init_spec + is no_init, a special + __init__ function + is generated which always raises a Python exception. Otherwise, + this->def(init_spec) + is called. * If init_spec + is not supplied, this->def(init<>()) is called. +

+
+
Rationale
+

+ Allowing the user to specify constructor arguments in the class_<> + constructor helps her to avoid the common run-time errors which + result from invoking wrapped member functions without having exposed + an __init__ function + which creates the requisite T + instance. Types which are not default-constructible will cause + a compile-time error unless Init + is supplied. The user must always supply name as there is currently + no portable method to derive the text of the class name from its + type. +

+
+
+
+
+ +
template <class Init>
+class_& def(Init init_expr);
+
+
+

+
+
Requires
+

+ init_expr is the + result of an init-expression + compatible with T. +

+
Effects
+

+ For each valid + prefix P + of Init, adds an + __init__(...) + function overload to the extension class accepting P as arguments. + Each overload generated constructs an object of HeldType according + to the semantics described above, using a copy of init_expr's call + policies. If the longest valid + prefix of Init contains N types and init_expr holds M keywords, + an initial sequence of the keywords are used for all but the first + N - M arguments of each overload. +

+
Returns
+

+ *this +

+
Rationale
+

+ Allows users to easily expose a class' constructor to Python. +

+
+
+
template <class F>
+class_& def(char const* name, Fn fn);
+template <class Fn, class A1>
+class_& def(char const* name, Fn fn, A1 const& a1);
+template <class Fn, class A1, class A2>
+class_& def(char const* name, Fn fn, A1 const& a1, A2 const& a2);
+template <class Fn, class A1, class A2, class A3>
+class_& def(char const* name, Fn fn, A1 const& a1, A2 const& a2, A3 const& a3);
+
+
+

+
+
Requires
+
+

+ name is an ntbs which conforms to Python's + identifier + naming rules. * If a1 is the result of an overload-dispatch-expression, + only the second form is allowed and fn must be a pointer to function + or pointer to member function whose arity + is the same as A1's maximum + arity. +

+

+ Effects: For each prefix P of Fn's + sequence of argument types, beginning with the one whose length + is A1's minimum + arity, adds a name(...) method overload to the extension + class. Each overload generated invokes a1's call-expression with + P, using a copy + of a1's call policies. If the longest valid prefix of A1 contains N + types and a1 holds M + keywords, an initial sequence of the keywords are used for all + but the first N - M + arguments of each overload. +

+

+ * Otherwise, a single method overload is built around fn, which + must not be null: +

+

+ * If fn is a function pointer, its first argument must be of the + form U, U cv&, U cv*, or U cv* const&, where T* is convertible + to U*, and a1-a3, if supplied, may be selected in any order from + the table below. * Otherwise, if fn is a member function pointer, + its target must be T or one of its public base classes, and a1-a3, + if supplied, may be selected in any order from the table below. + * Otherwise, Fn must be [derived from] object, + and a1-a2, if supplied, may be selcted in any order from the first + two rows of the table below. To be useful, fn should be callable. +

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +
+

+ Mnemonic Name +

+
+

+ Requirements/Type properties +

+
+

+ Effects +

+
+

+ docstring +

+
+

+ Any ntbs +

+
+

+ Value will be bound to the __doc__ attribute of the resulting + method overload. If an earlier overload supplied a docstring, + two newline characters and the new docstring are appended + to it. +

+
+

+ policies +

+
+

+ A model of CallPolicies +

+
+

+ A copy will be used as the call policies of the resulting + method overload. +

+
+

+ keywords +

+
+

+ The result of a keyword-expression + specifying no more arguments than the arity + of fn. +

+
+

+ A copy will be used as the call policies of the resulting + method overload. +

+
+
+
Returns
+

+ *this +

+
+
+
class_& staticmethod(char const* name);
+
+

+
+
Requires
+

+ name is an ntbs which conforms to Python's + identifier + naming rules, and corresponds to a method whose overloads + have all been defined. +

+
Effects
+

+ Replaces the existing named attribute x + with the result of invoking staticmethod(x) in Python. Specifies that the + corresponding method is static and therefore no object instance + will be passed to it. This is equivalent to the Python statement: +

+
+
+
setattr(self, name, staticmethod(getattr(self, name)))
+
+

+
+
Note
+

+ Attempting to invoke def(name,...) after invoking staticmethod(name) + will raise a RuntimeError. +

+
Returns
+

+ *this +

+
+
+
template <unspecified>
+class_& def(detail::operator_<unspecified>);
+
+
+

+
+
Effects
+

+ Adds a Python special + method as described here. +

+
Returns
+

+ *this +

+
+
+
template <class U>
+class_& setattr(char const* name, U const& u);
+
+
+

+
+
Requires
+

+ name is an ntbs which conforms to Python's + identifier + naming rules. +

+
Effects
+
+

+ Converts u to Python + and adds it to the attribute dictionary of the extension class: +

+
PyObject_SetAttrString(this->ptr(), name, object(u).ptr());
+
+
Returns
+

+ *this +

+
+
+
template <class Get>
+void add_property(char const* name, Get const& fget, char const* doc=0);
+template <class Get, class Set>
+void add_property(
+      char const* name, Get const& fget, Set const& fset, char const* doc=0);
+
+
+

+
+
Requires
+

+ name is an ntbs which conform to Python's + identifier + naming rules. +

+
Effects
+

+ Creates a new Python property + class instance, passing object(fget) (and object(fset) in the second form) with an (optional) + docstring doc to + its constructor, then adds that property to the Python class object + under construction with the given attribute name. +

+
Returns
+

+ *this +

+
Rationale
+

+ Allows users to easily expose functions that can be invoked from + Python with attribute access syntax. +

+
+
+
template <class Get>
+void add_static_property(char const* name, Get const& fget);
+template <class Get, class Set>
+void add_static_property(char const* name, Get const& fget, Set const& fset);
+
+
+

+
+
Requires
+

+ name is an ntbs which conforms to Python's + identifier + naming rules. +

+
Effects
+

+ Creates a Boost.Python.StaticProperty object, passing object(fget) + (and object(fset) + in the second form) to its constructor, then adds that property + to the Python class under construction with the given attribute + name. StaticProperty is a special subclass of Python's property + class which can be called without an initial self argument. +

+
Returns
+

+ *this +

+
Rationale
+

+ Allows users to easily expose functions that can be invoked from + Python with static attribute access syntax. +

+
+
+
template <class D>
+class_& def_readonly(char const* name, D T::*pm, char const* doc=0);
+template <class D>
+class_& def_readonly(char const* name, D const& d);
+
+
+

+
+
Requires
+

+ name is an ntbs which conforms to Python's + identifier + naming rules. doc + is also an ntbs. +

+
Effects
+
+
this->add_property(name, make_getter(pm), doc);
+

+ and +

+
this->add_static_property(name, make_getter(d));
+

+ respectively. +

+
+
Returns
+

+ *this +

+
Rationale
+

+ Allows users to easily expose a class' data member or free variable + such that it can be inspected from Python with a natural syntax. +

+
+
+
template <class D>
+class_& def_readwrite(char const* name, D T::*pm, char const* doc=0);
+template <class D>
+class_& def_readwrite(char const* name, D& d);
+
+
+

+
+
Effects
+
+
this->add_property(name, make_getter(pm), make_setter(pm), doc);
+

+ and +

+
this->add_static_property(name, make_getter(d), make_setter(d));
+

+ respectively. +

+
+
Returns
+

+ *this +

+
Rationale
+

+ Allows users to easily expose a class' data or free variable member + such that it can be inspected and set from Python with a natural + syntax. +

+
+
+
template <typename PickleSuite>
+class_& def_pickle(PickleSuite const&);
+
+
+

+
+
Requires
+

+ PickleSuite must be publically derived from pickle_suite. +

+
Effects
+

+ Defines a legal combination of the special attributes and methods: + __getinitargs__, __getstate__, __setstate__, __getstate_manages_dict__, + __safe_for_unpickling__, __reduce__ +

+
Returns
+

+ *this +

+
Rationale
+

+ Provides an easy + to use high-level interface for establishing complete pickle support + for the wrapped class. The user is protected by compile-time consistency + checks. +

+
+
+
class_& enable_pickling();
+
+

+
+
Effects
+

+ Defines the __reduce__ method and the __safe_for_unpickling__ attribute. +

+
Returns
+

+ *this +

+
Rationale
+

+ Light-weight alternative to def_pickle(). Enables implementation + of pickle support from Python. +

+
+
+
+
+
+ + +

+ An MPL sequence which can be used in class_<...> instantiations indicate + a list of base classes. +

+
+ +
namespace boost { namespace python
+{
+  template <T1 = unspecified,...Tn = unspecified>
+  struct bases
+  {};
+}}
+
+
+
+
+ +

+ Given a C++ class declaration: +

+
class Foo : public Bar, public Baz
+{
+ public:
+   Foo(int x, char const* y);
+   Foo(double);
+
+   std::string const& name() { return m_name; }
+   void name(char const*);
+
+   double value; // public data
+ private:
+   ...
+};
+
+

+ A corresponding Boost.Python extension class can be created with: +

+
using namespace boost::python;
+
+class_<Foo,bases<Bar,Baz> >("Foo",
+          "This is Foo's docstring."
+          "It describes our Foo extension class",
+
+          init<int,char const*>(args("x","y"), "__init__ docstring")
+          )
+   .def(init<double>())
+   .def("get_name", &Foo::get_name, return_internal_reference<>())
+   .def("set_name", &Foo::set_name)
+   .def_readwrite("value", &Foo::value);
+
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/high_level_components/boost_python_def_hpp.html b/develop/doc/html/reference/high_level_components/boost_python_def_hpp.html new file mode 100644 index 00000000..8cca967b --- /dev/null +++ b/develop/doc/html/reference/high_level_components/boost_python_def_hpp.html @@ -0,0 +1,212 @@ + + + +boost/python/def.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ def() + is the function which can be used to expose C++ functions and callable + objects as Python functions in the current + scope. +

+
+
+ +
template <class F>
+void def(char const* name, F f);
+
+template <class Fn, class A1>
+void def(char const* name, Fn fn, A1 const&);
+
+template <class Fn, class A1, class A2>
+void def(char const* name, Fn fn, A1 const&, A2 const&);
+
+template <class Fn, class A1, class A2, class A3>
+void def(char const* name, Fn fn, A1 const&, A2 const&, A3 const&);
+
+
+

+
+
Requires
+
+

+ name is an ntbs which conforms to Python's + identifier + naming rules. +

+

+ * If Fn is [derived + from] object, + it will be added to the current + scope as a single overload. To be useful, fn + should be callable. + * If a1 is the result + of an overload-dispatch-expression, + only the second form is allowed and fn + must be a pointer to function or pointer to member function whose + arity is the same as A1's maximum + arity. +

+

+ Effects: For each prefix P of Fn's + sequence of argument types, beginning with the one whose length is + A1's minimum + arity, adds a name(...) function overload to the current + scope. Each overload generated invokes a1's call-expression + with P, using a copy of a1's call policies. If the longest valid + prefix of A1 contains N types and a1 holds M keywords, an initial + sequence of the keywords are used for all but the first N - M arguments + of each overload. +

+

+ * Otherwise, fn must be a non-null function or member function pointer, + and a single function overload built around fn is added to the current + scope. If any of a1-a3 are supplied, they may be selected in any + order from the table below. +

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +
+

+ Mnemonic Name +

+
+

+ Requirements/Type properties +

+
+

+ Effects +

+
+

+ docstring +

+
+

+ Any ntbs +

+
+

+ Value will be bound to the __doc__ + attribute of the resulting method overload. +

+
+

+ policies +

+
+

+ A model of CallPolicies +

+
+

+ A copy will be used as the call policies of the resulting + method overload. +

+
+

+ keywords +

+
+

+ The result of a keyword-expression + specifying no more arguments than the arity + of fn. +

+
+

+ A copy will be used as the call policies of the resulting + method overload. +

+
+
+
+
+
+
+ +
#include <boost/python/def.hpp>
+#include <boost/python/module.hpp>
+#include <boost/python/args.hpp>
+
+using namespace boost::python;
+
+char const* foo(int x, int y) { return "foo"; }
+
+BOOST_PYTHON_MODULE(def_test)
+{
+    def("foo", foo, args("x", "y"), "foo's docstring");
+}
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/high_level_components/boost_python_def_visitor_hpp.html b/develop/doc/html/reference/high_level_components/boost_python_def_visitor_hpp.html new file mode 100644 index 00000000..4d4658ab --- /dev/null +++ b/develop/doc/html/reference/high_level_components/boost_python_def_visitor_hpp.html @@ -0,0 +1,208 @@ + + + +boost/python/def_visitor.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ <boost/python/def_visitor.hpp> provides a generic visitation interface + through which the class_ + def member functionality can be extended non-intrusively to avoid cluttering + the class_ + interface. It declares the def_visitor<T> class template, which is parameterized + on the derived type DerivedVisitor, + which provides the actual def + functionality through its visit + member functions. +

+
+
+ +

+ The class def_visitor is + a base class paramaterized by its derived class. The def_visitor + class is a protocol class. Its derived class, DerivedVisitor, is expected + to have a member function visit. + The def_visitor class is + never instantiated directly. Instead, an instance of its subclass, DerivedVisitor, + is passed on as an argument to the class_ + def member function. +

+
namespace boost { namespace python {
+
+    template <class DerivedVisitor>
+    class def_visitor {};
+}
+
+
+

+
+
Requires
+
+

+ The client supplied class DerivedVisitor template parameter is expected + to: * be privately derived from def_visitor * grant friend access + to class def_visitor_access * define either or both visit member + functions listed in the table below: +

+
++++++ + + + + + + + + + + + + + + + + + + + + +
+

+ Expression +

+
+

+ Return Type +

+
+

+ Requirements +

+
+

+ Effects +

+
+

+ visitor.visit(cls) +

+
+

+ void +

+
+

+ cls is + an instance of a class_ + being wrapped to Python. visitor + is a def_visitor + derived class. +

+
+

+ A call to cls.def(visitor) forwards to this member + function. +

+
+

+ visitor.visit(cls, name, options) +

+
+

+ void +

+
+

+ cls is + a class_ + instance, name is a C string. visitor + is a def_visitor + derived class. options is a context specific optional argument. +

+
+

+ A call to cls.def(name, visitor) or cls.def(name, visitor, options) forwards to this member + function. +

+
+
+
+
+
+
+ +
class X {/*...*/};
+
+class my_def_visitor : boost::python::def_visitor<my_def_visitor>
+{
+  friend class def_visitor_access;
+
+  template <class classT>
+  void visit(classT& c) const
+  {
+    c.def("foo", &my_def_visitor::foo);
+    c.def("bar", &my_def_visitor::bar);
+  }
+
+  static void foo(X& self);
+  static void bar(X& self);
+};
+
+BOOST_PYTHON_MODULE(my_ext)
+{
+  class_<X>("X")
+    .def(my_def_visitor());
+}
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/high_level_components/boost_python_docstring_options_h.html b/develop/doc/html/reference/high_level_components/boost_python_docstring_options_h.html new file mode 100644 index 00000000..505a8d21 --- /dev/null +++ b/develop/doc/html/reference/high_level_components/boost_python_docstring_options_h.html @@ -0,0 +1,363 @@ + + + +boost/python/docstring_options.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ Boost.Python supports user-defined docstrings with automatic appending + of C++ signatures. These features are enabled by default. The class docstring_options + is available to selectively suppress the user-defined docstrings, signatures, + or both. +

+
+
+ +

+ Controls the appearance of docstrings of wrapped functions and member functions + for the life-time of the instance. The instances are noncopyable to eliminate + the possibility of surprising side effects. +

+
namespace boost { namespace python {
+
+  class docstring_options : boost::noncopyable
+  {
+  public:
+    docstring_options(bool show_all=true);
+    docstring_options(bool show_user_defined, bool show_signatures);
+    docstring_options(bool show_user_defined, bool show_py_signatures, bool show_cpp_signatures);
+    ~docstring_options();
+    void disable_user_defined();
+    void enable_user_defined();
+    void disable_signatures();
+    void enable_signatures();
+    void disable_py_signatures();
+    void enable_py_signatures();
+    void disable_cpp_signatures();
+    void enable_cpp_signatures();
+    void disable_all();
+    void enable_all();
+  };
+}}
+
+
+
+ +
docstring_options(bool show_all=true);
+
+
+

+
+
Effects
+

+ Constructs a docstring_options object which controls the appearance + of function and member-function docstrings defined in the code that + follows. If show_all is true, both the user-defined docstrings and + the automatically generated Python and C++ signatures are shown. + If show_all is false the __doc__ + attributes are None. +

+
+
+
docstring_options(bool show_user_defined, bool show_signatures);
+
+
+

+
+
Effects
+

+ Constructs a docstring_options + object which controls the appearance of function and member-function + docstrings defined in the code that follows. Iff show_user_defined + is true, the user-defined + docstrings are shown. Iff show_signatures + is true, Python and + C++ signatures are automatically added. If both show_user_defined + and show_signatures + are false, the __doc__ attributes are None. +

+
+
+
docstring_options(bool show_user_defined, bool show_py_signatures, bool show_cpp_signatures);
+
+
+

+
+
Effects
+

+ Constructs a docstring_options + object which controls the appearance of function and member-function + docstrings defined in the code that follows. Iff show_user_defined + is true, the user-defined + docstrings are shown. Iff show_py_signatures + is true, Python signatures + are automatically added. Iff show_cpp_signatures + is true, C++ signatures are automatically added. If all parameters + are false, the __doc__ attributes are None. +

+
+
+
+
+ +
~docstring_options();
+
+

+
+
Effects
+

+ Restores the previous state of the docstring options. In particular, + if docstring_options + instances are in nested C++ scopes the settings effective in the + enclosing scope are restored. If the last docstring_options + instance goes out of scope the default "all on" settings + are restored. +

+
+
+
+
+ +
void disable_user_defined();
+void enable_user_defined();
+void disable_signatures();
+void enable_signatures();
+void disable_py_signatures();
+void enable_py_signatures();
+void disable_cpp_signatures();
+void enable_cpp_signatures();
+void disable_all();
+void enable_all();
+
+

+ These member functions dynamically change the appearance of docstrings + in the code that follows. The *_user_defined() + and *_signatures() member functions are provided for fine-grained + control. The *_all() member functions are convenient shortcuts + to manipulate all settings simultaneously. +

+
+
+ + +
+ +
#include <boost/python/module.hpp>
+#include <boost/python/def.hpp>
+#include <boost/python/docstring_options.hpp>
+
+void foo() {}
+
+BOOST_PYTHON_MODULE(demo)
+{
+    using namespace boost::python;
+    docstring_options doc_options(DEMO_DOCSTRING_SHOW_ALL);
+    def("foo", foo, "foo doc");
+}
+
+

+ If compiled with -DDEMO_DOCSTRING_SHOW_ALL=true: +

+
>>> import demo
+>>> print demo.foo.__doc__
+foo() -> None : foo doc
+C++ signature:
+    foo(void) -> void
+
+

+ If compiled with -DDEMO_DOCSTRING_SHOW_ALL=false: +

+
>>> import demo
+>>> print demo.foo.__doc__
+None
+
+
+
+ +
#include <boost/python/module.hpp>
+#include <boost/python/def.hpp>
+#include <boost/python/args.hpp>
+#include <boost/python/docstring_options.hpp>
+
+int foo1(int i) { return i; }
+int foo2(long l) { return static_cast<int>(l); }
+int foo3(float f) { return static_cast<int>(f); }
+int foo4(double d) { return static_cast<int>(d); }
+
+BOOST_PYTHON_MODULE(demo)
+{
+    using namespace boost::python;
+    docstring_options doc_options;
+    def("foo1", foo1, arg("i"), "foo1 doc");
+    doc_options.disable_user_defined();
+    def("foo2", foo2, arg("l"), "foo2 doc");
+    doc_options.disable_signatures();
+    def("foo3", foo3, arg("f"), "foo3 doc");
+    doc_options.enable_user_defined();
+    def("foo4", foo4, arg("d"), "foo4 doc");
+    doc_options.enable_py_signatures();
+    def("foo5", foo4, arg("d"), "foo5 doc");
+    doc_options.disable_py_signatures();
+    doc_options.enable_cpp_signatures();
+    def("foo6", foo4, arg("d"), "foo6 doc");
+}
+
+

+ Python code: +

+
>>> import demo
+>>> print demo.foo1.__doc__
+foo1( (int)i) -> int : foo1 doc
+C++ signature:
+    foo1(int i) -> int
+>>> print demo.foo2.__doc__
+foo2( (int)l) -> int :
+C++ signature:
+    foo2(long l) -> int
+>>> print demo.foo3.__doc__
+None
+>>> print demo.foo4.__doc__
+foo4 doc
+>>> print demo.foo5.__doc__
+foo5( (float)d) -> int : foo5 doc
+>>> print demo.foo6.__doc__
+foo6 doc
+C++ signature:
+    foo6(double d) -> int
+
+
+
+ +
#include <boost/python/module.hpp>
+#include <boost/python/def.hpp>
+#include <boost/python/args.hpp>
+#include <boost/python/docstring_options.hpp>
+
+int foo1(int i) { return i; }
+int foo2(long l) { return static_cast<int>(l); }
+
+int bar1(int i) { return i; }
+int bar2(long l) { return static_cast<int>(l); }
+
+namespace {
+
+    void wrap_foos()
+    {
+        using namespace boost::python;
+        // no docstring_options here
+        //   -> settings from outer C++ scope are in effect
+        def("foo1", foo1, arg("i"), "foo1 doc");
+        def("foo2", foo2, arg("l"), "foo2 doc");
+    }
+
+    void wrap_bars()
+    {
+        using namespace boost::python;
+        bool show_user_defined = true;
+        bool show_signatures = false;
+        docstring_options doc_options(show_user_defined, show_signatures);
+        def("bar1", bar1, arg("i"), "bar1 doc");
+        def("bar2", bar2, arg("l"), "bar2 doc");
+    }
+}
+
+BOOST_PYTHON_MODULE(demo)
+{
+    boost::python::docstring_options doc_options(false);
+    wrap_foos();
+    wrap_bars();
+}
+
+

+ Python code: +

+
>>> import demo
+>>> print demo.foo1.__doc__
+None
+>>> print demo.foo2.__doc__
+None
+>>> print demo.bar1.__doc__
+bar1 doc
+>>> print demo.bar2.__doc__
+bar2 doc
+
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/high_level_components/boost_python_enum_hpp.html b/develop/doc/html/reference/high_level_components/boost_python_enum_hpp.html new file mode 100644 index 00000000..188e983c --- /dev/null +++ b/develop/doc/html/reference/high_level_components/boost_python_enum_hpp.html @@ -0,0 +1,217 @@ + + + +boost/python/enum.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ <boost/python/enum.hpp> defines the interface through which users + expose their C++ enumeration types to Python. It declares the enum_ class template, which is parameterized + on the enumeration type being exposed. +

+
+
+ +

+ Creates a Python class derived from Python's int + type which is associated with the C++ type passed as its first parameter. +

+
namespace boost { namespace python
+{
+  template <class T>
+  class enum_ : public object
+  {
+    enum_(char const* name, char const* doc = 0);
+    enum_<T>& value(char const* name, T);
+    enum_<T>& export_values();
+  };
+}}
+
+
+
+ +
enum_(char const* name, char const* doc=0);
+
+

+
+
Requires
+

+ name is an ntbs which conforms to Python's + identifier + naming rules. +

+
Effects
+

+ Constructs an enum_ + object holding a Python extension type derived from int which is named name. + The named attribute of the current + scope is bound to the new extension type. +

+
+
+
+
+ +
enum_<T>& value(char const* name, T x);
+
+

+
+
Requires
+

+ name is an ntbs which conforms to Python's + identifier + naming rules. +

+
Effects
+

+ adds an instance of the wrapped enumeration type with value x to + the type's dictionary as the named attribute. +

+
Returns
+

+ *this +

+
+
+
enum_<T>& export_values();
+
+

+
+
Effects
+

+ sets attributes in the current + scope with the same names and values as all enumeration values + exposed so far by calling value(). +

+
Returns
+

+ *this +

+
+
+
+
+ +

+ C++ module definition +

+
#include <boost/python/enum.hpp>
+#include <boost/python/def.hpp>
+#include <boost/python/module.hpp>
+
+using namespace boost::python;
+
+enum color { red = 1, green = 2, blue = 4 };
+
+color identity_(color x) { return x; }
+
+BOOST_PYTHON_MODULE(enums)
+{
+  enum_<color>("color")
+    .value("red", red)
+    .value("green", green)
+    .export_values()
+    .value("blue", blue)
+    ;
+
+  def("identity", identity_);
+}
+
+

+ Interactive Python: +

+
>>> from enums import *
+
+>>> identity(red)
+enums.color.red
+
+>>> identity(color.red)
+enums.color.red
+
+>>> identity(green)
+enums.color.green
+
+>>> identity(color.green)
+enums.color.green
+
+>>> identity(blue)
+Traceback (most recent call last):
+  File "<stdin>", line 1, in ?
+NameError: name 'blue' is not defined
+
+>>> identity(color.blue)
+enums.color.blue
+
+>>> identity(color(1))
+enums.color.red
+
+>>> identity(color(2))
+enums.color.green
+
+>>> identity(color(3))
+enums.color(3)
+
+>>> identity(color(4))
+enums.color.blue
+
+>>> identity(1)
+Traceback (most recent call last):
+  File "<stdin>", line 1, in ?
+TypeError: bad argument type for built-in operation
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/high_level_components/boost_python_errors_hpp.html b/develop/doc/html/reference/high_level_components/boost_python_errors_hpp.html new file mode 100644 index 00000000..137b2264 --- /dev/null +++ b/develop/doc/html/reference/high_level_components/boost_python_errors_hpp.html @@ -0,0 +1,278 @@ + + + +boost/python/errors.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ <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. +

+
+
+ +

+ 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. + Portable code shouldn't throw this exception type directly, but should + instead use throw_error_already_set(), + below. +

+
namespace boost { namespace python
+{
+    class error_already_set {};
+}}
+
+
+
+ +
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 which first attempts + to use all registered exception + translators. If none of those translates the exception, the + catch clauses then set an appropriate Python exception for the C++ + exception caught, returning true if an exception was thrown, 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 necessary 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(), + 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. +

+
+
+
template <class T> T* expect_non_null(T* x);
+
+

+
+
Returns
+

+ x +

+
Throws
+

+ error_already_set() iff x == 0. +

+
Rationale
+

+ Simplifies error-handling when calling functions in the Python/C + API which return 0 on error. +

+
+
+
void throw_error_already_set();
+
+

+
+
Effects
+

+ throw error_already_set(); +

+
Rationale
+

+ Simplifies error-handling when calling functions in the Python/C + API which return 0 on error. +

+
+
+
void throw_error_already_set();
+
+

+
+
Effects
+

+ throw error_already_set(); +

+
Rationale
+

+ Many platforms and compilers are not able to consistently catch exceptions + thrown across shared library boundaries. Using this function from + the Boost.Python library ensures that the appropriate catch block + in handle_exception() can catch the exception. +

+
+
+
+
+ +
#include <string>
+#include <boost/python/errors.hpp>
+#include <boost/python/object.hpp>
+#include <boost/python/handle.hpp>
+
+// Returns a std::string which has the same value as obj's "__name__"
+// attribute.
+std::string get_name(boost::python::object obj)
+{
+   // throws if there's no __name__ attribute
+   PyObject* p = boost::python::expect_non_null(
+      PyObject_GetAttrString(obj.ptr(), "__name__"));
+
+   char const* s = PyString_AsString(p);
+   if (s != 0)
+        Py_DECREF(p);
+
+   // throws if it's not a Python string
+   std::string result(
+      boost::python::expect_non_null(
+         PyString_AsString(p)));
+
+   Py_DECREF(p); // Done with p
+
+   return result;
+}
+
+//
+// Demonstrate form 1 of handle_exception
+//
+
+// Place into result a Python Int object whose value is 1 if a and b have
+// identical "__name__" attributes, 0 otherwise.
+void same_name_impl(PyObject*& result, boost::python::object a, boost::python::object b)
+{
+   result = PyInt_FromLong(
+      get_name(a) == get_name(a2));
+}
+
+object borrowed_object(PyObject* p)
+{
+   return boost::python::object(
+        boost::python::handle<>(
+             boost::python::borrowed(a1)));
+}
+
+// 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), borrowed_object(a1), borrowed_object(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(borrowed_object(a1)) == get_name(borrowed_object(a2)));
+   }
+   catch(...)
+   {
+      // If an exception was thrown, translate it to Python
+      boost::python::handle_exception();
+      return 0;
+   }
+}
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/high_level_components/boost_python_exception_translato.html b/develop/doc/html/reference/high_level_components/boost_python_exception_translato.html new file mode 100644 index 00000000..019640a1 --- /dev/null +++ b/develop/doc/html/reference/high_level_components/boost_python_exception_translato.html @@ -0,0 +1,130 @@ + + + +boost/python/exception_translator.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ As described here, + it is important to make sure that exceptions thrown by C++ code do not + pass into the Python interpreter core. By default, Boost.Python translates + all C++ exceptions thrown by wrapped functions and module init functions + into Python, but the default translators are extremely limited: most C++ + exceptions will appear in Python as a RuntimeError + exception whose representation is 'Unidentifiable C++ Exception'. To produce + better error messages, users can register additional exception translators + as described below. +

+
+
+ +
template<class ExceptionType, class Translate>
+void register_exception_translator(Translate translate);
+
+
+

+
+
Requires
+
+

+ Translate is CopyConstructible, and the following code must be well-formed: +

+
void f(ExceptionType x) { translate(x); }
+

+ . The expression translate(x) must either throw a C++ exception, + or a subsequent call to PyErr_Occurred() must return 1. +

+
+
Effects
+

+ Adds a copy of translate to the sequence of exception translators + tried when Boost.Python catches an exception that is about to pass + into Python's core interpreter. The new translator will get "first + shot" at translating all exceptions matching the catch clause + shown above. Any subsequently-registered translators will be allowed + to translate the exception earlier. A translator which cannot translate + a given C++ exception can re-throw it, and it will be handled by + a translator which was registered earlier (or by the default translator). +

+
+
+
+
+ +
#include <boost/python/module.hpp>
+#include <boost/python/def.hpp>
+#include <boost/python/exception_translator.hpp>
+#include <exception>
+
+struct my_exception : std::exception
+{
+  char const* what() throw() { return "One of my exceptions"; }
+};
+
+void translate(my_exception const& e)
+{
+    // Use the Python 'C' API to set up an exception object
+    PyErr_SetString(PyExc_RuntimeError, e.what());
+}
+
+void something_which_throws()
+{
+    ...
+    throw my_exception();
+    ...
+}
+
+BOOST_PYTHON_MODULE(exception_translator_ext)
+{
+  using namespace boost::python;
+  register_exception_translator<my_exception>(&translate);
+
+  def("something_which_throws", something_which_throws);
+}
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/high_level_components/boost_python_init_hpp.html b/develop/doc/html/reference/high_level_components/boost_python_init_hpp.html new file mode 100644 index 00000000..7a3b5cf0 --- /dev/null +++ b/develop/doc/html/reference/high_level_components/boost_python_init_hpp.html @@ -0,0 +1,233 @@ + + + +boost/python/init.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ + +

+ <boost/python/init.hpp> defines the interface for exposing C++ constructors + to Python as extension class __init__ + functions. +

+
+ +

+ An init-expression is used to describe a family of __init__ + methods to be generated for an extension class, and the result has the + following properties: +

+
+

+
+
docstring
+

+ An ntbs whose value will bound to the + method's __doc__ + attribute +

+
keywords
+

+ A keyword-expression + which will be used to name (a trailing subsequence of) the arguments + to the generated __init__ + function(s). +

+
call_policies
+

+ An instance of a model of CallPolicies. +

+
argument_types
+

+ An MPL sequence of C++ argument types which will be used to construct + the wrapped C++ object. An init expression has one or more valid + prefixes which are given by a sequence of prefixes of its argument + types. +

+
+
+
+
+
+ + +

+ A MPL sequence which can be used to specify a family of one or more __init__ + functions. Only the last Ti supplied may be an instantiation of optional<...>. +

+
namespace boost { namespace python
+{
+  template <T1 = unspecified,...Tn = unspecified>
+  struct init
+  {
+    init(char const* doc = 0);
+    template <class Keywords> init(Keywords const& kw, char const* doc = 0);
+    template <class Keywords> init(char const* doc, Keywords const& kw);
+
+    template <class CallPolicies>
+    unspecified operator[](CallPolicies const& policies) const
+  };
+}}
+
+
+ +
init(char const* doc = 0);
+template <class Keywords> init(Keywords const& kw, char const* doc = 0);
+template <class Keywords> init(char const* doc, Keywords const& kw);
+
+
+

+
+
Requires
+

+ If supplied, doc is an ntbs. If supplied, + kw is the result of a +

+
Effects
+
+

+ The result is an init-expression whose docstring is doc and whose + keywords are a reference to kw. If the first form is used, the + resulting expression's keywords are empty. The expression's call + policies are an instance of default_call_policies. + If Tn is optional<U1, + U2,... Um>, the expression's valid prefixes are given + by: +

+
(T1, T2,...Tn-1), (T1, T2,...Tn-1 , U1), (T1, T2,...Tn-1 , U1, U2), ...(T1, T2,...Tn-1 , U1, U2,...Um)
+

+ . Otherwise, the expression has one valid prefix given by the template + arguments the user specified. +

+
+
+
+
+
+ +
template <class Policies>
+unspecified operator[](Policies const& policies) const
+
+
+

+
+
Requires
+

+ Policies is a model of CallPolicies. +

+
Effects
+

+ Returns a new init-expression + with all the same properties as the init object except that its + call policies are replaced by a reference to policies. +

+
+
+
+
+
+ +

+ A MPL sequence which can be used to specify the optional arguments to an + __init__ function. +

+
namespace boost { namespace python
+{
+  template <T1 = unspecified,...Tn = unspecified>
+  struct optional {};
+}}
+
+
+
+ +

+ Given the C++ declarations: +

+
class Y;
+class X
+{
+ public:
+   X(int x, Y* y) : m_y(y) {}
+   X(double);
+ private:
+   Y* m_y;
+};
+
+

+ A corresponing Boost.Python extension class can be created with: +

+
using namespace boost::python;
+
+class_<X>("X", "This is X's docstring.",
+          init<int,char const*>(args("x","y"), "X.__init__'s docstring")[
+                with_custodian_and_ward<1,3>()]
+          )
+   .def(init<double>())
+   ;
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/high_level_components/boost_python_iterator_hpp.html b/develop/doc/html/reference/high_level_components/boost_python_iterator_hpp.html new file mode 100644 index 00000000..4161bbfa --- /dev/null +++ b/develop/doc/html/reference/high_level_components/boost_python_iterator_hpp.html @@ -0,0 +1,391 @@ + + + +boost/python/iterator.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ <boost/python/iterator.hpp> provides types and functions for creating + Python + iterators from C++ Containers and Iterators. Note that if your + class_ supports random-access + iterators, implementing __getitem__ + (also known as the Sequence Protocol) may serve you better than using this + facility: Python will automatically create an iterator type for you (see + iter()), + and each access can be range-checked, leaving no possiblity of accessing + through an invalidated C++ iterator. +

+
+
+ +

+ Instances of iterator<C,P> hold a reference to a callable Python + object which, when invoked from Python, expects a single argument c convertible + to C and creates a Python iterator that traverses [c.begin(), c.end()). The optional CallPolicies + P can be used to control + how elements are returned during iteration. +

+

+ In the table below, c is an instance of Container. +

+
++++++ + + + + + + + + + + + + + + + + + + + + +
+

+ Template Parameter +

+
+

+ Requirements +

+
+

+ Semantics +

+
+

+ Default +

+
+

+ Container +

+
+

+ [c.begin(),c.end()) is a valid Iterator range. +

+
+

+ The result will convert its argument to c and call c.begin() + and c.end() to acquire iterators. To invoke Container's const + begin() + and end() + functions, make it const. +

+
+
+

+ NextPolicies +

+
+

+ A default-constructible model of CallPolicies. +

+
+

+ Applied to the resulting iterators' next() method. +

+
+

+ An unspecified model of CallPolicies + which always makes a copy of the result of deferencing the underlying + C++ iterator +

+
+
namespace boost { namespace python
+  {
+    template <class Container, class NextPolicies = unspecified>
+    struct iterator : object
+    {
+      iterator();
+    };
+  }}
+
+
+
+ +
iterator()
+
+

+
+
Effects
+
+

+ Initializes its base class with the result of: +

+
range<NextPolicies>(&iterators<Container>::begin, &iterators<Container>::end)
+
+
Postconditions
+

+ this->get() + points to a Python callable object which creates a Python iterator + as described above. +

+
Rationale
+

+ Provides an easy way to create iterators for the common case where + a C++ class being wrapped provides begin() and end(). +

+
+
+
+
+ +

+ A utility class template which provides a way to reliably call its argument's + begin() + and end() + member functions. Note that there is no portable way to take the address + of a member function of a C++ standard library container, so iterators<> + can be particularly helpful when wrapping them. +

+

+ In the table below, x is an instance of C. +

+
++++ + + + + + + + + + + + + + + +
+

+ Required Valid Expression +

+
+

+ Type +

+
+

+ x.begin() +

+
+

+ Convertible to C::const_iterator if C is a const type; convertible + to C::iterator otherwise. +

+
+

+ x.end() +

+
+

+ Convertible to C::const_iterator if C is a const type; convertible + to C::iterator otherwise. +

+
+
namespace boost { namespace python
+{
+  template <class C>
+  struct iterators
+  {
+      typedef typename C::const_iterator iterator;
+      static iterator begin(C& x);
+      static iterator end(C& x);
+  };
+}}
+
+
+
+ +

+ If C is a const type, +

+
typedef typename C::const_iterator iterator;
+

+ Otherwise: +

+
typedef typename C::iterator iterator;
+
+
+ +
static iterator begin(C&);
+
+

+
+
Returns
+

+ x.begin() +

+
+
+
static iterator end(C&);
+
+

+
+
Returns
+

+ x.end() +

+
+
+
+
+ +
template <class NextPolicies, class Target, class Accessor1, class Accessor2>
+object range(Accessor1 start, Accessor2 finish);
+
+template <class NextPolicies, class Accessor1, class Accessor2>
+object range(Accessor1 start, Accessor2 finish);
+
+template <class Accessor1, class Accessor2>
+object range(Accessor1 start, Accessor2 finish);
+
+
+

+
+
Requires
+

+ NextPolicies is a default-constructible model of CallPolicies. +

+
Effects
+
+

+ The first form creates a Python callable object which, when invoked, + converts its argument to a Target object x, and creates a Python + iterator which traverses [bind(start,_1)(x), bind(finish,_1)(x)), + applying NextPolicies to the iterator's next() function. The second form is identical + to the first, except that Target is deduced from Accessor1 as follows: +

+

+ # If Accessor1 is a function type, Target is the type of its first + argument. # If Accessor1 is a data member pointer of the form R (T::*), + Target is identical to T. + # If Accessor1 is a member function pointer of the form R (T::*)(arguments...) + cv-opt, where cv-opt is an optional + cv-qualifier, Target is identical to T. +

+

+ The third form is identical to the second, except that NextPolicies + is an unspecified model of CallPolicies + which always makes a copy of the result of deferencing the underlying + C++ iterator +

+
+
Rationale
+

+ The use of boost::bind() allows C++ iterators to be accessed + through functions, member functions or data member pointers. Customization + of NextPolicies (e.g. using return_internal_reference) + is useful when it is expensive to copy sequence elements of a wrapped + class type. Customization of Target is useful when Accessor1 is a + function object, or when a base class of the intended target type + would otherwise be deduced. +

+
+
+
+
+ +
#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+
+#include <vector>
+
+using namespace boost::python;
+BOOST_PYTHON_MODULE(demo)
+{
+    class_<std::vector<double> >("dvec")
+        .def("__iter__", iterator<std::vector<double> >())
+        ;
+}
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/high_level_components/boost_python_module_hpp.html b/develop/doc/html/reference/high_level_components/boost_python_module_hpp.html new file mode 100644 index 00000000..6f2c47ba --- /dev/null +++ b/develop/doc/html/reference/high_level_components/boost_python_module_hpp.html @@ -0,0 +1,111 @@ + + + +boost/python/module.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ This header provides the basic facilities needed to create a Boost.Python + extension module. +

+
+
+

+Macros +

+

+ BOOST_PYTHON_MODULE(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 +

+
extern "C" void initname()
+{
+   ...
+}
+
+

+ Boost.Python modules should be initialized with +

+
BOOST_PYTHON_MODULE(name)
+{
+   ...
+}
+
+

+ This macro generates two functions in the scope where it is used: extern "C" + void initname(), and void + init_module_name(), + whose body must follow the macro invocation. init_name + passes init_module_name + to handle_exception() + so that any C++ exceptions generated are safely processeed. During the + body of init_name, the + current scope + refers to the module being initialized. +

+
+
+ +

+ C++ module definition: +

+
#include <boost/python/module.hpp>
+
+BOOST_PYTHON_MODULE(xxx)
+{
+    throw "something bad happened"
+}
+
+

+ Interactive Python: +

+
>>> import xxx
+Traceback (most recent call last):
+  File "", line 1, in ?
+RuntimeError: Unidentifiable C++ Exception
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/high_level_components/boost_python_operators_hpp.html b/develop/doc/html/reference/high_level_components/boost_python_operators_hpp.html new file mode 100644 index 00000000..fe528585 --- /dev/null +++ b/develop/doc/html/reference/high_level_components/boost_python_operators_hpp.html @@ -0,0 +1,1558 @@ + + + +boost/python/operators.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ <boost/python/operators.hpp> provides types and functions for automatically + generating Python special + methods from the corresponding C++ constructs. Most of these constructs + are operator expressions, hence the name. To use the facility, substitute + the self + object for an object of the class type being wrapped in the expression + to be exposed, and pass the result to class_<>::def(). + Much of what is exposed in this header should be considered part of the + implementation, so is not documented in detail here. +

+
+
+ + +

+ self_ns::self_t is the actual type of the self + object. The library isolates self_t + in its own namespace, self_ns, + in order to prevent the generalized operator templates which operate on + it from being found by argument-dependent lookup in other contexts. This + should be considered an implementation detail, since users should never + have to mention self_t + directly. +

+
namespace boost { namespace python { namespace self_ns {
+{
+   unspecified-type-declaration self_t;
+
+   // inplace operators
+   template <class T> operator_<unspecified> operator+=(self_t, T);
+   template <class T> operator_<unspecified> operator-=(self_t, T);
+   template <class T> operator_<unspecified> operator*=(self_t, T);
+   template <class T> operator_<unspecified> operator/=(self_t, T);
+   template <class T> operator_<unspecified> operator%=(self_t, T);
+   template <class T> operator_<unspecified> operator>>=(self_t, T);
+   template <class T> operator_<unspecified> operator<<=(self_t, T);
+   template <class T> operator_<unspecified> operator&=(self_t, T);
+   template <class T> operator_<unspecified> operator^=(self_t, T);
+   template <class T> operator_<unspecified> operator|=(self_t, T);
+
+   // comparisons
+   template <class L, class R> operator_<unspecified> operator==(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator!=(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator<(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator>(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator<=(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator>=(L const&, R const&);
+
+   // non-member operations
+   template <class L, class R> operator_<unspecified> operator+(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator-(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator*(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator/(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator%(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator>>(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator<<(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator&(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator^(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator|(L const&, R const&);
+   template <class L, class R> operator_<unspecified> pow(L const&, R const&);
+
+   // unary operations
+   operator_<unspecified> operator-(self_t);
+   operator_<unspecified> operator+(self_t);
+   operator_<unspecified> operator~(self_t);
+   operator_<unspecified> operator!(self_t);
+
+   // value operations
+   operator_<unspecified> int_(self_t);
+   operator_<unspecified> long_(self_t);
+   operator_<unspecified> float_(self_t);
+   operator_<unspecified> complex_(self_t);
+   operator_<unspecified> str(self_t);
+
+   operator_<unspecified> repr(self_t);
+}}};
+
+

+ The tables below describe the methods generated when the results of the + expressions described are passed as arguments to class_<>::def(). + x is an object of the class + type being wrapped. +

+
+ +

+ In the table below, If r + is an object of type other<T>, + y is an object of type + T; otherwise, y is an object of the same type as + r. +

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ C++ Expression +

+
+

+ Python Method Name +

+
+

+ C++ Implementation +

+
+

+ self += + r +

+
+

+ __iadd__ +

+
+

+ x += + y +

+
+

+ self -= + r +

+
+

+ __isub__ +

+
+

+ x -= + y +

+
+

+ self *= + r +

+
+

+ __imul__ +

+
+

+ x *= + y +

+
+

+ self /= + r +

+
+

+ __idiv__ +

+
+

+ x /= + y +

+
+

+ self %= + r +

+
+

+ __imod__ +

+
+

+ x %= + y +

+
+

+ self >>= + r +

+
+

+ __irshift__ +

+
+

+ x >>= + y +

+
+

+ self <<= + r +

+
+

+ __ilshift__ +

+
+

+ x <<= + y +

+
+

+ self &= + r +

+
+

+ __iand__ +

+
+

+ x &= + y +

+
+

+ self ^= + r +

+
+

+ __ixor__ +

+
+

+ x ^= + y +

+
+

+ self |= + r +

+
+

+ __ior__ +

+
+

+ x |= + y +

+
+
+
+ +

+ In the tables below, if r + is of type self_t, + y is an object of the + same type as x; if l or r + is an object of type other<T>, + y is an object of type + T; otherwise, y is an object of the same type as + l or r. + l is never of type self_t. +

+

+ The column of Python Expressions illustrates the expressions that will + be supported in Python for objects convertible to the types of x and + y. The secondary operation arises due to Python's reflection + rules for rich comparison operators, and are only used when the + corresponding operation is not defined as a method of the y object. +

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ C++ Expression +

+
+

+ Python Method Name +

+
+

+ C++ Implementation +

+
+

+ Python Expression (primary, secondary) +

+
+

+ self == + r +

+
+

+ __eq__ +

+
+

+ x == + y +

+
+

+ x == + y, y == + x +

+
+

+ l == + self +

+
+

+ __eq__ +

+
+

+ y == + x +

+
+

+ y == + x, x == + y +

+
+

+ self != + r +

+
+

+ __nq__ +

+
+

+ x != + y +

+
+

+ x != + y, y != + x +

+
+

+ l != + self +

+
+

+ __nq__ +

+
+

+ y != + x +

+
+

+ y != + x, x != + y +

+
+

+ self < + r +

+
+

+ __lt__ +

+
+

+ x < + y +

+
+

+ x < + y, y > + x +

+
+

+ l < + self +

+
+

+ __gt__ +

+
+

+ y < + x +

+
+

+ y > + x, x < + y +

+
+

+ self > + r +

+
+

+ __gt__ +

+
+

+ x > + y +

+
+

+ x > + y, y < + x +

+
+

+ l > + self +

+
+

+ __lt__ +

+
+

+ y > + x +

+
+

+ y < + x, x > + y +

+
+

+ self <= + r +

+
+

+ __le__ +

+
+

+ x <= + y +

+
+

+ x <= + y, y >= + x +

+
+

+ l <= + self +

+
+

+ __ge__ +

+
+

+ y <= + x +

+
+

+ y >= + x, x <= + y +

+
+

+ self >= + r +

+
+

+ __ge__ +

+
+

+ x >= + y +

+
+

+ x >= + y, y <= + x +

+
+

+ l <= + self +

+
+

+ __le__ +

+
+

+ y >= + x +

+
+

+ y <= + x, x >= + y +

+
+
+
+ +

+ The operations whose names begin with "__r" below will only + be called if the left-hand operand does not already support the given + operation, as described here. +

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ C++ Expression +

+
+

+ Python Method Name +

+
+

+ C++ Implementation +

+
+

+ self + + r +

+
+

+ __add__ +

+
+

+ x + + y +

+
+

+ l + + self +

+
+

+ __radd__ +

+
+

+ y + + x +

+
+

+ self - + r +

+
+

+ __sub__ +

+
+

+ x - + y +

+
+

+ l - + self +

+
+

+ __rsub__ +

+
+

+ y - + x +

+
+

+ self * + r +

+
+

+ __mult__ +

+
+

+ x * + y +

+
+

+ l * + self +

+
+

+ __rmult__ +

+
+

+ y * + x +

+
+

+ self / + r +

+
+

+ __div__ +

+
+

+ x / + y +

+
+

+ l / + self +

+
+

+ __rdiv__ +

+
+

+ y / + x +

+
+

+ self % + r +

+
+

+ __mod__ +

+
+

+ x % + y +

+
+

+ l % + self +

+
+

+ __rmod__ +

+
+

+ y % + x +

+
+

+ self >> + r +

+
+

+ __rshift__ +

+
+

+ x >> + y +

+
+

+ l >> + self +

+
+

+ __rrshift__ +

+
+

+ y >> + x +

+
+

+ self << + r +

+
+

+ __lshift__ +

+
+

+ x << + y +

+
+

+ l << + self +

+
+

+ __rlshift__ +

+
+

+ y << + x +

+
+

+ self & + r +

+
+

+ __and__ +

+
+

+ x & + y +

+
+

+ l & + self +

+
+

+ __rand__ +

+
+

+ y & + x +

+
+

+ self ^ + r +

+
+

+ __xor__ +

+
+

+ x ^ + y +

+
+

+ l ^ + self +

+
+

+ __rxor__ +

+
+

+ y ^ + x +

+
+

+ self | + r +

+
+

+ __or__ +

+
+

+ x | + y +

+
+

+ l | + self +

+
+

+ __ror__ +

+
+

+ y | + x +

+
+

+ pow(self, + r) +

+
+

+ __pow__ +

+
+

+ x ** + y +

+
+

+ pow(l, + self) +

+
+

+ __rpow__ +

+
+

+ y ** + x +

+
+
+
+ +
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ C++ Expression +

+
+

+ Python Method Name +

+
+

+ C++ Implementation +

+
+

+ -self +

+
+

+ __neg__ +

+
+

+ -x +

+
+

+ +self +

+
+

+ __pos__ +

+
+

+ +x +

+
+

+ ~self +

+
+

+ __invert__ +

+
+

+ ~x +

+
+

+ not self + or !self +

+
+

+ __nonzero__ +

+
+

+ !!x +

+
+
+
+ +
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ C++ Expression +

+
+

+ Python Method Name +

+
+

+ C++ Implementation +

+
+

+ int_(self) +

+
+

+ __int__ +

+
+

+ long(x) +

+
+

+ long_(self) +

+
+

+ __long__ +

+
+

+ PyLong_FromLong(x) +

+
+

+ float_(self) +

+
+

+ __float__ +

+
+

+ double(x) +

+
+

+ complex_(self) +

+
+

+ __complex__ +

+
+

+ std::complex<double>(x) +

+
+

+ str(self) +

+
+

+ __str__ +

+
+

+ lexical_cast<std::string>(x) +

+
+

+ repr(self) +

+
+

+ __repr__ +

+
+

+ lexical_cast<std::string>(x) +

+
+
+
+
+ +

+ Instances of other<T> + can be used in operator expressions with self; + the result is equivalent to the same expression with a T + object in place of other<T>. Use other<T> to prevent construction of a T object in case it is heavyweight, when + no constructor is available, or simply for clarity. +

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

+ Instantiations of detail::operator_<> are used as the return type of + operator expressions involving self. + This should be considered an implementation detail and is only documented + here as a way of showing how the result of self-expressions match calls + to class_<>::def(). +

+
namespace boost { namespace python { namespace detail
+{
+  template <unspecified>
+  struct operator_
+  {
+  };
+}}}
+
+
+
+ +
namespace boost { namespace python
+{
+  using self_ns::self;
+}}
+
+
+
+ +
#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/operators.hpp>
+#include <boost/operators.hpp>
+
+struct number
+   : boost::integer_arithmetic<number>
+{
+    explicit number(long x_) : x(x_) {}
+    operator long() const { return x; }
+
+    template <class T>
+    number& operator+=(T const& rhs)
+    { x += rhs; return *this; }
+
+    template <class T>
+    number& operator-=(T const& rhs)
+    { x -= rhs; return *this; }
+
+    template <class T>
+    number& operator*=(T const& rhs)
+    { x *= rhs; return *this; }
+
+    template <class T>
+    number& operator/=(T const& rhs)
+    { x /= rhs; return *this; }
+
+    template <class T>
+    number& operator%=(T const& rhs)
+    { x %= rhs; return *this; }
+
+   long x;
+};
+
+using namespace boost::python;
+BOOST_PYTHON_MODULE(demo)
+{
+   class_<number>("number", init<long>())
+      // interoperate with self
+      .def(self += self)
+      .def(self + self)
+      .def(self -= self)
+      .def(self - self)
+      .def(self *= self)
+      .def(self * self)
+      .def(self /= self)
+      .def(self / self)
+      .def(self %= self)
+      .def(self % self)
+
+      // Convert to Python int
+      .def(int_(self))
+
+      // interoperate with long
+      .def(self += long())
+      .def(self + long())
+      .def(long() + self)
+      .def(self -= long())
+      .def(self - long())
+      .def(long() - self)
+      .def(self *= long())
+      .def(self * long())
+      .def(long() * self)
+      .def(self /= long())
+      .def(self / long())
+      .def(long() / self)
+      .def(self %= long())
+      .def(self % long())
+      .def(long() % self)
+      ;
+}
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/high_level_components/boost_python_scope_hpp.html b/develop/doc/html/reference/high_level_components/boost_python_scope_hpp.html new file mode 100644 index 00000000..85c2c172 --- /dev/null +++ b/develop/doc/html/reference/high_level_components/boost_python_scope_hpp.html @@ -0,0 +1,160 @@ + + + +boost/python/scope.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ Defines facilities for querying and controlling the Python scope (namespace) + which will contain new wrapped classes and functions. +

+
+
+ +

+ The scope class has an associated global Python object which controls the + Python namespace in which new extension classes and wrapped functions will + be defined as attributes. Default-constructing a new scope object binds + it to the associated global Python object. Constructing a scope object + with an argument changes the associated global Python object to the one + held by the argument, until the lifetime of the scope object ends, at which + time the associated global Python object reverts to what it was before + the scope object was constructed. +

+
namespace boost { namespace python
+{
+  class scope : public object
+  {
+   public:
+      scope(scope const&);
+      scope(object const&);
+      scope();
+      ~scope()
+   private:
+      void operator=(scope const&);
+  };
+}}
+
+
+
+ +
explicit scope(scope const& x);
+explicit scope(object const& x);
+
+

+ Stores a reference to the current associated scope object, and sets the + associated scope object to the one referred to by x.ptr(). The object base + class is initialized with x. +

+
scope();
+

+ Stores a reference to the current associated scope object. The object base + class is initialized with the current associated scope object. Outside + any module initialization function, the current associated Python object + is None. +

+
~scope()
+

+ Sets the current associated Python object to the stored object. +

+
+
+ +

+ The following example shows how scope setting can be used to define nested + classes. +

+

+ C++ Module definition: +

+
#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/scope.hpp>
+using namespace boost::python;
+
+struct X
+{
+  void f() {}
+
+  struct Y { int g() { return 42; } };
+};
+
+BOOST_PYTHON_MODULE(nested)
+{
+   // add some constants to the current (module) scope
+   scope().attr("yes") = 1;
+   scope().attr("no") = 0;
+
+   // Change the current scope 
+   scope outer
+       = class_<X>("X")
+            .def("f", &X::f)
+            ;
+
+   // Define a class Y in the current scope, X
+   class_<X::Y>("Y")
+      .def("g", &X::Y::g)
+      ;
+}
+
+

+ Interactive Python: +

+
>>> import nested
+>>> nested.yes
+1
+>>> y = nested.X.Y()
+>>> y.g()
+42
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/high_level_components/boost_python_stl_iterator_hpp.html b/develop/doc/html/reference/high_level_components/boost_python_stl_iterator_hpp.html new file mode 100644 index 00000000..68995855 --- /dev/null +++ b/develop/doc/html/reference/high_level_components/boost_python_stl_iterator_hpp.html @@ -0,0 +1,311 @@ + + + +boost/python/stl_iterator.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ <boost/python/stl_iterator.hpp> provides types for creating C++ Iterators + from Python + iterables. +

+
+
+ +

+ Instances of stl_input_iterator<T> hold a Python iterator and adapt it + for use with STL algorithms. stl_input_iterator<T> satisfies the requirements for an Input + Iterator. +

+
++++++ + + + + + + + + + + + + +
+

+ Template Parameter +

+
+

+ Requirements +

+
+

+ Semantics +

+
+

+ Default +

+
+

+ ValueType +

+
+

+ ValueType must be CopyConstructible. +

+
+

+ Dereferencing an instance of stl_input_iterator<ValueType> will return an rvalue of + type ValueType. +

+
+

+ None +

+
+
namespace boost { namespace python
+{
+  template <class ValueType>
+  struct stl_input_iterator
+  {
+      typedef std::ptrdiff_t difference_type;
+      typedef ValueType value_type;
+      typedef ValueType* pointer;
+      typedef ValueType reference;
+      typedef std::input_iterator_tag iterator_category;
+
+      stl_input_iterator();
+      stl_input_iterator(object const& ob);
+
+      stl_input_iterator& operator++();
+      stl_input_iterator operator++(int);
+
+      ValueType operator*() const;
+
+      friend bool operator==(stl_input_iterator const& lhs, stl_input_iterator const& rhs);
+      friend bool operator!=(stl_input_iterator const& lhs, stl_input_iterator const& rhs);
+  private:
+      object it; // For exposition only
+      object ob; // For exposition only
+  };
+}}
+
+
+
+ +
stl_input_iterator()
+
+
+

+
+
Effects
+

+ Creates a past-the-end input iterator, useful for signifying the + end of a sequence. +

+
Postconditions
+

+ this is past-the-end +

+
Throws
+

+ Nothing. +

+
+
+
stl_input_iterator(object const& ob)
+
+

+
+
Effects
+

+ Calls ob.attr("__iter__")() and stores the resulting Python + iterator object in this->it. Then, calls this->it.attr("next")() + and stores the result in this->ob. If the sequence is exhausted, + sets this->ob to object(). +

+
Postconditions
+

+ this is a dereferenceable or past-the-end. +

+
+
+
+
+ +
stl_input_iterator &operator++()
+
+
+

+
+
Effects
+

+ Calls this->it.attr("next")() and stores the result + in this->ob. If the sequence is exhausted, sets this->ob to + object(). +

+
Postconditions
+

+ this is a dereferenceable or past-the-end. +

+
Returns
+

+ *this +

+
+
+
stl_input_iterator &operator++(int)
+
+

+
+
Effects
+

+ stl_input_iterator tmp = + *this; ++*this; return tmp; +

+
Postconditions
+

+ this is a dereferenceable or past-the-end. +

+
+
+
+
+ +
ValueType operator*() const
+
+
+

+
+
Effects
+

+ Returns the current element in the sequence. +

+
Returns
+

+ extract<ValueType>(this->ob); +

+
+
+
friend bool operator==(stl_input_iterator const& lhs, stl_input_iterator const& rhs)
+
+
+

+
+
Effects
+

+ Returns true if both iterators are dereferenceable or if both iterators + are past-the-end, false otherwise. +

+
Returns
+

+ (lhs.ob == object()) == (rhs.ob == object()) +

+
+
+
friend bool operator!=(stl_input_iterator const& lhs, stl_input_iterator const& rhs)
+
+
+

+
+
Effects
+

+ Returns false if both iterators are dereferenceable or if both iterators + are past-the-end, true otherwise. +

+
Returns
+

+ !(lhs + == rhs) +

+
+
+
+
+ +
#include <boost/python/object.hpp>
+#include <boost/python/stl_iterator.hpp>
+
+#include <list>
+
+using namespace boost::python;
+std::list<int> sequence_to_int_list(object const& ob)
+{
+    stl_input_iterator<int> begin(ob), end;
+    return std::list<int>(begin, end);
+}
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/high_level_components/boost_python_wrapper_hpp.html b/develop/doc/html/reference/high_level_components/boost_python_wrapper_hpp.html new file mode 100644 index 00000000..fed5d67f --- /dev/null +++ b/develop/doc/html/reference/high_level_components/boost_python_wrapper_hpp.html @@ -0,0 +1,222 @@ + + + +boost/python/wrapper.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ To wrap a class T such that its virtual functions can be "overridden + in Python"—so that the corresponding method of a Python derived + class will be called when the virtual function is invoked from C++—you + must create a C++ wrapper class derived from T + that overrides those virtual functions so that they call into Python. This + header contains classes that can be used to make that job easier. +

+
+
+ +

+ Encapsulates a Python override of a C++ virtual function. An override object + either holds a callable Python object or None. +

+
namespace boost
+{
+  class override : object
+  {
+   public:
+      unspecified operator() const;
+      template <class A0>
+      unspecified operator(A0) const;
+      template <class A0, class A1>
+      unspecified operator(A0, A1) const;
+      ...
+      template <class A0, class A1, ...class An>
+      unspecified operator(A0, A1, ...An) const;
+  };
+};
+
+
+
+ +
unspecified operator() const;
+template <class A0>
+unspecified operator(A0) const;
+template <class A0, class A1>
+unspecified operator(A0, A1) const;
+...
+template <class A0, class A1, ...class An>
+unspecified operator(A0, A1, ...An) const;
+
+
+

+
+
Effects
+

+ If *this holds a callable Python object, it is invoked with the specified + arguments in the manner specified here. Otherwise, throws error_already_set. +

+
Returns
+

+ An object of unspecified type that holds the Python result of the + invocation and, when converted to a C++ type R, attempts to convert + that result object to R. If that conversion fails, throws error_already_set. +

+
+
+
+
+ +

+ Deriving your wrapper class from both T + and wrapper<T> + makes writing that derived class easier. +

+
namespace boost
+{
+  class wrapper
+  {
+   protected:
+      override get_override(char const* name) const;
+  };
+};
+
+
+
+ +
override get_override(char const* name) const;
+
+

+
+
Requires
+

+ name is a ntbs. +

+
Returns
+

+ If *this + is the C++ base class subobject of a Python derived class instance + that overrides the named function, returns an override object that + delegates to the Python override. Otherwise, returns an override + object that holds None. +

+
+
+
+
+ +
#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/wrapper.hpp>
+#include <boost/python/call.hpp>
+
+using namespace boost::python;
+
+// Class with one pure virtual function
+struct P
+{
+    virtual ~P(){}
+    virtual char const* f() = 0;
+    char const* g() { return "P::g()"; }
+};
+
+struct PCallback : P, wrapper<P>
+{
+    char const* f()
+    {
+        return this->get_override("f")();
+    }
+};
+
+// Class with one non-pure virtual function
+struct A
+{
+    virtual ~A(){}
+    virtual char const* f() { return "A::f()"; }
+};
+
+struct ACallback :  A, wrapper<A>
+{
+    char const* f()
+    {
+        if (override f = this->get_override("f"))
+            return f();
+        return A::f();
+    }
+
+    char const* default_f() { return this->A::f(); }
+};
+
+BOOST_PYTHON_MODULE_INIT(polymorphism)
+{
+    class_<PCallback,boost::noncopyable>("P")
+        .def("f", pure_virtual(&P::f))
+        ;
+
+    class_<ACallback,boost::noncopyable>("A")
+        .def("f", &A::f, &ACallback::default_f)
+        ;
+}
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/index.html b/develop/doc/html/reference/index.html new file mode 100644 index 00000000..2162c540 --- /dev/null +++ b/develop/doc/html/reference/index.html @@ -0,0 +1,137 @@ + + + +Boost.Python Reference Manual + + + + + + +
+
+
Next
+
+
+
+

+Boost.Python Reference Manual

+
+

+David Abrahams +

+

+Stefan Seefeld +

+
+
+
+

+ Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt +

+
+
+
+
+
+

Table of Contents

+
+
1. Concepts
+
+
CallPolicies
+
Dereferenceable
+
Extractor
+
HolderGenerator
+
ResultConverter
+
ObjectWrapper
+
+
2. High Level Components
+
+
boost/python/class.hpp
+
boost/python/def.hpp
+
boost/python/def_visitor.hpp
+
boost/python/docstring_options.hpp
+
boost/python/enum.hpp
+
boost/python/errors.hpp
+
boost/python/exception_translator.hpp
+
boost/python/init.hpp
+
boost/python/iterator.hpp
+
boost/python/module.hpp
+
boost/python/operators.hpp
+
boost/python/scope.hpp
+
boost/python/stl_iterator.hpp
+
boost/python/wrapper.hpp
+
+
3. Object Wrappers
+
+
boost/python/dict.hpp
+
boost_python_list.hpp
+
boost/python/long.hpp
+
boost/python/numeric.hpp
+
boost/python/object.hpp
+
boost/python/str.hpp
+
boost/python/slice.hpp
+
boost/python/tuple.hpp
+
+
4. Function Invocation and Creation
+
+
boost/python/args.hpp
+
boost/python/call.hpp
+
boost/python/call_method.hpp
+
boost/python/data_members.hpp
+
boost/python/make_function.hpp
+
boost/python/overloads.hpp
+
boost/python/ptr.hpp
+
boost/python/raw_function.hpp
+
Function + documentation
+
Models + of CallPolicies
+
Models + of ResultConverter
+
Models + of ResultConverterGenerator
+
+
5. To/From Python Type Conversion
+
+
boost/python/extract.hpp
+
boost/python/implicit.hpp
+
boost/python/lvalue_from_pytype.hpp
+
boost/python/opaque_pointer_converter.hpp
+
boost/python/to_python_converter.hpp
+
boost/python/register_ptr_to_python.hpp
+
+
6. Embedding
+
+
boost/python/exec.hpp
+
boost/python/import.hpp
+
+
7. Utility and Infrastructure
+
+
boost/python/has_back_reference.hpp
+
boost/python/instance_holder.hpp
+
boost/python/pointee.hpp
+
boost/python/handle.hpp
+
boost/python/type_id.hpp
+
boost/python/ssize_t.hpp
+
+
8. Topics
+
+
Calling Python + Functions and Methods
+
Pickle support
+
Indexing support
+
+
9. Glossary
+
+
+
+ + + +

Last revised: October 07, 2016 at 15:41:15 GMT

+
+
Next
+ + diff --git a/develop/doc/html/reference/object_wrappers.html b/develop/doc/html/reference/object_wrappers.html new file mode 100644 index 00000000..123f7fc8 --- /dev/null +++ b/develop/doc/html/reference/object_wrappers.html @@ -0,0 +1,260 @@ + + + +Chapter 3. Object Wrappers + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+

+Chapter 3. Object Wrappers

+
+

Table of Contents

+
+
boost/python/dict.hpp
+
+
Introduction
+
Class + dict
+
Example
+
+
boost_python_list.hpp
+
+
Introduction
+
Class + list
+
Example
+
+
boost/python/long.hpp
+
+
Introduction
+
Class + long_
+
Example
+
+
boost/python/numeric.hpp
+
+
Introduction
+
Class + array
+
Class + array observer functions
+
Class + array static functions
+
Example
+
+
boost/python/object.hpp
+
+
Introduction
+
Class + slice_nil
+
Class + const_attribute_policies
+
Class + const_attribute_policies + static functions
+
Class + attribute_policies
+
Class + attribute_policies static + functions
+
Class + const_objattribute_policies
+
Class + const_objattribute_policies + static functions
+
Class + objattribute_policies
+
Class + objattribute_policies static + functions
+
Class + const_item_policies
+
Class + const_item_policies static + functions
+
Class + item_policies
+
Class + item_policies static functions
+
Class + const_slice_policies
+
Class + const_slice_policies static + functions
+
Class + slice_policies
+
Class + slice_policies static functions
+
Class + template object_operators
+
Class + template object_operators + observer functions
+
Class + object
+
Class + object constructors and destructor
+
Class + object modifiers
+
Class + template proxy
+
Class + template proxy observer functions
+
Class + template proxy modifier functions
+
Functions
+
Example
+
+
boost/python/str.hpp
+
+
Introduction
+
Class + str
+
Example
+
+
boost/python/slice.hpp
+
+
Introduction
+
Class + slice
+
Class + slice constructors
+
Class + slice observer functions
+
Example
+
+
boost/python/tuple.hpp
+
+
Introduction
+
Class + tuple
+
Function + make_tuple
+
Example
+
+
+
+
+ + +
+ +

+ Exposes a TypeWrapper + for the Python dict type. +

+
+
+ +

+ Exposes the mapping + protocol of Python's built-in dict + type. The semantics of the constructors and member functions defined below + can be fully understood by reading the TypeWrapper + concept definition. Since dict + is publicly derived from object, the public object interface applies to dict instances as well. +

+
namespace boost { namespace python
+{
+   class dict : public object
+   {
+      dict();
+
+      template< class T >
+      dict(T const & data);
+
+      // modifiers
+      void clear();
+      dict copy();
+
+      template <class T1, class T2>
+      tuple popitem();
+
+      template <class T>
+      object setdefault(T const &k);
+
+      template <class T1, class T2>
+      object setdefault(T1 const & k, T2 const & d);
+
+      void update(object_cref E);
+
+      template< class T >
+      void update(T const & E);
+
+      // observers
+      list values() const;
+
+      object get(object_cref k) const;
+
+      template<class T>
+      object get(T const & k) const;
+
+      object get(object_cref k, object_cref d) const;
+      object get(T1 const & k, T2 const & d) const;
+
+      bool has_key(object_cref k) const;
+
+      template< class T >
+      bool has_key(T const & k) const;
+
+      list items() const;
+      object iteritems() const;
+      object iterkeys() const;
+      object itervalues() const;
+      list keys() const;
+  };
+}}
+
+
+
+ +
using namespace boost::python;
+dict swap_object_dict(object target, dict d)
+{
+    dict result = extract<dict>(target.attr("__dict__"));
+    target.attr("__dict__") = d;
+    return result;
+}
+
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/object_wrappers/boost_python_list_hpp.html b/develop/doc/html/reference/object_wrappers/boost_python_list_hpp.html new file mode 100644 index 00000000..5c075e40 --- /dev/null +++ b/develop/doc/html/reference/object_wrappers/boost_python_list_hpp.html @@ -0,0 +1,120 @@ + + + +boost_python_list.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ Exposes a TypeWrapper + for the Python list + type. +

+
+
+ +

+ Exposes the mapping + protocol of Python's built-in list + type. The semantics of the constructors and member functions defined below + can be fully understood by reading the TypeWrapper + concept definition. Since list + is publicly derived from object, the public object interface applies to list instances as well. +

+
namespace boost { namespace python
+{
+  class list : public object
+  {
+   public:
+      list(); // new list
+
+      template <class T>
+      explicit list(T const& sequence);
+
+      template <class T>
+      void append(T const& x);
+
+      template <class T>
+      long count(T const& value) const;
+
+      template <class T>
+      void extend(T const& x);
+
+      template <class T>
+      long index(T const& x) const;
+
+      template <class T>
+      void insert(object const& index, T const& x); // insert object before index
+
+      object pop(); // remove and return item at index (default last)
+      object pop(long index);
+      object pop(object const& index);
+
+      template <class T>
+      void remove(T const& value);
+
+      void reverse(); // reverse *IN PLACE*
+
+      void sort(); //  sort *IN PLACE*; if given, cmpfunc(x, y) -> -1, 0, 1
+
+      template <class T>
+      void sort(T const& value);
+  };
+}}
+
+
+
+ +
using namespace boost::python;
+
+// Return the number of zeroes in the list
+long zeroes(list l)
+{
+   return l.count(0);
+}
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/object_wrappers/boost_python_long_hpp.html b/develop/doc/html/reference/object_wrappers/boost_python_long_hpp.html new file mode 100644 index 00000000..1d505cfc --- /dev/null +++ b/develop/doc/html/reference/object_wrappers/boost_python_long_hpp.html @@ -0,0 +1,97 @@ + + + +boost/python/long.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ Exposes a TypeWrapper + for the Python long + integer type. +

+
+
+ +

+ Exposes the numeric + type protocol of Python's built-in long + type. The semantics of the constructors and member functions defined below + can be fully understood by reading the TypeWrapper + concept definition. Since long_ + is publicly derived from object, the public object interface applies to long_ instances as well. +

+
namespace boost { namespace python
+{
+  class long_ : public object
+  {
+   public:
+      long_(); // new long_
+
+      template <class T>
+      explicit long_(T const& rhs);
+
+      template <class T, class U>
+      long_(T const& rhs, U const& base);
+  };
+}}
+
+
+
+ +
namespace python = boost::python;
+
+// compute a factorial without overflowing
+python::long_ fact(long n)
+{
+   if (n == 0)
+      return python::long_(1);
+   else
+      return n * fact(n - 1);
+}
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/object_wrappers/boost_python_numeric_hpp.html b/develop/doc/html/reference/object_wrappers/boost_python_numeric_hpp.html new file mode 100644 index 00000000..2734a9d6 --- /dev/null +++ b/develop/doc/html/reference/object_wrappers/boost_python_numeric_hpp.html @@ -0,0 +1,259 @@ + + + +boost/python/numeric.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ Exposes a TypeWrapper + for the Python array + type. +

+
+
+ +

+ Provides access to the array types of Numerical + Python's Numeric + and NumArray + modules. With the exception of the functions documented below, the semantics + of the constructors and member functions defined below can be fully understood + by reading the TypeWrapper + concept definition. Since array is publicly derived from object, the public + object interface applies to array instances as well. +

+

+ The default behavior is to use numarray.NDArray as the associated Python + type if the numarray module is installed in the default location. Otherwise + it falls back to use Numeric.ArrayType. If neither extension module is + installed, overloads of wrapped C++ functions with numeric::array parameters + will never be matched, and other attempted uses of numeric::array will + raise an appropriate Python exception. The associated Python type can be + set manually using the set_module_and_type(...) static function. +

+
namespace boost { namespace python { namespace numeric
+{
+   class array : public object
+   {
+    public:
+      object astype();
+      template <class Type>
+      object astype(Type const& type_);
+
+      template <class Type>
+      array new_(Type const& type_) const;
+
+      template <class Sequence>
+      void resize(Sequence const& x);
+      void resize(long x1);
+      void resize(long x1, long x2);
+      ...
+      void resize(long x1, long x2,...long xn);
+
+      template <class Sequence>
+      void setshape(Sequence const& x);
+      void setshape(long x1);
+      void setshape(long x1, long x2);
+      ...
+      void setshape(long x1, long x2,...long xn);
+
+      template <class Indices, class Values>
+      void put(Indices const& indices, Values const& values);
+
+      template <class Sequence>
+      object take(Sequence const& sequence, long axis = 0);
+
+      template <class File>
+      void tofile(File const& f) const;
+
+      object factory();
+      template <class Sequence>
+      object factory(Sequence const&);
+      template <class Sequence, class Typecode>
+      object factory(Sequence const&, Typecode const&, bool copy = true, bool savespace = false);
+      template <class Sequence, class Typecode, class Type>
+      object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&);
+      template <class Sequence, class Typecode, class Type, class Shape>
+      object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&, Shape const&);
+
+      template <class T1>
+      explicit array(T1 const& x1);
+      template <class T1, class T2>
+      explicit array(T1 const& x1, T2 const& x2);
+      ...
+      template <class T1, class T2,...class Tn>
+      explicit array(T1 const& x1, T2 const& x2,...Tn const& xn);
+
+      static void set_module_and_type();
+      static void set_module_and_type(char const* package_path = 0, char const* type_name = 0);
+      static void get_module_name();
+
+      object argmax(long axis=-1);
+
+      object argmin(long axis=-1);
+
+      object argsort(long axis=-1);
+
+      void byteswap();
+
+      object copy() const;
+
+      object diagonal(long offset = 0, long axis1 = 0, long axis2 = 1) const;
+
+      void info() const;
+
+      bool is_c_array() const;
+      bool isbyteswapped() const;
+      void sort();
+      object trace(long offset = 0, long axis1 = 0, long axis2 = 1) const;
+      object type() const;
+      char typecode() const;
+
+      object getflat() const;
+      long getrank() const;
+      object getshape() const;
+      bool isaligned() const;
+      bool iscontiguous() const;
+      long itemsize() const;
+      long nelements() const;
+      object nonzero() const;
+
+      void ravel();
+      object repeat(object const& repeats, long axis=0);
+      void setflat(object const& flat);
+      void swapaxes(long axis1, long axis2);
+      str tostring() const;
+      void transpose(object const& axes = object());
+      object view() const;
+  };
+}}}
+
+
+
+ +
object factory();
+template <class Sequence>
+object factory(Sequence const&);
+template <class Sequence, class Typecode>
+object factory(Sequence const&, Typecode const&, bool copy = true, bool savespace = false);
+template <class Sequence, class Typecode, class Type>
+object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&);
+template <class Sequence, class Typecode, class Type, class Shape>
+object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&, Shape const&);
+
+

+ These functions map to the underlying array type's array() function family. + They are not called "array" because of the C++ limitation that + you can't define a member function with the same name as its enclosing + class. +

+
template <class Type>
+array new_(Type const&) const;
+
+

+ This function maps to the underlying array type's new() function. It is + not called "new" because that is a keyword in C++. +

+
+
+ +
static void set_module_and_type(char const* package_path, char const* type_name);
+static void set_module_and_type();
+
+
+

+
+
Requires
+

+ package_path and type_name, if supplied, is an ntbs. +

+
Effects
+

+ The first form sets the package path of the module that supplies + the type named by type_name to package_path. The second form restores + the default search behavior. The associated Python type will be searched + for only the first time it is needed, and thereafter the first time + it is needed after an invocation of set_module_and_type. +

+
+
+
static std::string get_module_name()
+
+

+
+
Effects
+

+ Returns the name of the module containing the class that will be + held by new numeric::array + instances. +

+
+
+
+
+ +
#include <boost/python/numeric.hpp>
+#include <boost/python/tuple.hpp>
+
+// sets the first element in a 2d numeric array
+void set_first_element(numeric::array& y, double value)
+{
+    y[make_tuple(0,0)] = value;
+}
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/object_wrappers/boost_python_object_hpp.html b/develop/doc/html/reference/object_wrappers/boost_python_object_hpp.html new file mode 100644 index 00000000..e753e762 --- /dev/null +++ b/develop/doc/html/reference/object_wrappers/boost_python_object_hpp.html @@ -0,0 +1,1148 @@ + + + +boost/python/object.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ Exposes the generic Python object wrapper class object, and related classes. + In order to avoid some potenential problems with argument-dependent lookup + and the generalized operators defined on object, all these facilities are + defined in namespace boost::python::api, and object is imported into namespace + boost::python with a using-declaration. +

+
+
+ +
class slice_nil;
+static const _ = slice_nil();
+
+

+ A type that can be used to get the effect of leaving out an index in a + Python slice expression: +

+
>>> x[:-1]
+>>> x[::-1]
+
+

+ C++ equivalent: +

+
x.slice(_,-1)
+x[slice(_,_,-1)]
+
+
+
+ +

+ The policies which are used for proxies representing an attribute access + to a const object. +

+
namespace boost { namespace python { namespace api
+{
+  struct const_attribute_policies
+  {
+      typedef char const* key_type;
+      static object get(object const& target, char const* key);
+  };
+}}}
+
+
+
+ +
static object get(object const& target, char const* key);
+
+
+

+
+
Requires
+

+ key is an ntbs. +

+
Effects
+

+ accesses the attribute of target named by key. +

+
Returns
+

+ An object managing the result of the attribute access. +

+
Throws
+

+ error_already_set + if a Python exception is raised. +

+
+
+
+
+ +

+ The policies which are used for proxies representing an attribute access + to a mutable object. +

+
namespace boost { namespace python { namespace api
+{
+  struct attribute_policies : const_attribute_policies
+  {
+      static object const& set(object const& target, char const* key, object const& value);
+      static void del(object const&target, char const* key);
+  };
+}}}
+
+
+
+ +
static object const& set(object const& target, char const* key, object const& value);
+
+
+

+
+
Requires
+

+ key is an ntbs. +

+
Effects
+

+ sets the attribute of target named by key to value. +

+
Throws
+

+ error_already_set + if a Python exception is raised. +

+
+
+
static void del(object const&target, char const* key);
+
+
+

+
+
Requires
+

+ key is an ntbs. +

+
Effects
+

+ deletes the attribute of target named by key. +

+
Throws
+

+ error_already_set + if a Python exception is raised. +

+
+
+
+
+ +

+ The policies which are used for proxies representing an attribute access + to a const object when the attribute name is given as a const object. +

+
namespace boost { namespace python { namespace api
+{
+  struct const_objattribute_policies
+  {
+      typedef object const& key_type;
+      static object get(object const& target, object const& key);
+  };
+}}}
+
+
+
+ +
static object get(object const& target, object const& key);
+
+
+

+
+
Requires
+

+ key is an object holding a string. +

+
Effects
+

+ accesses the attribute of target named by key. +

+
Returns
+

+ An object managing the result of the attribute access. +

+
Throws
+

+ error_already_set + if a Python exception is raised. +

+
+
+
+
+ +

+ The policies which are used for proxies representing an attribute access + to a mutable object when the attribute name is given as a const object. +

+
namespace boost { namespace python { namespace api
+{
+  struct objattribute_policies : const_objattribute_policies
+  {
+      static object const& set(object const& target, object const& key, object const& value);
+      static void del(object const&target, object const& key);
+  };
+}}}
+
+
+
+ +
static object const& set(object const& target, object const& key, object const& value);
+
+
+

+
+
Requires
+

+ key is an object holding a string. +

+
Effects
+

+ sets the attribute of target named by key to value. +

+
Throws
+

+ error_already_set + if a Python exception is raised. +

+
+
+
static void del(object const&target, object const& key);
+
+
+

+
+
Requires
+

+ key is an object holding a string. +

+
Effects
+

+ deletes the attribute of target named by key. +

+
Throws
+

+ error_already_set + if a Python exception is raised. +

+
+
+
+
+ +

+ The policies which are used for proxies representing an item access (via + the Python bracket operators []) to a const object. +

+
namespace boost { namespace python { namespace api
+{
+  struct const_item_policies
+  {
+      typedef object key_type;
+      static object get(object const& target, object const& key);
+  };
+}}}
+
+
+
+ +
static object get(object const& target, object const& key);
+
+
+

+
+
Effects
+

+ accesses the item of target specified by key. +

+
Returns
+

+ An object managing the result of the item access. +

+
Throws
+

+ error_already_set + if a Python exception is raised. +

+
+
+
+
+ +

+ The policies which are used for proxies representing an item access (via + the Python bracket operators []) to a mutable object. +

+
namespace boost { namespace python { namespace api
+{
+  struct item_policies : const_item_policies
+  {
+      static object const& set(object const& target, object const& key, object const& value);
+      static void del(object const& target, object const& key);
+  };
+}}}
+
+
+
+ +
static object const& set(object const& target, object const& key, object const& value);
+
+
+

+
+
Effects
+

+ sets the item of target specified by key to value. +

+
Throws
+

+ error_already_set + if a Python exception is raised. +

+
+
+
static void del(object const& target, object const& key);
+
+
+

+
+
Effects
+

+ deletes the item of target specified by key. +

+
Throws
+

+ error_already_set + if a Python exception is raised. +

+
+
+
+
+ +

+ The policies which are used for proxies representing an slice access (via + the Python slice notation [x:y]) to a const object. +

+
namespace boost { namespace python { namespace api
+{
+  struct const_slice_policies
+  {
+      typedef std::pair<handle<>, handle<> > key_type;
+      static object get(object const& target, key_type const& key);
+  };
+}}}
+
+
+
+ +
static object get(object const& target, key_type const& key);
+
+
+

+
+
Effects
+

+ accesses the slice of target specified by key. +

+
Returns
+

+ An object managing the result of the slice access. +

+
Throws
+

+ error_already_set + if a Python exception is raised. +

+
+
+
+
+ +

+ The policies which are used for proxies representing an slice access to + a mutable object. +

+
namespace boost { namespace python { namespace api
+{
+  struct slice_policies : const_slice_policies
+  {
+      static object const& set(object const& target, key_type const& key, object const& value);
+      static void del(object const& target, key_type const& key);
+  };
+}}}
+
+
+
+ +
static object const& set(object const& target, key_type const& key, object const& value);
+
+
+

+
+
Effects
+

+ sets the slice of target specified by key to value. +

+
Throws
+

+ error_already_set + if a Python exception is raised. +

+
+
+
static void del(object const& target, key_type const& key);
+
+
+

+
+
Effects
+

+ deletes the slice of target specified by key. +

+
Throws
+

+ error_already_set + if a Python exception is raised. +

+
+
+
+
+ +

+ This is the base class of object and its proxy template used to supply + common interface: member functions, and operators which must be defined + within the class body. Its template parameter U is expected to be a class + derived from object_operators<U>. In practice users should never + use this class directly, but it is documented here because it supplies + important interface to object and its proxies. +

+
namespace boost { namespace python { namespace api
+{
+  template <class U>
+  class object_operators
+  {
+   public:
+      // function call
+      //
+      object operator()() const;
+
+      template <class A0>
+      object operator()(A0 const&) const;
+      template <class A0, class A1>
+      object operator()(A0 const&, A1 const&) const;
+      ...
+      template <class A0, class A1,...class An>
+      object operator()(A0 const&, A1 const&,...An const&) const;
+
+      detail::args_proxy operator* () const;
+      object operator()(detail::args_proxy const &args) const;
+      object operator()(detail::args_proxy const &args,
+                        detail::kwds_proxy const &kwds) const;
+
+      // truth value testing
+      //
+      typedef unspecified bool_type;
+      operator bool_type() const;
+
+      // Attribute access
+      //
+      proxy<const_object_attribute> attr(char const*) const;
+      proxy<object_attribute> attr(char const*);
+      proxy<const_object_objattribute> attr(object const&) const;
+      proxy<object_objattribute> attr(object const&);
+
+      // item access
+      //
+      template <class T>
+      proxy<const_object_item> operator[](T const& key) const;
+
+      template <class T>
+      proxy<object_item> operator[](T const& key);
+
+      // slicing
+      //
+      template <class T, class V>
+      proxy<const_object_slice> slice(T const& start, V const& end) const
+
+      template <class T, class V>
+      proxy<object_slice> slice(T const& start, V const& end);
+  };
+}}}
+
+
+
+ +
object operator()() const;
+template <class A0>
+object operator()(A0 const&) const;
+template <class A0, class A1>
+object operator()(A0 const&, A1 const&) const;
+...
+template <class A0, class A1,...class An>
+object operator()(A0 const& a1, A1 const& a2,...An const& aN) const;
+
+
+

+
+
Effects
+

+ call<object>(object(*static_cast<U*>(this)).ptr(), + a1, + a2,...aN) +

+
+
+
object operator()(detail::args_proxy const &args) const;
+
+

+
+
Effects
+

+ call object + with arguments + given by + the tuple + args +

+
+
+
object operator()(detail::args_proxy const &args,
+                  detail::kwds_proxy const &kwds) const;
+
+
+

+
+
Effects
+

+ call object + with arguments + given by + the tuple + args, + and named + arguments given + by the + dictionary kwds +

+
+
+
operator bool_type() const;
+
+

+
+
Effects
+

+ Tests truth value of *this. +

+
Returns
+

+ call<object>(object(*static_cast<U*>(this)).ptr(), + a1, + a2,...aN) +

+
+
+
proxy<const_object_attribute> attr(char const* name) const;
+proxy<object_attribute> attr(char const* name);
+
+
+

+
+
Requires
+

+ name is an ntbs. +

+
Effects
+

+ accesses the named attribute of *this. +

+
Returns
+

+ a proxy object which binds object(*static_cast<U*>(this)) as its target, and name as its + key. +

+
+
+
proxy<const_object_objattribute> attr(const object& name) const;
+proxy<object_objattribute> attr(const object& name);
+
+
+

+
+
Requires
+

+ name is a object holding a string. +

+
Effects
+

+ accesses the named attribute of *this. +

+
Returns
+

+ a proxy object which binds object(*static_cast<U*>(this)) as its target, and name as its + key. +

+
+
+
template <class T>
+proxy<const_object_item> operator[](T const& key) const;
+template <class T>
+proxy<object_item> operator[](T const& key);
+
+
+

+
+
Effects
+

+ accesses the item of *this indicated by key. +

+
Returns
+

+ a proxy object which binds object(*static_cast<U*>(this)) as its target, and object(key) + as its key. +

+
+
+
template <class T, class V>
+proxy<const_object_slice> slice(T const& start; start, V const& finish) const
+template <class T, class V>
+proxy<object_slice> slice(T const& start; start, V const& finish);
+
+
+

+
+
Effects
+

+ accesses the slice of *this indicated by std::make_pair(object(start), object(finish)). +

+
Returns
+

+ a proxy object which binds object(*static_cast<U*>(this)) as its target, and std::make_pair(object(start), + object(finish)) + as its key. +

+
+
+
+
+ +

+ The intention is that object acts as much like a Python variable as possible. + Thus expressions you'd expect to work in Python should generally work in + the same way from C++. Most of object's interface is provided by its base + class object_operators<object>, and the free functions defined in + this header. +

+
namespace boost { namespace python { namespace api
+{
+  class object : public object_operators<object>
+  {
+   public:
+      object();
+      object(object const&);
+      template <class T>
+      explicit object(T const& x);
+
+      ~object();
+
+      object& operator=(object const&);
+      PyObject* ptr() const;
+      bool is_none() const;
+  };
+}}}
+
+
+
+ +
object();
+
+

+
+
Effects
+

+ Constructs an object managing a reference to the Python None object. +

+
Throws
+

+ nothing. +

+
+
+
template <class T>
+explicit object(T const& x);
+
+
+

+
+
Effects
+

+ converts x to python and manages a reference to it. +

+
Throws
+

+ error_already_set + and sets a Python TypeError exception if no such conversion is possible. +

+
+
+
~object();
+
+
+

+
+
Effects
+

+ decrements the reference count of the internally-held object. +

+
+
+
+
+ +
PyObject* ptr() const;
+
+

+
+
Returns
+

+ a pointer to the internally-held Python object. +

+
+
+
bool is_none() const;
+
+

+
+
Returns
+

+ result of (ptr() == Py_None) +

+
+
+
+
+ +

+ This template is instantiated with various Policies described in this document + in order to implement attribute, item, and slice access for object. It + stores an object of type Policies::key_type. +

+
namespace boost { namespace python { namespace api
+{
+  template <class Policies>
+  class proxy : public object_operators<proxy<Policies> >
+  {
+   public:
+      operator object() const;
+
+      proxy const& operator=(proxy const&) const;
+      template <class T>
+      inline proxy const& operator=(T const& rhs) const;
+
+      void del() const;
+
+      template <class R>
+      proxy operator+=(R const& rhs);
+      template <class R>
+      proxy operator-=(R const& rhs);
+      template <class R>
+      proxy operator*=(R const& rhs);
+      template <class R>
+      proxy operator/=(R const& rhs);
+      template <class R>
+      proxy operator%=(R const& rhs);
+      template <class R>
+      proxy operator<<=(R const& rhs);
+      template <class R>
+      proxy operator>>=(R const& rhs);
+      template <class R>
+      proxy operator&=(R const& rhs);
+      template <class R>
+      proxy operator|=(R const& rhs);
+  };
+}}}
+
+
+
+ +
operator object() const;
+
+

+
+
Effects
+

+ applies Policies::get(target, key) with the proxy's target and key + objects. +

+
+
+
+
+ +
proxy const& operator=(proxy const& rhs) const;
+template <class T>
+inline proxy const& operator=(T const& rhs) const;
+
+
+

+
+
Effects
+

+ Policies::set(target, + key , + object(rhs)) + with the proxy's target and key objects. +

+
+
+
template <class R>
+proxy operator+=(R const& rhs);
+template <class R>
+proxy operator-=(R const& rhs);
+template <class R>
+proxy operator*=(R const& rhs);
+template <class R>
+proxy operator/=(R const& rhs);
+template <class R>
+proxy operator%=(R const& rhs);
+template <class R>
+proxy operator<<=(R const& rhs);
+template <class R>
+proxy operator>>=(R const& rhs);
+template <class R>
+proxy operator&=(R const& rhs);
+template <class R>
+proxy operator|=(R const& rhs);
+
+
+

+
+
Effects
+

+ for a given operator@=, + object(*this) @= rhs; +

+
Returns
+

+ *this +

+
+
+
void del() const;
+
+

+
+
Effects
+

+ Policies::del(target, key ) with the proxy's target and key objects. +

+
+
+
+
+ +
template <class T>
+void del(proxy<T> const& x);
+
+
+

+
+
Effects
+

+ x.del() +

+
+
+
template<class L,class R> object operator>(L const&l,R const&r);
+template<class L,class R> object operator>=(L const&l,R const&r);
+template<class L,class R> object operator<(L const&l,R const&r);
+template<class L,class R> object operator<=(L const&l,R const&r);
+template<class L,class R> object operator==(L const&l,R const&r);
+template<class L,class R> object operator!=(L const&l,R const&r);
+
+
+

+
+
Effects
+

+ returns the result of applying the operator to object(l) and object(r), respectively, in Python. +

+
+
+
template<class L,class R> object operator+(L const&l,R const&r);
+template<class L,class R> object operator-(L const&l,R const&r);
+template<class L,class R> object operator*(L const&l,R const&r);
+template<class L,class R> object operator/(L const&l,R const&r);
+template<class L,class R> object operator%(L const&l,R const&r);
+template<class L,class R> object operator<<(L const&l,R const&r);
+template<class L,class R> object operator>>(L const&l,R const&r);
+template<class L,class R> object operator&(L const&l,R const&r);
+template<class L,class R> object operator^(L const&l,R const&r);
+template<class L,class R> object operator|(L const&l,R const&r);
+
+
+

+
+
Effects
+

+ returns the result of applying the operator to object(l) and object(r), respectively, in Python. +

+
+
+
template<class R> object& operator+=(object&l,R const&r);
+template<class R> object& operator-=(object&l,R const&r);
+template<class R> object& operator*=(object&l,R const&r);
+template<class R> object& operator/=(object&l,R const&r);
+template<class R> object& operator%=(object&l,R const&r);
+template<class R> object& operator<<=(object&l,R const&r)
+template<class R> object& operator>>=(object&l,R const&r);
+template<class R> object& operator&=(object&l,R const&r);
+template<class R> object& operator^=(object&l,R const&r);
+template<class R> object& operator|=(object&l,R const&r);
+
+
+

+
+
Effects
+

+ assigns to l the + result of applying the corresponding Python inplace operator to + l and object(r), + respectively. +

+
Returns
+

+ l +

+
+
+
long len(object const& obj);
+
+

+
+
Effects
+

+ PyObject_Length(obj.ptr()) +

+
Returns
+

+ len() + of object. +

+
+
+
+
+ +

+ Python code: +

+
def sum_items(seq):
+   result = 0
+   for x in seq:
+      result += x
+   return result
+
+

+ C++ version +

+
object sum_items(object seq)
+{
+   object result = object(0);
+   for (int i = 0; i < len(seq); ++i)
+      result += seq[i];
+   return result;
+}
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/object_wrappers/boost_python_slice_hpp.html b/develop/doc/html/reference/object_wrappers/boost_python_slice_hpp.html new file mode 100644 index 00000000..55c6ce85 --- /dev/null +++ b/develop/doc/html/reference/object_wrappers/boost_python_slice_hpp.html @@ -0,0 +1,305 @@ + + + +boost/python/slice.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ Exposes a TypeWrapper + for the Python slice type. +

+
+
+ +

+ Exposes the extended slicing protocol by wrapping the built-in slice type. + The semantics of the constructors and member functions defined below can + be fully understood by reading the TypeWrapper + concept definition. Since slice + is publicly derived from object, the public object interface applies to slice instances as well. +

+
namespace boost { namespace python
+{
+  class slice : public object
+  {
+   public:
+      slice(); // create an empty slice, equivalent to [::]
+
+      template <typename Int1, typename Int2>
+      slice(Int1 start, Int2 stop);
+
+      template <typename Int1, typename Int2, typename Int3>
+      slice(Int1 start, Int2 stop, Int3 step);
+
+      // Access the parameters this slice was created with.
+      object start();
+      object stop();
+      object step();
+
+      // The return type of slice::get_indices()
+      template <typename RandomAccessIterator>
+      struct range
+      {
+          RandomAccessIterator start;
+          RandomAccessIterator stop;
+          int step;
+      };
+
+      template <typename RandomAccessIterator>
+      range<RandomAccessIterator>
+      get_indices(
+          RandomAccessIterator const& begin,
+          RandomAccessIterator const& end);
+  };
+}}
+
+
+
+ +
slice();
+
+

+
+
Effects
+

+ constructs a slice with default stop, start, and step values. Equivalent + to the slice object created as part of the Python expression base[::]. +

+
Throws
+

+ nothing +

+
+
+
template <typename Int1, typename Int2>
+slice(Int1 start, Int2 stop);
+
+
+

+
+
Requires
+

+ start, stop, and step + are of type slice_nil + or convertible to type object. +

+
Effects
+

+ constructs a new slice with default step value and the provided start + and stop values. Equivalent to the slice object created by the built-in + Python function slice(start,stop), or as part of the Python expression + base[start:stop]. +

+
Throws
+

+ error_already_set + and sets a Python TypeError exception if no conversion is possible + from the arguments to type object. +

+
+
+
template <typename Int1, typename Int2, typename Int3>
+slice(Int1 start, Int2 stop, Int3 step);
+
+
+

+
+
Requires
+

+ start, stop, and step + are slice_nil or + convertible to type object. +

+
Effects
+

+ constructs a new slice with start stop and step values. Equivalent + to the slice object created by the built-in Python function slice(start,stop,step), + or as part of the Python expression base[start:stop:step]. +

+
Throws
+

+ error_already_set + and sets a Python TypeError exception if no conversion is possible + from the arguments to type object. +

+
+
+
+
+ +
object slice::start() const;
+object slice::stop() const;
+object slice::step() const;
+
+
+

+
+
Effects
+

+ None +

+
Throws
+

+ nothing +

+
Returns
+

+ the parameter that the slice was created with. If the parameter was + omitted or slice_nil + was used when the slice was created, than that parameter will be + a reference to PyNone + and compare equal to a default-constructed object. In principal, + any object may be used when creating a slice object, but in practice + they are usually integers. +

+
+
+
template <typename RandomAccessIterator>
+slice::range<RandomAccessIterator>
+slice::get_indices(
+    RandomAccessIterator const& begin,
+    RandomAccessIterator const& end) const;
+
+
+

+
+
Arguments
+

+ A pair of STL-conforming Random Access Iterators that form a half-open + range. +

+
Effects
+

+ Create a RandomAccessIterator pair that defines a fully-closed range + within the [begin,end) range of its arguments. This function + translates this slice's indices while accounting for the effects + of any PyNone or negative indices, and non-singular step sizes. +

+
Returns
+

+ a slice::range that has been initialized + with a non-zero value of step and a pair of RandomAccessIterators + that point within the range of this functions arguments and define + a closed interval. +

+
Throws
+

+ Raises a Python TypeError exception if any of this slice's arguments + are neither references to PyNone nor convertible to int. Throws + std::invalid_argument if the resulting + range would be empty. You should always wrap calls to slice::get_indices() + within try { + ...; } + catch (std::invalid_argument) + {} to handle this case and + take appropriate action. +

+
Rationale
+

+ closed-interval: If an open interval were used, then for step size + other than 1, the required state for the end iterator would point + beyond the one-past-the-end position or before the beginning of the + specified range. exceptions on empty slice: It is impossible to define + a closed interval over an empty range, so some other form of error + checking would have to be used to prevent undefined behavior. In + the case where the exception is not caught, it will simply be translated + to Python by the default exception handling mechanisms. +

+
+
+
+
+ +
using namespace boost::python;
+
+// Perform an extended slice of a Python list.
+// Warning: extended slicing was not supported for built-in types prior 
+// to Python 2.3
+list odd_elements(list l)
+{
+    return l[slice(_,_,2)];
+}
+
+// Perform a multidimensional extended slice of a Numeric.array
+numeric::array even_columns(numeric::array arr)
+{
+    // select every other column, starting with the second, of a 2-D array.
+    // Equivalent to "return arr[:, 1::2]" in Python.
+    return arr[make_tuple( slice(), slice(1,_,2))];
+}
+
+// Perform a summation over a slice of a std::vector.
+double partial_sum(std::vector<double> const& Foo, const slice index)
+{
+    slice::range<std::vector<double>::const_iterator> bounds;
+    try {
+        bounds = index.get_indices<>(Foo.begin(), Foo.end());
+    }
+    catch (std::invalid_argument) {
+        return 0.0;
+    }
+    double sum = 0.0;
+    while (bounds.start != bounds.stop) {
+        sum += *bounds.start;
+        std::advance( bounds.start, bounds.step);
+    }
+    sum += *bounds.start;
+    return sum;
+}
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/object_wrappers/boost_python_str_hpp.html b/develop/doc/html/reference/object_wrappers/boost_python_str_hpp.html new file mode 100644 index 00000000..5d12989b --- /dev/null +++ b/develop/doc/html/reference/object_wrappers/boost_python_str_hpp.html @@ -0,0 +1,211 @@ + + + +boost/python/str.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ Exposes a TypeWrapper + for the Python str type. +

+
+
+ +

+ Exposes the string + methods of Python's built-in str + type. The semantics of the constructors and member functions defined below, + except for the two-argument constructors which construct str objects from + a range of characters, can be fully understood by reading the TypeWrapper + concept definition. Since str is publicly derived from object, the public object interface applies to str instances as well. +

+
namespace boost { namespace python
+{
+  class str : public object
+  {
+   public:
+      str(); // new str
+
+      str(char const* s); // new str
+
+      str(char const* start, char const* finish); // new str
+      str(char const* start, std::size_t length); // new str
+
+      template <class T>
+      explicit str(T const& other);
+
+      str capitalize() const;
+
+      template <class T>
+      str center(T const& width) const;
+
+      template<class T>
+      long count(T const& sub) const;
+      template<class T1, class T2>
+      long count(T1 const& sub,T2 const& start) const;
+      template<class T1, class T2, class T3>
+      long count(T1 const& sub,T2 const& start, T3 const& end) const;
+
+      object decode() const;
+      template<class T>
+      object decode(T const& encoding) const;
+      template<class T1, class T2>
+      object decode(T1 const& encoding, T2 const& errors) const;
+
+      object encode() const;
+      template <class T>
+      object encode(T const& encoding) const;
+      template <class T1, class T2>
+      object encode(T1 const& encoding, T2 const& errors) const;
+
+      template <class T>
+      bool endswith(T const& suffix) const;
+      template <class T1, class T2>
+      bool endswith(T1 const& suffix, T2 const& start) const;
+      template <class T1, class T2, class T3>
+      bool endswith(T1 const& suffix, T2 const& start, T3 const& end) const;
+
+      str expandtabs() const;
+      template <class T>
+      str expandtabs(T const& tabsize) const;
+
+      template <class T>
+      long find(T const& sub) const;
+      template <class T1, class T2>
+      long find(T1 const& sub, T2 const& start) const;
+      template <class T1, class T2, class T3>
+      long find(T1 const& sub, T2 const& start, T3 const& end) const;
+
+      template <class T>
+      long index(T const& sub) const;
+      template <class T1, class T2>
+      long index(T1 const& sub, T2 const& start) const;
+      template <class T1, class T2, class T3>
+      long index(T1 const& sub, T2 const& start, T3 const& end) const;
+
+      bool isalnum() const;
+      bool isalpha() const;
+      bool isdigit() const;
+      bool islower() const;
+      bool isspace() const;
+      bool istitle() const;
+      bool isupper() const;
+
+      template <class T>
+      str join(T const& sequence) const;
+
+      template <class T>
+      str ljust(T const& width) const;
+
+      str lower() const;
+      str lstrip() const;
+
+      template <class T1, class T2>
+      str replace(T1 const& old, T2 const& new_) const;
+      template <class T1, class T2, class T3>
+      str replace(T1 const& old, T2 const& new_, T3 const& maxsplit) const;
+
+      template <class T>
+      long rfind(T const& sub) const;
+      template <class T1, class T2>
+      long rfind(T1 const& sub, T2 const& start) const;
+      template <class T1, class T2, class T3>
+      long rfind(T1 const& sub, T2 const& start, T3 const& end) const;
+
+      template <class T>
+      long rindex(T const& sub) const;
+      template <class T1, class T2>
+      long rindex(T1 const& sub, T2 const& start) const;
+      template <class T1, class T2, class T3>
+      long rindex(T1 const& sub, T2 const& start, T3 const& end) const;
+
+      template <class T>
+      str rjust(T const& width) const;
+
+      str rstrip() const;
+
+      list split() const;
+      template <class T>
+      list split(T const& sep) const;
+      template <class T1, class T2>
+      list split(T1 const& sep, T2 const& maxsplit) const;
+
+      list splitlines() const;
+      template <class T>
+      list splitlines(T const& keepends) const;
+
+      template <class T>
+      bool startswith(T const& prefix) const;
+      template <class T1, class T2>
+      bool startswidth(T1 const& prefix, T2 const& start) const;
+      template <class T1, class T2, class T3>
+      bool startswidth(T1 const& prefix, T2 const& start, T3 const& end) const;
+
+      str strip() const;
+      str swapcase() const;
+      str title() const;
+
+      template <class T>
+      str translate(T const& table) const;
+      template <class T1, class T2>
+      str translate(T1 const& table, T2 const& deletechars) const;
+
+      str upper() const;
+  };
+}}
+
+
+
+ +
using namespace boost::python;
+str remove_angle_brackets(str x)
+{
+  return x.strip('<').strip('>');
+}
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/object_wrappers/boost_python_tuple_hpp.html b/develop/doc/html/reference/object_wrappers/boost_python_tuple_hpp.html new file mode 100644 index 00000000..f0b78554 --- /dev/null +++ b/develop/doc/html/reference/object_wrappers/boost_python_tuple_hpp.html @@ -0,0 +1,119 @@ + + + +boost/python/tuple.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + + +
+ +

+ Exposes the interface of Python's built-in tuple type. The semantics of + the constructors and member functions defined below can be fully understood + by reading the TypeWrapper + concept definition. Since tuple is publicly derived from object, the public object interface applies to tuple instances as well. +

+
namespace boost { namespace python
+{
+   class tuple : public object
+   {
+      // tuple() -> an empty tuple
+      tuple();
+
+      // tuple(sequence) -> tuple initialized from sequence's items
+      template <class T>
+      explicit tuple(T const& sequence)
+  };
+}}
+
+
+
+ +
namespace boost { namespace python
+{
+  tuple make_tuple();
+
+  template <class A0>
+  tuple make_tuple(A0 const& a0);
+
+  template <class A0, class A1>
+  tuple make_tuple(A0 const& a0, A1 const& a1);
+  ...
+  template <class A0, class A1,...class An>
+  tuple make_tuple(A0 const& a0, A1 const& a1,...An const& an);
+}}
+
+
+

+
+
Effect
+

+ Constructs a new tuple object composed of object(a0), object(a0),...object(an). +

+
+
+
+
+ +
using namespace boost::python;
+tuple head_and_tail(object sequence)
+{
+    return make_tuple(sequence[0],sequence[-1]);
+}
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/to_from_python_type_conversion.html b/develop/doc/html/reference/to_from_python_type_conversion.html new file mode 100644 index 00000000..39f34819 --- /dev/null +++ b/develop/doc/html/reference/to_from_python_type_conversion.html @@ -0,0 +1,287 @@ + + + +Chapter 5. To/From Python Type Conversion + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+

+Chapter 5. To/From Python Type Conversion

+ +
+ + +
+ +

+ Exposes a mechanism for extracting C++ object values from generalized Python + objects. Note that extract<...> can also be used to "downcast" + an object to some specific ObjectWrapper. Because invoking + a mutable python type with an argument of the same type (e.g. list([1,2]) typically makes a copy of the argument + object, this may be the only way to access the ObjectWrapper's + interface on the original object. +

+
+
+ +

+ extract<T> + can be used to extract a value of an arbitrary C++ type from an instance + of object. + Two usages are supported: +

+
    +
  1. + extract<T>(o) + is a temporary object which is implicitly convertible to T (explicit conversion is also available + through the object's function-call operator). However, if no conversion + is available which can convert o to an object of type T, a Python TypeError exception will + be raised. +
  2. +
  3. + extract<T> x(o); + constructs an extractor whose check() member function can be used to ask + whether a conversion is available without causing an exception to be + thrown. +
  4. +
+
namespace boost { namespace python
+{
+  template <class T>
+  struct extract
+  {
+      typedef unspecified result_type;
+
+      extract(PyObject*);
+      extract(object const&);
+
+      result_type operator()() const;
+      operator result_type() const;
+
+      bool check() const;
+  };
+}}
+
+
+
+ +
extract(PyObject* p);
+extract(object const&);
+
+
+

+
+
Requires
+

+ The first form requires that p is non-null. +

+
Effects
+

+ Stores a pointer to the Python object managed by its constructor + argument. In particular, the reference count of the object is not + incremented. The onus is on the user to be sure it is not destroyed + before the extractor's conversion function is called. +

+
+
+
+
+ +
result_type operator()() const;
+operator result_type() const;
+
+
+

+
+
Effects
+

+ Converts the stored pointer to result_type, which is either T or + T const&. +

+
Returns
+

+ An object of result_type corresponding to the one referenced by the + stored pointer. +

+
Throws
+

+ error_already_set and sets + a TypeError if no + such conversion is available. May also emit other unspecified exceptions + thrown by the converter which is actually used. +

+
+
+
bool check() const;
+
+

+
+
Postconditions
+

+ None. In particular, note that a return value of true does not preclude + an exception being thrown from operator result_type() or operator()(). +

+
Returns
+

+ false only if no conversion from the stored pointer to T is available. +

+
+
+
+
+ +
#include <cstdio>
+using namespace boost::python;
+int Print(str s)
+{
+   // extract a C string from the Python string object
+   char const* c_str = extract<char const*>(s);
+
+   // Print it using printf
+   std::printf("%s\n", c_str);
+
+   // Get the Python string's length and convert it to an int
+   return extract<int>(s.attr("__len__")())
+}
+
+

+ The following example shows how extract can be used along with class_<...> + to create and access an instance of a wrapped C++ class. +

+
struct X
+{
+   X(int x) : v(x) {}
+   int value() { return v; }
+ private:
+   int v;
+};
+
+BOOST_PYTHON_MODULE(extract_ext)
+{
+    object x_class(
+       class_<X>("X", init<int>())
+          .def("value", &X::value))
+          ;
+
+    // Instantiate an X object through the Python interface. 
+    // Its lifetime is now managed by x_obj.
+    object x_obj = x_class(3);
+
+    // Get a reference to the C++ object out of the Python object
+    X& x = extract<X&>(x_obj);
+    assert(x.value() == 3);
+}
+
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/to_from_python_type_conversion/boost_python_implicit_hpp.html b/develop/doc/html/reference/to_from_python_type_conversion/boost_python_implicit_hpp.html new file mode 100644 index 00000000..719b109d --- /dev/null +++ b/develop/doc/html/reference/to_from_python_type_conversion/boost_python_implicit_hpp.html @@ -0,0 +1,181 @@ + + + +boost/python/implicit.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ implicitly_convertible + allows Boost.Python to implicitly take advantage of a C++ implicit or explicit + conversion when matching Python objects to C++ argument types. +

+
+
+ +
template <class Source, class Target>
+void implicitly_convertible();
+
+
++++ + + + + + + + + + + + + + + +
+

+ Parameter +

+
+

+ Description +

+
+

+ Source +

+
+

+ The source type of the implicit conversion +

+
+

+ Target +

+
+

+ The target type of the implicit conversion +

+
+
+

+
+
Requires
+

+ The declaration Target + t(s);, + where s is of type Source, is valid. +

+
Effects
+

+ registers an rvalue from_python + converter to Target which can succeed for any PyObject* p + iff there exists any registered converter which can produce Source + rvalues +

+
Rationale
+

+ C++ users expect to be able to take advantage of the same sort of + interoperability in Python as they do in C++. +

+
+
+
+
+ +

+ In C++: +

+
#include <boost/python/class.hpp>
+#include <boost/python/implicit.hpp>
+#include <boost/python/module.hpp>
+
+using namespace boost::python;
+
+struct X
+{
+    X(int x) : v(x) {}
+    operator int() const { return v; }
+    int v;
+};
+
+int x_value(X const& x)
+{
+    return x.v;
+}
+
+X make_x(int n) { return X(n); }
+
+BOOST_PYTHON_MODULE(implicit_ext)
+{
+    def("x_value", x_value);
+    def("make_x", make_x);
+
+    class_<X>("X",
+        init<int>())
+        ;
+
+    implicitly_convertible<X,int>();
+    implicitly_convertible<int,X>();
+}
+
+

+ In Python: +

+
>>> from implicit_ext import *
+>>> x_value(X(42))
+42
+>>> x_value(42)
+42
+>>> x = make_x(X(42))
+>>> x_value(x)
+42
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/to_from_python_type_conversion/boost_python_lvalue_from_pytype_.html b/develop/doc/html/reference/to_from_python_type_conversion/boost_python_lvalue_from_pytype_.html new file mode 100644 index 00000000..df4b0a0e --- /dev/null +++ b/develop/doc/html/reference/to_from_python_type_conversion/boost_python_lvalue_from_pytype_.html @@ -0,0 +1,305 @@ + + + +boost/python/lvalue_from_pytype.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

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

+
+
+ + +

+ Class template lvalue_from_pytype will register from_python converters + which, given an object of the given Python type, can extract references + and pointers to a particular C++ type. Its template arguments are: +

+
In the table below, x denotes an object of type PythonObject&
+
+
+++++ + + + + + + + + + + + + + + + + + +
+

+ Parameter +

+
+

+ Requirements +

+
+

+ Semantics +

+
+

+ Extractor +

+
+

+ a model of Extractor + whose execute function returns a reference type. +

+
+

+ Extracts the lvalue from the Python object once its type has + been confirmed +

+
+

+ python_type +

+
+

+ A compile-time constant PyTypeObject* +

+
+

+ The Python type of instances convertible by this converter. Python + subtypes are also convertible. +

+
+
namespace boost { namespace python
+{
+   template <class Extractor, PyTypeObject const* python_type>
+   struct lvalue_from_pytype
+   {
+       lvalue_from_pytype();
+   };
+}}
+
+
+ +
lvalue_from_pytype();
+
+

+
+
Effects
+

+ Registers converters which can convert Python objects of the given + type to lvalues of the type returned by Extractor::execute. +

+
+
+
+
+
+ + +

+ extract_identity is a model of Extractor which can be used in + the common case where the C++ type to be extracted is the same as the Python + object type. +

+
namespace boost { namespace python
+{
+   template <class InstanceType>
+   struct extract_identity
+   {
+      static InstanceType& execute(InstanceType& c);
+   };
+}}
+
+
+ +
InstanceType& execute(InstanceType& c);
+
+

+
+
Returns
+

+ c +

+
+
+
+
+
+ + +

+ extract_member is a model + of Extractor + which can be used in the common case in the common case where the C++ type + to be extracted is a member of the Python object. +

+
namespace boost { namespace python
+{
+   template <class InstanceType, class MemberType, MemberType (InstanceType::*member)>
+   struct extract_member
+   {
+      static MemberType& execute(InstanceType& c);
+   };
+}}
+
+
+ +
static MemberType& execute(InstanceType& c);
+
+

+
+
Returns
+

+ c.*member +

+
+
+
+
+
+ +

+ 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. This module + would have to be dynamically linked to the module which defines noddy_NoddyType. +

+

+ In C++: +

+
#include <boost/python/module.hpp>
+#include <boost/python/handle.hpp>
+#include <boost/python/borrowed.hpp>
+#include <boost/python/lvalue_from_pytype.hpp>
+
+// definition lifted from the Python docs
+typedef struct {
+   PyObject_HEAD
+} noddy_NoddyObject;
+
+using namespace boost::python;
+static handle<noddy_NoddyObject> cache;
+
+bool is_cached(noddy_NoddyObject* x)
+{
+   return x == cache.get();
+}
+
+void set_cache(noddy_NoddyObject* x)
+{
+   cache = handle<noddy_NoddyObject>(borrowed(x));
+}
+
+BOOST_PYTHON_MODULE(noddy_cache)
+{
+   def("is_cached", is_cached);
+   def("set_cache", set_cache);
+
+   // register Noddy lvalue converter
+   lvalue_from_pytype<extract_identity<noddy_NoddyObject>,&noddy_NoddyType>();
+}
+
+

+ In Python: +

+
>>> 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
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/to_from_python_type_conversion/boost_python_opaque_pointer_conv.html b/develop/doc/html/reference/to_from_python_type_conversion/boost_python_opaque_pointer_conv.html new file mode 100644 index 00000000..54fc6588 --- /dev/null +++ b/develop/doc/html/reference/to_from_python_type_conversion/boost_python_opaque_pointer_conv.html @@ -0,0 +1,113 @@ + + + +boost/python/opaque_pointer_converter.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ opaque<> + registers itself as a converter from Python objects to pointers to undefined + types and vice versa. +

+
namespace boost { namespace python
+{
+    template<class Pointee>
+    struct opaque
+    {
+        opaque();
+    };
+}}
+
+
+
+ +
opaque();
+
+

+
+
Effects
+

+ * Registers the instance as a lvalue_from_pytype converter + from Python objects into opaque pointers. The Python Objects created + are named after the type pointed to by the opaque pointer being wrapped. + * Registers the instance as a to_python_converter from + opaque pointers to Python objects. +

+
+
+
+ + + + + +
[Note]Note

+ If there is already an instance registered by another module, this instance + doesn't try to register again in order to avoid warnings about multiple + registrations. +

+
+
+ +

+ This macro must be used to define specializations of the type_id function which can't be + instantiated for incomplete types. +

+
+ + + + + +
[Note]Note

+ The macro must be invoked in every translation unit which uses the opaque + converter. +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/to_from_python_type_conversion/boost_python_register_ptr_to_pyt.html b/develop/doc/html/reference/to_from_python_type_conversion/boost_python_register_ptr_to_pyt.html new file mode 100644 index 00000000..239dc345 --- /dev/null +++ b/develop/doc/html/reference/to_from_python_type_conversion/boost_python_register_ptr_to_pyt.html @@ -0,0 +1,166 @@ + + + +boost/python/register_ptr_to_python.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ <boost/python/register_ptr_to_python.hpp> supplies register_ptr_to_python, a function template + which registers a conversion for smart pointers to Python. The resulting + Python object holds a copy of the converted smart pointer, but behaves + as though it were a wrapped copy of the pointee. If the pointee type has + virtual functions and the class representing its dynamic (most-derived) + type has been wrapped, the Python object will be an instance of the wrapper + for the most-derived type. More than one smart pointer type for a pointee's + class can be registered. +

+

+ Note that in order to convert a Python X + object to a smart_ptr<X>& + (non-const reference), the embedded C++ object must be held by smart_ptr<X>, + and that when wrapped objects are created by calling the constructor from + Python, how they are held is determined by the HeldType parameter to class_<...> + instances. +

+
+
+ +
template <class P>
+void register_ptr_to_python()
+
+
+

+
+
Requires
+

+ P is Dereferenceable. +

+
Effects
+

+ Allows conversions to-python of P instances. +

+
+
+
+
+ +

+ Here is an example of a module that contains a class A with virtual functions + and some functions that work with boost::shared_ptr<A>. +

+

+ In C++: +

+
struct A
+{
+    virtual int f() { return 0; }
+};
+
+shared_ptr<A> New() { return shared_ptr<A>( new A() ); }
+
+int Ok( const shared_ptr<A>& a ) { return a->f(); }
+
+int Fail( shared_ptr<A>& a ) { return a->f(); }
+
+struct A_Wrapper: A
+{
+    A_Wrapper(PyObject* self_): self(self_) {}
+    int f() { return call_method<int>(self, "f"); }
+    int default_f() { return A::f(); }
+    PyObject* self;
+};
+
+BOOST_PYTHON_MODULE(register_ptr)
+{
+    class_<A, A_Wrapper>("A")
+        .def("f", &A::f, &A_Wrapper::default_f)
+    ;
+
+    def("New", &New);
+    def("Ok", &Call);
+    def("Fail", &Fail);
+
+    register_ptr_to_python< shared_ptr<A> >();
+}
+
+

+ In Python: +

+
>>> from register_ptr import *
+>>> a = A()
+>>> Ok(a)     # ok, passed as shared_ptr<A>
+0
+>>> Fail(a)   # passed as shared_ptr<A>&, and was created in Python!
+Traceback (most recent call last):
+  File "<stdin>", line 1, in ?
+TypeError: bad argument type for built-in operation
+>>>
+>>> na = New()   # now "na" is actually a shared_ptr<A>
+>>> Ok(a)
+0
+>>> Fail(a)
+0
+>>>
+
+

+ If shared_ptr<A> is registered as follows: +

+
class_<A, A_Wrapper, shared_ptr<A> >("A")
+    .def("f", &A::f, &A_Wrapper::default_f)
+;
+
+

+ There will be an error when trying to convert shared_ptr<A> to shared_ptr<A_Wrapper>: +

+
>>> a = New()
+Traceback (most recent call last):
+File "<stdin>", line 1, in ?
+TypeError: No to_python (by-value) converter found for C++ type: class boost::shared_ptr<struct A>
+>>>
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/to_from_python_type_conversion/boost_python_to_python_converter.html b/develop/doc/html/reference/to_from_python_type_conversion/boost_python_to_python_converter.html new file mode 100644 index 00000000..46b36e5f --- /dev/null +++ b/develop/doc/html/reference/to_from_python_type_conversion/boost_python_to_python_converter.html @@ -0,0 +1,252 @@ + + + +boost/python/to_python_converter.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

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

+
+
+ + +

+ 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. +

+

+ 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. +

+
+

+ bool has_get_pytype=false +

+
+

+ PyTypeObject const * + p = + Conversion::get_pytype() +

+
+

+ Optional member - if Conversion has get_pytype + member supply true + for this parameters. If present get_pytype + is used to document the return type of functions using this conversion. + The get_pytype + may be implemented using the classes and functions from pytype_function.hpp + NOTE : For backward compatibility this parameter may be passed + after checking if BOOST_PYTHON_SUPPORTS_PY_SIGNATURES is defined + (see here). +

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

+
+
Effects
+

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

+
+
+
+
+
+ +

+ 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. +

+

+ In C++: +

+
#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);
+    }
+    static PyTypeObject const* get_pytype()
+    {
+        return &noddy_NoddyType;
+    }
+};
+
+BOOST_PYTHON_MODULE(to_python_converter)
+{
+    def("make_tag", make_tag);
+    to_python_converter<tag, tag_to_noddy, true>(); //"true" because tag_to_noddy has member get_pytype
+}
+
+

+ In Python: +

+
>>> 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'>
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/topics.html b/develop/doc/html/reference/topics.html new file mode 100644 index 00000000..1f245124 --- /dev/null +++ b/develop/doc/html/reference/topics.html @@ -0,0 +1,332 @@ + + + +Chapter 8. Topics + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+

+Chapter 8. Topics

+ +
+ + +
+ +

+ The simplest way to call a Python function from C++, given an object instance f holding the + function, is simply to invoke its function call operator. +

+
f("tea", 4, 2) // In Python: f('tea', 4, 2)
+

+ And of course, a method of an object instance x can be invoked by using the function-call + operator of the corresponding attribute: +

+
x.attr("tea")(4, 2); // In Python: x.tea(4, 2)
+

+ If you don't have an object instance, Boost.Python provides two families of function + templates, call and call_method, for invoking Python + functions and methods respectively on PyObject*s. The interface for calling a Python function + object (or any Python callable object) looks like: +

+
call<ResultType>(callable_object, a1, a2... aN);
+

+ Calling a method of a Python object is similarly easy: +

+
call_method<ResultType>(self_object, "method-name", a1, a2... aN);
+

+ This comparitively low-level interface is the one you'll use when implementing + C++ virtual functions that can be overridden in Python. +

+
+
+ +

+ Arguments are converted to Python according to their type. By default, + the arguments a1...aN are copied into new Python objects, + but this behavior can be overridden by the use of ptr() + and ref(): +

+
class X : boost::noncopyable
+{
+   ...
+};
+
+void apply(PyObject* callable, X& x)
+{
+   // Invoke callable, passing a Python object which holds a reference to x
+   boost::python::call<void>(callable, boost::ref(x));
+}
+
+

+ In the table below, x denotes the actual argument object and cv denotes + an optional cv-qualification: "const", "volatile", + or "const volatile". +

+
++++ + + + + + + + + + + + + + + + + + + + + + + +
+

+ Argument Type +

+
+

+ Behavior +

+
+

+ T cv + & T + cv +

+
+

+ The Python argument is created by the same means used for the + return value of a wrapped C++ function returning T. When T is + a class type, that normally means *x is copy-constructed into + the new Python object. +

+
+

+ T* +

+
+

+ If x == 0, the Python argument will be None. Otherwise, the Python + argument is created by the same means used for the return value + of a wrapped C++ function returning T. When T is a class type, + that normally means *x is copy-constructed into the new Python + object. +

+
+

+ boost::reference_wrapper<T> +

+
+

+ The Python argument contains a pointer to, rather than a copy + of, x.get(). Note: failure to ensure that no Python code holds + a reference to the resulting object beyond the lifetime of *x.get() + may result in a crash! +

+
+

+ pointer_wrapper<T> +

+
+

+ If x.get() == 0, the Python argument will be None. Otherwise, + the Python argument contains a pointer to, rather than a copy + of, *x.get(). Note: failure to ensure that no Python code holds + a reference to the resulting object beyond the lifetime of *x.get() + may result in a crash! +

+
+
+
+ +

+ In general, call<ResultType>() + and call_method<ResultType>() return ResultType by exploiting all + lvalue and rvalue from_python converters registered for ResultType and + returning a copy of the result. However, when ResultType is a pointer or + reference type, Boost.Python searches only for lvalue converters. To prevent + dangling pointers and references, an exception will be thrown if the Python + result object has only a single reference count. +

+
+
+ +

+ In general, to get Python arguments corresponding to a1...aN, a new Python + object must be created for each one; should the C++ object be copied into + that Python object, or should the Python object simply hold a reference/pointer + to the C++ object? In general, the latter approach is unsafe, since the + called function may store a reference to the Python object somewhere. If + the Python object is used after the C++ object is destroyed, we'll crash + Python. +

+

+ In keeping with the philosophy that users on the Python side shouldn't + have to worry about crashing the interpreter, the default behavior is to + copy the C++ object, and to allow a non-copying behavior only if the user + writes boost::ref(a1) instead of a1 directly. At least this way, the user + doesn't get dangerous behavior "by accident". It's also worth + noting that the non-copying ("by-reference") behavior is in general + only available for class types, and will fail at runtime with a Python + exception if used otherwise[1]. +

+

+ However, pointer types present a problem: one approach is to refuse to + compile if any aN has pointer type: after all, a user can always pass *aN + to pass "by-value" or ref(*aN) to indicate a pass-by-reference + behavior. However, this creates a problem for the expected null pointer + to None conversion: it's illegal to dereference a null pointer value. +

+

+ The compromise I've settled on is this: +

+
    +
  1. + The default behavior is pass-by-value. If you pass a non-null pointer, + the pointee is copied into a new Python object; otherwise the corresponding + Python argument will be None. +
  2. +
  3. + if you want by-reference behavior, use ptr(aN) if aN is a pointer and + ref(aN) otherwise. If a null pointer is passed to ptr(aN), the corresponding + Python argument will be None. +
  4. +
+

+ As for results, we have a similar problem: if ResultType is allowed to + be a pointer or reference type, the lifetime of the object it refers to + is probably being managed by a Python object. When that Python object is + destroyed, our pointer dangles. The problem is particularly bad when the + ResultType is char const* - the corresponding Python String object is typically + uniquely-referenced, meaning that the pointer dangles as soon as call<char + const*>(...) returns. +

+

+ The old Boost.Python v1 deals with this issue by refusing to compile any + uses of call<char const*>(), but this goes both too far and not far + enough. It goes too far because there are cases where the owning Python + string object survives beyond the call (just for instance, when it's the + name of a Python class), and it goes not far enough because we might just + as well have the same problem with a returned pointer or reference of any + other type. +

+

+ In Boost.Python this is dealt with by: +

+
    +
  1. + lifting the compile-time restriction on char + const * + callback returns +
  2. +
  3. + detecting the case when the reference count on the result Python object + is 1 and throwing an exception inside of call<U>(...) when U + is a pointer or reference type. +
  4. +
+

+ This should be acceptably safe because users have to explicitly specify + a pointer/reference for U + in call<U>, + and they will be protected against dangles at runtime, at least long enough + to get out of the call<U>(...) invocation. +

+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/topics/indexing_support.html b/develop/doc/html/reference/topics/indexing_support.html new file mode 100644 index 00000000..bd873bbc --- /dev/null +++ b/develop/doc/html/reference/topics/indexing_support.html @@ -0,0 +1,830 @@ + + + +Indexing support + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ Indexing is a Boost Python + facility for easy exportation of indexable C++ containers to Python. Indexable + containers are containers that allow random access through the operator[] + (e.g. std::vector). +

+

+ While Boost Python + has all the facilities needed to expose indexable C++ containers such as + the ubiquitous std::vector to Python, the procedure is not as straightforward + as we'd like it to be. Python containers do not map easily to C++ containers. + Emulating Python containers in C++ (see Python Reference Manual, Emulating + container types) using Boost.Python + is non trivial. There are a lot of issues to consider before we can map + a C++ container to Python. These involve implementing wrapper functions + for the methods __len__, + __getitem__, __setitem__, __delitem__, + __iter__ and __contains__. +

+

+ The goals: +

+
    +
  • + Make indexable C++ containers behave exactly as one would expect a + Python container to behave. +
  • +
  • + Provide default reference semantics for container element indexing + (__getitem__) such + that c[i] can be mutable. Require: +
    val = c[i]
    +c[i].m()
    +val == c[i]
    +
    +

    + where m is a non-const (mutating) member function (method). +

    +
  • +
  • + Return safe references from __getitem__ + such that subsequent adds and deletes to and from the container will + not result in dangling references (will not crash Python). +
  • +
  • + Support slice indexes. +
  • +
  • + Accept Python container arguments (e.g. lists, + tuples) wherever appropriate. +
  • +
  • + Allow for extensibility through re-definable policy classes. +
  • +
  • + Provide predefined support for the most common STL and STL-like indexable + containers. +
  • +
+
+
+ +

+ The indexing_suite class + is the base class for the management of C++ containers intended to be integrated + to Python. The objective is make a C++ container look and feel and behave + exactly as we'd expect a Python container. The class automatically wraps + these special Python methods (taken from the Python reference: Emulating + container types): +

+
+

+
+
__len__(self)
+

+ Called to implement the built-in function len(). Should return the length of the + object, an integer >= 0. Also, an object that doesn't define + a __nonzero__() + method and whose __len__() method returns zero is considered + to be false in a Boolean context. +

+
__getitem__(self, key)
+

+ Called to implement evaluation of self[key]. For sequence types, the accepted + keys should be integers and slice objects. Note that the special + interpretation of negative indexes (if the class wishes to emulate + a sequence type) is up to the __getitem__() method. If key is of an inappropriate + type, TypeError may + be raised; if of a value outside the set of indexes for the sequence + (after any special interpretation of negative values), IndexError + should be raised. [Note: for loops expect that an IndexError will + be raised for illegal indexes to allow proper detection of the end + of the sequence.] +

+
__setitem__(self, key, value)
+

+ Called to implement assignment to self[key]. Same note as for __getitem__(). + This should only be implemented for mappings if the objects support + changes to the values for keys, or if new keys can be added, or for + sequences if elements can be replaced. The same exceptions should + be raised for improper key values as for the __getitem__() method. +

+
__delitem__(self, key)
+

+ Called to implement deletion of self[key]. Same note as for __getitem__(). + This should only be implemented for mappings if the objects support + removal of keys, or for sequences if elements can be removed from + the sequence. The same exceptions should be raised for improper key + values as for the __getitem__() method. +

+
__iter__(self)
+
+

+ This method is called when an iterator is required for a container. + This method should return a new iterator object that can iterate + over all the objects in the container. For mappings, it should iterate + over the keys of the container, and should also be made available + as the method iterkeys(). +

+

+ Iterator objects also need to implement this method; they are required + to return themselves. For more information on iterator objects, see + Iterator + Types in the Python + Library Reference. +

+
+
__contains__(self, item)
+

+ Called to implement membership test operators. Should return true + if item is in self, false otherwise. For mapping objects, this should + consider the keys of the mapping rather than the values or the key-item + pairs. +

+
+
+
+
+ + +

+ The indexing_suite is not + meant to be used as is. A couple of policy functions must be supplied by + subclasses of indexing_suite. + However, a set of indexing_suite subclasses for the standard indexable + STL containers will be provided, In most cases, we can simply use the available + predefined suites. In some cases, we can refine the predefined suites to + suit our needs. +

+
+ +

+ The vector_indexing_suite + class is a predefined indexing_suite + derived class designed to wrap std::vector + (and std::vector-like [i.e. a class with std::vector interface]) classes. It provides + all the policies required by the indexing_suite. +

+

+ Example usage: +

+
class X {...};
+...
+class_<std::vector<X> >("XVec")
+  .def(vector_indexing_suite<std::vector<X> >())
+;
+
+

+ XVec is now a full-fledged Python container (see the example in full, + along with its python test). +

+
+
+ +

+ The map_indexing_suite + class is a predefined indexing_suite + derived class designed to wrap std::map + (and std::map-like [i.e. a class with std::map interface]) classes. It provides + all the policies required by the indexing_suite. +

+

+ Example usage: +

+
class X {...};
+...
+
+class_<std::map<X> >("XMap")
+    .def(map_indexing_suite<std::map<X> >())
+;
+
+

+ By default indexed elements are returned by proxy. This can be disabled + by supplying true in the + NoProxy template parameter. + XMap is now a full-fledged Python container (see the example in full, + along with its python test). +

+
+
+
+ + +
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Template Parameter +

+
+

+ Requirements +

+
+

+ Semantics +

+
+

+ Default +

+
+

+ Container +

+
+

+ A class type +

+
+

+ The container type to be wrapped to Python. +

+
+
+

+ DerivedPolicies +

+
+

+ A subclass of indexing_suite +

+
+

+ Derived classes provide the policy hooks. See DerivedPolicies + below. +

+
+
+

+ NoProxy +

+
+

+ A boolean +

+
+

+ By default indexed elements have Python reference semantics and + are returned by proxy. This can be disabled by supplying true + in the NoProxy template parameter. +

+
+

+ false +

+
+

+ NoSlice +

+
+

+ A boolean +

+
+

+ Do not allow slicing. +

+
+

+ false +

+
+

+ Data +

+
+ +

+ The container's data type. +

+
+

+ Container::value_type +

+
+

+ Index +

+
+ +

+ The container's index type. +

+
+

+ Container::size_type +

+
+

+ Key +

+
+ +

+ The container's key type. +

+
+

+ Container::value_type +

+
+
template <class Container,
+	  class DerivedPolicies,
+	   bool NoProxy = false,
+	   bool NoSlice = false,
+	   class Data = typename Container::value_type,
+	   class Index = typename Container::size_type,
+	   class Key = typename Container::value_type>
+class indexing_suite : unspecified
+{
+public:
+  indexing_suite(); // default constructor
+}
+
+
+ +

+ Derived classes provide the hooks needed by the indexing_suite: +

+
data_type&
+get_item(Container& container, index_type i);
+
+static object
+get_slice(Container& container, index_type from, index_type to);
+
+static void
+set_item(Container& container, index_type i, data_type const& v);
+
+static void
+set_slice(
+    Container& container, index_type from,
+    index_type to, data_type const& v
+);
+
+template <class Iter>
+static void
+set_slice(Container& container, index_type from,
+    index_type to, Iter first, Iter last
+);
+
+static void
+delete_item(Container& container, index_type i);
+
+static void
+delete_slice(Container& container, index_type from, index_type to);
+
+static size_t
+size(Container& container);
+
+template <class T>
+static bool
+contains(Container& container, T const& val);
+
+static index_type
+convert_index(Container& container, PyObject* i);
+
+static index_type
+adjust_index(index_type current, index_type from,
+    index_type to, size_type len);
+
+

+ Most of these policies are self explanatory. However, convert_index and + adjust_index deserve some explanation. +

+

+ convert_index converts a Python index into a C++ index that the container + can handle. For instance, negative indexes in Python, by convention, + start counting from the right(e.g. C1 + indexes the rightmost element in C). convert_index should handle the + necessary conversion for the C++ container (e.g. convert -1 to C.size()-1). + convert_index should also be able to convert the type of the index (A + dynamic Python type) to the actual type that the C++ container expects. +

+

+ When a container expands or contracts, held indexes to its elements must + be adjusted to follow the movement of data. For instance, if we erase + 3 elements, starting from index 0 from a 5 element vector, what used + to be at index 4 will now be at index 1: +

+
[a][b][c][d][e] ---> [d][e]
+              ^           ^
+              4           1
+
+

+ adjust_index takes care of the adjustment. Given a current index, the + function should return the adjusted index when data in the container + at index from..to is replaced by len elements. +

+
+
+
+ +
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Template Parameter +

+
+

+ Requirements +

+
+

+ Semantics +

+
+

+ Default +

+
+

+ Container +

+
+

+ A class type +

+
+

+ The container type to be wrapped to Python. +

+
+
+

+ NoProxy +

+
+

+ A boolean +

+
+

+ By default indexed elements have Python reference semantics and + are returned by proxy. This can be disabled by supplying true + in the NoProxy template parameter. +

+
+

+ false +

+
+

+ DerivedPolicies +

+
+

+ A subclass of indexing_suite +

+
+

+ The vector_indexing_suite may still be derived to further tweak + any of the predefined policies. Static polymorphism through CRTP + (James Coplien. "Curiously Recurring Template Pattern". + C++ Report, Feb. 1995) enables the base indexing_suite class + to call policy function of the most derived class +

+
+
+
template <class Container,
+	  bool NoProxy = false,
+          class DerivedPolicies = unspecified_default>
+class vector_indexing_suite : unspecified_base
+{
+public:
+
+    typedef typename Container::value_type data_type;
+    typedef typename Container::value_type key_type;
+    typedef typename Container::size_type index_type;
+    typedef typename Container::size_type size_type;
+    typedef typename Container::difference_type difference_type;
+
+    data_type&
+    get_item(Container& container, index_type i);
+
+    static object
+    get_slice(Container& container, index_type from, index_type to);
+
+    static void
+    set_item(Container& container, index_type i, data_type const& v);
+
+    static void
+    set_slice(Container& container, index_type from,
+        index_type to, data_type const& v);
+
+    template <class Iter>
+    static void
+    set_slice(Container& container, index_type from,
+        index_type to, Iter first, Iter last);
+
+    static void
+    delete_item(Container& container, index_type i);
+
+    static void
+    delete_slice(Container& container, index_type from, index_type to);
+
+    static size_t
+    size(Container& container);
+
+    static bool
+    contains(Container& container, key_type const& key);
+
+    static index_type
+    convert_index(Container& container, PyObject* i);
+
+    static index_type
+    adjust_index(index_type current, index_type from,
+        index_type to, size_type len);
+};
+
+
+
+ +
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Template Parameter +

+
+

+ Requirements +

+
+

+ Semantics +

+
+

+ Default +

+
+

+ Container +

+
+

+ A class type +

+
+

+ The container type to be wrapped to Python. +

+
+
+

+ NoProxy +

+
+

+ A boolean +

+
+

+ By default indexed elements have Python reference semantics and + are returned by proxy. This can be disabled by supplying true + in the NoProxy template parameter. +

+
+

+ false +

+
+

+ DerivedPolicies +

+
+

+ A subclass of indexing_suite +

+
+

+ The vector_indexing_suite may still be derived to further tweak + any of the predefined policies. Static polymorphism through CRTP + (James Coplien. "Curiously Recurring Template Pattern". + C++ Report, Feb. 1995) enables the base indexing_suite class + to call policy function of the most derived class +

+
+
+
template <class Container,
+          bool NoProxy = false,
+          class DerivedPolicies = unspecified_default>
+class map_indexing_suite : unspecified_base
+{
+public:
+
+    typedef typename Container::value_type value_type;
+    typedef typename Container::value_type::second_type data_type;
+    typedef typename Container::key_type key_type;
+    typedef typename Container::key_type index_type;
+    typedef typename Container::size_type size_type;
+    typedef typename Container::difference_type difference_type;
+
+    static data_type&
+    get_item(Container& container, index_type i);
+
+    static void
+    set_item(Container& container, index_type i, data_type const& v);
+
+    static void
+    delete_item(Container& container, index_type i);
+
+    static size_t
+    size(Container& container);
+
+    static bool
+    contains(Container& container, key_type const& key);
+
+    static bool
+    compare_index(Container& container, index_type a, index_type b);
+
+    static index_type
+    convert_index(Container& container, PyObject* i);
+};
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/topics/pickle_support.html b/develop/doc/html/reference/topics/pickle_support.html new file mode 100644 index 00000000..fa3b57fb --- /dev/null +++ b/develop/doc/html/reference/topics/pickle_support.html @@ -0,0 +1,356 @@ + + + +Pickle support + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ 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 through the interface + as described in detail in the Python + Library Reference for pickle. This interface involves the special + methods __getinitargs__, + __getstate__ and __setstate__ as described in the following. + Note that Boost.Python is also fully compatible with + Python's cPickle module. +

+
+
+ +

+ At the user level, the Boost.Python pickle interface involves three special + methods: +

+
+

+
+
__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 + (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, pickle.load + will call the constructor (__init__) + without arguments; i.e., the object must be default-constructible. +

+
+
__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. +

+
__setstate__
+

+ When an instance of a Boost.Python + extension class is restored by the unpickler (pickle.load), + 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. +

+
+
+

+ The three special methods described above may be .def()'ed + individually by the user. However, Boost.Python + provides an easy to use high-level interface via the boost::python::pickle_suite + class that also enforces consistency: __getstate__ + and __setstate__ must be + defined as pairs. Use of this interface is demonstrated by the following + examples. +

+
+
+ + +

+ There are three files in python/test + that show how to provide pickle support. +

+
+ +

+ 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__. + This is done in the following way: Definition of the C++ pickle function: +

+
struct world_pickle_suite : boost::python::pickle_suite
+{
+  static
+  boost::python::tuple
+  getinitargs(world const& w)
+  {
+      return boost::python::make_tuple(w.get_country());
+  }
+};
+
+

+ Establishing the Python binding: +

+
class_<world>("world", args<const std::string&>())
+      // ...
+      .def_pickle(world_pickle_suite())
+      // ...
+
+
+
+ +

+ 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: +

+

+ Definition of the C++ pickle functions: +

+
struct world_pickle_suite : boost::python::pickle_suite
+  {
+    static
+    boost::python::tuple
+    getinitargs(const world& w)
+    {
+      // ...
+    }
+
+    static
+    boost::python::tuple
+    getstate(const world& w)
+    {
+      // ...
+    }
+
+    static
+    void
+    setstate(world& w, boost::python::tuple state)
+    {
+      // ...
+    }
+  };
+
+

+ Establishing the Python bindings for the entire suite: +

+
class_<world>("world", args<const std::string&>())
+    // ...
+    .def_pickle(world_pickle_suite())
+    // ...
+
+

+ 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 guard described below will + catch the cases where this assumption is violated. +

+
+
+ +

+ This example is similar to pickle2.cpp. However, the object's __dict__ is included in the result + of __getstate__. This + requires a little more code but is unavoidable if the object's __dict__ is not always empty. +

+
+
+
+ +

+ The pickle protocol described above has an important pitfall that the end + user of a Boost.Python extension module might not be aware of: +

+

+ __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: * 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. +

+

+ 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: +

+
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 either at the C++ or the Python level. + Finally, the safety guard should intentionally be overridden. E.g. in C++ + (from pickle3.cpp): +

+
struct world_pickle_suite : boost::python::pickle_suite
+{
+  // ...
+
+  static bool getstate_manages_dict() { return true; }
+};
+
+

+ Alternatively 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
+
+
+
+ +
    +
  • + 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. +
  • +
  • + Avoid using __getstate__ + if the instance can also be reconstructed by way of __getinitargs__. + This automatically avoids the pitfall described above. +
  • +
  • + If __getstate__ is + required, include the instance's __dict__ + in the Python object that is returned. +
  • +
+
+
+ +

+ The pickle4.cpp example demonstrates an alternative technique for implementing + pickle support. First we direct Boost.Python via the class_::enable_pickling() + member function to define only the basic attributes required for pickling: +

+
class_<world>("world", args<const std::string&>())
+    // ...
+    .enable_pickling()
+    // ...
+
+

+ This enables the standard Python pickle interface as described in the Python + documentation. By "injecting" a __getinitargs__ + method into the definition of the wrapped class we make all instances pickleable: +

+
# import the wrapped world class
+from pickle4_ext import world
+
+# definition of __getinitargs__
+def world_getinitargs(self):
+  return (self.get_country(),)
+
+# now inject __getinitargs__ (Python is a dynamic language!)
+world.__getinitargs__ = world_getinitargs
+
+

+ See also the tutorial section on injecting additional methods from Python. +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/utility_and_infrastructure.html b/develop/doc/html/reference/utility_and_infrastructure.html new file mode 100644 index 00000000..6efe2aec --- /dev/null +++ b/develop/doc/html/reference/utility_and_infrastructure.html @@ -0,0 +1,240 @@ + + + +Chapter 7. Utility and Infrastructure + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+

+Chapter 7. Utility and Infrastructure

+ +
+ + +
+ +

+ <boost/python/has_back_reference.hpp> defines the predicate metafunction + has_back_reference<>, + which can be specialized by the user to indicate that a wrapped class instance + holds a PyObject* + corresponding to a Python object. +

+
+
+ +

+ A unary metafunction whose value is true iff its argument is a pointer_wrapper<>. +

+
namespace boost { namespace python
+{
+    template<class WrappedClass> class has_back_reference
+    {
+        typedef mpl::false_ type;
+    };
+}}
+
+

+ A metafunction that is inspected by Boost.Python to determine how wrapped + classes can be constructed. +

+

+ type::value is an integral constant convertible + to bool of unspecified type. Specializations may substitute a true-valued + integral constant wrapper for type iff for each invocation of class_<WrappedClass>::def(init< type-sequence...>()) + and the implicitly wrapped copy constructor (unless it is noncopyable), + there exists a corresponding constructor WrappedClass::WrappedClass(PyObject*, type-sequence...). If such a specialization exists, the + WrappedClass constructors will be called with a "back reference" + pointer to the corresponding Python object whenever they are invoked from + Python. The easiest way to provide this nested type is to derive the specialization + from mpl::true_. +

+
+
+ +

+ In C++: +

+
#include <boost/python/class.hpp>
+#include <boost/python/module.hpp>
+#include <boost/python/has_back_reference.hpp>
+#include <boost/python/handle.hpp>
+#include <boost/shared_ptr.hpp>
+
+using namespace boost::python;
+using boost::shared_ptr;
+
+struct X
+{
+    X(PyObject* self) : m_self(self), m_x(0) {}
+    X(PyObject* self, int x) : m_self(self), m_x(x) {}
+    X(PyObject* self, X const& other) : m_self(self), m_x(other.m_x) {}
+
+    handle<> self() { return handle<>(borrowed(m_self)); }
+    int get() { return m_x; }
+    void set(int x) { m_x = x; }
+
+    PyObject* m_self;
+    int m_x;
+};
+
+// specialize has_back_reference for X
+namespace boost { namespace python
+{
+  template <>
+  struct has_back_reference<X>
+    : mpl::true_
+  {};
+}}
+
+struct Y
+{
+    Y() : m_x(0) {}
+    Y(int x) : m_x(x) {}
+    int get() { return m_x; }
+    void set(int x) { m_x = x; }
+
+    int m_x;
+};
+
+shared_ptr<Y>
+Y_self(shared_ptr<Y> self) { return self; }
+
+BOOST_PYTHON_MODULE(back_references)
+{
+    class_<X>("X")
+       .def(init<int>())
+       .def("self", &X::self)
+       .def("get", &X::get)
+       .def("set", &X::set)
+       ;
+
+    class_<Y, shared_ptr<Y> >("Y")
+       .def(init<int>())
+       .def("get", &Y::get)
+       .def("set", &Y::set)
+       .def("self", Y_self)
+       ;
+}
+
+

+ The following Python session illustrates that x.self() returns the same + Python object on which it is invoked, while y.self() must create a new + Python object which refers to the same Y instance. +

+

+ In Python: +

+
>>> from back_references import *
+>>> x = X(1)
+>>> x2 = x.self()
+>>> x2 is x
+1
+>>> (x.get(), x2.get())
+(1, 1)
+>>> x.set(10)
+>>> (x.get(), x2.get())
+(10, 10)
+>>>
+>>>
+>>> y = Y(2)
+>>> y2 = y.self()
+>>> y2 is y
+0
+>>> (y.get(), y2.get())
+(2, 2)
+>>> y.set(20)
+>>> (y.get(), y2.get())
+(20, 20)
+
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/utility_and_infrastructure/boost_python_handle_hpp.html b/develop/doc/html/reference/utility_and_infrastructure/boost_python_handle_hpp.html new file mode 100644 index 00000000..aee1aa0f --- /dev/null +++ b/develop/doc/html/reference/utility_and_infrastructure/boost_python_handle_hpp.html @@ -0,0 +1,363 @@ + + + +boost/python/handle.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ <boost/python/handle.hpp> provides class template handle, + a smart pointer for managing reference-counted Python objects. +

+
+
+ + +

+ handle is a smart pointer + to a Python object type; it holds a pointer of type T*, where T + is its template parameter. T must be either a type derived from PyObject or a POD + type whose initial sizeof(PyObject) bytes are layout-compatible with PyObject. Use handle<> at the boundary between the Python/'C' + API and high-level code; prefer object for a generalized interface to Python + objects. +

+

+ In this document, the term "upcast" refers to an operation which + converts a pointer Y* + to a base class pointer T* via + static_cast<T*> + if Y is derived from T, or via C-style cast (T*) if + it is not. However, in the latter case the "upcast" is ill-formed + if the initial sizeof(PyObject) + bytes of Y are not layout-compatible + with PyObject. +

+
namespace boost { namespace python
+{
+  template <class T>
+  class handle
+  {
+      typedef unspecified-member-function-pointer bool_type;
+
+   public: // types
+      typedef T element_type;
+
+   public: // member functions
+      ~handle();
+
+      template <class Y>
+      explicit handle(detail::borrowed<null_ok<Y> >* p);
+
+      template <class Y>
+      explicit handle(null_ok<detail::borrowed<Y> >* p);
+
+      template <class Y>
+      explicit handle(detail::borrowed<Y>* p);
+
+      template <class Y>
+      explicit handle(null_ok<Y>* p);
+
+      template <class Y>
+      explicit handle(Y* p);
+
+      handle();
+
+      handle& operator=(handle const& r);
+
+      template<typename Y>
+      handle& operator=(handle<Y> const & r); // never throws
+
+
+      template <typename Y>
+      handle(handle<Y> const& r);
+
+      handle(handle const& r);
+
+      T* operator-> () const;
+      T& operator* () const;
+      T* get() const;
+      void reset();
+      T* release();
+
+      operator bool_type() const; // never throws
+   private:
+      T* m_p;
+  };
+
+  template <class T> struct null_ok;
+  namespace detail { template <class T> struct borrowed; }
+}}
+
+
+ +
virtual ~handle();
+
+

+
+
Effects
+

+ Py_XDECREF(upcast<PyObject*>(m_p)) +

+
+
+
template <class Y>
+explicit handle(detail::borrowed<null_ok<Y> >* p);
+
+
+

+
+
Effects
+
Py_XINCREF(upcast<PyObject*>(p));
+m_p = upcast<T*>(p);
+
+
+
+
template <class Y>
+explicit handle(null_ok<detail::borrowed<Y> >* p);
+
+

+
+
Effects
+
Py_XINCREF(upcast<PyObject*>(p));
+      m_p = upcast<T*>(p);
+
+
+
+
template <class Y>
+explicit handle(detail::borrowed<Y>* p);
+
+

+
+
Effects
+
Py_XINCREF(upcast<PyObject*>(p));
+      m_p = upcast<T*>(expect_non_null(p));
+
+
+
+
template <class Y>
+explicit handle(null_ok<Y>* p);
+
+
+

+
+
Effects
+

+ m_p = + upcast<T*>(p); +

+
+
+
template <class Y>
+explicit handle(Y* p);
+
+
+

+
+
Effects
+

+ m_p = + upcast<T*>(expect_non_null(p)); +

+
+
+
handle();
+
+
+

+
+
Effects
+

+ m_p = + 0; +

+
+
+
template <typename Y>
+handle(handle<Y> const& r);
+handle(handle const& r);
+
+
+

+
+
Effects
+

+ m_p = r.m_p; Py_XINCREF(upcast<PyObject*>(m_p)); +

+
+
+
+
+ +
handle& operator=(handle const& r);
+template<typename Y>
+handle& operator=(handle<Y> const & r); // never throws
+
+
+

+
+
Effects
+

+ Py_XINCREF(upcast<PyObject*>(r.m_p)); + Py_XDECREF( + upcast<PyObject*>(m_p)); + m_p = + r.m_p; +

+
+
+
T* release();
+
+
+

+
+
Effects
+

+ T* + x = + m_p; + m_p = + 0; + return x; +

+
+
+
void reset();
+
+
+

+
+
Effects
+

+ *this + = handle<T>(); +

+
+
+
+
+ +
T* operator-> () const;
+T* get() const;
+
+
+

+
+
Returns
+

+ m_p; +

+
+
+
T& operator* () const;
+
+
+

+
+
Returns
+

+ *m_p; +

+
+
+
operator bool_type() const; // never throws
+
+
+

+
+
Returns
+

+ 0 if m_p == + 0, a pointer convertible + to true otherwise. +

+
+
+
+
+
+ +
template <class T>
+detail::borrowed<T>* borrowed(T* p)
+{
+    return (detail::borrowed<T>*)p;
+}
+
+
+
+ +
template <class T>
+null_ok<T>* allow_null(T* p)
+{
+    return (null_ok<T>*)p;
+}
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/utility_and_infrastructure/boost_python_instance_holder_hpp.html b/develop/doc/html/reference/utility_and_infrastructure/boost_python_instance_holder_hpp.html new file mode 100644 index 00000000..da0b58d1 --- /dev/null +++ b/develop/doc/html/reference/utility_and_infrastructure/boost_python_instance_holder_hpp.html @@ -0,0 +1,212 @@ + + + +boost/python/instance_holder.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ <boost/python/instance_holder.hpp> provides class instance_holder, + the base class for types which hold C++ instances of wrapped classes. +

+
+
+ + +

+ instance_holder is an abstract + base class whose concrete derived classes hold C++ class instances within + their Python object wrappers. To allow multiple inheritance in Python from + C++ class wrappers, each such Python object contains a chain of instance_holders. + When an __init__ function + for a wrapped C++ class is invoked, a new instance_holder + instance is created and installed in the Python object using its install() + function. Each concrete class derived from instance_holder + must provide a holds() + implementation which allows Boost.Python to query it for the type(s) it + is holding. In order to support the held type's wrapped constructor(s), + the class must also provide constructors that can accept an initial PyObject* + argument referring to the owning Python object, and which forward the rest + of their arguments to the constructor of the held type. The initial argument + is needed to enable virtual function overriding in Python, and may be ignored, + depending on the specific instance_holder + subclass. +

+
namespace boost { namespace python
+{
+  class instance_holder : noncopyable
+  {
+   public:
+      // destructor
+      virtual ~instance_holder();
+
+      // instance_holder modifiers
+      void install(PyObject* inst) throw();
+
+      // instance_holder observers
+      virtual void* holds(type_info) = 0;
+  };
+}}
+
+
+ +
virtual ~instance_holder();
+
+

+
+
Effects
+

+ destroys the object +

+
+
+
+
+ +
void install(PyObject* inst) throw();
+
+

+
+
Requires
+

+ inst is a Python + instance of a wrapped C++ class type, or is a type derived from + a wrapped C++ class type. +

+
Effects
+

+ installs the new instance at the head of the Python object's chain + of held instances. +

+
Throws
+

+ nothing +

+
+
+
+
+ +
virtual void *holds(type_info x) = 0;
+
+

+
+
Returns
+

+ A pointer to an object of the type described by x + if *this + contains such an object, 0 otherwise. +

+
+
+
+
+
+ +

+ The following is a simplified version of the instance holder template used + by Boost.Python to wrap classes held by smart pointers: +

+
template <class SmartPtr, class Value>
+struct pointer_holder : instance_holder
+{
+   // construct from the SmartPtr type
+   pointer_holder(SmartPtr p)
+       :m_p(p)
+
+   // Forwarding constructors for the held type
+   pointer_holder(PyObject*)
+       :m_p(new Value())
+   {
+   }
+
+   template<class A0>
+   pointer_holder(PyObject*,A0 a0)
+       :m_p(new Value(a0))
+   {
+   }
+
+   template<class A0,class A1>
+   pointer_holder(PyObject*,A0 a0,A1 a1)
+       :m_p(new Value(a0,a1))
+   {
+   }
+   ...
+
+ private: // required holder implementation
+   void* holds(type_info dst_t)
+   {
+       // holds an instance of the SmartPtr type...
+       if (dst_t == python::type_id<SmartPtr>())
+           return &this->m_p;
+
+       // ...and an instance of the SmartPtr's element_type, if the
+       // pointer is non-null
+       return python::type_id<Value>() == dst_t ? &*this->m_p : 0;
+   }
+
+ private: // data members
+   SmartPtr m_p;
+};
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/utility_and_infrastructure/boost_python_pointee_hpp.html b/develop/doc/html/reference/utility_and_infrastructure/boost_python_pointee_hpp.html new file mode 100644 index 00000000..4ef868b8 --- /dev/null +++ b/develop/doc/html/reference/utility_and_infrastructure/boost_python_pointee_hpp.html @@ -0,0 +1,106 @@ + + + +boost/python/pointee.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ <boost/python/pointee.hpp> introduces a traits metafunction template pointee<T> that can be used to extract the "pointed-to" + type from the type of a pointer or smart pointer. +

+
+
+ +

+ pointee<T> + is used by the class_<...> + template to deduce the type being held when a pointer or smart pointer + type is used as its HeldType argument. +

+
namespace boost { namespace python
+{
+   template <class T> struct pointee
+   {
+      typedef T::element_type type;
+   };
+
+   // specialization for pointers
+   template <T> struct pointee<T*>
+   {
+      typedef T type;
+   };
+}
+
+
+
+ +

+ Given a 3rd-party smart pointer type smart_pointer<T>, one might partially specialize pointee<smart_pointer<T> > so that it can be used as the HeldType + for a class wrapper: +

+
#include <boost/python/pointee.hpp>
+#include <boost/python/class.hpp>
+#include <third_party_lib.hpp>
+
+namespace boost { namespace python
+{
+  template <class T> struct pointee<smart_pointer<T> >
+  {
+     typedef T type;
+  };
+}}
+
+BOOST_PYTHON_MODULE(pointee_demo)
+{
+   class_<third_party_class, smart_pointer<third_party_class> >("third_party_class")
+      .def(...)
+      ...
+      ;
+}
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/utility_and_infrastructure/boost_python_ssize_t_hpp.html b/develop/doc/html/reference/utility_and_infrastructure/boost_python_ssize_t_hpp.html new file mode 100644 index 00000000..a0b168d3 --- /dev/null +++ b/develop/doc/html/reference/utility_and_infrastructure/boost_python_ssize_t_hpp.html @@ -0,0 +1,90 @@ + + + +boost/python/ssize_t.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ Python 2.5 introduces a new Py_ssize_t + typedef and two related macros (PEP + 353). The <boost/python/ssize_t.hpp> header imports these + definitions into the boost::python + namespace as ssize_t, + ssize_t_max, and ssize_t_min. Appropriate definitions + are provided for backward compatibility with previous Python versions. +

+
+
+ +

+ Imports Py_ssize_t into + the boost::python namespace if available, or provides + an appropriate typedef for backward compatibility: +

+
#if PY_VERSION_HEX >= 0x02050000
+typedef Py_ssize_t ssize_t;
+#else
+typedef int ssize_t;
+#endif
+
+
+
+ +

+ Imports PY_SSIZE_T_MAX + and PY_SSIZE_T_MIN as constants + into the boost::python namespace if available, or provides + appropriate constants for backward compatibility: +

+
#if PY_VERSION_HEX >= 0x02050000
+ssize_t const ssize_t_max = PY_SSIZE_T_MAX;
+ssize_t const ssize_t_min = PY_SSIZE_T_MIN;
+#else
+ssize_t const ssize_t_max = INT_MAX;
+ssize_t const ssize_t_min = INT_MIN;
+#endif
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/reference/utility_and_infrastructure/boost_python_type_id_hpp.html b/develop/doc/html/reference/utility_and_infrastructure/boost_python_type_id_hpp.html new file mode 100644 index 00000000..f5e05260 --- /dev/null +++ b/develop/doc/html/reference/utility_and_infrastructure/boost_python_type_id_hpp.html @@ -0,0 +1,234 @@ + + + +boost/python/type_id.hpp + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ <boost/python/type_id.hpp> provides types and functions for runtime + type identification like those of of <typeinfo>. + It exists mostly to work around certain compiler bugs and platform-dependent + interactions with shared libraries. +

+
+
+ + +

+ type_info instances identify + a type. As std::type_info is specified to (but unlike + its implementation in some compilers), boost::python::type_info + never represents top-level references or cv-qualification (see section + 5.2.8 in the C++ standard). Unlike std::type_info, + boost::python::type_info instances are copyable, and + comparisons always work reliably across shared library boundaries. +

+
namespace boost { namespace python
+{
+  class type_info : totally_ordered<type_info>
+  {
+  public:
+    // constructor
+    type_info(std::type_info const& = typeid(void));
+
+    // comparisons
+    bool operator<(type_info const& rhs) const;
+    bool operator==(type_info const& rhs) const;
+
+    // observers
+    char const* name() const;
+  };
+}}
+
+
+ +
type_info(std::type_info const& = typeid(void));
+
+

+
+
Effects
+

+ constructs a type_info + object which identifies the same type as its argument. +

+
Rationale
+

+ Since it is occasionally necessary to make an array of type_info objects a benign default + argument is supplied. Note: this constructor does not correct for + non-conformance of compiler typeid() implementations. See type_id, below. +

+
+
+
+
+ +
bool operator<(type_info const &rhs) const;
+
+

+
+
Effects
+

+ yields a total order over type_info + objects. +

+
+
+
bool operator==(type_info const &rhs) const;
+
+

+
+
Returns
+

+ true iff the two values + describe the same type. +

+
Note
+

+ The use of totally_ordered<type_info> as a private base class supplies + operators <=, + >=, >, and != +

+
+
+
+
+ +
char const* name() const;
+
+
+

+
+
Returns
+

+ The result of calling name() on the argument used to construct + the object. +

+
+
+
+
+
+ +
std::ostream& operator<<(std::ostream&s, type_info const&x);
+
+
+

+
+
Effects
+

+ Writes a description of the type described by to x + into s. +

+
Rationale
+

+ Not every C++ implementation provides a truly human-readable type_info::name() + string, but for some we may be able to decode the string and produce + a reasonable representation. +

+
Note
+

+ On some non-conforming C++ implementations, the code is not actually + as simple as described above; the semantics are adjusted to work + as-if the C++ implementation were conforming. +

+
+
+
template <class T> type_info type_id()
+
+
+

+
+
Returns
+

+ type_info(typeid(T)) +

+
Note
+

+ On some non-conforming C++ implementations, the code is not actually + as simple as described above; the semantics are adjusted to work + as-if the C++ implementation were conforming. +

+
+
+
+
+ +

+ The following example, though silly, illustrates how the type_id facility + might be used +

+
#include <boost/python/type_id.hpp>
+
+// Returns true iff the user passes an int argument
+template <class T>
+bool is_int(T x)
+{
+   using boost::python::type_id;
+   return type_id<T>() == type_id<int>();
+}
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/rst.css b/develop/doc/html/rst.css new file mode 100644 index 00000000..afd9a98c --- /dev/null +++ b/develop/doc/html/rst.css @@ -0,0 +1,149 @@ +@import url("doc/src/boostbook.css"); +@import url("doc/src/docutils.css"); +/* Copyright David Abrahams 2006. Distributed under the Boost + Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +dl.docutils dt { + font-weight: bold } + +img.boost-logo { + border: none; + vertical-align: middle +} + +pre.literal-block span.concept { + font-style: italic; +} + +.nav { +display: inline; +list-style-type: none; +} + +.prevpage { +padding-top: -5px; +text-align: left; +float: left; +} + +.nextpage { +padding-top: -20px; +text-align: right; +float: right; +} + +div.small { + font-size: smaller } + +h2 a { + font-size: 90%; +} +h3 a { + font-size: 80%; +} +h4 a { + font-size: 70%; +} +h5 a { + font-size: 60%; +} + +dl,table +{ + text-align: left; + font-size: 10pt; + line-height: 1.15; +} + + +/*============================================================================= + Tables +=============================================================================*/ + +/* The only clue docutils gives us that tables are logically tables, + and not, e.g., footnotes, is that they have border="1". Therefore + we're keying off of that. We used to manually patch docutils to + add a "table" class to all logical tables, but that proved much too + fragile. +*/ + + table[border="1"] + { + width: 92%; + margin-left: 4%; + margin-right: 4%; + } + + table[border="1"] + { + padding: 4px; + } + + /* Table Cells */ + table[border="1"] tr td + { + padding: 0.5em; + text-align: left; + font-size: 9pt; + } + + table[border="1"] tr th + { + padding: 0.5em 0.5em 0.5em 0.5em; + border: 1pt solid white; + font-size: 80%; + } + + @media screen + { + + /* Tables */ + table[border="1"] tr td + { + border: 1px solid #DCDCDC; + } + + table[border="1"] tr th + { + background-color: #F0F0F0; + border: 1px solid #DCDCDC; + } + + pre, + .screen + { + border: 1px solid #DCDCDC; + } + + td pre + td .screen + { + border: 0px + } + + .sidebar pre + { + border: 0px + } + + } + + pre, + .screen + { + font-size: 9pt; + display: block; + margin: 1pc 4% 0pc 4%; + padding: 0.5pc 0.5pc 0.5pc 0.5pc; + } + + /* Program listings in tables don't get borders */ + td pre, + td .screen + { + margin: 0pc 0pc 0pc 0pc; + padding: 0pc 0pc 0pc 0pc; + } + diff --git a/develop/doc/html/support.html b/develop/doc/html/support.html new file mode 100644 index 00000000..01908ff2 --- /dev/null +++ b/develop/doc/html/support.html @@ -0,0 +1,85 @@ + + + +Chapter 3. Support Resources + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+

+Chapter 3. Support Resources

+

+ + Synopsis +

+

+ This is a list of available resources for support with Boost.Python problems + and feature requests. Please try to resist emailing the Boost.Python developers + directly for support. Use the following resources instead; the developers are + listening! +

+

+ + Support +

+
    +
  • + The Boost.Python + mailing list is a forum for discussing Python/C++ interoperability, + and Boost.Python in particular. Post your Boost.Python questions here. +
  • +
  • + The Boost.Build + mailing list is a forum for discussing Boost's Build System. +
  • +
  • +

    + The Boost.Python Issue + tracker +

    +
    + + + + + +
    [Note]Note

    + In the past we used Trac, which still hosts a considerable number of + open + issues. We hope to be able to either close them or migrate + them to the new issue tracker. +

    +
  • +
  • + The Boost.Python Wiki +
  • +
  • + Boost.Python Source repository +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/tutorial/HTML.manifest b/develop/doc/html/tutorial/HTML.manifest new file mode 100644 index 00000000..15d1dc13 --- /dev/null +++ b/develop/doc/html/tutorial/HTML.manifest @@ -0,0 +1,9 @@ +index.html +tutorial/hello.html +tutorial/exposing.html +tutorial/functions.html +tutorial/object.html +tutorial/embedding.html +tutorial/iterators.html +tutorial/exception.html +tutorial/techniques.html diff --git a/develop/doc/html/tutorial/index.html b/develop/doc/html/tutorial/index.html new file mode 100644 index 00000000..304bb9b1 --- /dev/null +++ b/develop/doc/html/tutorial/index.html @@ -0,0 +1,149 @@ + + + +Boost.Python Tutorial + + + + + + +
+
+
Next
+
+
+
+

+Boost.Python Tutorial

+
+

+Joel de Guzman +

+

+David Abrahams +

+
+
+
+

+ Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt +

+
+
+
+
+ +
+ +

+ The Boost Python Library is a framework for interfacing Python and C++. It + allows you to quickly and seamlessly expose C++ classes functions and objects + to Python, and vice-versa, using no special tools -- just your C++ compiler. + It is designed to wrap C++ interfaces non-intrusively, so that you should not + have to change the C++ code at all in order to wrap it, making Boost.Python + ideal for exposing 3rd-party libraries to Python. The library's use of advanced + metaprogramming techniques simplifies its syntax for users, so that wrapping + code takes on the look of a kind of declarative interface definition language + (IDL). +

+

+ + Hello + World +

+

+ Following C/C++ tradition, let's start with the "hello, world". A + C++ Function: +

+
char const* greet()
+{
+   return "hello, world";
+}
+
+

+ can be exposed to Python by writing a Boost.Python wrapper: +

+
#include <boost/python.hpp>
+
+BOOST_PYTHON_MODULE(hello_ext)
+{
+    using namespace boost::python;
+    def("greet", greet);
+}
+
+

+ That's it. We're done. We can now build this as a shared library. The resulting + DLL is now visible to Python. Here's a sample Python session: +

+
>>> import hello_ext
+>>> print hello_ext.greet()
+hello, world
+
+

+ Next stop... Building your Hello World module + from start to finish... +

+
+
+ + + +

Last revised: October 07, 2016 at 15:41:24 GMT

+
+
Next
+ + diff --git a/develop/doc/html/tutorial/tutorial/embedding.html b/develop/doc/html/tutorial/tutorial/embedding.html new file mode 100644 index 00000000..69371aec --- /dev/null +++ b/develop/doc/html/tutorial/tutorial/embedding.html @@ -0,0 +1,268 @@ + + + +Embedding + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +

+ By now you should know how to use Boost.Python to call your C++ code from Python. + However, sometimes you may need to do the reverse: call Python code from the + C++-side. This requires you to embed the Python interpreter + into your C++ program. +

+

+ Currently, Boost.Python does not directly support everything you'll need when + embedding. Therefore you'll need to use the Python/C + API to fill in the gaps. However, Boost.Python already makes embedding + a lot easier and, in a future version, it may become unnecessary to touch the + Python/C API at all. So stay tuned... +

+

+ + Building + embedded programs +

+

+ To be able to embed python into your programs, you have to link to both Boost.Python's + as well as Python's own runtime library. +

+

+ Boost.Python's library comes in two variants. Both are located in Boost's + /libs/python/build/bin-stage subdirectory. On Windows, the + variants are called boost_python.lib (for release builds) + and boost_python_debug.lib (for debugging). If you can't + find the libraries, you probably haven't built Boost.Python yet. See Building and Testing on how to do this. +

+

+ Python's library can be found in the /libs subdirectory + of your Python directory. On Windows it is called pythonXY.lib where X.Y is + your major Python version number. +

+

+ Additionally, Python's /include subdirectory has to be added + to your include path. +

+

+ In a Jamfile, all the above boils down to: +

+
projectroot c:\projects\embedded_program ; # location of the program
+
+# bring in the rules for python
+SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
+include python.jam ;
+
+exe embedded_program # name of the executable
+  : #sources
+     embedded_program.cpp
+  : # requirements
+     <find-library>boost_python <library-path>c:\boost\libs\python
+  $(PYTHON_PROPERTIES)
+    <library-path>$(PYTHON_LIB_PATH)
+    <find-library>$(PYTHON_EMBEDDED_LIBRARY) ;
+
+

+ + Getting + started +

+

+ Being able to build is nice, but there is nothing to build yet. Embedding the + Python interpreter into one of your C++ programs requires these 4 steps: +

+
    +
  1. + #include <boost/python.hpp> +
  2. +
  3. + Call Py_Initialize() + to start the interpreter and create the __main__ module. +
  4. +
  5. + Call other Python C API routines to use the interpreter. +
  6. +
+
+ + + + + +
[Note]Note

+ Note that at this time you must not call Py_Finalize() + to stop the interpreter. This may be fixed in a future version of boost.python. +

+

+ (Of course, there can be other C++ code between all of these steps.) +

+

+ Now that we can embed the interpreter in + our programs, lets see how to put it to use... +

+
+ +

+ As you probably already know, objects in Python are reference-counted. Naturally, + the PyObjects of the Python C API are also reference-counted. + There is a difference however. While the reference-counting is fully automatic + in Python, the Python C API requires you to do it by + hand. This is messy and especially hard to get right in the presence + of C++ exceptions. Fortunately Boost.Python provides the handle + and object + class templates to automate the process. +

+

+ + Running + Python code +

+

+ Boost.python provides three related functions to run Python code from C++. +

+
object eval(str expression, object globals = object(), object locals = object())
+object exec(str code, object globals = object(), object locals = object())
+object exec_file(str filename, object globals = object(), object locals = object())
+
+

+ eval evaluates the given expression and returns the resulting value. exec + executes the given code (typically a set of statements) returning the result, + and exec_file executes the code contained in the given file. +

+

+ The globals and locals parameters are + Python dictionaries containing the globals and locals of the context in which + to run the code. For most intents and purposes you can use the namespace + dictionary of the __main__ module for both parameters. +

+

+ Boost.python provides a function to import a module: +

+
object import(str name)
+
+

+ import imports a python module (potentially loading it into the running process + first), and returns it. +

+

+ Let's import the __main__ module and run some Python code + in its namespace: +

+
object main_module = import("__main__");
+object main_namespace = main_module.attr("__dict__");
+
+object ignored = exec("hello = file('hello.txt', 'w')\n"
+                      "hello.write('Hello world!')\n"
+                      "hello.close()",
+                      main_namespace);
+
+

+ This should create a file called 'hello.txt' in the current directory containing + a phrase that is well-known in programming circles. +

+

+ + Manipulating + Python objects +

+

+ Often we'd like to have a class to manipulate Python objects. But we have + already seen such a class above, and in the previous + section: the aptly named object class and its derivatives. + We've already seen that they can be constructed from a handle. + The following examples should further illustrate this fact: +

+
object main_module = import("__main__");
+object main_namespace = main_module.attr("__dict__");
+object ignored = exec("result = 5 ** 2", main_namespace);
+int five_squared = extract<int>(main_namespace["result"]);
+
+

+ Here we create a dictionary object for the __main__ module's + namespace. Then we assign 5 squared to the result variable and read this + variable from the dictionary. Another way to achieve the same result is to + use eval instead, which returns the result directly: +

+
object result = eval("5 ** 2");
+int five_squared = extract<int>(result);
+
+

+ + Exception + handling +

+

+ If an exception occurs in the evaluation of the python expression, error_already_set + is thrown: +

+
try
+{
+    object result = eval("5/0");
+    // execution will never get here:
+    int five_divided_by_zero = extract<int>(result);
+}
+catch(error_already_set const &)
+{
+    // handle the exception in some way
+}
+
+

+ The error_already_set exception class doesn't carry any + information in itself. To find out more about the Python exception that occurred, + you need to use the exception + handling functions of the Python C API in your catch-statement. This + can be as simple as calling PyErr_Print() + to print the exception's traceback to the console, or comparing the type + of the exception with those of the standard + exceptions: +

+
catch(error_already_set const &)
+{
+    if (PyErr_ExceptionMatches(PyExc_ZeroDivisionError))
+    {
+        // handle ZeroDivisionError specially
+    }
+    else
+    {
+        // print all other errors to stderr
+        PyErr_Print();
+    }
+}
+
+

+ (To retrieve even more information from the exception you can use some of + the other exception handling functions listed here.) +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/tutorial/tutorial/exception.html b/develop/doc/html/tutorial/tutorial/exception.html new file mode 100644 index 00000000..c600ede8 --- /dev/null +++ b/develop/doc/html/tutorial/tutorial/exception.html @@ -0,0 +1,56 @@ + + + +Exception Translation + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ All C++ exceptions must be caught at the boundary with Python code. This boundary + is the point where C++ meets Python. Boost.Python provides a default exception + handler that translates selected standard exceptions, then gives up: +

+
raise RuntimeError, 'unidentifiable C++ Exception'
+
+

+ Users may provide custom translation. Here's an example: +

+
struct PodBayDoorException;
+void translator(PodBayDoorException const& x) {
+    PyErr_SetString(PyExc_UserWarning, "I'm sorry Dave...");
+}
+BOOST_PYTHON_MODULE(kubrick) {
+     register_exception_translator<
+          PodBayDoorException>(translator);
+     ...
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/tutorial/tutorial/exposing.html b/develop/doc/html/tutorial/tutorial/exposing.html new file mode 100644 index 00000000..13c08f79 --- /dev/null +++ b/develop/doc/html/tutorial/tutorial/exposing.html @@ -0,0 +1,601 @@ + + + +Exposing Classes + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +

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

+

+ Consider a C++ class/struct that we want to expose to Python: +

+
struct World
+{
+    void set(std::string msg) { this->msg = msg; }
+    std::string greet() { return msg; }
+    std::string msg;
+};
+
+

+ We can expose this to Python by writing a corresponding Boost.Python C++ Wrapper: +

+
#include <boost/python.hpp>
+using namespace boost::python;
+
+BOOST_PYTHON_MODULE(hello)
+{
+    class_<World>("World")
+        .def("greet", &World::greet)
+        .def("set", &World::set)
+    ;
+}
+
+

+ Here, we wrote a C++ class wrapper that exposes the member functions greet + and set. Now, after building our module as a shared library, + we may use our class World in Python. Here's a sample Python + session: +

+
>>> import hello
+>>> planet = hello.World()
+>>> planet.set('howdy')
+>>> planet.greet()
+'howdy'
+
+
+ +

+ Our previous example didn't have any explicit constructors. Since World + is declared as a plain struct, it has an implicit default constructor. Boost.Python + exposes the default constructor by default, which is why we were able to + write +

+
>>> planet = hello.World()
+
+

+ We may wish to wrap a class with a non-default constructor. Let us build + on our previous example: +

+
struct World
+{
+    World(std::string msg): msg(msg) {} // added constructor
+    void set(std::string msg) { this->msg = msg; }
+    std::string greet() { return msg; }
+    std::string msg;
+};
+
+

+ This time World has no default constructor; our previous + wrapping code would fail to compile when the library tried to expose it. + We have to tell class_<World> about the constructor + we want to expose instead. +

+
#include <boost/python.hpp>
+using namespace boost::python;
+
+BOOST_PYTHON_MODULE(hello)
+{
+    class_<World>("World", init<std::string>())
+        .def("greet", &World::greet)
+        .def("set", &World::set)
+    ;
+}
+
+

+ init<std::string>() exposes the constructor taking + in a std::string (in Python, constructors are spelled + ""__init__""). +

+

+ We can expose additional constructors by passing more init<...>s + to the def() member function. Say for example we have + another World constructor taking in two doubles: +

+
class_<World>("World", init<std::string>())
+    .def(init<double, double>())
+    .def("greet", &World::greet)
+    .def("set", &World::set)
+;
+
+

+ On the other hand, if we do not wish to expose any constructors at all, we + may use no_init instead: +

+
class_<Abstract>("Abstract", no_init)
+
+

+ This actually adds an __init__ method which always raises + a Python RuntimeError exception. +

+
+
+ +

+ Data members may also be exposed to Python so that they can be accessed as + attributes of the corresponding Python class. Each data member that we wish + to be exposed may be regarded as read-only + or read-write. Consider this class Var: +

+
struct Var
+{
+    Var(std::string name) : name(name), value() {}
+    std::string const name;
+    float value;
+};
+
+

+ Our C++ Var class and its data members can be exposed + to Python: +

+
class_<Var>("Var", init<std::string>())
+    .def_readonly("name", &Var::name)
+    .def_readwrite("value", &Var::value);
+
+

+ Then, in Python, assuming we have placed our Var class inside the namespace + hello as we did before: +

+
>>> x = hello.Var('pi')
+>>> x.value = 3.14
+>>> print x.name, 'is around', x.value
+pi is around 3.14
+
+

+ Note that name is exposed as read-only + while value is exposed as read-write. +

+
>>> x.name = 'e' # can't change name
+Traceback (most recent call last):
+  File "<stdin>", line 1, in ?
+AttributeError: can't set attribute
+
+
+
+ +

+ In C++, classes with public data members are usually frowned upon. Well designed + classes that take advantage of encapsulation hide the class' data members. + The only way to access the class' data is through access (getter/setter) + functions. Access functions expose class properties. Here's an example: +

+
struct Num
+{
+    Num();
+    float get() const;
+    void set(float value);
+    ...
+};
+
+

+ However, in Python attribute access is fine; it doesn't neccessarily break + encapsulation to let users handle attributes directly, because the attributes + can just be a different syntax for a method call. Wrapping our Num + class using Boost.Python: +

+
class_<Num>("Num")
+    .add_property("rovalue", &Num::get)
+    .add_property("value", &Num::get, &Num::set);
+
+

+ And at last, in Python: +

+
>>> x = Num()
+>>> x.value = 3.14
+>>> x.value, x.rovalue
+(3.14, 3.14)
+>>> x.rovalue = 2.17 # error!
+
+

+ Take note that the class property rovalue is exposed as + read-only since the rovalue + setter member function is not passed in: +

+
.add_property("rovalue", &Num::get)
+
+
+
+ +

+ In the previous examples, we dealt with classes that are not polymorphic. + This is not often the case. Much of the time, we will be wrapping polymorphic + classes and class hierarchies related by inheritance. We will often have + to write Boost.Python wrappers for classes that are derived from abstract + base classes. +

+

+ Consider this trivial inheritance structure: +

+
struct Base { virtual ~Base(); };
+struct Derived : Base {};
+
+

+ And a set of C++ functions operating on Base and Derived + object instances: +

+
void b(Base*);
+void d(Derived*);
+Base* factory() { return new Derived; }
+
+

+ We've seen how we can wrap the base class Base: +

+
class_<Base>("Base")
+    /*...*/
+    ;
+
+

+ Now we can inform Boost.Python of the inheritance relationship between Derived + and its base class Base. Thus: +

+
class_<Derived, bases<Base> >("Derived")
+    /*...*/
+    ;
+
+

+ Doing so, we get some things for free: +

+
    +
  1. + Derived automatically inherits all of Base's Python methods (wrapped + C++ member functions) +
  2. +
  3. + If Base is polymorphic, Derived + objects which have been passed to Python via a pointer or reference to + Base can be passed where a pointer or reference to + Derived is expected. +
  4. +
+

+ Now, we will expose the C++ free functions b and d + and factory: +

+
def("b", b);
+def("d", d);
+def("factory", factory);
+
+

+ Note that free function factory is being used to generate + new instances of class Derived. In such cases, we use + return_value_policy<manage_new_object> to instruct + Python to adopt the pointer to Base and hold the instance + in a new Python Base object until the the Python object + is destroyed. We will see more of Boost.Python call + policies later. +

+
// Tell Python to take ownership of factory's result
+def("factory", factory,
+    return_value_policy<manage_new_object>());
+
+
+
+ +

+ In this section, we will learn how to make functions behave polymorphically + through virtual functions. Continuing our example, let us add a virtual function + to our Base class: +

+
struct Base
+{
+    virtual ~Base() {}
+    virtual int f() = 0;
+};
+
+

+ 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. It is not ideal to add anything + to our class Base. Yet, when + you have a virtual function that's going to be overridden in Python and called + polymorphically from C++, we'll need to + add some scaffoldings to make things work properly. What we'll do is write + a class wrapper that derives from Base + that will unintrusively hook into the virtual functions so that a Python + override may be called: +

+
struct BaseWrap : Base, wrapper<Base>
+{
+    int f()
+    {
+        return this->get_override("f")();
+    }
+};
+
+

+ Notice too that in addition to inheriting from Base, + we also multiply- inherited wrapper<Base> (See Wrapper). + The wrapper template makes + the job of wrapping classes that are meant to overridden in Python, easier. +

+ +

+ BaseWrap's overridden virtual member function f + in effect calls the corresponding method of the Python object through get_override. +

+

+ Finally, exposing Base: +

+
class_<BaseWrap, boost::noncopyable>("Base")
+    .def("f", pure_virtual(&Base::f))
+    ;
+
+

+ pure_virtual signals Boost.Python + that the function f is a + pure virtual function. +

+
+ + + + + +
[Note]Note
+

+ member function and methods +

+

+ Python, like many object oriented languages uses the term methods. + Methods correspond roughly to C++'s member functions +

+
+
+
+ +

+ We've seen in the previous section how classes with pure virtual functions + are wrapped using Boost.Python's class + wrapper facilities. If we wish to wrap non-pure-virtual + functions instead, the mechanism is a bit different. +

+

+ Recall that in the previous + section, we wrapped a class with a pure virtual function that we then + implemented in C++, or Python classes derived from it. Our base class: +

+
struct Base
+{
+    virtual int f() = 0;
+};
+
+

+ had a pure virtual function f. If, however, its member + function f was not declared as pure virtual: +

+
struct Base
+{
+    virtual ~Base() {}
+    virtual int f() { return 0; }
+};
+
+

+ We wrap it this way: +

+
struct BaseWrap : Base, wrapper<Base>
+{
+    int f()
+    {
+        if (override f = this->get_override("f"))
+            return f(); // *note*
+        return Base::f();
+    }
+
+    int default_f() { return this->Base::f(); }
+};
+
+

+ Notice how we implemented BaseWrap::f. Now, + we have to check if there is an override for f. + If none, then we call Base::f(). +

+ +

+ Finally, exposing: +

+
class_<BaseWrap, boost::noncopyable>("Base")
+    .def("f", &Base::f, &BaseWrap::default_f)
+    ;
+
+

+ Take note that we expose both &Base::f and &BaseWrap::default_f. Boost.Python needs to keep track + of 1) the dispatch function f and 2) the forwarding function + to its default implementation default_f. There's a special + def function for this purpose. +

+

+ In Python, the results would be as expected: +

+
>>> base = Base()
+>>> class Derived(Base):
+...     def f(self):
+...         return 42
+...
+>>> derived = Derived()
+
+

+ Calling base.f(): +

+
>>> base.f()
+0
+
+

+ Calling derived.f(): +

+
>>> derived.f()
+42
+
+
+
+ +

+ + Python + Operators +

+

+ C is well known for the abundance of operators. C++ extends this to the extremes + by allowing operator overloading. Boost.Python takes advantage of this and + makes it easy to wrap C++ operator-powered classes. +

+

+ Consider a file position class FilePos and a set of operators + that take on FilePos instances: +

+
class FilePos { /*...*/ };
+
+FilePos     operator+(FilePos, int);
+FilePos     operator+(int, FilePos);
+int         operator-(FilePos, FilePos);
+FilePos     operator-(FilePos, int);
+FilePos&    operator+=(FilePos&, int);
+FilePos&    operator-=(FilePos&, int);
+bool        operator<(FilePos, FilePos);
+
+

+ The class and the various operators can be mapped to Python rather easily + and intuitively: +

+
class_<FilePos>("FilePos")
+    .def(self + int())          // __add__
+    .def(int() + self)          // __radd__
+    .def(self - self)           // __sub__
+    .def(self - int())          // __sub__
+    .def(self += int())         // __iadd__
+    .def(self -= other<int>())
+    .def(self < self);          // __lt__
+
+

+ The code snippet above is very clear and needs almost no explanation at all. + It is virtually the same as the operators' signatures. Just take note that + self refers to FilePos object. Also, not every class + T that you might need to interact with in an operator + expression is (cheaply) default-constructible. You can use other<T>() + in place of an actual T instance when writing "self + expressions". +

+

+ + Special + Methods +

+

+ Python has a few more Special Methods. Boost.Python + supports all of the standard special method names supported by real Python + class instances. A similar set of intuitive interfaces can also be used to + wrap C++ functions that correspond to these Python special functions. + Example: +

+
class Rational
+{ public: operator double() const; };
+
+Rational pow(Rational, Rational);
+Rational abs(Rational);
+ostream& operator<<(ostream&,Rational);
+
+class_<Rational>("Rational")
+    .def(float_(self))                  // __float__
+    .def(pow(self, other<Rational>))    // __pow__
+    .def(abs(self))                     // __abs__
+    .def(str(self))                     // __str__
+    ;
+
+

+ Need we say more? +

+
+ + + + + +
[Note]Note

+ What is the business of operator<<? Well, the method str requires the operator<< to do its work (i.e. operator<< + is used by the method defined by def(str(self)). +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/tutorial/tutorial/functions.html b/develop/doc/html/tutorial/tutorial/functions.html new file mode 100644 index 00000000..ddf3f624 --- /dev/null +++ b/develop/doc/html/tutorial/tutorial/functions.html @@ -0,0 +1,587 @@ + + + +Functions + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +

+ In this chapter, we'll look at Boost.Python powered functions in closer detail. + We will see some facilities to make exposing C++ functions to Python safe from + potential pifalls such as dangling pointers and references. We will also see + facilities that will make it even easier for us to expose C++ functions that + take advantage of C++ features such as overloading and default arguments. +

+

+ Read on... +

+

+ But before you do, you might want to fire up Python 2.2 or later and type + >>> import this. +

+
>>> import this
+The Zen of Python, by Tim Peters
+Beautiful is better than ugly.
+Explicit is better than implicit.
+Simple is better than complex.
+Complex is better than complicated.
+Flat is better than nested.
+Sparse is better than dense.
+Readability counts.
+Special cases aren't special enough to break the rules.
+Although practicality beats purity.
+Errors should never pass silently.
+Unless explicitly silenced.
+In the face of ambiguity, refuse the temptation to guess.
+There should be one-- and preferably only one --obvious way to do it
+Although that way may not be obvious at first unless you're Dutch.
+Now is better than never.
+Although never is often better than right now.
+If the implementation is hard to explain, it's a bad idea.
+If the implementation is easy to explain, it may be a good idea.
+Namespaces are one honking great idea -- let's do more of those!
+
+
+ +

+ In C++, we often deal with arguments and return types such as pointers and + references. Such primitive types are rather, ummmm, low level and they really + don't tell us much. At the very least, we don't know the owner of the pointer + or the referenced object. No wonder languages such as Java and Python never + deal with such low level entities. In C++, it's usually considered a good + practice to use smart pointers which exactly describe ownership semantics. + Still, even good C++ interfaces use raw references and pointers sometimes, + so Boost.Python must deal with them. To do this, it may need your help. Consider + the following C++ function: +

+
X& f(Y& y, Z* z);
+
+

+ How should the library wrap this function? A naive approach builds a Python + X object around result reference. This strategy might or might not work out. + Here's an example where it didn't +

+
>>> x = f(y, z) # x refers to some C++ X
+>>> del y
+>>> x.some_method() # CRASH!
+
+

+ What's the problem? +

+

+ Well, what if f() was implemented as shown below: +

+
X& f(Y& y, Z* z)
+{
+    y.z = z;
+    return y.x;
+}
+
+

+ The problem is that the lifetime of result X& is tied to the lifetime + of y, because the f() returns a reference to a member of the y object. This + idiom is is not uncommon and perfectly acceptable in the context of C++. + However, Python users should not be able to crash the system just by using + our C++ interface. In this case deleting y will invalidate the reference + to X. We have a dangling reference. +

+

+ Here's what's happening: +

+
    +
  1. + f is called passing in a reference to y + and a pointer to z +
  2. +
  3. + A reference to y.x is returned +
  4. +
  5. + y is deleted. x is a dangling reference +
  6. +
  7. + x.some_method() is called +
  8. +
  9. + BOOM! +
  10. +
+

+ We could copy result into a new object: +

+
>>> f(y, z).set(42) # Result disappears
+>>> y.x.get()       # No crash, but still bad
+3.14
+
+

+ This is not really our intent of our C++ interface. We've broken our promise + that the Python interface should reflect the C++ interface as closely as + possible. +

+

+ Our problems do not end there. Suppose Y is implemented as follows: +

+
struct Y
+{
+    X x; Z* z;
+    int z_value() { return z->value(); }
+};
+
+

+ Notice that the data member z is held by class Y using + a raw pointer. Now we have a potential dangling pointer problem inside Y: +

+
>>> x = f(y, z) # y refers to z
+>>> del z       # Kill the z object
+>>> y.z_value() # CRASH!
+
+

+ For reference, here's the implementation of f again: +

+
X& f(Y& y, Z* z)
+{
+    y.z = z;
+    return y.x;
+}
+
+

+ Here's what's happening: +

+
    +
  1. + f is called passing in a reference to y + and a pointer to z +
  2. +
  3. + A pointer to z is held by y +
  4. +
  5. + A reference to y.x is returned +
  6. +
  7. + z is deleted. y.z is a dangling + pointer +
  8. +
  9. + y.z_value() is called +
  10. +
  11. + z->value() is called +
  12. +
  13. + BOOM! +
  14. +
+

+ + Call + Policies +

+

+ Call Policies may be used in situations such as the example detailed above. + In our example, return_internal_reference and with_custodian_and_ward + are our friends: +

+
def("f", f,
+    return_internal_reference<1,
+        with_custodian_and_ward<1, 2> >());
+
+

+ What are the 1 and 2 parameters, you + ask? +

+
return_internal_reference<1
+
+

+ Informs Boost.Python that the first argument, in our case Y& + y, is the owner of the returned reference: X&. + The "1" simply specifies the first argument. + In short: "return an internal reference X& owned + by the 1st argument Y& y". +

+
with_custodian_and_ward<1, 2>
+
+

+ Informs Boost.Python that the lifetime of the argument indicated by ward + (i.e. the 2nd argument: Z* z) is dependent on the lifetime + of the argument indicated by custodian (i.e. the 1st argument: Y& + y). +

+

+ It is also important to note that we have defined two policies above. Two + or more policies can be composed by chaining. Here's the general syntax: +

+
policy1<args...,
+    policy2<args...,
+        policy3<args...> > >
+
+

+ Here is the list of predefined call policies. A complete reference detailing + these can be found here. +

+
    +
  • + with_custodian_and_ward: Ties lifetimes + of the arguments +
  • +
  • + with_custodian_and_ward_postcall: Ties + lifetimes of the arguments and results +
  • +
  • + return_internal_reference: Ties lifetime + of one argument to that of result +
  • +
  • + return_value_policy<T> with T one of: +
      +
    • + reference_existing_object: naive + (dangerous) approach +
    • +
    • + copy_const_reference: Boost.Python + v1 approach +
    • +
    • + copy_non_const_reference: +
    • +
    • + manage_new_object: Adopt a pointer + and hold the instance +
    • +
    +
  • +
+ +
+
+ +

+ The following illustrates a scheme for manually wrapping an overloaded member + functions. Of course, the same technique can be applied to wrapping overloaded + non-member functions. +

+

+ We have here our C++ class: +

+
struct X
+{
+    bool f(int a)
+    {
+        return true;
+    }
+
+    bool f(int a, double b)
+    {
+        return true;
+    }
+
+    bool f(int a, double b, char c)
+    {
+        return true;
+    }
+
+    int f(int a, int b, int c)
+    {
+        return a + b + c;
+    };
+};
+
+

+ Class X has 4 overloaded functions. We will start by introducing some member + function pointer variables: +

+
bool    (X::*fx1)(int)              = &X::f;
+bool    (X::*fx2)(int, double)      = &X::f;
+bool    (X::*fx3)(int, double, char)= &X::f;
+int     (X::*fx4)(int, int, int)    = &X::f;
+
+

+ With these in hand, we can proceed to define and wrap this for Python: +

+
.def("f", fx1)
+.def("f", fx2)
+.def("f", fx3)
+.def("f", fx4)
+
+
+
+ +

+ Boost.Python wraps (member) function pointers. Unfortunately, C++ function + pointers carry no default argument info. Take a function f + with default arguments: +

+
int f(int, double = 3.14, char const* = "hello");
+
+

+ But the type of a pointer to the function f has no information + about its default arguments: +

+
int(*g)(int,double,char const*) = f;    // defaults lost!
+
+

+ When we pass this function pointer to the def function, + there is no way to retrieve the default arguments: +

+
def("f", f);                            // defaults lost!
+
+

+ Because of this, when wrapping C++ code, we had to resort to manual wrapping + as outlined in the previous + section, or writing thin wrappers: +

+
// write "thin wrappers"
+int f1(int x) { return f(x); }
+int f2(int x, double y) { return f(x,y); }
+
+/*...*/
+
+    // in module init
+    def("f", f);  // all arguments
+    def("f", f2); // two arguments
+    def("f", f1); // one argument
+
+

+ When you want to wrap functions (or member functions) that either: +

+
    +
  • + have default arguments, or +
  • +
  • + are overloaded with a common sequence of initial arguments +
  • +
+

+ + BOOST_PYTHON_FUNCTION_OVERLOADS +

+

+ Boost.Python now has a way to make it easier. For instance, given a function: +

+
int foo(int a, char b = 1, unsigned c = 2, double d = 3)
+{
+    /*...*/
+}
+
+

+ The macro invocation: +

+
BOOST_PYTHON_FUNCTION_OVERLOADS(foo_overloads, foo, 1, 4)
+
+

+ will automatically create the thin wrappers for us. This macro will create + a class foo_overloads that can be passed on to def(...). + The third and fourth macro argument are the minimum arguments and maximum + arguments, respectively. In our foo function the minimum + number of arguments is 1 and the maximum number of arguments is 4. The def(...) + function will automatically add all the foo variants for us: +

+
def("foo", foo, foo_overloads());
+
+

+ + BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS +

+

+ Objects here, objects there, objects here there everywhere. More frequently + than anything else, we need to expose member functions of our classes to + Python. Then again, we have the same inconveniences as before when default + arguments or overloads with a common sequence of initial arguments come into + play. Another macro is provided to make this a breeze. +

+

+ Like BOOST_PYTHON_FUNCTION_OVERLOADS, BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS + may be used to automatically create the thin wrappers for wrapping member + functions. Let's have an example: +

+
struct george
+{
+    void
+    wack_em(int a, int b = 0, char c = 'x')
+    {
+        /*...*/
+    }
+};
+
+

+ The macro invocation: +

+
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(george_overloads, wack_em, 1, 3)
+
+

+ will generate a set of thin wrappers for george's wack_em + member function accepting a minimum of 1 and a maximum of 3 arguments (i.e. + the third and fourth macro argument). The thin wrappers are all enclosed + in a class named george_overloads that can then be used + as an argument to def(...): +

+
.def("wack_em", &george::wack_em, george_overloads());
+
+

+ See the overloads + reference for details. +

+

+ + init and + optional +

+

+ A similar facility is provided for class constructors, again, with default + arguments or a sequence of overloads. Remember init<...>? + For example, given a class X with a constructor: +

+
struct X
+{
+    X(int a, char b = 'D', std::string c = "constructor", double d = 0.0);
+    /*...*/
+}
+
+

+ You can easily add this constructor to Boost.Python in one shot: +

+
.def(init<int, optional<char, std::string, double> >())
+
+

+ Notice the use of init<...> and optional<...> + to signify the default (optional arguments). +

+
+
+ +

+ It was mentioned in passing in the previous section that BOOST_PYTHON_FUNCTION_OVERLOADS + and BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS can also be + used for overloaded functions and member functions with a common sequence + of initial arguments. Here is an example: +

+
void foo()
+{
+   /*...*/
+}
+
+void foo(bool a)
+{
+   /*...*/
+}
+
+void foo(bool a, int b)
+{
+   /*...*/
+}
+
+void foo(bool a, int b, char c)
+{
+   /*...*/
+}
+
+

+ Like in the previous section, we can generate thin wrappers for these overloaded + functions in one-shot: +

+
BOOST_PYTHON_FUNCTION_OVERLOADS(foo_overloads, foo, 0, 3)
+
+

+ Then... +

+
.def("foo", (void(*)(bool, int, char))0, foo_overloads());
+
+

+ Notice though that we have a situation now where we have a minimum of zero + (0) arguments and a maximum of 3 arguments. +

+

+ + Manual + Wrapping +

+

+ It is important to emphasize however that the overloaded + functions must have a common sequence of initial arguments. Otherwise, + our scheme above will not work. If this is not the case, we have to wrap + our functions manually. +

+

+ Actually, we can mix and match manual wrapping of overloaded functions and + automatic wrapping through BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS + and its sister, BOOST_PYTHON_FUNCTION_OVERLOADS. Following + up on our example presented in the section on + overloading, since the first 4 overload functins have a common sequence + of initial arguments, we can use BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS + to automatically wrap the first three of the defs and + manually wrap just the last. Here's how we'll do this: +

+
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(xf_overloads, f, 1, 4)
+
+

+ Create a member function pointers as above for both X::f overloads: +

+
bool    (X::*fx1)(int, double, char)    = &X::f;
+int     (X::*fx2)(int, int, int)        = &X::f;
+
+

+ Then... +

+
.def("f", fx1, xf_overloads());
+.def("f", fx2)
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/tutorial/tutorial/hello.html b/develop/doc/html/tutorial/tutorial/hello.html new file mode 100644 index 00000000..4ada7ed5 --- /dev/null +++ b/develop/doc/html/tutorial/tutorial/hello.html @@ -0,0 +1,191 @@ + + + +Building Hello World + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ + From + Start To Finish +

+

+ Now the first thing you'd want to do is to build the Hello World module and + try it for yourself in Python. In this section, we will outline the steps necessary + to achieve that. We will use the build tool that comes bundled with every boost + distribution: bjam. +

+
+ + + + + +
[Note]Note
+

+ Building without bjam +

+

+ Besides bjam, there are of course other ways to get your module built. What's + written here should not be taken as "the one and only way". There + are of course other build tools apart from bjam. +

+

+ Take note however that the preferred build tool for Boost.Python is bjam. + There are so many ways to set up the build incorrectly. Experience shows + that 90% of the "I can't build Boost.Python" problems come from + people who had to use a different tool. +

+
+

+ We will skip over the details. Our objective will be to simply create the hello + world module and run it in Python. For a complete reference to building Boost.Python, + check out: building.html. After + this brief bjam tutorial, we should have built the DLLs + and run a python program using the extension. +

+

+ The tutorial example can be found in the directory: libs/python/example/tutorial. + There, you can find: +

+
    +
  • + hello.cpp +
  • +
  • + hello.py +
  • +
  • + Jamroot +
  • +
+

+ The hello.cpp file is our C++ hello world example. The + Jamroot is a minimalist bjam script + that builds the DLLs for us. Finally, hello.py is our Python + program that uses the extension in hello.cpp. +

+

+ Before anything else, you should have the bjam executable in your boost directory + or somewhere in your path such that bjam can be executed + in the command line. Pre-built Boost.Jam executables are available for most + platforms. The complete list of Bjam executables can be found here. +

+

+ + Let's + Jam! +

+

+ +

+

+ Here is our minimalist + Jamroot file. Simply copy the file and tweak use-project boost + to where your boost root directory is and you're OK. +

+

+ The comments contained in the Jamrules file above should be sufficient to get + you going. +

+

+ + Running + bjam +

+

+ bjam is run using your operating system's command line + interpreter. +

+

+ Start it up. +

+

+ A file called user-config.jam in your home directory is used to configure your + tools. In Windows, your home directory can be found by typing: +

+
ECHO %HOMEDRIVE%%HOMEPATH%
+
+

+ into a command prompt window. Your file should at least have the rules for + your compiler and your python installation. A specific example of this on Windows + would be: +

+
#  MSVC configuration
+using msvc : 8.0 ;
+
+#  Python configuration
+using python : 2.4 : C:dev/tools/Python ;
+
+

+ The first rule tells Bjam to use the MSVC 8.0 compiler and associated tools. + The second rule provides information on Python, its version and where it is + located. The above assumes that the Python installation is in C:dev/tools\/Python. + If you have one fairly "standard" python installation for your platform, + you might not need to do this. +

+

+ Now we are ready... Be sure to cd to libs/python/example/tutorial + where the tutorial "hello.cpp" and the "Jamroot" + is situated. +

+

+ Finally: +

+
bjam
+
+

+ It should be building now: +

+
cd C:\dev\boost\libs\python\example\tutorial
+bjam
+...patience...
+...found 1101 targets...
+...updating 35 targets...
+
+

+ And so on... Finally: +

+
   Creating library path-to-boost_python.dll
+   Creating library /path-to-hello_ext.exp/
+**passed** ... hello.test
+...updated 35 targets...
+
+

+ Or something similar. If all is well, you should now have built the DLLs and + run the Python program. +

+

+ There you go... Have fun! +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/tutorial/tutorial/iterators.html b/develop/doc/html/tutorial/tutorial/iterators.html new file mode 100644 index 00000000..e8705346 --- /dev/null +++ b/develop/doc/html/tutorial/tutorial/iterators.html @@ -0,0 +1,180 @@ + + + +Iterators + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ +

+ In C++, and STL in particular, we see iterators everywhere. Python also has + iterators, but these are two very different beasts. +

+

+ C++ iterators: +

+
    +
  • + C++ has 5 type categories (random-access, bidirectional, forward, input, + output) +
  • +
  • + There are 2 Operation categories: reposition, access +
  • +
  • + A pair of iterators is needed to represent a (first/last) range. +
  • +
+

+ Python Iterators: +

+
    +
  • + 1 category (forward) +
  • +
  • + 1 operation category (next()) +
  • +
  • + Raises StopIteration exception at end +
  • +
+

+ The typical Python iteration protocol: for y + in x... is as follows: +

+
iter = x.__iter__()         # get iterator
+try:
+    while 1:
+    y = iter.next()         # get each item
+    ...                     # process y
+except StopIteration: pass  # iterator exhausted
+
+

+ Boost.Python provides some mechanisms to make C++ iterators play along nicely + as Python iterators. What we need to do is to produce appropriate __iter__ function from C++ iterators that + is compatible with the Python iteration protocol. For example: +

+
object get_iterator = iterator<vector<int> >();
+object iter = get_iterator(v);
+object first = iter.next();
+
+

+ Or for use in class_<>: +

+
.def("__iter__", iterator<vector<int> >())
+
+

+ range +

+

+ We can create a Python savvy iterator using the range function: +

+
    +
  • + range(start, finish) +
  • +
  • + range<Policies,Target>(start, finish) +
  • +
+

+ Here, start/finish may be one of: +

+
    +
  • + member data pointers +
  • +
  • + member function pointers +
  • +
  • + adaptable function object (use Target parameter) +
  • +
+

+ iterator +

+
  • + iterator<T, Policies>() +
+

+ Given a container T, iterator is a shortcut that simply + calls range with &T::begin, &T::end. +

+

+ Let's put this into action... Here's an example from some hypothetical bogon + Particle accelerator code: +

+
f = Field()
+for x in f.pions:
+    smash(x)
+for y in f.bogons:
+    count(y)
+
+

+ Now, our C++ Wrapper: +

+
class_<F>("Field")
+    .property("pions", range(&F::p_begin, &F::p_end))
+    .property("bogons", range(&F::b_begin, &F::b_end));
+
+

+ stl_input_iterator +

+

+ So far, we have seen how to expose C++ iterators and ranges to Python. Sometimes + we wish to go the other way, though: we'd like to pass a Python sequence to + an STL algorithm or use it to initialize an STL container. We need to make + a Python iterator look like an STL iterator. For that, we use stl_input_iterator<>. + Consider how we might implement a function that exposes std::list<int>::assign() to Python: +

+
template<typename T>
+void list_assign(std::list<T>& l, object o) {
+    // Turn a Python sequence into an STL input range
+    stl_input_iterator<T> begin(o), end;
+    l.assign(begin, end);
+}
+
+// Part of the wrapper for list<int>
+class_<std::list<int> >("list_int")
+    .def("assign", &list_assign<int>)
+    // ...
+    ;
+
+

+ Now in Python, we can assign any integer sequence to list_int + objects: +

+
x = list_int();
+x.assign([1,2,3,4,5])
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/tutorial/tutorial/object.html b/develop/doc/html/tutorial/tutorial/object.html new file mode 100644 index 00000000..c162b290 --- /dev/null +++ b/develop/doc/html/tutorial/tutorial/object.html @@ -0,0 +1,366 @@ + + + +Object Interface + + + + + + + + +
+
+
+PrevUpHomeNext +
+
+ + +

+ Python is dynamically typed, unlike C++ which is statically typed. Python variables + may hold an integer, a float, list, dict, tuple, str, long etc., among other + things. In the viewpoint of Boost.Python and C++, these Pythonic variables + are just instances of class object. We will see in this + chapter how to deal with Python objects. +

+

+ As mentioned, one of the goals of Boost.Python is to provide a bidirectional + mapping between C++ and Python while maintaining the Python feel. Boost.Python + C++ objects are as close as possible to Python. This should + minimize the learning curve significantly. +

+

+ +

+
+ +

+ Class object wraps PyObject*. All the + intricacies of dealing with PyObjects such as managing + reference counting are handled by the object class. C++ + object interoperability is seamless. Boost.Python C++ objects + can in fact be explicitly constructed from any C++ object. +

+

+ To illustrate, this Python code snippet: +

+
def f(x, y):
+     if (y == 'foo'):
+         x[3:7] = 'bar'
+     else:
+         x.items += y(3, x)
+     return x
+
+def getfunc():
+   return f;
+
+

+ Can be rewritten in C++ using Boost.Python facilities this way: +

+
object f(object x, object y) {
+     if (y == "foo")
+         x.slice(3,7) = "bar";
+     else
+         x.attr("items") += y(3, x);
+     return x;
+}
+object getfunc() {
+    return object(f);
+}
+
+

+ Apart from cosmetic differences due to the fact that we are writing the code + in C++, the look and feel should be immediately apparent to the Python coder. +

+
+
+ +

+ Boost.Python comes with a set of derived object types + corresponding to that of Python's: +

+
    +
  • + list +
  • +
  • + dict +
  • +
  • + tuple +
  • +
  • + str +
  • +
  • + long_ +
  • +
  • + enum +
  • +
+

+ These derived object types act like real Python types. + For instance: +

+
str(1) ==> "1"
+
+

+ Wherever appropriate, a particular derived object has + corresponding Python type's methods. For instance, dict + has a keys() method: +

+
d.keys()
+
+

+ make_tuple is provided for declaring tuple literals. + Example: +

+
make_tuple(123, 'D', "Hello, World", 0.0);
+
+

+ In C++, when Boost.Python objects are used as arguments + to functions, subtype matching is required. For example, when a function + f, as declared below, is wrapped, it will only accept + instances of Python's str type and subtypes. +

+
void f(str name)
+{
+    object n2 = name.attr("upper")();   // NAME = name.upper()
+    str NAME = name.upper();            // better
+    object msg = "%s is bigger than %s" % make_tuple(NAME,name);
+}
+
+

+ In finer detail: +

+
str NAME = name.upper();
+
+

+ Illustrates that we provide versions of the str type's methods as C++ member + functions. +

+
object msg = "%s is bigger than %s" % make_tuple(NAME,name);
+
+

+ Demonstrates that you can write the C++ equivalent of "format" + % x,y,z in Python, which is useful since there's no easy way to + do that in std C++. +

+ +

+ Python: +

+
>>> d = dict(x.__dict__)     # copies x.__dict__
+>>> d['whatever'] = 3        # modifies the copy
+
+

+ C++: +

+
dict d(x.attr("__dict__"));  // copies x.__dict__
+d['whatever'] = 3;           // modifies the copy
+
+

+ + class_<T> + as objects +

+

+ Due to the dynamic nature of Boost.Python objects, any class_<T> + may also be one of these types! The following code snippet wraps the class + (type) object. +

+

+ We can use this to create wrapped instances. Example: +

+
object vec345 = (
+    class_<Vec2>("Vec2", init<double, double>())
+        .def_readonly("length", &Point::length)
+        .def_readonly("angle", &Point::angle)
+    )(3.0, 4.0);
+
+assert(vec345.attr("length") == 5.0);
+
+
+
+ +

+ At some point, we will need to get C++ values out of object instances. This + can be achieved with the extract<T> function. Consider + the following: +

+
double x = o.attr("length"); // compile error
+
+

+ In the code above, we got a compiler error because Boost.Python object + can't be implicitly converted to doubles. Instead, what + we wanted to do above can be achieved by writing: +

+
double l = extract<double>(o.attr("length"));
+Vec2& v = extract<Vec2&>(o);
+assert(l == v.length());
+
+

+ The first line attempts to extract the "length" attribute of the + Boost.Python object. The second line attempts to extract + the Vec2 object from held by the Boost.Python object. +

+

+ Take note that we said "attempt to" above. What if the Boost.Python + object does not really hold a Vec2 + type? This is certainly a possibility considering the dynamic nature of Python + objects. To be on the safe side, if the C++ type can't + be extracted, an appropriate exception is thrown. To avoid an exception, + we need to test for extractibility: +

+
extract<Vec2&> x(o);
+if (x.check()) {
+    Vec2& v = x(); ...
+
+

+ + The astute reader might have noticed that the extract<T> + facility in fact solves the mutable copying problem: +

+
dict d = extract<dict>(x.attr("__dict__"));
+d["whatever"] = 3;          // modifies x.__dict__ !
+
+
+
+

+Enums +

+

+ Boost.Python has a nifty facility to capture and wrap C++ enums. While Python + has no enum type, we'll often want to expose our C++ enums + to Python as an int. Boost.Python's enum facility makes + this easy while taking care of the proper conversions from Python's dynamic + typing to C++'s strong static typing (in C++, ints cannot be implicitly converted + to enums). To illustrate, given a C++ enum: +

+
enum choice { red, blue };
+
+

+ the construct: +

+
enum_<choice>("choice")
+    .value("red", red)
+    .value("blue", blue)
+    ;
+
+

+ can be used to expose to Python. The new enum type is created in the current + scope(), which is usually the current module. The snippet + above creates a Python class derived from Python's int + type which is associated with the C++ type passed as its first parameter. +

+
+ + + + + +
[Note]Note
+

+ what is a scope? +

+

+ The scope is a class that has an associated global Python object which + controls the Python namespace in which new extension classes and wrapped + functions will be defined as attributes. Details can be found here. +

+
+

+ You can access those values in Python as +

+
>>> my_module.choice.red
+my_module.choice.red
+
+

+ where my_module is the module where the enum is declared. You can also create + a new scope around a class: +

+
scope in_X = class_<X>("X")
+                .def( ... )
+                .def( ... )
+            ;
+
+// Expose X::nested as X.nested
+enum_<X::nested>("nested")
+    .value("red", red)
+    .value("blue", blue)
+    ;
+
+
+
+ +

+ When you want a boost::python::object to manage a pointer to PyObject* + pyobj one does: +

+
boost::python::object o(boost::python::handle<>(pyobj));
+
+

+ In this case, the o object, + manages the pyobj, it won’t + increase the reference count on construction. +

+

+ Otherwise, to use a borrowed reference: +

+
boost::python::object o(boost::python::handle<>(boost::python::borrowed(pyobj)));
+
+

+ In this case, Py_INCREF is + called, so pyobj is not destructed + when object o goes out of scope. +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/develop/doc/html/tutorial/tutorial/techniques.html b/develop/doc/html/tutorial/tutorial/techniques.html new file mode 100644 index 00000000..1081efe3 --- /dev/null +++ b/develop/doc/html/tutorial/tutorial/techniques.html @@ -0,0 +1,429 @@ + + + +General Techniques + + + + + + + +
+
+
+PrevUpHome +
+
+ + +

+ Here are presented some useful techniques that you can use while wrapping code + with Boost.Python. +

+
+ +

+ A Python package is a collection of modules that provide to the user a certain + functionality. If you're not familiar on how to create packages, a good introduction + to them is provided in the Python + Tutorial. +

+

+ But we are wrapping C++ code, using Boost.Python. How can we provide a nice + package interface to our users? To better explain some concepts, let's work + with an example. +

+

+ We have a C++ library that works with sounds: reading and writing various + formats, applying filters to the sound data, etc. It is named (conveniently) + sounds. Our library already has a neat C++ namespace hierarchy, + like so: +

+
sounds::core
+sounds::io
+sounds::filters
+
+

+ We would like to present this same hierarchy to the Python user, allowing + him to write code like this: +

+
import sounds.filters
+sounds.filters.echo(...) # echo is a C++ function
+
+

+ The first step is to write the wrapping code. We have to export each module + separately with Boost.Python, like this: +

+
/* file core.cpp */
+BOOST_PYTHON_MODULE(core)
+{
+    /* export everything in the sounds::core namespace */
+    ...
+}
+
+/* file io.cpp */
+BOOST_PYTHON_MODULE(io)
+{
+    /* export everything in the sounds::io namespace */
+    ...
+}
+
+/* file filters.cpp */
+BOOST_PYTHON_MODULE(filters)
+{
+    /* export everything in the sounds::filters namespace */
+    ...
+}
+
+

+ Compiling these files will generate the following Python extensions: core.pyd, + io.pyd and filters.pyd. +

+
+ + + + + +
[Note]Note

+ The extension .pyd is used for python extension modules, + which are just shared libraries. Using the default for your system, like + .so for Unix and .dll for Windows, + works just as well. +

+

+ Now, we create this directory structure for our Python package: +

+
sounds/
+    __init__.py
+    core.pyd
+    filters.pyd
+    io.pyd
+
+

+ The file __init__.py is what tells Python that the directory + sounds/ is actually a Python package. It can be a empty + file, but can also perform some magic, that will be shown later. +

+

+ Now our package is ready. All the user has to do is put sounds + into his PYTHONPATH + and fire up the interpreter: +

+
>>> import sounds.io
+>>> import sounds.filters
+>>> sound = sounds.io.open('file.mp3')
+>>> new_sound = sounds.filters.echo(sound, 1.0)
+
+

+ Nice heh? +

+

+ This is the simplest way to create hierarchies of packages, but it is not + very flexible. What if we want to add a pure Python + function to the filters package, for instance, one that applies 3 filters + in a sound object at once? Sure, you can do this in C++ and export it, but + why not do so in Python? You don't have to recompile the extension modules, + plus it will be easier to write it. +

+

+ If we want this flexibility, we will have to complicate our package hierarchy + a little. First, we will have to change the name of the extension modules: +

+
/* file core.cpp */
+BOOST_PYTHON_MODULE(_core)
+{
+    ...
+    /* export everything in the sounds::core namespace */
+}
+
+

+ Note that we added an underscore to the module name. The filename will have + to be changed to _core.pyd as well, and we do the same + to the other extension modules. Now, we change our package hierarchy like + so: +

+
sounds/
+    __init__.py
+    core/
+        __init__.py
+        _core.pyd
+    filters/
+        __init__.py
+        _filters.pyd
+    io/
+        __init__.py
+        _io.pyd
+
+

+ Note that we created a directory for each extension module, and added a __init__.py + to each one. But if we leave it that way, the user will have to access the + functions in the core module with this syntax: +

+
>>> import sounds.core._core
+>>> sounds.core._core.foo(...)
+
+

+ which is not what we want. But here enters the __init__.py + magic: everything that is brought to the __init__.py namespace + can be accessed directly by the user. So, all we have to do is bring the + entire namespace from _core.pyd to core/__init__.py. + So add this line of code to sounds/core/__init__.py: +

+
from _core import *
+
+

+ We do the same for the other packages. Now the user accesses the functions + and classes in the extension modules like before: +

+
>>> import sounds.filters
+>>> sounds.filters.echo(...)
+
+

+ with the additional benefit that we can easily add pure Python functions + to any module, in a way that the user can't tell the difference between a + C++ function and a Python function. Let's add a pure + Python function, echo_noise, to the filters + package. This function applies both the echo and noise + filters in sequence in the given sound object. We create + a file named sounds/filters/echo_noise.py and code our + function: +

+
import _filters
+def echo_noise(sound):
+    s = _filters.echo(sound)
+    s = _filters.noise(sound)
+    return s
+
+

+ Next, we add this line to sounds/filters/__init__.py: +

+
from echo_noise import echo_noise
+
+

+ And that's it. The user now accesses this function like any other function + from the filters package: +

+
>>> import sounds.filters
+>>> sounds.filters.echo_noise(...)
+
+
+
+ +

+ Thanks to Python's flexibility, you can easily add new methods to a class, + even after it was already created: +

+
>>> class C(object): pass
+>>>
+>>> # a regular function
+>>> def C_str(self): return 'A C instance!'
+>>>
+>>> # now we turn it in a member function
+>>> C.__str__ = C_str
+>>>
+>>> c = C()
+>>> print c
+A C instance!
+>>> C_str(c)
+A C instance!
+
+

+ Yes, Python rox. +

+

+ We can do the same with classes that were wrapped with Boost.Python. Suppose + we have a class point in C++: +

+
class point {...};
+
+BOOST_PYTHON_MODULE(_geom)
+{
+    class_<point>("point")...;
+}
+
+

+ If we are using the technique from the previous session, Creating + Packages, we can code directly into geom/__init__.py: +

+
from _geom import *
+
+# a regular function
+def point_str(self):
+    return str((self.x, self.y))
+
+# now we turn it into a member function
+point.__str__ = point_str
+
+

+ All point instances created from C++ will + also have this member function! This technique has several advantages: +

+
    +
  • + Cut down compile times to zero for these additional functions +
  • +
  • + Reduce the memory footprint to virtually zero +
  • +
  • + Minimize the need to recompile +
  • +
  • + Rapid prototyping (you can move the code to C++ if required without changing + the interface) +
  • +
+

+ You can even add a little syntactic sugar with the use of metaclasses. Let's + create a special metaclass that "injects" methods in other classes. +

+
# The one Boost.Python uses for all wrapped classes.
+# You can use here any class exported by Boost instead of "point"
+BoostPythonMetaclass = point.__class__
+
+class injector(object):
+    class __metaclass__(BoostPythonMetaclass):
+        def __init__(self, name, bases, dict):
+            for b in bases:
+                if type(b) not in (self, type):
+                    for k,v in dict.items():
+                        setattr(b,k,v)
+            return type.__init__(self, name, bases, dict)
+
+# inject some methods in the point foo
+class more_point(injector, point):
+    def __repr__(self):
+        return 'Point(x=%s, y=%s)' % (self.x, self.y)
+    def foo(self):
+        print 'foo!'
+
+

+ Now let's see how it got: +

+
>>> print point()
+Point(x=10, y=10)
+>>> point().foo()
+foo!
+
+

+ Another useful idea is to replace constructors with factory functions: +

+
_point = point
+
+def point(x=0, y=0):
+    return _point(x, y)
+
+

+ In this simple case there is not much gained, but for constructurs with many + overloads and/or arguments this is often a great simplification, again with + virtually zero memory footprint and zero compile-time overhead for the keyword + support. +

+
+
+ +

+ If you have ever exported a lot of classes, you know that it takes quite + a good time to compile the Boost.Python wrappers. Plus the memory consumption + can easily become too high. If this is causing you problems, you can split + the class_ definitions in multiple files: +

+
/* file point.cpp */
+#include <point.h>
+#include <boost/python.hpp>
+
+void export_point()
+{
+    class_<point>("point")...;
+}
+
+/* file triangle.cpp */
+#include <triangle.h>
+#include <boost/python.hpp>
+
+void export_triangle()
+{
+    class_<triangle>("triangle")...;
+}
+
+

+ Now you create a file main.cpp, which contains the BOOST_PYTHON_MODULE + macro, and call the various export functions inside it. +

+
void export_point();
+void export_triangle();
+
+BOOST_PYTHON_MODULE(_geom)
+{
+    export_point();
+    export_triangle();
+}
+
+

+ Compiling and linking together all this files produces the same result as + the usual approach: +

+
#include <boost/python.hpp>
+#include <point.h>
+#include <triangle.h>
+
+BOOST_PYTHON_MODULE(_geom)
+{
+    class_<point>("point")...;
+    class_<triangle>("triangle")...;
+}
+
+

+ but the memory is kept under control. +

+

+ This method is recommended too if you are developing the C++ library and + exporting it to Python at the same time: changes in a class will only demand + the compilation of a single cpp, instead of the entire wrapper code. +

+
+ + + + + +
[Note]Note

+ This method is useful too if you are getting the error message "fatal + error C1204:Compiler limit:internal structure overflow" + when compiling a large source file, as explained in the FAQ. +

+
+
+ + + +
+
+
+PrevUpHome +
+ + diff --git a/develop/doc/index.html b/develop/doc/index.html new file mode 100644 index 00000000..d5225757 --- /dev/null +++ b/develop/doc/index.html @@ -0,0 +1,13 @@ + + + + + + + Automatic redirection failed, click this + link  
+

© Copyright Stefan Seefeld, 2015

+

Distributed under the Boost Software License, Version 1.0. (See accompanying + file http://www.boost.org/LICENSE_1_0.txt)

+ +