pybind11_tests.cpp revision 12391
111986Sandreas.sandberg@arm.com/* 211986Sandreas.sandberg@arm.com tests/pybind11_tests.cpp -- pybind example plugin 311986Sandreas.sandberg@arm.com 411986Sandreas.sandberg@arm.com Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> 511986Sandreas.sandberg@arm.com 611986Sandreas.sandberg@arm.com All rights reserved. Use of this source code is governed by a 711986Sandreas.sandberg@arm.com BSD-style license that can be found in the LICENSE file. 811986Sandreas.sandberg@arm.com*/ 911986Sandreas.sandberg@arm.com 1011986Sandreas.sandberg@arm.com#include "pybind11_tests.h" 1111986Sandreas.sandberg@arm.com#include "constructor_stats.h" 1211986Sandreas.sandberg@arm.com 1312391Sjason@lowepower.com#include <functional> 1412391Sjason@lowepower.com#include <list> 1512391Sjason@lowepower.com 1612037Sandreas.sandberg@arm.com/* 1712037Sandreas.sandberg@arm.comFor testing purposes, we define a static global variable here in a function that each individual 1812037Sandreas.sandberg@arm.comtest .cpp calls with its initialization lambda. It's convenient here because we can just not 1912037Sandreas.sandberg@arm.comcompile some test files to disable/ignore some of the test code. 2012037Sandreas.sandberg@arm.com 2112037Sandreas.sandberg@arm.comIt is NOT recommended as a way to use pybind11 in practice, however: the initialization order will 2212037Sandreas.sandberg@arm.combe essentially random, which is okay for our test scripts (there are no dependencies between the 2312037Sandreas.sandberg@arm.comindividual pybind11 test .cpp files), but most likely not what you want when using pybind11 2412037Sandreas.sandberg@arm.comproductively. 2512037Sandreas.sandberg@arm.com 2612037Sandreas.sandberg@arm.comInstead, see the "How can I reduce the build time?" question in the "Frequently asked questions" 2712037Sandreas.sandberg@arm.comsection of the documentation for good practice on splitting binding code over multiple files. 2812037Sandreas.sandberg@arm.com*/ 2911986Sandreas.sandberg@arm.comstd::list<std::function<void(py::module &)>> &initializers() { 3011986Sandreas.sandberg@arm.com static std::list<std::function<void(py::module &)>> inits; 3111986Sandreas.sandberg@arm.com return inits; 3211986Sandreas.sandberg@arm.com} 3311986Sandreas.sandberg@arm.com 3412391Sjason@lowepower.comtest_initializer::test_initializer(Initializer init) { 3512391Sjason@lowepower.com initializers().push_back(init); 3612391Sjason@lowepower.com} 3712391Sjason@lowepower.com 3812391Sjason@lowepower.comtest_initializer::test_initializer(const char *submodule_name, Initializer init) { 3912391Sjason@lowepower.com initializers().push_back([=](py::module &parent) { 4012391Sjason@lowepower.com auto m = parent.def_submodule(submodule_name); 4112391Sjason@lowepower.com init(m); 4212391Sjason@lowepower.com }); 4311986Sandreas.sandberg@arm.com} 4411986Sandreas.sandberg@arm.com 4511986Sandreas.sandberg@arm.comvoid bind_ConstructorStats(py::module &m) { 4611986Sandreas.sandberg@arm.com py::class_<ConstructorStats>(m, "ConstructorStats") 4711986Sandreas.sandberg@arm.com .def("alive", &ConstructorStats::alive) 4811986Sandreas.sandberg@arm.com .def("values", &ConstructorStats::values) 4911986Sandreas.sandberg@arm.com .def_readwrite("default_constructions", &ConstructorStats::default_constructions) 5011986Sandreas.sandberg@arm.com .def_readwrite("copy_assignments", &ConstructorStats::copy_assignments) 5111986Sandreas.sandberg@arm.com .def_readwrite("move_assignments", &ConstructorStats::move_assignments) 5211986Sandreas.sandberg@arm.com .def_readwrite("copy_constructions", &ConstructorStats::copy_constructions) 5311986Sandreas.sandberg@arm.com .def_readwrite("move_constructions", &ConstructorStats::move_constructions) 5412391Sjason@lowepower.com .def_static("get", (ConstructorStats &(*)(py::object)) &ConstructorStats::get, py::return_value_policy::reference_internal) 5512391Sjason@lowepower.com 5612391Sjason@lowepower.com // Not exactly ConstructorStats, but related: expose the internal pybind number of registered instances 5712391Sjason@lowepower.com // to allow instance cleanup checks (invokes a GC first) 5812391Sjason@lowepower.com .def_static("detail_reg_inst", []() { 5912391Sjason@lowepower.com ConstructorStats::gc(); 6012391Sjason@lowepower.com return py::detail::get_internals().registered_instances.size(); 6112391Sjason@lowepower.com }) 6212391Sjason@lowepower.com ; 6311986Sandreas.sandberg@arm.com} 6411986Sandreas.sandberg@arm.com 6512391Sjason@lowepower.comPYBIND11_MODULE(pybind11_tests, m) { 6612391Sjason@lowepower.com m.doc() = "pybind11 test module"; 6711986Sandreas.sandberg@arm.com 6811986Sandreas.sandberg@arm.com bind_ConstructorStats(m); 6911986Sandreas.sandberg@arm.com 7012391Sjason@lowepower.com#if !defined(NDEBUG) 7112391Sjason@lowepower.com m.attr("debug_enabled") = true; 7212391Sjason@lowepower.com#else 7312391Sjason@lowepower.com m.attr("debug_enabled") = false; 7412391Sjason@lowepower.com#endif 7512391Sjason@lowepower.com 7612391Sjason@lowepower.com py::class_<UserType>(m, "UserType", "A `py::class_` type for testing") 7712391Sjason@lowepower.com .def(py::init<>()) 7812391Sjason@lowepower.com .def(py::init<int>()) 7912391Sjason@lowepower.com .def("get_value", &UserType::value, "Get value using a method") 8012391Sjason@lowepower.com .def("set_value", &UserType::set, "Set value using a method") 8112391Sjason@lowepower.com .def_property("value", &UserType::value, &UserType::set, "Get/set value using a property") 8212391Sjason@lowepower.com .def("__repr__", [](const UserType& u) { return "UserType({})"_s.format(u.value()); }); 8312391Sjason@lowepower.com 8412391Sjason@lowepower.com py::class_<IncType, UserType>(m, "IncType") 8512391Sjason@lowepower.com .def(py::init<>()) 8612391Sjason@lowepower.com .def(py::init<int>()) 8712391Sjason@lowepower.com .def("__repr__", [](const IncType& u) { return "IncType({})"_s.format(u.value()); }); 8812391Sjason@lowepower.com 8911986Sandreas.sandberg@arm.com for (const auto &initializer : initializers()) 9011986Sandreas.sandberg@arm.com initializer(m); 9111986Sandreas.sandberg@arm.com 9211986Sandreas.sandberg@arm.com if (!py::hasattr(m, "have_eigen")) m.attr("have_eigen") = false; 9311986Sandreas.sandberg@arm.com} 94