mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-11 08:03:55 +00:00
Make test initialization self-registering
Adding or removing tests is a little bit cumbersome currently: the test needs to be added to CMakeLists.txt, the init function needs to be predeclared in pybind11_tests.cpp, then called in the plugin initialization. While this isn't a big deal for tests that are being committed, it's more of a hassle when working on some new feature or test code for which I temporarily only care about building and linking the test being worked on rather than the entire test suite. This commit changes tests to self-register their initialization by having each test initialize a local object (which stores the initialization function in a static variable). This makes changing the set of tests being build easy: one only needs to add or comment out test names in tests/CMakeLists.txt. A couple other minor changes that go along with this: - test_eigen.cpp is now included in the test list, then removed if eigen isn't available. This lets you disable the eigen tests by commenting it out, just like all the other tests, but keeps the build working without eigen eigen isn't available. (Also, if it's commented out, we don't even bother looking for and reporting the building with/without eigen status message). - pytest is now invoked with all the built test names (with .cpp changed to .py) so that it doesn't try to run tests that weren't built.
This commit is contained in:
parent
06d8de113a
commit
52f4be8946
@ -7,6 +7,7 @@ set(PYBIND11_TEST_FILES
|
||||
test_buffers.cpp
|
||||
test_callbacks.cpp
|
||||
test_constants_and_functions.cpp
|
||||
test_eigen.cpp
|
||||
test_enum.cpp
|
||||
test_eval.cpp
|
||||
test_exceptions.cpp
|
||||
@ -28,15 +29,22 @@ set(PYBIND11_TEST_FILES
|
||||
test_virtual_functions.cpp
|
||||
)
|
||||
|
||||
# Check if Eigen is available
|
||||
string(REPLACE ".cpp" ".py" PYBIND11_PYTEST_FILES "${PYBIND11_TEST_FILES}")
|
||||
|
||||
# Check if Eigen is available; if not, remove from PYBIND11_TEST_FILES (but
|
||||
# keep it in PYBIND11_PYTEST_FILES, so that we get the "eigen is not installed"
|
||||
# skip message).
|
||||
list(FIND PYBIND11_TEST_FILES test_eigen.cpp PYBIND11_TEST_FILES_EIGEN_I)
|
||||
if(PYBIND11_TEST_FILES_EIGEN_I GREATER -1)
|
||||
find_package(Eigen3 QUIET)
|
||||
|
||||
if(EIGEN3_FOUND)
|
||||
list(APPEND PYBIND11_TEST_FILES test_eigen.cpp)
|
||||
message(STATUS "Building tests with Eigen v${EIGEN3_VERSION}")
|
||||
else()
|
||||
list(REMOVE_AT PYBIND11_TEST_FILES ${PYBIND11_TEST_FILES_EIGEN_I})
|
||||
message(STATUS "Building tests WITHOUT Eigen")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Create the binding library
|
||||
pybind11_add_module(pybind11_tests pybind11_tests.cpp ${PYBIND11_TEST_FILES})
|
||||
@ -74,5 +82,5 @@ if(NOT PYBIND11_PYTEST_FOUND)
|
||||
endif()
|
||||
|
||||
# A single command to compile and run the tests
|
||||
add_custom_target(pytest COMMAND ${PYTHON_EXECUTABLE} -m pytest -rws
|
||||
add_custom_target(pytest COMMAND ${PYTHON_EXECUTABLE} -m pytest -rws ${PYBIND11_PYTEST_FILES}
|
||||
DEPENDS pybind11_tests WORKING_DIRECTORY ${testdir})
|
||||
|
@ -10,32 +10,14 @@
|
||||
#include "pybind11_tests.h"
|
||||
#include "constructor_stats.h"
|
||||
|
||||
void init_ex_methods_and_attributes(py::module &);
|
||||
void init_ex_python_types(py::module &);
|
||||
void init_ex_operator_overloading(py::module &);
|
||||
void init_ex_constants_and_functions(py::module &);
|
||||
void init_ex_callbacks(py::module &);
|
||||
void init_ex_sequences_and_iterators(py::module &);
|
||||
void init_ex_buffers(py::module &);
|
||||
void init_ex_smart_ptr(py::module &);
|
||||
void init_ex_modules(py::module &);
|
||||
void init_ex_numpy_vectorize(py::module &);
|
||||
void init_ex_arg_keywords_and_defaults(py::module &);
|
||||
void init_ex_virtual_functions(py::module &);
|
||||
void init_ex_keep_alive(py::module &);
|
||||
void init_ex_opaque_types(py::module &);
|
||||
void init_ex_pickling(py::module &);
|
||||
void init_ex_inheritance(py::module &);
|
||||
void init_ex_stl_binder_vector(py::module &);
|
||||
void init_ex_eval(py::module &);
|
||||
void init_ex_custom_exceptions(py::module &);
|
||||
void init_ex_numpy_dtypes(py::module &);
|
||||
void init_ex_enum(py::module &);
|
||||
void init_issues(py::module &);
|
||||
std::list<std::function<void(py::module &)>> &initializers() {
|
||||
static std::list<std::function<void(py::module &)>> inits;
|
||||
return inits;
|
||||
}
|
||||
|
||||
#if defined(PYBIND11_TEST_EIGEN)
|
||||
void init_eigen(py::module &);
|
||||
#endif
|
||||
test_initializer::test_initializer(std::function<void(py::module &)> initializer) {
|
||||
initializers().push_back(std::move(initializer));
|
||||
}
|
||||
|
||||
void bind_ConstructorStats(py::module &m) {
|
||||
py::class_<ConstructorStats>(m, "ConstructorStats")
|
||||
@ -54,35 +36,10 @@ PYBIND11_PLUGIN(pybind11_tests) {
|
||||
|
||||
bind_ConstructorStats(m);
|
||||
|
||||
init_ex_methods_and_attributes(m);
|
||||
init_ex_python_types(m);
|
||||
init_ex_operator_overloading(m);
|
||||
init_ex_constants_and_functions(m);
|
||||
init_ex_callbacks(m);
|
||||
init_ex_sequences_and_iterators(m);
|
||||
init_ex_buffers(m);
|
||||
init_ex_smart_ptr(m);
|
||||
init_ex_modules(m);
|
||||
init_ex_numpy_vectorize(m);
|
||||
init_ex_arg_keywords_and_defaults(m);
|
||||
init_ex_virtual_functions(m);
|
||||
init_ex_keep_alive(m);
|
||||
init_ex_opaque_types(m);
|
||||
init_ex_pickling(m);
|
||||
init_ex_inheritance(m);
|
||||
init_ex_stl_binder_vector(m);
|
||||
init_ex_eval(m);
|
||||
init_ex_custom_exceptions(m);
|
||||
init_ex_numpy_dtypes(m);
|
||||
init_ex_enum(m);
|
||||
init_issues(m);
|
||||
for (const auto &initializer : initializers())
|
||||
initializer(m);
|
||||
|
||||
#if defined(PYBIND11_TEST_EIGEN)
|
||||
init_eigen(m);
|
||||
m.attr("have_eigen") = py::cast(true);
|
||||
#else
|
||||
m.attr("have_eigen") = py::cast(false);
|
||||
#endif
|
||||
if (!m.attr("have_eigen")) m.attr("have_eigen") = py::cast(false);
|
||||
|
||||
return m.ptr();
|
||||
}
|
||||
|
@ -1,7 +1,15 @@
|
||||
#pragma once
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
#include <list>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
class test_initializer {
|
||||
public:
|
||||
test_initializer(std::function<void(py::module &)> initializer);
|
||||
};
|
||||
|
@ -74,7 +74,7 @@ private:
|
||||
float *m_data;
|
||||
};
|
||||
|
||||
void init_ex_buffers(py::module &m) {
|
||||
test_initializer buffers([](py::module &m) {
|
||||
py::class_<Matrix> mtx(m, "Matrix");
|
||||
|
||||
mtx.def(py::init<size_t, size_t>())
|
||||
@ -114,4 +114,4 @@ void init_ex_buffers(py::module &m) {
|
||||
);
|
||||
})
|
||||
;
|
||||
}
|
||||
});
|
||||
|
@ -71,7 +71,7 @@ struct Payload {
|
||||
}
|
||||
};
|
||||
|
||||
void init_ex_callbacks(py::module &m) {
|
||||
test_initializer callbacks([](py::module &m) {
|
||||
m.def("test_callback1", &test_callback1);
|
||||
m.def("test_callback2", &test_callback2);
|
||||
m.def("test_callback3", &test_callback3);
|
||||
@ -95,4 +95,4 @@ void init_ex_callbacks(py::module &m) {
|
||||
m.def("test_dummy_function", &test_dummy_function);
|
||||
// Export the payload constructor statistics for testing purposes:
|
||||
m.def("payload_cstats", &ConstructorStats::get<Payload>);
|
||||
}
|
||||
});
|
||||
|
@ -38,7 +38,7 @@ std::string print_bytes(py::bytes bytes) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void init_ex_constants_and_functions(py::module &m) {
|
||||
test_initializer constants_and_functions([](py::module &m) {
|
||||
m.attr("some_constant") = py::int_(14);
|
||||
|
||||
m.def("test_function", &test_function1);
|
||||
@ -52,4 +52,4 @@ void init_ex_constants_and_functions(py::module &m) {
|
||||
|
||||
m.def("return_bytes", &return_bytes);
|
||||
m.def("print_bytes", &print_bytes);
|
||||
}
|
||||
});
|
||||
|
@ -32,7 +32,7 @@ typedef Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> Ma
|
||||
MatrixXfRowMajor double_mat_rm(const MatrixXfRowMajor& x)
|
||||
{ return 2.0f * x; }
|
||||
|
||||
void init_eigen(py::module &m) {
|
||||
test_initializer eigen([](py::module &m) {
|
||||
typedef Eigen::Matrix<float, 5, 6, Eigen::RowMajor> FixedMatrixR;
|
||||
typedef Eigen::Matrix<float, 5, 6> FixedMatrixC;
|
||||
typedef Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> DenseMatrixR;
|
||||
@ -40,6 +40,8 @@ void init_eigen(py::module &m) {
|
||||
typedef Eigen::SparseMatrix<float, Eigen::RowMajor> SparseMatrixR;
|
||||
typedef Eigen::SparseMatrix<float> SparseMatrixC;
|
||||
|
||||
m.attr("have_eigen") = py::cast(true);
|
||||
|
||||
// Non-symmetric matrix with zero elements
|
||||
Eigen::MatrixXf mat(5, 6);
|
||||
mat << 0, 3, 0, 0, 0, 11, 22, 0, 0, 0, 17, 11, 7, 5, 0, 1, 0, 11, 0,
|
||||
@ -129,4 +131,4 @@ void init_eigen(py::module &m) {
|
||||
m.def("sparse_passthrough_c", [](const SparseMatrixC &m) -> SparseMatrixC {
|
||||
return m;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -35,7 +35,7 @@ std::string test_scoped_enum(ScopedEnum z) {
|
||||
return "ScopedEnum::" + std::string(z == ScopedEnum::Two ? "Two" : "Three");
|
||||
}
|
||||
|
||||
void init_ex_enum(py::module &m) {
|
||||
test_initializer enums([](py::module &m) {
|
||||
m.def("test_scoped_enum", &test_scoped_enum);
|
||||
|
||||
py::enum_<UnscopedEnum>(m, "UnscopedEnum")
|
||||
@ -54,4 +54,4 @@ void init_ex_enum(py::module &m) {
|
||||
.value("EFirstMode", ClassWithUnscopedEnum::EFirstMode)
|
||||
.value("ESecondMode", ClassWithUnscopedEnum::ESecondMode)
|
||||
.export_values();
|
||||
}
|
||||
});
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include <pybind11/eval.h>
|
||||
#include "pybind11_tests.h"
|
||||
|
||||
void init_ex_eval(py::module & m) {
|
||||
test_initializer eval([](py::module &m) {
|
||||
auto global = py::dict(py::module::import("__main__").attr("__dict__"));
|
||||
|
||||
m.def("test_eval_statements", [global]() {
|
||||
@ -77,4 +77,4 @@ void init_ex_eval(py::module & m) {
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -66,7 +66,7 @@ void throws_logic_error() {
|
||||
throw std::logic_error("this error should fall through to the standard handler");
|
||||
}
|
||||
|
||||
void init_ex_custom_exceptions(py::module &m) {
|
||||
test_initializer custom_exceptions([](py::module &m) {
|
||||
// make a new custom exception and use it as a translation target
|
||||
static py::exception<MyException> ex(m, "MyException");
|
||||
py::register_exception_translator([](std::exception_ptr p) {
|
||||
@ -104,5 +104,5 @@ void init_ex_custom_exceptions(py::module &m) {
|
||||
m.def("throws3", &throws3);
|
||||
m.def("throws4", &throws4);
|
||||
m.def("throws_logic_error", &throws_logic_error);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -44,7 +44,7 @@ struct BaseClass { virtual ~BaseClass() {} };
|
||||
struct DerivedClass1 : BaseClass { };
|
||||
struct DerivedClass2 : BaseClass { };
|
||||
|
||||
void init_ex_inheritance(py::module &m) {
|
||||
test_initializer inheritance([](py::module &m) {
|
||||
py::class_<Pet> pet_class(m, "Pet");
|
||||
pet_class
|
||||
.def(py::init<std::string, std::string>())
|
||||
@ -69,4 +69,4 @@ void init_ex_inheritance(py::module &m) {
|
||||
m.def("return_class_1", []() -> BaseClass* { return new DerivedClass1(); });
|
||||
m.def("return_class_2", []() -> BaseClass* { return new DerivedClass2(); });
|
||||
m.def("return_none", []() -> BaseClass* { return nullptr; });
|
||||
}
|
||||
});
|
||||
|
@ -173,3 +173,6 @@ void init_issues(py::module &m) {
|
||||
m2.def("get_NestB", [](const NestB &b) { return b.value; });
|
||||
m2.def("get_NestC", [](const NestC &c) { return c.value; });
|
||||
}
|
||||
|
||||
// MSVC workaround: trying to use a lambda here crashes MSCV
|
||||
test_initializer issues(&init_issues);
|
||||
|
@ -25,7 +25,7 @@ public:
|
||||
Child *returnNullChild() { return nullptr; }
|
||||
};
|
||||
|
||||
void init_ex_keep_alive(py::module &m) {
|
||||
test_initializer keep_alive([](py::module &m) {
|
||||
py::class_<Parent>(m, "Parent")
|
||||
.def(py::init<>())
|
||||
.def("addChild", &Parent::addChild)
|
||||
@ -37,4 +37,4 @@ void init_ex_keep_alive(py::module &m) {
|
||||
|
||||
py::class_<Child>(m, "Child")
|
||||
.def(py::init<>());
|
||||
}
|
||||
});
|
||||
|
@ -39,7 +39,7 @@ struct KWClass {
|
||||
void foo(int, float) {}
|
||||
};
|
||||
|
||||
void init_ex_arg_keywords_and_defaults(py::module &m) {
|
||||
test_initializer arg_keywords_and_defaults([](py::module &m) {
|
||||
m.def("kw_func0", &kw_func);
|
||||
m.def("kw_func1", &kw_func, py::arg("x"), py::arg("y"));
|
||||
m.def("kw_func2", &kw_func, py::arg("x") = 100, py::arg("y") = 200);
|
||||
@ -63,4 +63,4 @@ void init_ex_arg_keywords_and_defaults(py::module &m) {
|
||||
py::class_<KWClass>(m, "KWClass")
|
||||
.def("foo0", &KWClass::foo)
|
||||
.def("foo1", &KWClass::foo, "x"_a, "y"_a);
|
||||
}
|
||||
});
|
||||
|
@ -53,7 +53,7 @@ public:
|
||||
int value = 0;
|
||||
};
|
||||
|
||||
void init_ex_methods_and_attributes(py::module &m) {
|
||||
test_initializer methods_and_attributes([](py::module &m) {
|
||||
py::class_<ExampleMandA>(m, "ExampleMandA")
|
||||
.def(py::init<>())
|
||||
.def(py::init<int>())
|
||||
@ -81,4 +81,4 @@ void init_ex_methods_and_attributes(py::module &m) {
|
||||
.def("__str__", &ExampleMandA::toString)
|
||||
.def_readwrite("value", &ExampleMandA::value)
|
||||
;
|
||||
}
|
||||
});
|
||||
|
@ -39,7 +39,7 @@ public:
|
||||
A a2{2};
|
||||
};
|
||||
|
||||
void init_ex_modules(py::module &m) {
|
||||
test_initializer modules([](py::module &m) {
|
||||
py::module m_sub = m.def_submodule("submodule");
|
||||
m_sub.def("submodule_func", &submodule_func);
|
||||
|
||||
@ -55,4 +55,4 @@ void init_ex_modules(py::module &m) {
|
||||
.def_readwrite("a2", &B::a2);
|
||||
|
||||
m.attr("OD") = py::module::import("collections").attr("OrderedDict");
|
||||
}
|
||||
});
|
||||
|
@ -267,7 +267,7 @@ py::list test_dtype_methods() {
|
||||
return list;
|
||||
}
|
||||
|
||||
void init_ex_numpy_dtypes(py::module &m) {
|
||||
test_initializer numpy_dtypes([](py::module &m) {
|
||||
try {
|
||||
py::module::import("numpy");
|
||||
} catch (...) {
|
||||
@ -297,6 +297,6 @@ void init_ex_numpy_dtypes(py::module &m) {
|
||||
m.def("test_array_ctors", &test_array_ctors);
|
||||
m.def("test_dtype_ctors", &test_dtype_ctors);
|
||||
m.def("test_dtype_methods", &test_dtype_methods);
|
||||
}
|
||||
});
|
||||
|
||||
#undef PYBIND11_PACKED
|
||||
|
@ -20,7 +20,7 @@ std::complex<double> my_func3(std::complex<double> c) {
|
||||
return c * std::complex<double>(2.f);
|
||||
}
|
||||
|
||||
void init_ex_numpy_vectorize(py::module &m) {
|
||||
test_initializer numpy_vectorize([](py::module &m) {
|
||||
// Vectorize all arguments of a function (though non-vector arguments are also allowed)
|
||||
m.def("vectorized_func", py::vectorize(my_func));
|
||||
|
||||
@ -38,4 +38,4 @@ void init_ex_numpy_vectorize(py::module &m) {
|
||||
m.def("selective_func", [](py::array_t<int, py::array::c_style>) { return "Int branch taken."; });
|
||||
m.def("selective_func", [](py::array_t<float, py::array::c_style>) { return "Float branch taken."; });
|
||||
m.def("selective_func", [](py::array_t<std::complex<float>, py::array::c_style>) { return "Complex float branch taken."; });
|
||||
}
|
||||
});
|
||||
|
@ -21,7 +21,7 @@ public:
|
||||
/* IMPORTANT: Disable internal pybind11 translation mechanisms for STL data structures */
|
||||
PYBIND11_MAKE_OPAQUE(StringList);
|
||||
|
||||
void init_ex_opaque_types(py::module &m) {
|
||||
test_initializer opaque_types([](py::module &m) {
|
||||
py::class_<StringList>(m, "StringList")
|
||||
.def(py::init<>())
|
||||
.def("pop_back", &StringList::pop_back)
|
||||
@ -59,4 +59,4 @@ void init_ex_opaque_types(py::module &m) {
|
||||
result->push_back("some value");
|
||||
return std::unique_ptr<StringList>(result);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -52,7 +52,7 @@ private:
|
||||
float x, y;
|
||||
};
|
||||
|
||||
void init_ex_operator_overloading(py::module &m) {
|
||||
test_initializer operator_overloading([](py::module &m) {
|
||||
py::class_<Vector2>(m, "Vector2")
|
||||
.def(py::init<float, float>())
|
||||
.def(py::self + py::self)
|
||||
@ -73,4 +73,4 @@ void init_ex_operator_overloading(py::module &m) {
|
||||
;
|
||||
|
||||
m.attr("Vector") = m.attr("Vector2");
|
||||
}
|
||||
});
|
||||
|
@ -24,7 +24,7 @@ private:
|
||||
int m_extra2 = 0;
|
||||
};
|
||||
|
||||
void init_ex_pickling(py::module &m) {
|
||||
test_initializer pickling([](py::module &m) {
|
||||
py::class_<Pickleable>(m, "Pickleable")
|
||||
.def(py::init<std::string>())
|
||||
.def("value", &Pickleable::value)
|
||||
@ -48,4 +48,4 @@ void init_ex_pickling(py::module &m) {
|
||||
p.setExtra1(t[1].cast<int>());
|
||||
p.setExtra2(t[2].cast<int>());
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -167,7 +167,7 @@ public:
|
||||
int ExamplePythonTypes::value = 0;
|
||||
const int ExamplePythonTypes::value2 = 5;
|
||||
|
||||
void init_ex_python_types(py::module &m) {
|
||||
test_initializer python_types([](py::module &m) {
|
||||
/* No constructor is explicitly defined below. An exception is raised when
|
||||
trying to construct it directly from Python */
|
||||
py::class_<ExamplePythonTypes>(m, "ExamplePythonTypes", "Example 2 documentation")
|
||||
@ -197,4 +197,4 @@ void init_ex_python_types(py::module &m) {
|
||||
.def_readwrite_static("value", &ExamplePythonTypes::value, "Static value member")
|
||||
.def_readonly_static("value2", &ExamplePythonTypes::value2, "Static value member (readonly)")
|
||||
;
|
||||
}
|
||||
});
|
||||
|
@ -168,7 +168,7 @@ bool operator==(const NonZeroIterator<std::pair<A, B>>& it, const NonZeroSentine
|
||||
return !(*it).first || !(*it).second;
|
||||
}
|
||||
|
||||
void init_ex_sequences_and_iterators(py::module &m) {
|
||||
test_initializer sequences_and_iterators([](py::module &m) {
|
||||
|
||||
py::class_<Sequence> seq(m, "Sequence");
|
||||
|
||||
@ -271,4 +271,4 @@ void init_ex_sequences_and_iterators(py::module &m) {
|
||||
On the actual Sequence object, the iterator would be constructed as follows:
|
||||
.def("__iter__", [](py::object s) { return PySequenceIterator(s.cast<const Sequence &>(), s); })
|
||||
#endif
|
||||
}
|
||||
});
|
||||
|
@ -105,7 +105,7 @@ void print_myobject3_2(std::shared_ptr<MyObject3> obj) { std::cout << obj->toStr
|
||||
void print_myobject3_3(const std::shared_ptr<MyObject3> &obj) { std::cout << obj->toString() << std::endl; }
|
||||
void print_myobject3_4(const std::shared_ptr<MyObject3> *obj) { std::cout << (*obj)->toString() << std::endl; }
|
||||
|
||||
void init_ex_smart_ptr(py::module &m) {
|
||||
test_initializer smart_ptr([](py::module &m) {
|
||||
py::class_<Object, ref<Object>> obj(m, "Object");
|
||||
obj.def("getRefCount", &Object::getRefCount);
|
||||
|
||||
@ -147,4 +147,4 @@ void init_ex_smart_ptr(py::module &m) {
|
||||
|
||||
// Expose constructor stats for the ref type
|
||||
m.def("cstats_ref", &ConstructorStats::get<ref_tag>);
|
||||
}
|
||||
});
|
||||
|
@ -24,7 +24,7 @@ std::ostream & operator<<(std::ostream &s, El const&v) {
|
||||
return s;
|
||||
}
|
||||
|
||||
void init_ex_stl_binder_vector(py::module &m) {
|
||||
test_initializer stl_binder_vector([](py::module &m) {
|
||||
py::class_<El>(m, "El")
|
||||
.def(py::init<int>());
|
||||
|
||||
@ -34,4 +34,4 @@ void init_ex_stl_binder_vector(py::module &m) {
|
||||
py::bind_vector<El>(m, "VectorEl");
|
||||
|
||||
py::bind_vector<std::vector<El>>(m, "VectorVectorEl");
|
||||
}
|
||||
});
|
||||
|
@ -283,7 +283,7 @@ void initialize_inherited_virtuals(py::module &m) {
|
||||
};
|
||||
|
||||
|
||||
void init_ex_virtual_functions(py::module &m) {
|
||||
test_initializer virtual_functions([](py::module &m) {
|
||||
/* Important: indicate the trampoline class PyExampleVirt using the third
|
||||
argument to py::class_. The second argument with the unique pointer
|
||||
is simply the default holder type used by pybind11. */
|
||||
@ -315,4 +315,4 @@ void init_ex_virtual_functions(py::module &m) {
|
||||
|
||||
m.def("cstats_debug", &ConstructorStats::get<ExampleVirt>);
|
||||
initialize_inherited_virtuals(m);
|
||||
}
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user