Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Python] manually exposing std vector #148

Merged
merged 4 commits into from
Feb 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 9 additions & 10 deletions co_sim_io/python/co_sim_io_python.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
#include <pybind11/pybind11.h>
#include <pybind11/functional.h>
#include <pybind11/numpy.h>
#include <pybind11/stl.h>

// CoSimIO includes
#include "../co_sim_io.hpp"
Expand All @@ -45,15 +44,15 @@ PYBIND11_MODULE(CoSimIO, m)
m.def("ImportMesh", &CoSimIO::ImportMesh);
m.def("ExportMesh", &CoSimIO::ExportMesh);

m.def("ImportData", [](const CoSimIO::Info& I_Info, std::vector<double>& rValues){
m.def("ImportData", [](const CoSimIO::Info& I_Info, CoSimIO::VectorWrapper<double>& rValues){
return CoSimIO::ImportData(
I_Info,
rValues);
rValues.Vector());
});
m.def("ExportData", [](const CoSimIO::Info& I_Info, const std::vector<double>& rValues){
m.def("ExportData", [](const CoSimIO::Info& I_Info, const CoSimIO::VectorWrapper<double>& rValues){
return CoSimIO::ExportData(
I_Info,
rValues);
rValues.Vector());
});

m.def("ImportInfo", &CoSimIO::ImportInfo);
Expand All @@ -67,9 +66,9 @@ PYBIND11_MODULE(CoSimIO, m)
std::function<CoSimIO::Info(const CoSimIO::Info&)> FunctionPointer)
{ return CoSimIO::Register(I_Info, FunctionPointer); } );

AddCoSimIOInfoToPython(m);
AddCoSimIOModelPartToPython(m);
AddCoSimIOVectorToPython(m);
AddCoSimIOConnectionStatusToPython(m);
AddCoSimIOVersionToPython(m);
CoSimIO::AddCoSimIOInfoToPython(m);
CoSimIO::AddCoSimIOModelPartToPython(m);
CoSimIO::AddCoSimIOVectorToPython(m);
CoSimIO::AddCoSimIOConnectionStatusToPython(m);
CoSimIO::AddCoSimIOVersionToPython(m);
}
4 changes: 4 additions & 0 deletions co_sim_io/python/connection_status_to_python.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
// CoSimIO include
#include "../co_sim_io.hpp"

namespace CoSimIO {

void AddCoSimIOConnectionStatusToPython(pybind11::module& m)
{
namespace py = pybind11;
Expand All @@ -36,4 +38,6 @@ void AddCoSimIOConnectionStatusToPython(pybind11::module& m)
;
}

} // namespace CoSimIO

#endif // CO_SIM_IO_CONNECTION_STATUS_TO_PYHON_INCLUDED
4 changes: 4 additions & 0 deletions co_sim_io/python/info_to_python.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ void AddGetSetInterface(pybind11::class_<CoSimIO::Info>& PythonInfo, const std::

}

namespace CoSimIO {

void AddCoSimIOInfoToPython(pybind11::module& m)
{
namespace py = pybind11;
Expand All @@ -59,4 +61,6 @@ void AddCoSimIOInfoToPython(pybind11::module& m)
AddGetSetInterface<std::string>(py_info, "String");
}

} // namespace CoSimIO

#endif // CO_SIM_IO_INFO_TO_PYHON_INCLUDED
4 changes: 4 additions & 0 deletions co_sim_io/python/model_part_to_python.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
// CoSimIO include
#include "../impl/model_part.hpp"

namespace CoSimIO {

void AddCoSimIOModelPartToPython(pybind11::module& m)
{
namespace py = pybind11;
Expand Down Expand Up @@ -102,4 +104,6 @@ void AddCoSimIOModelPartToPython(pybind11::module& m)
;
}

} // namespace CoSimIO

#endif // CO_SIM_IO_MODEL_PART_TO_PYHON_INCLUDED
62 changes: 44 additions & 18 deletions co_sim_io/python/vector_to_python.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,40 @@
//
#include "../impl/define.hpp"

// has to be done outside of any namespace!
PYBIND11_MAKE_OPAQUE(std::vector<int>)
PYBIND11_MAKE_OPAQUE(std::vector<double>)
namespace CoSimIO {

namespace {
// small wrapper around std::vector for using it in Python
// Note: deliberately not using PYBIND11_MAKE_OPAQUE as this
// can be problematic if integrated in other libraries
template<typename TDataType>
class VectorWrapper
{
public:
VectorWrapper() = default;
VectorWrapper(const std::size_t I_Size) { mVector.resize(I_Size); }
VectorWrapper(const std::vector<TDataType>& I_Vector)
: mVector(I_Vector) {};

VectorWrapper(const VectorWrapper& Other) : mVector(Other.mVector) {}
VectorWrapper& operator=(const VectorWrapper&) = delete;

std::vector<TDataType>& Vector() {return mVector;}
const std::vector<TDataType>& Vector() const {return mVector;}

private:
std::vector<TDataType> mVector;
};

} // namespace CoSimIO

namespace { // anonymous namespace

template<typename TDataType>
void AddVectorWithTypeToPython(pybind11::module& m, const std::string& Name)
{
namespace py = pybind11;

using VectorType = std::vector<TDataType>;
using VectorType = CoSimIO::VectorWrapper<TDataType>;

const std::string full_name = Name+"Vector";

Expand All @@ -47,7 +69,7 @@ void AddVectorWithTypeToPython(pybind11::module& m, const std::string& Name)
.def(py::init( [](const py::list& l){
VectorType vec(l.size());
for(std::size_t i=0; i<l.size(); ++i) {
vec[i] = py::cast<TDataType>(l[i]);
vec.Vector()[i] = py::cast<TDataType>(l[i]);
}
return vec;
}))
Expand All @@ -57,49 +79,53 @@ void AddVectorWithTypeToPython(pybind11::module& m, const std::string& Name)
CO_SIM_IO_ERROR_IF(info.ndim != 1) << "Buffer dimension of 1 is required, got: " << info.ndim << std::endl;
VectorType vec(info.shape[0]);
for (int i=0; i<info.shape[0]; ++i) {
vec[i] = static_cast<TDataType *>(info.ptr)[i];
vec.Vector()[i] = static_cast<TDataType *>(info.ptr)[i];
}
return vec;
}))

.def("__len__", [](VectorType& v)
{ return v.size(); } )
{ return v.Vector().size(); } )
.def("size", [](VectorType& v)
{ return v.size(); } )
{ return v.Vector().size(); } )
.def("resize", [](VectorType& v, const std::size_t& size)
{ v.resize(size); } )
{ v.Vector().resize(size); } )
.def("append", [](VectorType& v, const TDataType& val)
{ v.push_back(val); } )
{ v.Vector().push_back(val); } )
.def("__setitem__", [](VectorType& v, const std::size_t I_Index, const TDataType& val)
{ v[I_Index] = val; } )
{ v.Vector()[I_Index] = val; } )
.def("__getitem__", [](VectorType& v, const std::size_t I_Index)
{ return v[I_Index]; } )
{ return v.Vector()[I_Index]; } )
.def("__iter__", [](VectorType& v)
{return py::make_iterator(v.begin(), v.end());}, py::keep_alive<0,1>())
{return py::make_iterator(v.Vector().begin(), v.Vector().end());}, py::keep_alive<0,1>())

.def("__str__", [](const VectorType& v)
{
std::stringstream ss;
const std::size_t size = v.size();
const std::size_t size = v.Vector().size();

ss << "[";
if(size>0) ss << v[0];
if(size>0) ss << v.Vector()[0];
if(size>1) {
for(std::size_t i=1; i<size; ++i)
ss<<", "<<v[i];
ss<<", "<<v.Vector()[i];
}
ss << "]";

return ss.str(); } )
;
}

}
} // anonymous namespace

namespace CoSimIO {

void AddCoSimIOVectorToPython(pybind11::module& m)
{
AddVectorWithTypeToPython<int>(m, "Int");
AddVectorWithTypeToPython<double>(m, "Double");
}

} // namespace CoSimIO

#endif // CO_SIM_IO_VECTOR_TO_PYHON_INCLUDED
4 changes: 4 additions & 0 deletions co_sim_io/python/version_to_python.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
// CoSimIO include
#include "../co_sim_io.hpp"

namespace CoSimIO {

void AddCoSimIOVersionToPython(pybind11::module& m)
{
namespace py = pybind11;
Expand All @@ -36,4 +38,6 @@ void AddCoSimIOVersionToPython(pybind11::module& m)
m.attr("__version__") = version_stream.str();
}

} // namespace CoSimIO

#endif // CO_SIM_IO_VERSION_TO_PYHON_INCLUDED