From 692ddc71b17196487dcad982836e074cab9a0f25 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Mon, 4 Feb 2019 16:00:16 +0100 Subject: python: Replace Boost.Python with PyBind11 This does not change the Python API itself, but it is still a significant change. Most importantly, it removes the dependency on Boost.Python. --- host/python/pyuhd.cpp | 179 +++++++------------------------------------------- 1 file changed, 24 insertions(+), 155 deletions(-) (limited to 'host/python/pyuhd.cpp') diff --git a/host/python/pyuhd.cpp b/host/python/pyuhd.cpp index e0f35d929..16badbe8c 100644 --- a/host/python/pyuhd.cpp +++ b/host/python/pyuhd.cpp @@ -1,29 +1,21 @@ // // Copyright 2017-2018 Ettus Research, a National Instruments Company +// Copyright 2019 Ettus Research, a National Instruments Brand // // SPDX-License-Identifier: GPL-3.0-or-later // -#include -#include -#include -#include - -/* -This solution was adapted from an Issue posted to the Boost.Python Github. -https://github.com/boostorg/python/pull/159/files -*/ -#if (BOOST_VERSION >= 106400) && (BOOST_VERSION < 106600) -#warning overriding broken boost python implementation of BOOST_PYTHON_MODULE_INIT -# define BOOST_PYTHON_MODULE_INIT(name) \ - void BOOST_PP_CAT(init_module_,name)(); \ -extern "C" BOOST_SYMBOL_EXPORT _BOOST_PYTHON_MODULE_INIT(name) -#endif +#include #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION #include -namespace bp = boost::python; +namespace py = pybind11; + +// Allow boost::shared_ptr to be a holder class of an object (PyBind11 +// supports std::shared_ptr and std::unique_ptr out of the box) +#include +PYBIND11_DECLARE_HOLDER_TYPE(T, boost::shared_ptr); #include "stream_python.hpp" @@ -40,81 +32,6 @@ namespace bp = boost::python; #include "usrp/subdev_spec_python.hpp" #include "usrp/multi_usrp_python.hpp" -// Converter for std::vector / std::list arguments from python iterables -struct iterable_converter -{ - template - iterable_converter& from_python() - { - bp::converter::registry::push_back( - &iterable_converter::convertible, - &iterable_converter::construct, - bp::type_id() - ); - return *this; - } - - static void* convertible(PyObject* object) - { - return PyObject_GetIter(object) ? object : NULL; - } - - template - static void construct( - PyObject* object, - bp::converter::rvalue_from_python_stage1_data* data) - { - // Object is a borrowed reference, so create a handle indicting it is - // borrowed for proper reference counting. - bp::handle<> handle(bp::borrowed(object)); - - // Obtain a handle to the memory block that the converter has - // allocated for the C++ type. - typedef bp::converter::rvalue_from_python_storage storage_type; - - void* storage = reinterpret_cast(data)->storage.bytes; - typedef bp::stl_input_iterator iterator; - - // Allocate the C++ type into the converter's memory block, and assign - // its handle to the converter's convertible variable. The C++ - // container is populated by passing the begin and end iterators of - // the python object to the container's constructor. - new (storage) Container( - iterator(bp::object(handle)), // begin - iterator() // end - ); - - data->convertible = storage; - } -}; - -template -struct uhd_to_python_dict -{ - static PyObject* convert(uhd::dict const& input_dict) - { - bp::dict py_dict; - for (const auto& key: input_dict.keys()){ - py_dict[key] = input_dict[key]; - } - return bp::incref(py_dict.ptr()); - } - -}; - -template -struct iterable_to_python_list -{ - static PyObject* convert(Container const& input) - { - bp::list py_list; - for (const auto& element: input){ - py_list.append(element); - } - return bp::incref(py_list.ptr()); - } -}; - // We need this hack because import_array() returns NULL // for newer Python versions. // This function is also necessary because it ensures access to the C API @@ -132,80 +49,32 @@ void init_numpy() } #endif -BOOST_PYTHON_MODULE(libpyuhd) +PYBIND11_MODULE(libpyuhd, m) { // Initialize the numpy C API // (otherwise we will see segmentation faults) init_numpy(); - bp::object package = bp::scope(); - package.attr("__path__") = "libpyuhd"; - - // Declare converters - iterable_converter() - .from_python >() - .from_python >() - .from_python >() - ; - - bp::to_python_converter< - uhd::dict, - uhd_to_python_dict, false >(); - bp::to_python_converter< - std::vector, - iterable_to_python_list >, false >(); - // Register types submodule - { - bp::object types_module( - bp::handle<>(bp::borrowed(PyImport_AddModule("libpyuhd.types"))) - ); - bp::scope().attr("types") = types_module; - bp::scope io_scope = types_module; - - bp::implicitly_convertible(); - - export_types(); - export_time_spec(); - export_spi_config(); - export_metadata(); - export_sensors(); - export_tune(); + auto types_module = m.def_submodule("types", "UHD Types"); - // Declare some more converters - iterable_converter() - .from_python>() - ; - - bp::to_python_converter< - std::vector, - iterable_to_python_list>, false >(); - } + export_types(types_module); + export_time_spec(types_module); + export_spi_config(types_module); + export_metadata(types_module); + export_sensors(types_module); + export_tune(types_module); // Register usrp submodule - { - bp::object usrp_module( - bp::handle<>(bp::borrowed(PyImport_AddModule("libpyuhd.usrp"))) - ); - bp::scope().attr("usrp") = usrp_module; - bp::scope io_scope = usrp_module; - - export_multi_usrp(); - export_subdev_spec(); - export_dboard_iface(); - export_fe_connection(); - export_stream(); - } + auto usrp_module = m.def_submodule("usrp", "USRP Objects"); + export_multi_usrp(usrp_module); + export_subdev_spec(usrp_module); + export_dboard_iface(usrp_module); + export_fe_connection(usrp_module); + export_stream(usrp_module); // Register filters submodule - { - bp::object filters_module( - bp::handle<>(bp::borrowed(PyImport_AddModule("libpyuhd.filters"))) - ); - bp::scope().attr("filters") = filters_module; - bp::scope io_scope = filters_module; - - export_filters(); - } + auto filters_module = m.def_submodule("filters", "Filter Submodule"); + export_filters(filters_module); } -- cgit v1.2.3