diff --git a/CMakeLists.txt b/CMakeLists.txt index ef70103..1b18c9a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -141,7 +141,6 @@ add_custom_target(uninstall ######################################################################## add_subdirectory(include/gr_air_modes) add_subdirectory(lib) -add_subdirectory(swig) add_subdirectory(python) add_subdirectory(grc) add_subdirectory(apps) diff --git a/include/gr_air_modes/preamble.h b/include/gr_air_modes/preamble.h index a86aba0..26e462e 100644 --- a/include/gr_air_modes/preamble.h +++ b/include/gr_air_modes/preamble.h @@ -36,7 +36,7 @@ namespace air_modes { class AIR_MODES_API preamble : virtual public gr::block { public: - typedef boost::shared_ptr sptr; + typedef std::shared_ptr sptr; static sptr make(float channel_rate, float threshold_db); virtual void set_rate(float channel_rate) = 0; diff --git a/include/gr_air_modes/slicer.h b/include/gr_air_modes/slicer.h index 4813c81..2658994 100644 --- a/include/gr_air_modes/slicer.h +++ b/include/gr_air_modes/slicer.h @@ -37,7 +37,7 @@ namespace air_modes { class AIR_MODES_API slicer : virtual public gr::sync_block { public: - typedef boost::shared_ptr sptr; + typedef std::shared_ptr sptr; static sptr make(gr::msg_queue::sptr queue); }; diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index fc16854..337e238 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -61,3 +61,5 @@ GR_PYTHON_INSTALL( #set(GR_TEST_TARGET_DEPS gnuradio-gr-air-modes) #set(GR_TEST_PYTHON_DIRS ${CMAKE_BINARY_DIR}/swig) #GR_ADD_TEST(qa_gr-air-modes ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr-air-modes.py) + +add_subdirectory(bindings) diff --git a/python/bindings/CMakeLists.txt b/python/bindings/CMakeLists.txt new file mode 100644 index 0000000..f216eee --- /dev/null +++ b/python/bindings/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright 2020 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# SPDX-License-Identifier: GPL-3.0-or-later +# + +######################################################################## +# Check if there is C++ code at all +######################################################################## +if(NOT air_modes_sources) + MESSAGE(STATUS "No C++ sources... skipping python bindings") + return() +endif(NOT air_modes_sources) + +######################################################################## +# Check for pygccxml +######################################################################## +GR_PYTHON_CHECK_MODULE_RAW( + "pygccxml" + "import pygccxml" + PYGCCXML_FOUND + ) + +include(GrPybind) + +######################################################################## +# Python Bindings +######################################################################## + +list(APPEND air_modes_python_files + python_bindings.cc) + +GR_PYBIND_MAKE_OOT(air_modes + ../.. + gr::air_modes + "${air_modes_python_files}") + +install(TARGETS air_modes_python DESTINATION ${GR_PYTHON_DIR}/air_modes COMPONENT pythonapi) diff --git a/python/bindings/README.md b/python/bindings/README.md new file mode 100644 index 0000000..e69de29 diff --git a/python/bindings/bind_oot_file.py b/python/bindings/bind_oot_file.py new file mode 100644 index 0000000..91719f7 --- /dev/null +++ b/python/bindings/bind_oot_file.py @@ -0,0 +1,57 @@ +import warnings +import argparse +import os +from gnuradio.bindtool import BindingGenerator +import pathlib +import sys + +parser = argparse.ArgumentParser(description='Bind a GR Out of Tree Block') +parser.add_argument('--module', type=str, + help='Name of gr module containing file to bind (e.g. fft digital analog)') + +parser.add_argument('--output_dir', default='/tmp', + help='Output directory of generated bindings') +parser.add_argument('--prefix', help='Prefix of Installed GNU Radio') +parser.add_argument('--src', help='Directory of gnuradio source tree', + default=os.path.dirname(os.path.abspath(__file__))+'/../../..') + +parser.add_argument( + '--filename', help="File to be parsed") + +parser.add_argument( + '--defines', help='Set additional defines for precompiler',default=(), nargs='*') +parser.add_argument( + '--include', help='Additional Include Dirs, separated', default=(), nargs='*') + +parser.add_argument( + '--status', help='Location of output file for general status (used during cmake)', default=None +) +parser.add_argument( + '--flag_automatic', default='0' +) +parser.add_argument( + '--flag_pygccxml', default='0' +) + +args = parser.parse_args() + +prefix = args.prefix +output_dir = args.output_dir +defines = tuple(','.join(args.defines).split(',')) +includes = ','.join(args.include) +name = args.module + +namespace = ['gr', name] +prefix_include_root = name + + +with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning) + + bg = BindingGenerator(prefix, namespace, + prefix_include_root, output_dir, define_symbols=defines, addl_includes=includes, + catch_exceptions=False, write_json_output=False, status_output=args.status, + flag_automatic=True if args.flag_automatic.lower() in [ + '1', 'true'] else False, + flag_pygccxml=True if args.flag_pygccxml.lower() in ['1', 'true'] else False) + bg.gen_file_binding(args.filename) diff --git a/python/bindings/docstrings/README.md b/python/bindings/docstrings/README.md new file mode 100644 index 0000000..295455a --- /dev/null +++ b/python/bindings/docstrings/README.md @@ -0,0 +1 @@ +This directory stores templates for docstrings that are scraped from the include header files for each block \ No newline at end of file diff --git a/python/bindings/docstrings/preamble_pydoc_template.h b/python/bindings/docstrings/preamble_pydoc_template.h new file mode 100644 index 0000000..001c223 --- /dev/null +++ b/python/bindings/docstrings/preamble_pydoc_template.h @@ -0,0 +1,27 @@ +/* + * Copyright 2021 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ +#include "pydoc_macros.h" +#define D(...) DOC(gr,air-modes, __VA_ARGS__ ) +/* + This file contains placeholders for docstrings for the Python bindings. + Do not edit! These were automatically extracted during the binding process + and will be overwritten during the build process + */ + + + + static const char *__doc_gr_air-modes_preamble = R"doc()doc"; + + + static const char *__doc_gr_air-modes_preamble_preamble = R"doc()doc"; + + + static const char *__doc_gr_air-modes_preamble_make = R"doc()doc"; + + diff --git a/python/bindings/docstrings/slicer_pydoc_template.h b/python/bindings/docstrings/slicer_pydoc_template.h new file mode 100644 index 0000000..7fc17bb --- /dev/null +++ b/python/bindings/docstrings/slicer_pydoc_template.h @@ -0,0 +1,27 @@ +/* + * Copyright 2021 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ +#include "pydoc_macros.h" +#define D(...) DOC(gr,air-modes, __VA_ARGS__ ) +/* + This file contains placeholders for docstrings for the Python bindings. + Do not edit! These were automatically extracted during the binding process + and will be overwritten during the build process + */ + + + + static const char *__doc_gr_air-modes_slicer = R"doc()doc"; + + + static const char *__doc_gr_air-modes_slicer_slicer = R"doc()doc"; + + + static const char *__doc_gr_air-modes_slicer_make = R"doc()doc"; + + diff --git a/python/bindings/header_utils.py b/python/bindings/header_utils.py new file mode 100644 index 0000000..165124e --- /dev/null +++ b/python/bindings/header_utils.py @@ -0,0 +1,78 @@ +# Utilities for reading values in header files + +from argparse import ArgumentParser +import re + + +class PybindHeaderParser: + def __init__(self, pathname): + with open(pathname,'r') as f: + self.file_txt = f.read() + + def get_flag_automatic(self): + # p = re.compile(r'BINDTOOL_GEN_AUTOMATIC\(([^\s])\)') + # m = p.search(self.file_txt) + m = re.search(r'BINDTOOL_GEN_AUTOMATIC\(([^\s])\)', self.file_txt) + if (m and m.group(1) == '1'): + return True + else: + return False + + def get_flag_pygccxml(self): + # p = re.compile(r'BINDTOOL_USE_PYGCCXML\(([^\s])\)') + # m = p.search(self.file_txt) + m = re.search(r'BINDTOOL_USE_PYGCCXML\(([^\s])\)', self.file_txt) + if (m and m.group(1) == '1'): + return True + else: + return False + + def get_header_filename(self): + # p = re.compile(r'BINDTOOL_HEADER_FILE\(([^\s]*)\)') + # m = p.search(self.file_txt) + m = re.search(r'BINDTOOL_HEADER_FILE\(([^\s]*)\)', self.file_txt) + if (m): + return m.group(1) + else: + return None + + def get_header_file_hash(self): + # p = re.compile(r'BINDTOOL_HEADER_FILE_HASH\(([^\s]*)\)') + # m = p.search(self.file_txt) + m = re.search(r'BINDTOOL_HEADER_FILE_HASH\(([^\s]*)\)', self.file_txt) + if (m): + return m.group(1) + else: + return None + + def get_flags(self): + return f'{self.get_flag_automatic()};{self.get_flag_pygccxml()};{self.get_header_filename()};{self.get_header_file_hash()};' + + + +def argParse(): + """Parses commandline args.""" + desc='Reads the parameters from the comment block in the pybind files' + parser = ArgumentParser(description=desc) + + parser.add_argument("function", help="Operation to perform on comment block of pybind file", choices=["flag_auto","flag_pygccxml","header_filename","header_file_hash","all"]) + parser.add_argument("pathname", help="Pathname of pybind c++ file to read, e.g. blockname_python.cc") + + return parser.parse_args() + +if __name__ == "__main__": + # Parse command line options and set up doxyxml. + args = argParse() + + pbhp = PybindHeaderParser(args.pathname) + + if args.function == "flag_auto": + print(pbhp.get_flag_automatic()) + elif args.function == "flag_pygccxml": + print(pbhp.get_flag_pygccxml()) + elif args.function == "header_filename": + print(pbhp.get_header_filename()) + elif args.function == "header_file_hash": + print(pbhp.get_header_file_hash()) + elif args.function == "all": + print(pbhp.get_flags()) \ No newline at end of file diff --git a/python/bindings/preamble_python.cc b/python/bindings/preamble_python.cc new file mode 100644 index 0000000..fe06386 --- /dev/null +++ b/python/bindings/preamble_python.cc @@ -0,0 +1,59 @@ +/* + * Copyright 2021 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +/***********************************************************************************/ +/* This file is automatically generated using bindtool and can be manually edited */ +/* The following lines can be configured to regenerate this file during cmake */ +/* If manual edits are made, the following tags should be modified accordingly. */ +/* BINDTOOL_GEN_AUTOMATIC(0) */ +/* BINDTOOL_USE_PYGCCXML(0) */ +/* BINDTOOL_HEADER_FILE(preamble.h) */ +/* BINDTOOL_HEADER_FILE_HASH(99cc0f448ffd5f8da017452a42ffb8c1) */ +/***********************************************************************************/ + +#include +#include +#include + +namespace py = pybind11; + +#include +// pydoc.h is automatically generated in the build directory +#include + +void bind_preamble(py::module& m) +{ + + using preamble = gr::air-modes::preamble; + + + py::class_>(m, "preamble", D(preamble)) + + .def(py::init(&preamble::make), + D(preamble,make) + ) + + + + + ; + + + + +} + + + + + + + + diff --git a/python/bindings/python_bindings.cc b/python/bindings/python_bindings.cc new file mode 100644 index 0000000..5dd673e --- /dev/null +++ b/python/bindings/python_bindings.cc @@ -0,0 +1,57 @@ +/* + * Copyright 2020 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include + +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION +#include + +namespace py = pybind11; + +// Headers for binding functions +/**************************************/ +/* The following comment block is used for +/* gr_modtool to insert function prototypes +/* Please do not delete +/**************************************/ +// BINDING_FUNCTION_PROTOTYPES( + void bind_preamble(py::module& m); + void bind_slicer(py::module& m); +// ) END BINDING_FUNCTION_PROTOTYPES + + +// 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 +// and removes a warning. +void* init_numpy() +{ + import_array(); + return NULL; +} + +PYBIND11_MODULE(air_modes_python, m) +{ + // Initialize the numpy C API + // (otherwise we will see segmentation faults) + init_numpy(); + + // Allow access to base block methods + py::module::import("gnuradio.gr"); + + /**************************************/ + /* The following comment block is used for + /* gr_modtool to insert binding function calls + /* Please do not delete + /**************************************/ + // BINDING_FUNCTION_CALLS( + bind_preamble(m); + bind_slicer(m); + // ) END BINDING_FUNCTION_CALLS +} \ No newline at end of file diff --git a/python/bindings/slicer_python.cc b/python/bindings/slicer_python.cc new file mode 100644 index 0000000..e23c595 --- /dev/null +++ b/python/bindings/slicer_python.cc @@ -0,0 +1,59 @@ +/* + * Copyright 2021 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +/***********************************************************************************/ +/* This file is automatically generated using bindtool and can be manually edited */ +/* The following lines can be configured to regenerate this file during cmake */ +/* If manual edits are made, the following tags should be modified accordingly. */ +/* BINDTOOL_GEN_AUTOMATIC(0) */ +/* BINDTOOL_USE_PYGCCXML(0) */ +/* BINDTOOL_HEADER_FILE(slicer.h) */ +/* BINDTOOL_HEADER_FILE_HASH(eec2a2cee44fc77b3705ab2abfac8702) */ +/***********************************************************************************/ + +#include +#include +#include + +namespace py = pybind11; + +#include +// pydoc.h is automatically generated in the build directory +#include + +void bind_slicer(py::module& m) +{ + + using slicer = gr::air-modes::slicer; + + + py::class_>(m, "slicer", D(slicer)) + + .def(py::init(&slicer::make), + D(slicer,make) + ) + + + + + ; + + + + +} + + + + + + + + diff --git a/swig/CMakeLists.txt b/swig/CMakeLists.txt deleted file mode 100644 index 3c8f15a..0000000 --- a/swig/CMakeLists.txt +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright 2011 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. - -######################################################################## -# Include swig generation macros -######################################################################## -find_package(SWIG) -find_package(PythonLibs) -if(NOT SWIG_FOUND OR NOT PYTHONLIBS_FOUND) - return() -endif() -include(GrSwig) -include(GrPython) - -######################################################################## -# Setup swig generation -######################################################################## -set(GR_SWIG_INCLUDE_DIRS $) -set(GR_SWIG_TARGET_DEPS gnuradio::runtime_swig) - -set(GR_SWIG_LIBRARIES air_modes) - -GR_SWIG_MAKE(air_modes_swig air_modes_swig.i) - -######################################################################## -# Install the build swig module -######################################################################## -GR_SWIG_INSTALL(TARGETS air_modes_swig DESTINATION ${GR_PYTHON_DIR}/air_modes) - -######################################################################## -# Install swig .i files for development -######################################################################## -#install( -# FILES -# air_modes.i -#${CMAKE_CURRENT_BINARY_DIR}/air_modes_swig_doc.i -# DESTINATION $(GR_INCLUDE_DIR)/air_modes/swig -#) diff --git a/swig/air_modes_swig.i b/swig/air_modes_swig.i deleted file mode 100644 index 6f5a42b..0000000 --- a/swig/air_modes_swig.i +++ /dev/null @@ -1,17 +0,0 @@ -/* -*- c++ -*- */ - -#define AIR_MODES_API - -%include "gnuradio.i" - -%{ -#include "gr_air_modes/preamble.h" -#include "gr_air_modes/slicer.h" -%} - -%include "gr_air_modes/preamble.h" -%include "gr_air_modes/slicer.h" - -GR_SWIG_BLOCK_MAGIC2(air_modes,preamble); -GR_SWIG_BLOCK_MAGIC2(air_modes,slicer); -