pybind11_tests.cpp revision 12391
112855Sgabeblack@google.com/*
212855Sgabeblack@google.com    tests/pybind11_tests.cpp -- pybind example plugin
312855Sgabeblack@google.com
412855Sgabeblack@google.com    Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
512855Sgabeblack@google.com
612855Sgabeblack@google.com    All rights reserved. Use of this source code is governed by a
712855Sgabeblack@google.com    BSD-style license that can be found in the LICENSE file.
812855Sgabeblack@google.com*/
912855Sgabeblack@google.com
1012855Sgabeblack@google.com#include "pybind11_tests.h"
1112855Sgabeblack@google.com#include "constructor_stats.h"
1212855Sgabeblack@google.com
1312855Sgabeblack@google.com#include <functional>
1412855Sgabeblack@google.com#include <list>
1512855Sgabeblack@google.com
1612855Sgabeblack@google.com/*
1712855Sgabeblack@google.comFor testing purposes, we define a static global variable here in a function that each individual
1812855Sgabeblack@google.comtest .cpp calls with its initialization lambda.  It's convenient here because we can just not
1912855Sgabeblack@google.comcompile some test files to disable/ignore some of the test code.
2012855Sgabeblack@google.com
2112855Sgabeblack@google.comIt is NOT recommended as a way to use pybind11 in practice, however: the initialization order will
2212855Sgabeblack@google.combe essentially random, which is okay for our test scripts (there are no dependencies between the
2312855Sgabeblack@google.comindividual pybind11 test .cpp files), but most likely not what you want when using pybind11
2412855Sgabeblack@google.comproductively.
2512855Sgabeblack@google.com
2612855Sgabeblack@google.comInstead, see the "How can I reduce the build time?" question in the "Frequently asked questions"
2712855Sgabeblack@google.comsection of the documentation for good practice on splitting binding code over multiple files.
2812855Sgabeblack@google.com*/
2912855Sgabeblack@google.comstd::list<std::function<void(py::module &)>> &initializers() {
3012855Sgabeblack@google.com    static std::list<std::function<void(py::module &)>> inits;
3112855Sgabeblack@google.com    return inits;
3212855Sgabeblack@google.com}
3312855Sgabeblack@google.com
3412855Sgabeblack@google.comtest_initializer::test_initializer(Initializer init) {
3512855Sgabeblack@google.com    initializers().push_back(init);
3612855Sgabeblack@google.com}
3712855Sgabeblack@google.com
3812855Sgabeblack@google.comtest_initializer::test_initializer(const char *submodule_name, Initializer init) {
3912855Sgabeblack@google.com    initializers().push_back([=](py::module &parent) {
4012855Sgabeblack@google.com        auto m = parent.def_submodule(submodule_name);
4112855Sgabeblack@google.com        init(m);
4212855Sgabeblack@google.com    });
4312855Sgabeblack@google.com}
4412855Sgabeblack@google.com
4512855Sgabeblack@google.comvoid bind_ConstructorStats(py::module &m) {
4612855Sgabeblack@google.com    py::class_<ConstructorStats>(m, "ConstructorStats")
4712855Sgabeblack@google.com        .def("alive", &ConstructorStats::alive)
4812855Sgabeblack@google.com        .def("values", &ConstructorStats::values)
4912855Sgabeblack@google.com        .def_readwrite("default_constructions", &ConstructorStats::default_constructions)
5012855Sgabeblack@google.com        .def_readwrite("copy_assignments", &ConstructorStats::copy_assignments)
5112855Sgabeblack@google.com        .def_readwrite("move_assignments", &ConstructorStats::move_assignments)
5212855Sgabeblack@google.com        .def_readwrite("copy_constructions", &ConstructorStats::copy_constructions)
5312855Sgabeblack@google.com        .def_readwrite("move_constructions", &ConstructorStats::move_constructions)
5412855Sgabeblack@google.com        .def_static("get", (ConstructorStats &(*)(py::object)) &ConstructorStats::get, py::return_value_policy::reference_internal)
5512855Sgabeblack@google.com
5612855Sgabeblack@google.com        // Not exactly ConstructorStats, but related: expose the internal pybind number of registered instances
5712855Sgabeblack@google.com        // to allow instance cleanup checks (invokes a GC first)
5812855Sgabeblack@google.com        .def_static("detail_reg_inst", []() {
5912855Sgabeblack@google.com            ConstructorStats::gc();
6012855Sgabeblack@google.com            return py::detail::get_internals().registered_instances.size();
6112855Sgabeblack@google.com        })
6212855Sgabeblack@google.com        ;
6312855Sgabeblack@google.com}
6412855Sgabeblack@google.com
6512855Sgabeblack@google.comPYBIND11_MODULE(pybind11_tests, m) {
6612855Sgabeblack@google.com    m.doc() = "pybind11 test module";
6712855Sgabeblack@google.com
6812855Sgabeblack@google.com    bind_ConstructorStats(m);
6912855Sgabeblack@google.com
7012855Sgabeblack@google.com#if !defined(NDEBUG)
7112855Sgabeblack@google.com    m.attr("debug_enabled") = true;
7212855Sgabeblack@google.com#else
7312855Sgabeblack@google.com    m.attr("debug_enabled") = false;
7412855Sgabeblack@google.com#endif
7512855Sgabeblack@google.com
7612855Sgabeblack@google.com    py::class_<UserType>(m, "UserType", "A `py::class_` type for testing")
7712855Sgabeblack@google.com        .def(py::init<>())
7812855Sgabeblack@google.com        .def(py::init<int>())
7912855Sgabeblack@google.com        .def("get_value", &UserType::value, "Get value using a method")
8012855Sgabeblack@google.com        .def("set_value", &UserType::set, "Set value using a method")
8112855Sgabeblack@google.com        .def_property("value", &UserType::value, &UserType::set, "Get/set value using a property")
8212855Sgabeblack@google.com        .def("__repr__", [](const UserType& u) { return "UserType({})"_s.format(u.value()); });
8312855Sgabeblack@google.com
8412855Sgabeblack@google.com    py::class_<IncType, UserType>(m, "IncType")
8512855Sgabeblack@google.com        .def(py::init<>())
8612855Sgabeblack@google.com        .def(py::init<int>())
8712855Sgabeblack@google.com        .def("__repr__", [](const IncType& u) { return "IncType({})"_s.format(u.value()); });
8812855Sgabeblack@google.com
8912855Sgabeblack@google.com    for (const auto &initializer : initializers())
9012855Sgabeblack@google.com        initializer(m);
9112855Sgabeblack@google.com
9212855Sgabeblack@google.com    if (!py::hasattr(m, "have_eigen")) m.attr("have_eigen") = false;
9312855Sgabeblack@google.com}
9412855Sgabeblack@google.com