Skip to content

Commit

Permalink
Ability to generate complex structs containing internal structs
Browse files Browse the repository at this point in the history
  • Loading branch information
dubzzz committed Oct 10, 2015
1 parent 7ec8982 commit 98ac35a
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 9 deletions.
26 changes: 21 additions & 5 deletions src/py2cpp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,22 @@ template<class U, class K, class T> struct CppBuilder<std::map<U,std::map<K,T>>>
* Objects builders
*/

template <class T> struct ToBuildable : T {};
template <> struct ToBuildable<bool> : CppBuilder<bool> {};
template <> struct ToBuildable<int> : CppBuilder<int> {};
template <> struct ToBuildable<unsigned int> : CppBuilder<unsigned int> {};
template <> struct ToBuildable<long> : CppBuilder<long> {};
template <> struct ToBuildable<unsigned long> : CppBuilder<unsigned long> {};
template <> struct ToBuildable<long long> : CppBuilder<long long> {};
template <> struct ToBuildable<unsigned long long> : CppBuilder<unsigned long long> {};
template <> struct ToBuildable<double> : CppBuilder<double> {};
template <> struct ToBuildable<std::string> : CppBuilder<std::string> {};
template <> struct ToBuildable<std::wstring> : CppBuilder<std::wstring> {};
template <class... Args> struct ToBuildable<std::tuple<Args...>> : CppBuilder<std::tuple<Args...>> {};
template <class T> struct ToBuildable<std::vector<T>> : CppBuilder<std::vector<T>> {};
template <class T> struct ToBuildable<std::set<T>> : CppBuilder<std::set<T>> {};
template <class K, class T> struct ToBuildable<std::map<K,T>> : CppBuilder<std::map<K,T>> {};

template <class OBJ, class T>
inline std::pair<std::string, std::function<void(OBJ&,T)>> make_mapping(const std::string &key, std::function<void(OBJ&,T)> fun)
{
Expand Down Expand Up @@ -639,13 +655,13 @@ template <class OBJ, class... Args>
struct CppBuilder<FromTuple<OBJ, Args...>>
{
typedef OBJ value_type;
const CppBuilderHelper<OBJ, 0, CppBuilder<Args>...> subBuilder;
const CppBuilderHelper<OBJ, 0, ToBuildable<Args>...> subBuilder;

CppBuilder(std::function<void(OBJ&, Args)>... args)
CppBuilder(std::function<void(OBJ&, typename ToBuildable<Args>::value_type)>... args)
: subBuilder(args...)
{}

CppBuilder(Args OBJ::*... args)
CppBuilder(typename ToBuildable<Args>::value_type OBJ::*... args)
: subBuilder(args...)
{}

Expand Down Expand Up @@ -678,9 +694,9 @@ template <class OBJ, class... Args>
struct CppBuilder<FromDict<OBJ, Args...>>
{
typedef OBJ value_type;
CppBuilderHelper<OBJ, 0, CppBuilder<Args>...> subBuilder;
CppBuilderHelper<OBJ, 0, ToBuildable<Args>...> subBuilder;

CppBuilder(std::pair<std::string, std::function<void(OBJ&, Args)>>... args)
CppBuilder(std::pair<std::string, std::function<void(OBJ&, typename ToBuildable<Args>::value_type)>>... args)
: subBuilder(args...)
{}

Expand Down
68 changes: 64 additions & 4 deletions test/test-py2cpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,43 @@ namespace
, make_mapping("z", &Point::z)) {}
};
};
class Line
{
Point pt1, pt2;
bool oriented;

public:
Line() : pt1(), pt2(), oriented(false) {}
Line(const Point &pt1, const Point &pt2, bool oriented) : pt1(pt1), pt2(pt2), oriented(oriented) {}
Line(const Line&) = default;
bool operator==(const Line& l) const {return pt1 == l.pt1 && pt2 == l.pt2 && oriented == l.oriented;}

struct FromPy : CppBuilder<FromDict<Line, Point::FromPy, Point::FromPy, bool>>
{
FromPy() : CppBuilder<FromDict<Line, Point::FromPy, Point::FromPy, bool>>(
make_mapping("pt1", &Line::pt1)
, make_mapping("pt2", &Line::pt2)
, make_mapping("oriented", &Line::oriented)) {}
};
};
class Path
{
std::vector<Point> path;
unsigned int length;

public:
Path() : path(), length(0) {}
Path(const std::vector<Point> &path, unsigned int length) : path(path), length(length) {}
Path(const Path&) = default;
bool operator==(const Path& p) const {return path == p.path && length == p.length;}

struct FromPy : CppBuilder<FromDict<Path, std::vector<Point::FromPy>, unsigned int>>
{
FromPy() : CppBuilder<FromDict<Path, std::vector<Point::FromPy>, unsigned int>>(
make_mapping("path", &Path::path)
, make_mapping("length", &Path::length)) {}
};
};
}

TEST(CppBuilder_struct, FromTuple)
Expand Down Expand Up @@ -605,7 +642,7 @@ TEST(CppBuilder_struct, FromObject)
EXPECT_FALSE(uncaught_exception());
}

TEST(CppBuilder_struct, VectorOf)
TEST(CppBuilder_struct, VectorOfStructs)
{
std::unique_ptr<PyObject, decref> pyo { PyRun_String("[(1, 3, 4), (1, 5, 5), (0, -1, 0)]", Py_eval_input, py_dict, NULL) };
Point pts[] = { { 1, 3, 4 }, { 1, 5, 5 }, { 0, -1, 0 } };
Expand All @@ -619,7 +656,7 @@ TEST(CppBuilder_struct, VectorOf)
EXPECT_FALSE(uncaught_exception());
}

TEST(CppBuilder_struct, SetOf)
TEST(CppBuilder_struct, SetOfStructs)
{
std::unique_ptr<PyObject, decref> pyo { PyRun_String("set([(1, 3, 4), (1, 5, 5), (0, -1, 0)])", Py_eval_input, py_dict, NULL) };
Point pts[] = { { 1, 3, 4 }, { 1, 5, 5 }, { 0, -1, 0 } };
Expand All @@ -633,7 +670,7 @@ TEST(CppBuilder_struct, SetOf)
EXPECT_FALSE(uncaught_exception());
}

TEST(CppBuilder_struct, MapOf)
TEST(CppBuilder_struct, MapOfIntStructs)
{
std::unique_ptr<PyObject, decref> pyo { PyRun_String("{'x': (1, 0, 4), 'y': (0, 5, 9)}", Py_eval_input, py_dict, NULL) };
Point pts[] = { { 1, 0, 4 }, { 0, 5, 9 } };
Expand All @@ -648,7 +685,7 @@ TEST(CppBuilder_struct, MapOf)
EXPECT_FALSE(uncaught_exception());
}

TEST(CppBuilder_struct, MapOfKeysAndValues)
TEST(CppBuilder_struct, MapOfKeysStructAndValuesStruct)
{
std::unique_ptr<PyObject, decref> pyo { PyRun_String("{(0, 0, 0): (1, 0, 4), (1, 1, 2): (0, 5, 9)}", Py_eval_input, py_dict, NULL) };
Point keys[] = { { 0, 0, 0 }, { 1, 1, 2 } };
Expand All @@ -664,6 +701,29 @@ TEST(CppBuilder_struct, MapOfKeysAndValues)
EXPECT_FALSE(uncaught_exception());
}

TEST(CppBuilder_struct, StructOfStructs)
{
std::unique_ptr<PyObject, decref> pyo { PyRun_String("{'oriented': True, 'pt1': (0, 0, 0), 'pt2': (1, 0, 4)}", Py_eval_input, py_dict, NULL) };
Point pt1 { 0, 0, 0 };
Point pt2 { 1, 0, 4 };
Line line { pt1, pt2, true };

ASSERT_NE(nullptr, pyo.get());
EXPECT_EQ(line, Line::FromPy()(pyo.get()));
EXPECT_FALSE(uncaught_exception());
}

TEST(CppBuilder_struct, StructOfComplexStructs)
{
std::unique_ptr<PyObject, decref> pyo { PyRun_String("{'length': 56, 'path': [(0, 0, 0), (1, 0, 4), (1, 1, 2), (0, 5, 9)]}", Py_eval_input, py_dict, NULL) };
std::vector<Point> pts = { { 0, 0, 0 }, { 1, 0, 4 }, { 1, 1, 2 }, { 0, 5, 9 } };
Path path { pts, 56 };

ASSERT_NE(nullptr, pyo.get());
EXPECT_EQ(path, Path::FromPy()(pyo.get()));
EXPECT_FALSE(uncaught_exception());
}

/** MISC **/

TEST(CppBuilder_mix, AnyValue)
Expand Down

0 comments on commit 98ac35a

Please sign in to comment.