From bd29763b161991cb15cbb8ea666b5e6c4737691d Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Tue, 28 Sep 2021 22:34:11 +0200 Subject: [PATCH] Add std::any to py::object caster for archive registered types --- libsrc/core/CMakeLists.txt | 1 + libsrc/core/archive.cpp | 10 ++++++++ libsrc/core/archive.hpp | 34 ++++++++++---------------- libsrc/core/flags.hpp | 3 +++ libsrc/core/python_ngcore.cpp | 5 ++++ libsrc/core/register_archive.hpp | 42 ++++++++++++++++++++++++++++++++ libsrc/csg/algprim.cpp | 1 + libsrc/csg/brick.cpp | 1 + libsrc/csg/csgeom.cpp | 1 + libsrc/csg/extrusion.cpp | 1 + libsrc/csg/revolution.cpp | 1 + libsrc/csg/splinesurface.cpp | 1 + libsrc/csg/surface.cpp | 1 + libsrc/geom2d/geometry2d.cpp | 1 + libsrc/gprim/spline.cpp | 2 ++ libsrc/gprim/splinegeometry.cpp | 1 + libsrc/meshing/basegeom.cpp | 1 + libsrc/occ/occgeom.cpp | 1 + libsrc/stlgeom/stlgeom.cpp | 1 + libsrc/stlgeom/stltopology.cpp | 1 + tests/catch/CMakeLists.txt | 8 ++++-- tests/catch/archive.cpp | 1 + 22 files changed, 96 insertions(+), 23 deletions(-) create mode 100644 libsrc/core/register_archive.hpp diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index 7e577d29..0a57f984 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -74,6 +74,7 @@ install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp array.hpp taskmanager.hpp concurrentqueue.h localheap.hpp python_ngcore.hpp flags.hpp xbool.hpp signal.hpp bitarray.hpp table.hpp hashtable.hpp ranges.hpp ngstream.hpp simd.hpp simd_avx.hpp simd_avx512.hpp simd_generic.hpp simd_sse.hpp simd_arm64.hpp + register_archive.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel) if(ENABLE_CPP_CORE_GUIDELINES_CHECK) diff --git a/libsrc/core/archive.cpp b/libsrc/core/archive.cpp index 7937e64d..5454b929 100644 --- a/libsrc/core/archive.cpp +++ b/libsrc/core/archive.cpp @@ -1,5 +1,6 @@ #include "archive.hpp" +#include "register_archive.hpp" #include "version.hpp" #ifndef WIN32 @@ -28,4 +29,13 @@ namespace ngcore std::make_unique>(); return type_register->count(classname) != 0; } + +#ifdef NETGEN_PYTHON + pybind11::object CastAnyToPy(const std::any& a) + { + auto info = Archive::GetArchiveRegister(Demangle(a.type().name())); + return info.anyToPyCaster(a); + } +#endif // NETGEN_PYTHON + } // namespace ngcore diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index cbe17e27..0e5d69bc 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -1,6 +1,7 @@ #ifndef NETGEN_CORE_ARCHIVE_HPP #define NETGEN_CORE_ARCHIVE_HPP +#include #include // for array #include // for complex #include // for size_t, strlen @@ -32,8 +33,11 @@ namespace pybind11 namespace ngcore { - class NGCORE_API Archive; +#ifdef NETGEN_PYTHON + pybind11::object CastAnyToPy(const std::any& a); +#endif // NETGEN_PYTHON + class NGCORE_API Archive; namespace detail { // create new pointer of type T if it is default constructible, else throw @@ -88,6 +92,10 @@ namespace ngcore // This caster takes a void* pointer to the (base)class type_info and returns void* pointing // to the type stored in this info std::function downcaster; + +#ifdef NETGEN_PYTHON + std::function anyToPyCaster; +#endif // NETGEN_PYTHON }; } // namespace detail @@ -641,6 +649,10 @@ namespace ngcore template friend class RegisterClassForArchive; +#ifdef NETGEN_PYTHON + friend pybind11::object CastAnyToPy(const std::any&); +#endif // NETGEN_PYTHON + // Returns ClassArchiveInfo of Demangled typeid static const detail::ClassArchiveInfo& GetArchiveRegister(const std::string& classname); // Set ClassArchiveInfo for Demangled typeid, this is done by creating an instance of @@ -694,26 +706,6 @@ namespace ngcore }; }; - template - class RegisterClassForArchive - { - public: - RegisterClassForArchive() - { - static_assert(detail::all_of_tmpl::value...>, - "Variadic template arguments must be base classes of T"); - detail::ClassArchiveInfo info {}; - info.creator = [](const std::type_info& ti) -> void* - { return typeid(T) == ti ? detail::constructIfPossible() - : Archive::Caster::tryUpcast(ti, detail::constructIfPossible()); }; - info.upcaster = [/*this*/](const std::type_info& ti, void* p) -> void* - { return typeid(T) == ti ? p : Archive::Caster::tryUpcast(ti, static_cast(p)); }; - info.downcaster = [/*this*/](const std::type_info& ti, void* p) -> void* - { return typeid(T) == ti ? p : Archive::Caster::tryDowncast(ti, p); }; - Archive::SetArchiveRegister(std::string(Demangle(typeid(T).name())),info); - } - }; - // BinaryOutArchive ====================================================================== class NGCORE_API BinaryOutArchive : public Archive { diff --git a/libsrc/core/flags.hpp b/libsrc/core/flags.hpp index cd4b8272..942dd11b 100644 --- a/libsrc/core/flags.hpp +++ b/libsrc/core/flags.hpp @@ -167,6 +167,7 @@ namespace ngcore int GetNStringListFlags () const { return strlistflags.Size(); } /// number of num-list flags int GetNNumListFlags () const { return numlistflags.Size(); } + int GetNAnyFlags() const { return anyflags.Size(); } /// const std::string & GetStringFlag (int i, std::string & name) const @@ -181,6 +182,8 @@ namespace ngcore { name = strlistflags.GetName(i); return strlistflags[i]; } const Flags & GetFlagsFlag (int i, std::string & name) const { name = flaglistflags.GetName(i); return flaglistflags[i]; } + const std::any& GetAnyFlag(int i, std::string& name) const + { name = anyflags.GetName(i); return anyflags[i]; } }; /// Print flags diff --git a/libsrc/core/python_ngcore.cpp b/libsrc/core/python_ngcore.cpp index cb8c94d4..651db906 100644 --- a/libsrc/core/python_ngcore.cpp +++ b/libsrc/core/python_ngcore.cpp @@ -157,6 +157,11 @@ namespace ngcore auto val = flags.GetDefineFlag(i, key); d[key.c_str()] = val; } + for(auto i : Range(flags.GetNAnyFlags())) + { + auto& a = flags.GetAnyFlag(i, key); + d[key.c_str()] = CastAnyToPy(a); + } return d; } diff --git a/libsrc/core/register_archive.hpp b/libsrc/core/register_archive.hpp new file mode 100644 index 00000000..f2a05072 --- /dev/null +++ b/libsrc/core/register_archive.hpp @@ -0,0 +1,42 @@ +#ifndef NETGEN_REGISTER_ARCHIVE_HPP +#define NETGEN_REGISTER_ARCHIVE_HPP + +#ifdef NETGEN_PYTHON +#include +#include +#endif // NETGEN_PYTHON + +#include "archive.hpp" + +namespace ngcore { + + template + class RegisterClassForArchive + { + public: + RegisterClassForArchive() + { + static_assert(detail::all_of_tmpl::value...>, + "Variadic template arguments must be base classes of T"); + detail::ClassArchiveInfo info {}; + info.creator = [](const std::type_info& ti) -> void* + { return typeid(T) == ti ? detail::constructIfPossible() + : Archive::Caster::tryUpcast(ti, detail::constructIfPossible()); }; + info.upcaster = [/*this*/](const std::type_info& ti, void* p) -> void* + { return typeid(T) == ti ? p : Archive::Caster::tryUpcast(ti, static_cast(p)); }; + info.downcaster = [/*this*/](const std::type_info& ti, void* p) -> void* + { return typeid(T) == ti ? p : Archive::Caster::tryDowncast(ti, p); }; +#ifdef NETGEN_PYTHON + info.anyToPyCaster = [](const std::any& a) + { + std::cout << "call anytopycast on " << Demangle(a.type().name()) << std::endl; + const T* val = std::any_cast(&a); + if(!val) + throw Exception("Incorrect type in any object!"); + return pybind11::cast(val); }; +#endif // NETGEN_PYTHON + Archive::SetArchiveRegister(std::string(Demangle(typeid(T).name())),info); + } + }; +} // namespace ngcore +#endif // NETGEN_REGISTER_ARCHIVE_HPP diff --git a/libsrc/csg/algprim.cpp b/libsrc/csg/algprim.cpp index 09d1b497..45a16f9c 100644 --- a/libsrc/csg/algprim.cpp +++ b/libsrc/csg/algprim.cpp @@ -1,4 +1,5 @@ #include +#include #include diff --git a/libsrc/csg/brick.cpp b/libsrc/csg/brick.cpp index 3b3b7df6..0c1c6546 100644 --- a/libsrc/csg/brick.cpp +++ b/libsrc/csg/brick.cpp @@ -1,4 +1,5 @@ #include +#include #include #include diff --git a/libsrc/csg/csgeom.cpp b/libsrc/csg/csgeom.cpp index 59f34ca7..511eb4bf 100644 --- a/libsrc/csg/csgeom.cpp +++ b/libsrc/csg/csgeom.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include diff --git a/libsrc/csg/extrusion.cpp b/libsrc/csg/extrusion.cpp index 82b2e651..8584597a 100644 --- a/libsrc/csg/extrusion.cpp +++ b/libsrc/csg/extrusion.cpp @@ -1,4 +1,5 @@ #include +#include #include #include diff --git a/libsrc/csg/revolution.cpp b/libsrc/csg/revolution.cpp index e284a4f2..cc872cec 100644 --- a/libsrc/csg/revolution.cpp +++ b/libsrc/csg/revolution.cpp @@ -1,4 +1,5 @@ #include +#include #include #include diff --git a/libsrc/csg/splinesurface.cpp b/libsrc/csg/splinesurface.cpp index 25b0dd31..861838c2 100644 --- a/libsrc/csg/splinesurface.cpp +++ b/libsrc/csg/splinesurface.cpp @@ -1,5 +1,6 @@ #include +#include namespace netgen { diff --git a/libsrc/csg/surface.cpp b/libsrc/csg/surface.cpp index 6231897b..e0fcd398 100644 --- a/libsrc/csg/surface.cpp +++ b/libsrc/csg/surface.cpp @@ -1,4 +1,5 @@ #include +#include #include #include diff --git a/libsrc/geom2d/geometry2d.cpp b/libsrc/geom2d/geometry2d.cpp index 864ffe68..ad7143b8 100644 --- a/libsrc/geom2d/geometry2d.cpp +++ b/libsrc/geom2d/geometry2d.cpp @@ -6,6 +6,7 @@ #include #include +#include namespace netgen { diff --git a/libsrc/gprim/spline.cpp b/libsrc/gprim/spline.cpp index 1911c82b..ed11ef96 100644 --- a/libsrc/gprim/spline.cpp +++ b/libsrc/gprim/spline.cpp @@ -9,6 +9,8 @@ Spline curve for Mesh generator #include #include "spline.hpp" +#include + namespace netgen { diff --git a/libsrc/gprim/splinegeometry.cpp b/libsrc/gprim/splinegeometry.cpp index c7002e95..8c1eaf4b 100644 --- a/libsrc/gprim/splinegeometry.cpp +++ b/libsrc/gprim/splinegeometry.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "splinegeometry.hpp" namespace netgen diff --git a/libsrc/meshing/basegeom.cpp b/libsrc/meshing/basegeom.cpp index 56a79bc2..8ae67dc8 100644 --- a/libsrc/meshing/basegeom.cpp +++ b/libsrc/meshing/basegeom.cpp @@ -1,5 +1,6 @@ #include #include "meshing.hpp" +#include namespace netgen { diff --git a/libsrc/occ/occgeom.cpp b/libsrc/occ/occgeom.cpp index db97a543..1ceeddff 100644 --- a/libsrc/occ/occgeom.cpp +++ b/libsrc/occ/occgeom.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include "ShapeAnalysis_ShapeTolerance.hxx" #include "ShapeAnalysis_ShapeContents.hxx" diff --git a/libsrc/stlgeom/stlgeom.cpp b/libsrc/stlgeom/stlgeom.cpp index e65c0090..69991987 100644 --- a/libsrc/stlgeom/stlgeom.cpp +++ b/libsrc/stlgeom/stlgeom.cpp @@ -1,4 +1,5 @@ #include +#include #include "stlgeom.hpp" diff --git a/libsrc/stlgeom/stltopology.cpp b/libsrc/stlgeom/stltopology.cpp index 1341664a..b595e0c4 100644 --- a/libsrc/stlgeom/stltopology.cpp +++ b/libsrc/stlgeom/stltopology.cpp @@ -1,4 +1,5 @@ #include +#include #include #include diff --git a/tests/catch/CMakeLists.txt b/tests/catch/CMakeLists.txt index 12a665df..9f39f012 100644 --- a/tests/catch/CMakeLists.txt +++ b/tests/catch/CMakeLists.txt @@ -3,7 +3,7 @@ if(ENABLE_UNIT_TESTS) add_custom_target(unit_tests) # Build catch_main test object -include_directories(${CATCH_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../../libsrc/include ${SPDLOG_INCLUDE_DIR}) +include_directories(${CATCH_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../../libsrc/include ${SPDLOG_INCLUDE_DIR} ${PYTHON_INCLUDE_DIRS}) add_library(catch_main STATIC main.cpp) set_target_properties(catch_main PROPERTIES CXX_STANDARD 17) add_dependencies(unit_tests catch_main) @@ -14,7 +14,7 @@ add_test(NAME unit_tests_built COMMAND ${CMAKE_COMMAND} --build . --target unit_ macro(add_unit_test name sources) add_executable(test_${name} ${sources} ) - target_link_libraries(test_${name} ngcore catch_main nglib ${PYTHON_LIBRARIES}) + target_link_libraries(test_${name} ngcore catch_main nglib) add_dependencies(unit_tests test_${name}) add_test(NAME unit_${name} COMMAND test_${name}) @@ -26,6 +26,10 @@ macro(add_unit_test name sources) endmacro() add_unit_test(archive archive.cpp) +if(USE_PYTHON) + # RegisterForArchive needs Python.h if built with Python + target_link_libraries(test_archive ${PYTHON_LIBRARIES}) +endif(USE_PYTHON) add_unit_test(array array.cpp) add_unit_test(ranges ranges.cpp) add_unit_test(symboltable symboltable.cpp) diff --git a/tests/catch/archive.cpp b/tests/catch/archive.cpp index ef3c1a5d..8d7a413c 100644 --- a/tests/catch/archive.cpp +++ b/tests/catch/archive.cpp @@ -1,6 +1,7 @@ #include #include <../core/ngcore.hpp> +#include using namespace ngcore; using namespace std;