Add std::any to py::object caster for archive registered types

This commit is contained in:
Christopher Lackner 2021-09-28 22:34:11 +02:00
parent 8760559690
commit bd29763b16
22 changed files with 96 additions and 23 deletions

View File

@ -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)

View File

@ -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<std::map<std::string, detail::ClassArchiveInfo>>();
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

View File

@ -1,6 +1,7 @@
#ifndef NETGEN_CORE_ARCHIVE_HPP
#define NETGEN_CORE_ARCHIVE_HPP
#include <any>
#include <array> // for array
#include <complex> // for complex
#include <cstring> // 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<void*(const std::type_info&, void*)> downcaster;
#ifdef NETGEN_PYTHON
std::function<pybind11::object(const std::any&)> anyToPyCaster;
#endif // NETGEN_PYTHON
};
} // namespace detail
@ -641,6 +649,10 @@ namespace ngcore
template<typename T, typename ... Bases>
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<typename T, typename ... Bases>
class RegisterClassForArchive
{
public:
RegisterClassForArchive()
{
static_assert(detail::all_of_tmpl<std::is_base_of<Bases,T>::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<T>()
: Archive::Caster<T, Bases...>::tryUpcast(ti, detail::constructIfPossible<T>()); };
info.upcaster = [/*this*/](const std::type_info& ti, void* p) -> void*
{ return typeid(T) == ti ? p : Archive::Caster<T, Bases...>::tryUpcast(ti, static_cast<T*>(p)); };
info.downcaster = [/*this*/](const std::type_info& ti, void* p) -> void*
{ return typeid(T) == ti ? p : Archive::Caster<T, Bases...>::tryDowncast(ti, p); };
Archive::SetArchiveRegister(std::string(Demangle(typeid(T).name())),info);
}
};
// BinaryOutArchive ======================================================================
class NGCORE_API BinaryOutArchive : public Archive
{

View File

@ -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

View File

@ -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;
}

View File

@ -0,0 +1,42 @@
#ifndef NETGEN_REGISTER_ARCHIVE_HPP
#define NETGEN_REGISTER_ARCHIVE_HPP
#ifdef NETGEN_PYTHON
#include <pybind11/pybind11.h>
#include <pybind11/cast.h>
#endif // NETGEN_PYTHON
#include "archive.hpp"
namespace ngcore {
template<typename T, typename ... Bases>
class RegisterClassForArchive
{
public:
RegisterClassForArchive()
{
static_assert(detail::all_of_tmpl<std::is_base_of<Bases,T>::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<T>()
: Archive::Caster<T, Bases...>::tryUpcast(ti, detail::constructIfPossible<T>()); };
info.upcaster = [/*this*/](const std::type_info& ti, void* p) -> void*
{ return typeid(T) == ti ? p : Archive::Caster<T, Bases...>::tryUpcast(ti, static_cast<T*>(p)); };
info.downcaster = [/*this*/](const std::type_info& ti, void* p) -> void*
{ return typeid(T) == ti ? p : Archive::Caster<T, Bases...>::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<T>(&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

View File

@ -1,4 +1,5 @@
#include <mystdlib.h>
#include <core/register_archive.hpp>
#include <linalg.hpp>

View File

@ -1,4 +1,5 @@
#include <mystdlib.h>
#include <core/register_archive.hpp>
#include <linalg.hpp>
#include <csg.hpp>

View File

@ -1,5 +1,6 @@
#include <mystdlib.h>
#include <myadt.hpp>
#include <core/register_archive.hpp>
#include <linalg.hpp>
#include <csg.hpp>

View File

@ -1,4 +1,5 @@
#include <mystdlib.h>
#include <core/register_archive.hpp>
#include <linalg.hpp>
#include <csg.hpp>

View File

@ -1,4 +1,5 @@
#include <mystdlib.h>
#include <core/register_archive.hpp>
#include <linalg.hpp>
#include <csg.hpp>

View File

@ -1,5 +1,6 @@
#include <csg.hpp>
#include <core/register_archive.hpp>
namespace netgen
{

View File

@ -1,4 +1,5 @@
#include <mystdlib.h>
#include <core/register_archive.hpp>
#include <myadt.hpp>
#include <csg.hpp>

View File

@ -6,6 +6,7 @@
#include <meshing.hpp>
#include <geometry2d.hpp>
#include <core/register_archive.hpp>
namespace netgen
{

View File

@ -9,6 +9,8 @@ Spline curve for Mesh generator
#include <gprim.hpp>
#include "spline.hpp"
#include <core/register_archive.hpp>
namespace netgen
{

View File

@ -8,6 +8,7 @@
#include <mystdlib.h>
#include <linalg.hpp>
#include <gprim.hpp>
#include <core/register_archive.hpp>
#include "splinegeometry.hpp"
namespace netgen

View File

@ -1,5 +1,6 @@
#include <mystdlib.h>
#include "meshing.hpp"
#include <core/register_archive.hpp>
namespace netgen
{

View File

@ -3,6 +3,7 @@
#include <mystdlib.h>
#include <occgeom.hpp>
#include <core/register_archive.hpp>
#include <cstdio>
#include "ShapeAnalysis_ShapeTolerance.hxx"
#include "ShapeAnalysis_ShapeContents.hxx"

View File

@ -1,4 +1,5 @@
#include <meshing.hpp>
#include <core/register_archive.hpp>
#include "stlgeom.hpp"

View File

@ -1,4 +1,5 @@
#include <mystdlib.h>
#include <core/register_archive.hpp>
#include <myadt.hpp>
#include <linalg.hpp>

View File

@ -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)

View File

@ -1,6 +1,7 @@
#include <catch2/catch.hpp>
#include <../core/ngcore.hpp>
#include <core/register_archive.hpp>
using namespace ngcore;
using namespace std;