Skip to content

Commit

Permalink
Merge pull request #4732 from syershov/pytraffic
Browse files Browse the repository at this point in the history
Python bindings for traffic
  • Loading branch information
ygorshenin authored Nov 16, 2016
2 parents 549c82c + c084036 commit 878a4f1
Show file tree
Hide file tree
Showing 9 changed files with 533 additions and 59 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,5 @@ add_subdirectory(editor)
add_subdirectory(indexer)
add_subdirectory(routing)
add_subdirectory(search)
add_subdirectory(traffic)
add_subdirectory(tracking)
29 changes: 29 additions & 0 deletions pyhelpers/pair.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once

#include "std/utility.hpp"

#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>

namespace
{
using namespace boost::python;

// Converts a std::pair instance to a Python tuple.
template <typename T1, typename T2>
struct pair_to_tuple
{
static PyObject * convert(pair<T1, T2> const & p)
{
return incref(make_tuple(p.first, p.second).ptr());
}

static PyTypeObject const * get_pytype() { return &PyTuple_Type; }
};

template <typename T1, typename T2>
struct pair_to_python_converter
{
pair_to_python_converter() { to_python_converter<pair<T1, T2>, pair_to_tuple<T1, T2>, true>(); }
};
} // namespace
47 changes: 47 additions & 0 deletions pyhelpers/vector_uint8.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#pragma once

#include "std/vector.hpp"

#include <boost/python.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp>

namespace
{
using namespace boost::python;

// Converts a vector<uint8_t> to/from Python str.
struct vector_uint8t_to_str
{
static PyObject * convert(vector<uint8_t> const & v)
{
str s(reinterpret_cast<char const *>(v.data()), v.size());
return incref(s.ptr());
}
};

struct vector_uint8t_from_python_str
{
vector_uint8t_from_python_str()
{
converter::registry::push_back(&convertible, &construct, type_id<vector<uint8_t>>());
}

static void * convertible(PyObject * obj_ptr)
{
if (!PyString_Check(obj_ptr))
return nullptr;
return obj_ptr;
}

static void construct(PyObject * obj_ptr, converter::rvalue_from_python_stage1_data * data)
{
const char * value = PyString_AsString(obj_ptr);
if (value == nullptr)
throw_error_already_set();
void * storage =
((converter::rvalue_from_python_storage<vector<uint8_t>> *)data)->storage.bytes;
new (storage) vector<uint8_t>(value, value + PyString_Size(obj_ptr));
data->convertible = storage;
}
};
} // namespace
61 changes: 3 additions & 58 deletions tracking/pytracking/bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,67 +2,12 @@

#include "coding/traffic.hpp"

#include "pyhelpers/pair.hpp"
#include "pyhelpers/vector_uint8.hpp"

#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>

namespace
{
using namespace boost::python;

// Converts a std::pair instance to a Python tuple.
template <typename T1, typename T2>
struct pair_to_tuple
{
static PyObject * convert(pair<T1, T2> const & p)
{
return incref(make_tuple(p.first, p.second).ptr());
}

static PyTypeObject const * get_pytype() { return &PyTuple_Type; }
};

template <typename T1, typename T2>
struct pair_to_python_converter
{
pair_to_python_converter() { to_python_converter<pair<T1, T2>, pair_to_tuple<T1, T2>, true>(); }
};

// Converts a vector<uint8_t> to/from Python str.
struct vector_uint8t_to_str
{
static PyObject * convert(vector<uint8_t> const & v)
{
str s(reinterpret_cast<char const *>(v.data()), v.size());
return incref(s.ptr());
}
};

struct vector_uint8t_from_python_str
{
vector_uint8t_from_python_str()
{
converter::registry::push_back(&convertible, &construct, type_id<vector<uint8_t>>());
}

static void * convertible(PyObject * obj_ptr)
{
if (!PyString_Check(obj_ptr))
return nullptr;
return obj_ptr;
}

static void construct(PyObject * obj_ptr, converter::rvalue_from_python_stage1_data * data)
{
const char * value = PyString_AsString(obj_ptr);
if (value == nullptr)
throw_error_already_set();
void * storage =
((converter::rvalue_from_python_storage<vector<uint8_t>> *)data)->storage.bytes;
new (storage) vector<uint8_t>(value, value + PyString_Size(obj_ptr));
data->convertible = storage;
}
};
} // namespace

BOOST_PYTHON_MODULE(pytracking)
{
Expand Down
3 changes: 2 additions & 1 deletion traffic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ set(

add_library(${PROJECT_NAME} ${SRC})

add_subdirectory(traffic_tests)
add_subdirectory(pytraffic)
#add_subdirectory(traffic_tests)
48 changes: 48 additions & 0 deletions traffic/pytraffic/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
project(pytraffic)

check_pybindings()

set(
SRC
bindings.cpp
)

# Suppress boost-python warnings
add_compile_options(
"-Wno-unused-local-typedef"
)

set(Boost_USE_MULTITHREADED ON)

# For macOS we can use static linking, on Linux we can't.
if (PLATFORM_MAC)
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_STATIC_RUNTIME ON)
endif()

find_package(PythonLibs 2.7 REQUIRED)
find_package(Boost 1.54 REQUIRED COMPONENTS python)
include_directories(${PYTHON_INCLUDE_DIRS})

add_library(${PROJECT_NAME} MODULE ${SRC})

if (PLATFORM_MAC)
omim_link_libraries(
${PROJECT_NAME}
${Qt5Widgets_LIBRARIES}
"-framework Cocoa"
"-framework IOKit"
"-framework QuartzCore"
"-framework SystemConfiguration"
)
endif()

if (PLATFORM_WIN OR PLATFORM_LINUX)
omim_link_libraries(
${PROJECT_NAME}
${Qt5Widgets_LIBRARIES}
)
endif()

omim_link_libraries(${PROJECT_NAME} ${PYTHON_LIBRARIES} ${Boost_LIBRARIES} traffic platform geometry base)
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
64 changes: 64 additions & 0 deletions traffic/pytraffic/bindings.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "traffic/traffic_info.hpp"
#include "traffic/speed_groups.hpp"

#include "pyhelpers/vector_uint8.hpp"

#include <boost/python.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp>

namespace
{
using namespace boost::python;

vector<uint8_t> Serialize(traffic::TrafficInfo::Coloring const & coloring)
{
vector<uint8_t> data;
traffic::TrafficInfo::SerializeTrafficData(coloring, data);
return data;
}

traffic::TrafficInfo::Coloring Deserialize(vector<uint8_t> const & data)
{
traffic::TrafficInfo::Coloring coloring;
traffic::TrafficInfo::DeserializeTrafficData(data, coloring);
return coloring;
}

string RoadSegmentIdRepr(traffic::TrafficInfo::RoadSegmentId const & v)
{
stringstream ss;
ss << "RoadSegmentId(" << v.m_fid << ", " << v.m_idx << ", " << int(v.m_dir) << ")";
return ss.str();
}
} // namespace

BOOST_PYTHON_MODULE(pytraffic)
{
using namespace boost::python;

// Register the to-python converters.
to_python_converter<vector<uint8_t>, vector_uint8t_to_str>();
vector_uint8t_from_python_str();

class_<traffic::TrafficInfo::RoadSegmentId>("RoadSegmentId", init<uint32_t, uint16_t, uint8_t>())
.def("__repr__", &RoadSegmentIdRepr)
;

enum_<traffic::SpeedGroup>("SpeedGroup")
.value("G0", traffic::SpeedGroup::G0)
.value("G1", traffic::SpeedGroup::G1)
.value("G2", traffic::SpeedGroup::G2)
.value("G3", traffic::SpeedGroup::G3)
.value("G4", traffic::SpeedGroup::G4)
.value("G5", traffic::SpeedGroup::G5)
.value("TempBlock", traffic::SpeedGroup::TempBlock)
.value("Unknown", traffic::SpeedGroup::Unknown)
;

class_<traffic::TrafficInfo::Coloring>("Coloring")
.def(map_indexing_suite<traffic::TrafficInfo::Coloring>())
;

def("dumps", Serialize);
def("loads", Deserialize);
}
13 changes: 13 additions & 0 deletions xcode/omim.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 878a4f1

Please sign in to comment.