pybind11_cross_module_tests.cpp revision 12391
112391Sjason@lowepower.com/* 212391Sjason@lowepower.com tests/pybind11_cross_module_tests.cpp -- contains tests that require multiple modules 312391Sjason@lowepower.com 412391Sjason@lowepower.com Copyright (c) 2017 Jason Rhinelander <jason@imaginary.ca> 512391Sjason@lowepower.com 612391Sjason@lowepower.com All rights reserved. Use of this source code is governed by a 712391Sjason@lowepower.com BSD-style license that can be found in the LICENSE file. 812391Sjason@lowepower.com*/ 912391Sjason@lowepower.com 1012391Sjason@lowepower.com#include "pybind11_tests.h" 1112391Sjason@lowepower.com#include "local_bindings.h" 1212391Sjason@lowepower.com#include <pybind11/stl_bind.h> 1312391Sjason@lowepower.com#include <numeric> 1412391Sjason@lowepower.com 1512391Sjason@lowepower.comPYBIND11_MODULE(pybind11_cross_module_tests, m) { 1612391Sjason@lowepower.com m.doc() = "pybind11 cross-module test module"; 1712391Sjason@lowepower.com 1812391Sjason@lowepower.com // test_local_bindings.py tests: 1912391Sjason@lowepower.com // 2012391Sjason@lowepower.com // Definitions here are tested by importing both this module and the 2112391Sjason@lowepower.com // relevant pybind11_tests submodule from a test_whatever.py 2212391Sjason@lowepower.com 2312391Sjason@lowepower.com // test_load_external 2412391Sjason@lowepower.com bind_local<ExternalType1>(m, "ExternalType1", py::module_local()); 2512391Sjason@lowepower.com bind_local<ExternalType2>(m, "ExternalType2", py::module_local()); 2612391Sjason@lowepower.com 2712391Sjason@lowepower.com // test_exceptions.py 2812391Sjason@lowepower.com m.def("raise_runtime_error", []() { PyErr_SetString(PyExc_RuntimeError, "My runtime error"); throw py::error_already_set(); }); 2912391Sjason@lowepower.com m.def("raise_value_error", []() { PyErr_SetString(PyExc_ValueError, "My value error"); throw py::error_already_set(); }); 3012391Sjason@lowepower.com m.def("throw_pybind_value_error", []() { throw py::value_error("pybind11 value error"); }); 3112391Sjason@lowepower.com m.def("throw_pybind_type_error", []() { throw py::type_error("pybind11 type error"); }); 3212391Sjason@lowepower.com m.def("throw_stop_iteration", []() { throw py::stop_iteration(); }); 3312391Sjason@lowepower.com 3412391Sjason@lowepower.com // test_local_bindings.py 3512391Sjason@lowepower.com // Local to both: 3612391Sjason@lowepower.com bind_local<LocalType, 1>(m, "LocalType", py::module_local()) 3712391Sjason@lowepower.com .def("get2", [](LocalType &t) { return t.i + 2; }) 3812391Sjason@lowepower.com ; 3912391Sjason@lowepower.com 4012391Sjason@lowepower.com // Can only be called with our python type: 4112391Sjason@lowepower.com m.def("local_value", [](LocalType &l) { return l.i; }); 4212391Sjason@lowepower.com 4312391Sjason@lowepower.com // test_nonlocal_failure 4412391Sjason@lowepower.com // This registration will fail (global registration when LocalFail is already registered 4512391Sjason@lowepower.com // globally in the main test module): 4612391Sjason@lowepower.com m.def("register_nonlocal", [m]() { 4712391Sjason@lowepower.com bind_local<NonLocalType, 0>(m, "NonLocalType"); 4812391Sjason@lowepower.com }); 4912391Sjason@lowepower.com 5012391Sjason@lowepower.com // test_stl_bind_local 5112391Sjason@lowepower.com // stl_bind.h binders defaults to py::module_local if the types are local or converting: 5212391Sjason@lowepower.com py::bind_vector<LocalVec>(m, "LocalVec"); 5312391Sjason@lowepower.com py::bind_map<LocalMap>(m, "LocalMap"); 5412391Sjason@lowepower.com 5512391Sjason@lowepower.com // test_stl_bind_global 5612391Sjason@lowepower.com // and global if the type (or one of the types, for the map) is global (so these will fail, 5712391Sjason@lowepower.com // assuming pybind11_tests is already loaded): 5812391Sjason@lowepower.com m.def("register_nonlocal_vec", [m]() { 5912391Sjason@lowepower.com py::bind_vector<NonLocalVec>(m, "NonLocalVec"); 6012391Sjason@lowepower.com }); 6112391Sjason@lowepower.com m.def("register_nonlocal_map", [m]() { 6212391Sjason@lowepower.com py::bind_map<NonLocalMap>(m, "NonLocalMap"); 6312391Sjason@lowepower.com }); 6412391Sjason@lowepower.com // The default can, however, be overridden to global using `py::module_local()` or 6512391Sjason@lowepower.com // `py::module_local(false)`. 6612391Sjason@lowepower.com // Explicitly made local: 6712391Sjason@lowepower.com py::bind_vector<NonLocalVec2>(m, "NonLocalVec2", py::module_local()); 6812391Sjason@lowepower.com // Explicitly made global (and so will fail to bind): 6912391Sjason@lowepower.com m.def("register_nonlocal_map2", [m]() { 7012391Sjason@lowepower.com py::bind_map<NonLocalMap2>(m, "NonLocalMap2", py::module_local(false)); 7112391Sjason@lowepower.com }); 7212391Sjason@lowepower.com 7312391Sjason@lowepower.com // test_mixed_local_global 7412391Sjason@lowepower.com // We try this both with the global type registered first and vice versa (the order shouldn't 7512391Sjason@lowepower.com // matter). 7612391Sjason@lowepower.com m.def("register_mixed_global_local", [m]() { 7712391Sjason@lowepower.com bind_local<MixedGlobalLocal, 200>(m, "MixedGlobalLocal", py::module_local()); 7812391Sjason@lowepower.com }); 7912391Sjason@lowepower.com m.def("register_mixed_local_global", [m]() { 8012391Sjason@lowepower.com bind_local<MixedLocalGlobal, 2000>(m, "MixedLocalGlobal", py::module_local(false)); 8112391Sjason@lowepower.com }); 8212391Sjason@lowepower.com m.def("get_mixed_gl", [](int i) { return MixedGlobalLocal(i); }); 8312391Sjason@lowepower.com m.def("get_mixed_lg", [](int i) { return MixedLocalGlobal(i); }); 8412391Sjason@lowepower.com 8512391Sjason@lowepower.com // test_internal_locals_differ 8612391Sjason@lowepower.com m.def("local_cpp_types_addr", []() { return (uintptr_t) &py::detail::registered_local_types_cpp(); }); 8712391Sjason@lowepower.com 8812391Sjason@lowepower.com // test_stl_caster_vs_stl_bind 8912391Sjason@lowepower.com py::bind_vector<std::vector<int>>(m, "VectorInt"); 9012391Sjason@lowepower.com 9112391Sjason@lowepower.com m.def("load_vector_via_binding", [](std::vector<int> &v) { 9212391Sjason@lowepower.com return std::accumulate(v.begin(), v.end(), 0); 9312391Sjason@lowepower.com }); 9412391Sjason@lowepower.com 9512391Sjason@lowepower.com // test_cross_module_calls 9612391Sjason@lowepower.com m.def("return_self", [](LocalVec *v) { return v; }); 9712391Sjason@lowepower.com m.def("return_copy", [](const LocalVec &v) { return LocalVec(v); }); 9812391Sjason@lowepower.com 9912391Sjason@lowepower.com class Dog : public pets::Pet { public: Dog(std::string name) : Pet(name) {}; }; 10012391Sjason@lowepower.com py::class_<pets::Pet>(m, "Pet", py::module_local()) 10112391Sjason@lowepower.com .def("name", &pets::Pet::name); 10212391Sjason@lowepower.com // Binding for local extending class: 10312391Sjason@lowepower.com py::class_<Dog, pets::Pet>(m, "Dog") 10412391Sjason@lowepower.com .def(py::init<std::string>()); 10512391Sjason@lowepower.com m.def("pet_name", [](pets::Pet &p) { return p.name(); }); 10612391Sjason@lowepower.com 10712391Sjason@lowepower.com py::class_<MixGL>(m, "MixGL", py::module_local()).def(py::init<int>()); 10812391Sjason@lowepower.com m.def("get_gl_value", [](MixGL &o) { return o.i + 100; }); 10912391Sjason@lowepower.com 11012391Sjason@lowepower.com py::class_<MixGL2>(m, "MixGL2", py::module_local()).def(py::init<int>()); 11112391Sjason@lowepower.com 11212391Sjason@lowepower.com // test_vector_bool 11312391Sjason@lowepower.com // We can't test both stl.h and stl_bind.h conversions of `std::vector<bool>` within 11412391Sjason@lowepower.com // the same module (it would be an ODR violation). Therefore `bind_vector` of `bool` 11512391Sjason@lowepower.com // is defined here and tested in `test_stl_binders.py`. 11612391Sjason@lowepower.com py::bind_vector<std::vector<bool>>(m, "VectorBool"); 11712391Sjason@lowepower.com 11812391Sjason@lowepower.com // test_missing_header_message 11912391Sjason@lowepower.com // The main module already includes stl.h, but we need to test the error message 12012391Sjason@lowepower.com // which appears when this header is missing. 12112391Sjason@lowepower.com m.def("missing_header_arg", [](std::vector<float>) { }); 12212391Sjason@lowepower.com m.def("missing_header_return", []() { return std::vector<float>(); }); 12312391Sjason@lowepower.com} 124