Merge branch 'std_any_to_py_object' into 'master'

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

See merge request jschoeberl/netgen!426
This commit is contained in:
Matthias Hochsteger 2021-09-29 10:22:17 +00:00
commit 50ef307622
22 changed files with 90 additions and 22 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 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 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 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) DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel)
if(ENABLE_CPP_CORE_GUIDELINES_CHECK) if(ENABLE_CPP_CORE_GUIDELINES_CHECK)

View File

@ -1,5 +1,6 @@
#include "archive.hpp" #include "archive.hpp"
#include "register_archive.hpp"
#include "version.hpp" #include "version.hpp"
#ifndef WIN32 #ifndef WIN32
@ -28,4 +29,13 @@ namespace ngcore
std::make_unique<std::map<std::string, detail::ClassArchiveInfo>>(); std::make_unique<std::map<std::string, detail::ClassArchiveInfo>>();
return type_register->count(classname) != 0; 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 } // namespace ngcore

View File

@ -1,6 +1,7 @@
#ifndef NETGEN_CORE_ARCHIVE_HPP #ifndef NETGEN_CORE_ARCHIVE_HPP
#define NETGEN_CORE_ARCHIVE_HPP #define NETGEN_CORE_ARCHIVE_HPP
#include <any>
#include <array> // for array #include <array> // for array
#include <complex> // for complex #include <complex> // for complex
#include <cstring> // for size_t, strlen #include <cstring> // for size_t, strlen
@ -32,8 +33,11 @@ namespace pybind11
namespace ngcore 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 namespace detail
{ {
// create new pointer of type T if it is default constructible, else throw // 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 // This caster takes a void* pointer to the (base)class type_info and returns void* pointing
// to the type stored in this info // to the type stored in this info
std::function<void*(const std::type_info&, void*)> downcaster; 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 } // namespace detail
@ -641,6 +649,10 @@ namespace ngcore
template<typename T, typename ... Bases> template<typename T, typename ... Bases>
friend class RegisterClassForArchive; friend class RegisterClassForArchive;
#ifdef NETGEN_PYTHON
friend pybind11::object CastAnyToPy(const std::any&);
#endif // NETGEN_PYTHON
// Returns ClassArchiveInfo of Demangled typeid // Returns ClassArchiveInfo of Demangled typeid
static const detail::ClassArchiveInfo& GetArchiveRegister(const std::string& classname); static const detail::ClassArchiveInfo& GetArchiveRegister(const std::string& classname);
// Set ClassArchiveInfo for Demangled typeid, this is done by creating an instance of // 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 ====================================================================== // BinaryOutArchive ======================================================================
class NGCORE_API BinaryOutArchive : public Archive class NGCORE_API BinaryOutArchive : public Archive
{ {

View File

@ -167,6 +167,7 @@ namespace ngcore
int GetNStringListFlags () const { return strlistflags.Size(); } int GetNStringListFlags () const { return strlistflags.Size(); }
/// number of num-list flags /// number of num-list flags
int GetNNumListFlags () const { return numlistflags.Size(); } int GetNNumListFlags () const { return numlistflags.Size(); }
int GetNAnyFlags() const { return anyflags.Size(); }
/// ///
const std::string & GetStringFlag (int i, std::string & name) const const std::string & GetStringFlag (int i, std::string & name) const
@ -181,6 +182,8 @@ namespace ngcore
{ name = strlistflags.GetName(i); return strlistflags[i]; } { name = strlistflags.GetName(i); return strlistflags[i]; }
const Flags & GetFlagsFlag (int i, std::string & name) const const Flags & GetFlagsFlag (int i, std::string & name) const
{ name = flaglistflags.GetName(i); return flaglistflags[i]; } { 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 /// Print flags

View File

@ -157,6 +157,11 @@ namespace ngcore
auto val = flags.GetDefineFlag(i, key); auto val = flags.GetDefineFlag(i, key);
d[key.c_str()] = val; 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; return d;
} }

View File

@ -0,0 +1,39 @@
#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)
{
const T* val = std::any_cast<T>(&a);
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 <mystdlib.h>
#include <core/register_archive.hpp>
#include <linalg.hpp> #include <linalg.hpp>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -14,7 +14,7 @@ add_test(NAME unit_tests_built COMMAND ${CMAKE_COMMAND} --build . --target unit_
macro(add_unit_test name sources) macro(add_unit_test name sources)
add_executable(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_dependencies(unit_tests test_${name})
add_test(NAME unit_${name} COMMAND test_${name}) add_test(NAME unit_${name} COMMAND test_${name})
@ -26,6 +26,8 @@ macro(add_unit_test name sources)
endmacro() endmacro()
add_unit_test(archive archive.cpp) add_unit_test(archive archive.cpp)
# RegisterForArchive needs Python.h if built with Python
target_link_libraries(test_archive netgen_python)
add_unit_test(array array.cpp) add_unit_test(array array.cpp)
add_unit_test(ranges ranges.cpp) add_unit_test(ranges ranges.cpp)
add_unit_test(symboltable symboltable.cpp) add_unit_test(symboltable symboltable.cpp)

View File

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