summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt10
-rw-r--r--cmake/Modules/CMakeLists.txt20
-rw-r--r--cmake/Modules/GRASCommon.cmake64
-rw-r--r--cmake/Modules/GRASTool.in.cmake262
-rw-r--r--cmake/Modules/GrPython.cmake232
-rw-r--r--cmake/Modules/GrTest.cmake139
m---------grextras0
-rw-r--r--include/gras/detail/factory.hpp88
-rw-r--r--include/gras/factory.hpp260
-rw-r--r--lib/callable.cpp2
-rw-r--r--lib/factory.cpp18
-rw-r--r--python/gras/CMakeLists.txt1
-rw-r--r--python/gras/GRAS_Factory.i37
-rw-r--r--python/gras/GRAS_Loader.py2
-rw-r--r--python/gras/GRAS_TestUtils.py (renamed from tests/demo_blocks.py)18
-rw-r--r--python/gras/__init__.py3
-rw-r--r--tests/block_test.py42
-rw-r--r--tests/example_module.cpp7
-rw-r--r--tests/example_module.py2
-rw-r--r--tests/factory_test.cpp8
-rw-r--r--tests/module_loader_test.py4
-rw-r--r--tests/query_test.py16
-rw-r--r--tests/thread_pool_test.py9
-rw-r--r--tmpl/factory.tmpl.hpp68
-rw-r--r--tmpl/factory_detail.tmpl.hpp8
25 files changed, 1099 insertions, 221 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a65d3c3..d7f533c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -27,7 +27,9 @@ GRAS_CHECK_SUBMODULE(gnuradio)
GRAS_CHECK_SUBMODULE(grextras)
list(APPEND CMAKE_MODULE_PATH ${GRAS_SOURCE_DIR}/PMC/cmake/Modules)
-include(CMakeDefsHelper)
+list(APPEND CMAKE_MODULE_PATH ${GRAS_SOURCE_DIR}/cmake/Modules)
+list(APPEND CMAKE_MODULE_PATH ${GRAS_BINARY_DIR}/cmake/Modules)
+include(GRASCommon)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions(-DGRAS_DEBUG)
@@ -99,6 +101,7 @@ add_subdirectory(PMC)
add_subdirectory(python/gras)
add_subdirectory(tests)
add_subdirectory(query)
+add_subdirectory(cmake/Modules)
########################################################################
# add gnuradio as sub-project
@@ -147,6 +150,10 @@ CPACK_COMPONENT("${GRAS_COMP_PYTHON}"
########################################################################
# GNU Radio Extras as sub-project
########################################################################
+list(APPEND CMAKE_MODULE_PATH ${GRAS_SOURCE_DIR}/cmake/Modules)
+list(APPEND CMAKE_MODULE_PATH ${GRAS_BINARY_DIR}/cmake/Modules)
+set(GRAS_ROOT ${GRAS_SOURCE_DIR})
+list(APPEND GR_TEST_ENVIRONS "GRAS_ROOT=${GRAS_SOURCE_DIR}")
set(CMAKE_SOURCE_DIR ${GRAS_SOURCE_DIR}/grextras)
set(CMAKE_BINARY_DIR ${GRAS_BINARY_DIR}/grextras)
@@ -154,6 +161,7 @@ set(GRAS_FOUND TRUE)
#GRAS_INCLUDE_DIRS, GRAS_LIBRARIES set above
set(PMC_FOUND TRUE)
+set(PMC_INCLUDE_DIRS ${GRAS_SOURCE_DIR}/PMC/include)
set(PMC_LIBRARIES pmc)
set(VOLK_FOUND ${ENABLE_VOLK})
diff --git a/cmake/Modules/CMakeLists.txt b/cmake/Modules/CMakeLists.txt
new file mode 100644
index 0000000..d275f71
--- /dev/null
+++ b/cmake/Modules/CMakeLists.txt
@@ -0,0 +1,20 @@
+########################################################################
+# Install cmake modules to known location
+########################################################################
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/GRASTool.in.cmake
+ ${CMAKE_CURRENT_BINARY_DIR}/GRASTool.cmake
+@ONLY)
+list(APPEND GRAS_TOOL_SOURCES
+ ${CMAKE_CURRENT_BINARY_DIR}/GRASTool.cmake
+)
+
+install(
+ FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/GRASTool.cmake
+ GRASCommon.cmake
+ GrTest.cmake
+ GrPython.cmake
+ DESTINATION share/gras/cmake/Modules
+ COMPONENT ${GRAS_COMP_DEVEL}
+)
diff --git a/cmake/Modules/GRASCommon.cmake b/cmake/Modules/GRASCommon.cmake
new file mode 100644
index 0000000..6844dd4
--- /dev/null
+++ b/cmake/Modules/GRASCommon.cmake
@@ -0,0 +1,64 @@
+if(DEFINED __INCLUDED_GRAS_COMMON_CMAKE)
+ return()
+endif()
+set(__INCLUDED_GRAS_COMMON_CMAKE TRUE)
+
+########################################################################
+# select the release build type by default to get optimization flags
+########################################################################
+if(NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE "Release")
+ message(STATUS "Build type not specified: defaulting to release.")
+endif(NOT CMAKE_BUILD_TYPE)
+set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "")
+
+########################################################################
+# Setup Boost defines that get used before find_package(Boost)
+########################################################################
+if(UNIX AND NOT BOOST_ROOT AND EXISTS "/usr/lib64" AND NOT BOOST_LIBRARYDIR)
+ list(APPEND BOOST_LIBRARYDIR "/usr/lib64") #fedora 64-bit fix
+endif(UNIX AND NOT BOOST_ROOT AND EXISTS "/usr/lib64" AND NOT BOOST_LIBRARYDIR)
+
+set(Boost_ADDITIONAL_VERSIONS
+ "1.35.0" "1.35" "1.36.0" "1.36" "1.37.0" "1.37" "1.38.0" "1.38" "1.39.0" "1.39"
+ "1.40.0" "1.40" "1.41.0" "1.41" "1.42.0" "1.42" "1.43.0" "1.43" "1.44.0" "1.44"
+ "1.45.0" "1.45" "1.46.0" "1.46" "1.47.0" "1.47" "1.48.0" "1.48" "1.49.0" "1.49"
+ "1.50.0" "1.50" "1.51.0" "1.51" "1.52.0" "1.52" "1.53.0" "1.53" "1.54.0" "1.54"
+ "1.55.0" "1.55" "1.56.0" "1.56" "1.57.0" "1.57" "1.58.0" "1.58" "1.59.0" "1.59"
+ "1.60.0" "1.60" "1.61.0" "1.61" "1.62.0" "1.62" "1.63.0" "1.63" "1.64.0" "1.64"
+ "1.65.0" "1.65" "1.66.0" "1.66" "1.67.0" "1.67" "1.68.0" "1.68" "1.69.0" "1.69"
+)
+
+if(NOT Boost_INCLUDE_DIRS)
+ find_package(Boost)
+ if(NOT Boost_FOUND)
+ message(FATAL_ERROR "Boost C++ headers not found - required for GRAS_TOOL")
+ endif()
+endif()
+
+########################################################################
+# Linux detection stuff
+########################################################################
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ set(LINUX TRUE)
+endif()
+
+if(LINUX AND EXISTS "/etc/debian_version")
+ set(DEBIAN TRUE)
+endif()
+
+if(LINUX AND EXISTS "/etc/redhat-release")
+ set(REDHAT TRUE)
+endif()
+
+if(LINUX AND EXISTS "/etc/slackware-version")
+ set(SLACKWARE TRUE)
+endif()
+
+########################################################################
+# Automatic LIB_SUFFIX detection + configuration option
+########################################################################
+IF(NOT DEFINED LIB_SUFFIX AND (REDHAT OR SLACKWARE) AND CMAKE_SYSTEM_PROCESSOR MATCHES "64$")
+ SET(LIB_SUFFIX 64)
+ENDIF()
+SET(LIB_SUFFIX ${LIB_SUFFIX} CACHE STRING "lib directory suffix")
diff --git a/cmake/Modules/GRASTool.in.cmake b/cmake/Modules/GRASTool.in.cmake
new file mode 100644
index 0000000..502b271
--- /dev/null
+++ b/cmake/Modules/GRASTool.in.cmake
@@ -0,0 +1,262 @@
+if(DEFINED __INCLUDED_GRAS_TOOL_CMAKE)
+ return()
+endif()
+set(__INCLUDED_GRAS_TOOL_CMAKE TRUE)
+
+include(GRASCommon)
+
+########################################################################
+## Define GRAS_TOOL_PATH_SEP for utility purposes
+########################################################################
+if(UNIX)
+ set(GRAS_TOOL_PATH_SEP ":")
+elseif(WIN32)
+ set(GRAS_TOOL_PATH_SEP "\\;")
+else()
+ set(GRAS_TOOL_PATH_SEP ":")
+endif()
+
+########################################################################
+## Set installation constants
+## The GRAS_ROOT can be set via arg or environment variable
+########################################################################
+if(GRAS_ROOT)
+ #its already set
+elseif($ENV{GRAS_ROOT})
+ set(GRAS_ROOT $ENV{GRAS_ROOT})
+else()
+ set(GRAS_ROOT "@CMAKE_INSTALL_PREFIX@")
+endif()
+
+########################################################################
+## where to look for development files
+########################################################################
+set(GRAS_TOOL_INCLUDE_DIR ${GRAS_ROOT}/include)
+set(GRAS_TOOL_LIBRARY_DIR ${GRAS_ROOT}/lib@LIBSUFFIX@)
+
+#locate PMC and GRAS includes
+if (NOT PMC_INCLUDE_DIRS)
+ find_path(
+ PMC_INCLUDE_DIRS
+ NAMES PMC/PMC.hpp
+ PATHS ${GRAS_TOOL_INCLUDE_DIR}
+ )
+endif()
+if (NOT GRAS_INCLUDE_DIRS)
+ find_path(
+ GRAS_INCLUDE_DIRS
+ NAMES gras/gras.hpp
+ PATHS ${GRAS_TOOL_INCLUDE_DIR}
+ )
+endif()
+
+#locate PMC and GRAS libraries
+if (NOT PMC_LIBRARIES)
+ find_library(
+ PMC_LIBRARIES
+ NAMES pmc
+ PATHS ${GRAS_TOOL_LIBRARY_DIR}
+ )
+endif()
+if (NOT GRAS_LIBRARIES)
+ find_library(
+ GRAS_LIBRARIES
+ NAMES gras
+ PATHS ${GRAS_TOOL_LIBRARY_DIR}
+ )
+endif()
+
+########################################################################
+## GRAS_TOOL cmake function - the swiss army knife for GRAS users
+##
+## Options:
+## SOURCES - list of C++, Python, and GRC sources
+## TARGET - project name, used for library, and install prefix
+## DIRECTORY - name of installation directory or ${TARGET}
+## COMPONENT - name of installation component or ${TARGET}
+##
+## External vars:
+## GRAS_TOOL_LIBRARIES - list of additional libraries to link to
+########################################################################
+function(GRAS_TOOL)
+
+ include(CMakeParseArguments)
+ CMAKE_PARSE_ARGUMENTS(GRAS_TOOL "" "TARGET;DIRECTORY;COMPONENT" "SOURCES" ${ARGN})
+
+ #give an install directory if not specified
+ if(NOT GRAS_TOOL_DIRECTORY)
+ set(GRAS_TOOL_DIRECTORY ${GRAS_TOOL_TARGET})
+ endif()
+
+ #give the target a component name if not specified
+ if(NOT GRAS_TOOL_COMPONENT)
+ set(GRAS_TOOL_COMPONENT ${GRAS_TOOL_TARGET})
+ endif()
+
+ unset(GRAS_TOOL_CPP_SOURCES)
+ unset(GRAS_TOOL_PY_SOURCES)
+ unset(GRAS_TOOL_GRC_SOURCES)
+ foreach(source ${GRAS_TOOL_SOURCES})
+ get_filename_component(source_ext ${source} EXT)
+ if ("${source_ext}" STREQUAL ".cpp")
+ list(APPEND GRAS_TOOL_CPP_SOURCES ${source})
+ endif()
+ if ("${source_ext}" STREQUAL ".cxx")
+ list(APPEND GRAS_TOOL_CPP_SOURCES ${source})
+ endif()
+ if ("${source_ext}" STREQUAL ".cc")
+ list(APPEND GRAS_TOOL_CPP_SOURCES ${source})
+ endif()
+ if ("${source_ext}" STREQUAL ".c")
+ list(APPEND GRAS_TOOL_CPP_SOURCES ${source})
+ endif()
+ if ("${source_ext}" STREQUAL ".py")
+ list(APPEND GRAS_TOOL_PY_SOURCES ${source})
+ endif()
+ if ("${source_ext}" STREQUAL ".xml")
+ list(APPEND GRAS_TOOL_GRC_SOURCES ${source})
+ endif()
+ if ("${source_ext}" STREQUAL ".yml")
+ list(APPEND GRAS_TOOL_GRC_SOURCES ${source})
+ endif()
+ endforeach(source)
+
+ #suffix install path for project name
+ set(GRAS_TOOL_MOD_DIR lib@LIBSUFFIX@/gras/modules/${GRAS_TOOL_DIRECTORY})
+ set(GRAS_TOOL_PYTHON_DIR lib@LIBSUFFIX@/gras/python/${GRAS_TOOL_DIRECTORY})
+ set(GRAS_TOOL_GRC_DIR share/gnuradio/grc/blocks/${GRAS_TOOL_DIRECTORY})
+
+ #development and framework directories
+ include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+ include_directories(${PMC_INCLUDE_DIRS})
+ include_directories(${GRAS_INCLUDE_DIRS})
+ list(APPEND GRAS_TOOL_LIBRARIES ${PMC_LIBRARIES})
+ list(APPEND GRAS_TOOL_LIBRARIES ${GRAS_LIBRARIES})
+
+ #and boost includes as well
+ include_directories(${Boost_INCLUDE_DIRS})
+
+ #build and install module to path
+ if (GRAS_TOOL_CPP_SOURCES)
+ add_library(${GRAS_TOOL_TARGET} MODULE ${GRAS_TOOL_CPP_SOURCES})
+ target_link_libraries(${GRAS_TOOL_TARGET} ${GRAS_TOOL_LIBRARIES})
+ install(TARGETS ${GRAS_TOOL_TARGET}
+ LIBRARY DESTINATION ${GRAS_TOOL_MOD_DIR} COMPONENT ${GRAS_TOOL_COMPONENT} # .so file
+ ARCHIVE DESTINATION ${GRAS_TOOL_MOD_DIR} COMPONENT ${GRAS_TOOL_COMPONENT} # .lib file
+ RUNTIME DESTINATION ${GRAS_TOOL_MOD_DIR} COMPONENT ${GRAS_TOOL_COMPONENT} # .dll file
+ )
+
+ #export global variables for help locating build targets
+ get_target_property(module_location ${GRAS_TOOL_TARGET} LOCATION)
+ string(REGEX REPLACE "\\$\\(.*\\)" ${CMAKE_BUILD_TYPE} module_location ${module_location})
+ list(APPEND GRAS_TOOL_MODULE_LOCATIONS ${module_location})
+ set(GRAS_TOOL_MODULE_LOCATIONS ${GRAS_TOOL_MODULE_LOCATIONS} CACHE INTERNAL "")
+ string(REPLACE ";" "${GRAS_TOOL_PATH_SEP}" GRAS_TOOL_MODULE_PATH "${GRAS_TOOL_MODULE_LOCATIONS}")
+ set(GRAS_TOOL_MODULE_PATH ${GRAS_TOOL_MODULE_PATH} CACHE INTERNAL "")
+ set(${GRAS_TOOL_TARGET}_LOCATION ${module_location} CACHE INTERNAL "")
+ endif()
+
+ #python module install
+ if (GRAS_TOOL_PY_SOURCES)
+ install(
+ FILES ${GRAS_TOOL_PY_SOURCES}
+ DESTINATION ${GRAS_TOOL_PYTHON_DIR}
+ COMPONENT ${GRAS_TOOL_COMPONENT}
+ )
+ endif()
+
+ #install GRC files
+ if (GRAS_TOOL_GRC_SOURCES)
+ install(
+ FILES ${GRAS_TOOL_GRC_SOURCES}
+ DESTINATION ${GRAS_TOOL_GRC_DIR}
+ COMPONENT ${GRAS_TOOL_COMPONENT}
+ )
+ endif()
+
+endfunction(GRAS_TOOL)
+
+########################################################################
+## GRAS_SWIG_TOOL cmake function - export new types for the loader
+##
+## Options:
+## SOURCE - the swig .i file
+## TARGET - target name for the build products
+## DIRECTORY - name of installation directory or ${TARGET}
+## COMPONENT - name of installation component or ${TARGET}
+##
+## External vars:
+## GRAS_SWIG_TOOL_INCLUDES - list of additional include directories
+## GRAS_SWIG_TOOL_LIBRARIES - list of additional libraries to link to
+########################################################################
+function(GRAS_SWIG_TOOL)
+
+ find_package(SWIG)
+ if(NOT SWIG_FOUND)
+ return()
+ endif()
+
+ find_package(PythonLibs)
+ if(NOT PYTHONLIBS_FOUND)
+ return()
+ endif()
+
+ include(CMakeParseArguments)
+ CMAKE_PARSE_ARGUMENTS(GRAS_SWIG_TOOL "" "SOURCE;TARGET;DIRECTORY;COMPONENT" "" ${ARGN})
+
+ #give an install directory if not specified
+ if(NOT GRAS_SWIG_TOOL_DIRECTORY)
+ set(GRAS_SWIG_TOOL_DIRECTORY ${GRAS_SWIG_TOOL_TARGET})
+ endif()
+
+ #give the target a component name if not specified
+ if(NOT GRAS_SWIG_TOOL_COMPONENT)
+ set(GRAS_SWIG_TOOL_COMPONENT ${GRAS_SWIG_TOOL_TARGET})
+ endif()
+
+ #development and framework directories
+ list(APPEND GRAS_SWIG_TOOL_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR})
+ list(APPEND GRAS_SWIG_TOOL_INCLUDES ${PMC_SWIG_INCLUDE_DIRS})
+ list(APPEND GRAS_SWIG_TOOL_INCLUDES ${GRAS_SWIG_INCLUDE_DIRS})
+ list(APPEND GRAS_SWIG_TOOL_LIBRARIES ${PMC_LIBRARIES})
+ list(APPEND GRAS_SWIG_TOOL_LIBRARIES ${GRAS_LIBRARIES})
+
+ #and boost includes as well
+ include_directories(${Boost_INCLUDE_DIRS})
+
+ #setup python includes/libs
+ include_directories(${PYTHON_INCLUDE_PATH})
+ include_directories(${PYTHON_INCLUDE_DIRS})
+ list(APPEND GRAS_SWIG_TOOL_LIBRARIES ${PYTHON_LIBRARIES})
+
+ #include swig generation deps for compiling
+ include_directories(${GRAS_SWIG_TOOL_INCLUDES})
+
+ #set the C++ property on the swig .i file so it builds
+ set_source_files_properties(${GRAS_SWIG_TOOL_SOURCE} PROPERTIES CPLUSPLUS ON)
+
+ #setup swig flags
+ foreach(inc ${GRAS_SWIG_TOOL_INCLUDES})
+ list(APPEND CMAKE_SWIG_FLAGS "-I${inc}")
+ endforeach(inc)
+ set(CMAKE_SWIG_FLAGS -fvirtual -module ${GRAS_SWIG_TOOL_TARGET} ${CMAKE_SWIG_FLAGS})
+
+ #register swig build
+ include(UseSWIG)
+ SWIG_ADD_MODULE(${GRAS_SWIG_TOOL_TARGET} python ${GRAS_SWIG_TOOL_SOURCE})
+ SWIG_LINK_LIBRARIES(${GRAS_SWIG_TOOL_TARGET} ${GRAS_SWIG_TOOL_LIBRARIES})
+
+ #install rules for generated module and py file
+ set(GRAS_TOOL_PYTHON_DIR lib@LIBSUFFIX@/gras/python/${GRAS_SWIG_TOOL_DIRECTORY})
+ install(
+ TARGETS ${SWIG_MODULE_${GRAS_SWIG_TOOL_TARGET}_REAL_NAME}
+ DESTINATION ${GRAS_TOOL_PYTHON_DIR}
+ COMPONENT ${GRAS_SWIG_TOOL_COMPONENT}
+ )
+ install(
+ FILES ${CMAKE_CURRENT_BINARY_DIR}/${GRAS_SWIG_TOOL_TARGET}.py
+ DESTINATION ${GRAS_TOOL_PYTHON_DIR}
+ COMPONENT ${GRAS_SWIG_TOOL_COMPONENT}
+ )
+
+endfunction(GRAS_SWIG_TOOL)
diff --git a/cmake/Modules/GrPython.cmake b/cmake/Modules/GrPython.cmake
new file mode 100644
index 0000000..e598df4
--- /dev/null
+++ b/cmake/Modules/GrPython.cmake
@@ -0,0 +1,232 @@
+# Copyright 2010-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.
+
+if(DEFINED __INCLUDED_GR_PYTHON_CMAKE)
+ return()
+endif()
+set(__INCLUDED_GR_PYTHON_CMAKE TRUE)
+
+########################################################################
+# Setup the python interpreter:
+# This allows the user to specify a specific interpreter,
+# or finds the interpreter via the built-in cmake module.
+########################################################################
+#this allows the user to override PYTHON_EXECUTABLE
+if(PYTHON_EXECUTABLE)
+
+ set(PYTHONINTERP_FOUND TRUE)
+
+#otherwise if not set, try to automatically find it
+else(PYTHON_EXECUTABLE)
+
+ #use the built-in find script
+ find_package(PythonInterp)
+
+ #and if that fails use the find program routine
+ if(NOT PYTHONINTERP_FOUND)
+ find_program(PYTHON_EXECUTABLE NAMES python python2.7 python2.6 python2.5)
+ if(PYTHON_EXECUTABLE)
+ set(PYTHONINTERP_FOUND TRUE)
+ endif(PYTHON_EXECUTABLE)
+ endif(NOT PYTHONINTERP_FOUND)
+
+endif(PYTHON_EXECUTABLE)
+
+#make the path to the executable appear in the cmake gui
+set(PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE} CACHE FILEPATH "python interpreter")
+
+#make sure we can use -B with python (introduced in 2.6)
+if(PYTHON_EXECUTABLE)
+ execute_process(
+ COMMAND ${PYTHON_EXECUTABLE} -B -c ""
+ OUTPUT_QUIET ERROR_QUIET
+ RESULT_VARIABLE PYTHON_HAS_DASH_B_RESULT
+ )
+ if(PYTHON_HAS_DASH_B_RESULT EQUAL 0)
+ set(PYTHON_DASH_B "-B")
+ endif()
+endif(PYTHON_EXECUTABLE)
+
+########################################################################
+# Check for the existence of a python module:
+# - desc a string description of the check
+# - mod the name of the module to import
+# - cmd an additional command to run
+# - have the result variable to set
+########################################################################
+macro(GR_PYTHON_CHECK_MODULE desc mod cmd have)
+ message(STATUS "")
+ message(STATUS "Python checking for ${desc}")
+ execute_process(
+ COMMAND ${PYTHON_EXECUTABLE} -c "
+#########################################
+try:
+ import ${mod}
+ assert ${cmd}
+except ImportError, AssertionError: exit(-1)
+except: pass
+#########################################"
+ RESULT_VARIABLE ${have}
+ )
+ if(${have} EQUAL 0)
+ message(STATUS "Python checking for ${desc} - found")
+ set(${have} TRUE)
+ else(${have} EQUAL 0)
+ message(STATUS "Python checking for ${desc} - not found")
+ set(${have} FALSE)
+ endif(${have} EQUAL 0)
+endmacro(GR_PYTHON_CHECK_MODULE)
+
+########################################################################
+# Sets the python installation directory GR_PYTHON_DIR
+########################################################################
+execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "
+from distutils import sysconfig
+print sysconfig.get_python_lib(plat_specific=True, prefix='')
+" OUTPUT_VARIABLE GR_PYTHON_DIR OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+file(TO_CMAKE_PATH ${GR_PYTHON_DIR} GR_PYTHON_DIR)
+
+########################################################################
+# Create an always-built target with a unique name
+# Usage: GR_UNIQUE_TARGET(<description> <dependencies list>)
+########################################################################
+function(GR_UNIQUE_TARGET desc)
+ file(RELATIVE_PATH reldir ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR})
+ execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import re, hashlib
+unique = hashlib.md5('${reldir}${ARGN}').hexdigest()[:5]
+print(re.sub('\\W', '_', '${desc} ${reldir} ' + unique))"
+ OUTPUT_VARIABLE _target OUTPUT_STRIP_TRAILING_WHITESPACE)
+ add_custom_target(${_target} ALL DEPENDS ${ARGN})
+endfunction(GR_UNIQUE_TARGET)
+
+########################################################################
+# Install python sources (also builds and installs byte-compiled python)
+########################################################################
+function(GR_PYTHON_INSTALL)
+ include(CMakeParseArguments)
+ CMAKE_PARSE_ARGUMENTS(GR_PYTHON_INSTALL "" "DESTINATION;COMPONENT" "FILES;PROGRAMS" ${ARGN})
+
+ ####################################################################
+ if(GR_PYTHON_INSTALL_FILES)
+ ####################################################################
+ install(${ARGN}) #installs regular python files
+
+ #create a list of all generated files
+ unset(pysrcfiles)
+ unset(pycfiles)
+ unset(pyofiles)
+ foreach(pyfile ${GR_PYTHON_INSTALL_FILES})
+ get_filename_component(pyfile ${pyfile} ABSOLUTE)
+ list(APPEND pysrcfiles ${pyfile})
+
+ #determine if this file is in the source or binary directory
+ file(RELATIVE_PATH source_rel_path ${CMAKE_CURRENT_SOURCE_DIR} ${pyfile})
+ string(LENGTH "${source_rel_path}" source_rel_path_len)
+ file(RELATIVE_PATH binary_rel_path ${CMAKE_CURRENT_BINARY_DIR} ${pyfile})
+ string(LENGTH "${binary_rel_path}" binary_rel_path_len)
+
+ #and set the generated path appropriately
+ if(${source_rel_path_len} GREATER ${binary_rel_path_len})
+ set(pygenfile ${CMAKE_CURRENT_BINARY_DIR}/${binary_rel_path})
+ else()
+ set(pygenfile ${CMAKE_CURRENT_BINARY_DIR}/${source_rel_path})
+ endif()
+ list(APPEND pycfiles ${pygenfile}c)
+ list(APPEND pyofiles ${pygenfile}o)
+
+ #ensure generation path exists
+ get_filename_component(pygen_path ${pygenfile} PATH)
+ file(MAKE_DIRECTORY ${pygen_path})
+
+ endforeach(pyfile)
+
+ #the command to generate the pyc files
+ add_custom_command(
+ DEPENDS ${pysrcfiles} OUTPUT ${pycfiles}
+ COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_BINARY_DIR}/python_compile_helper.py ${pysrcfiles} ${pycfiles}
+ )
+
+ #the command to generate the pyo files
+ add_custom_command(
+ DEPENDS ${pysrcfiles} OUTPUT ${pyofiles}
+ COMMAND ${PYTHON_EXECUTABLE} -O ${CMAKE_BINARY_DIR}/python_compile_helper.py ${pysrcfiles} ${pyofiles}
+ )
+
+ #create install rule and add generated files to target list
+ set(python_install_gen_targets ${pycfiles} ${pyofiles})
+ install(FILES ${python_install_gen_targets}
+ DESTINATION ${GR_PYTHON_INSTALL_DESTINATION}
+ COMPONENT ${GR_PYTHON_INSTALL_COMPONENT}
+ )
+
+
+ ####################################################################
+ elseif(GR_PYTHON_INSTALL_PROGRAMS)
+ ####################################################################
+ file(TO_NATIVE_PATH ${PYTHON_EXECUTABLE} pyexe_native)
+
+ if (CMAKE_CROSSCOMPILING)
+ set(pyexe_native /usr/bin/env python)
+ endif()
+
+ foreach(pyfile ${GR_PYTHON_INSTALL_PROGRAMS})
+ get_filename_component(pyfile_name ${pyfile} NAME)
+ get_filename_component(pyfile ${pyfile} ABSOLUTE)
+ string(REPLACE "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" pyexefile "${pyfile}.exe")
+ list(APPEND python_install_gen_targets ${pyexefile})
+
+ get_filename_component(pyexefile_path ${pyexefile} PATH)
+ file(MAKE_DIRECTORY ${pyexefile_path})
+
+ add_custom_command(
+ OUTPUT ${pyexefile} DEPENDS ${pyfile}
+ COMMAND ${PYTHON_EXECUTABLE} -c
+ \"open('${pyexefile}', 'w').write('\#!${pyexe_native}\\n'+open('${pyfile}').read())\"
+ COMMENT "Shebangin ${pyfile_name}"
+ )
+
+ #on windows, python files need an extension to execute
+ get_filename_component(pyfile_ext ${pyfile} EXT)
+ if(WIN32 AND NOT pyfile_ext)
+ set(pyfile_name "${pyfile_name}.py")
+ endif()
+
+ install(PROGRAMS ${pyexefile} RENAME ${pyfile_name}
+ DESTINATION ${GR_PYTHON_INSTALL_DESTINATION}
+ COMPONENT ${GR_PYTHON_INSTALL_COMPONENT}
+ )
+ endforeach(pyfile)
+
+ endif()
+
+ GR_UNIQUE_TARGET("pygen" ${python_install_gen_targets})
+
+endfunction(GR_PYTHON_INSTALL)
+
+########################################################################
+# Write the python helper script that generates byte code files
+########################################################################
+file(WRITE ${CMAKE_BINARY_DIR}/python_compile_helper.py "
+import sys, py_compile
+files = sys.argv[1:]
+srcs, gens = files[:len(files)/2], files[len(files)/2:]
+for src, gen in zip(srcs, gens):
+ py_compile.compile(file=src, cfile=gen, doraise=True)
+")
diff --git a/cmake/Modules/GrTest.cmake b/cmake/Modules/GrTest.cmake
new file mode 100644
index 0000000..bb045dc
--- /dev/null
+++ b/cmake/Modules/GrTest.cmake
@@ -0,0 +1,139 @@
+# Copyright 2010-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.
+
+if(DEFINED __INCLUDED_GR_TEST_CMAKE)
+ return()
+endif()
+set(__INCLUDED_GR_TEST_CMAKE TRUE)
+
+########################################################################
+# Add a unit test and setup the environment for a unit test.
+# Takes the same arguments as the ADD_TEST function.
+#
+# Before calling set the following variables:
+# GR_TEST_TARGET_DEPS - built targets for the library path
+# GR_TEST_LIBRARY_DIRS - directories for the library path
+# GR_TEST_PYTHON_DIRS - directories for the python path
+# GR_TEST_ENVIRONS - other environment key/value pairs
+########################################################################
+function(GR_ADD_TEST test_name)
+
+ #Ensure that the build exe also appears in the PATH.
+ list(APPEND GR_TEST_TARGET_DEPS ${ARGN})
+
+ #In the land of windows, all libraries must be in the PATH.
+ #Since the dependent libraries are not yet installed,
+ #we must manually set them in the PATH to run tests.
+ #The following appends the path of a target dependency.
+ foreach(target ${GR_TEST_TARGET_DEPS})
+ get_target_property(location ${target} LOCATION)
+ if(location)
+ get_filename_component(path ${location} PATH)
+ string(REGEX REPLACE "\\$\\(.*\\)" ${CMAKE_BUILD_TYPE} path ${path})
+ list(APPEND GR_TEST_LIBRARY_DIRS ${path})
+ endif(location)
+ endforeach(target)
+
+ if(WIN32)
+ #SWIG generates the python library files into a subdirectory.
+ #Therefore, we must append this subdirectory into PYTHONPATH.
+ #Only do this for the python directories matching the following:
+ foreach(pydir ${GR_TEST_PYTHON_DIRS})
+ get_filename_component(name ${pydir} NAME)
+ if(name MATCHES "^(swig|lib|src)$")
+ list(APPEND GR_TEST_PYTHON_DIRS ${pydir}/${CMAKE_BUILD_TYPE})
+ endif()
+ endforeach(pydir)
+ endif(WIN32)
+
+ file(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR} srcdir)
+ file(TO_NATIVE_PATH "${GR_TEST_LIBRARY_DIRS}" libpath) #ok to use on dir list?
+ file(TO_NATIVE_PATH "${GR_TEST_PYTHON_DIRS}" pypath) #ok to use on dir list?
+
+ set(environs "GR_DONT_LOAD_PREFS=1" "srcdir=${srcdir}")
+ list(APPEND environs ${GR_TEST_ENVIRONS})
+
+ #http://www.cmake.org/pipermail/cmake/2009-May/029464.html
+ #Replaced this add test + set environs code with the shell script generation.
+ #Its nicer to be able to manually run the shell script to diagnose problems.
+ #ADD_TEST(${ARGV})
+ #SET_TESTS_PROPERTIES(${test_name} PROPERTIES ENVIRONMENT "${environs}")
+
+ if(UNIX)
+ set(LD_PATH_VAR "LD_LIBRARY_PATH")
+ if(APPLE)
+ set(LD_PATH_VAR "DYLD_LIBRARY_PATH")
+ endif()
+
+ set(binpath "${CMAKE_CURRENT_BINARY_DIR}:$PATH")
+ list(APPEND libpath "$${LD_PATH_VAR}")
+ list(APPEND pypath "$PYTHONPATH")
+
+ #replace list separator with the path separator
+ string(REPLACE ";" ":" libpath "${libpath}")
+ string(REPLACE ";" ":" pypath "${pypath}")
+ list(APPEND environs "PATH=${binpath}" "${LD_PATH_VAR}=${libpath}" "PYTHONPATH=${pypath}")
+
+ #generate a bat file that sets the environment and runs the test
+ find_program(SHELL sh)
+ set(sh_file ${CMAKE_CURRENT_BINARY_DIR}/${test_name}_test.sh)
+ file(WRITE ${sh_file} "#!${SHELL}\n")
+ #each line sets an environment variable
+ foreach(environ ${environs})
+ file(APPEND ${sh_file} "export ${environ}\n")
+ endforeach(environ)
+ #load the command to run with its arguments
+ foreach(arg ${ARGN})
+ file(APPEND ${sh_file} "${arg} ")
+ endforeach(arg)
+ file(APPEND ${sh_file} "\n")
+
+ #make the shell file executable
+ execute_process(COMMAND chmod +x ${sh_file})
+
+ add_test(${test_name} ${SHELL} ${sh_file})
+
+ endif(UNIX)
+
+ if(WIN32)
+ list(APPEND libpath ${DLL_PATHS} "%PATH%")
+ list(APPEND pypath "%PYTHONPATH%")
+
+ #replace list separator with the path separator (escaped)
+ string(REPLACE ";" "\\;" libpath "${libpath}")
+ string(REPLACE ";" "\\;" pypath "${pypath}")
+ list(APPEND environs "PATH=${libpath}" "PYTHONPATH=${pypath}")
+
+ #generate a bat file that sets the environment and runs the test
+ set(bat_file ${CMAKE_CURRENT_BINARY_DIR}/${test_name}_test.bat)
+ file(WRITE ${bat_file} "@echo off\n")
+ #each line sets an environment variable
+ foreach(environ ${environs})
+ file(APPEND ${bat_file} "SET ${environ}\n")
+ endforeach(environ)
+ #load the command to run with its arguments
+ foreach(arg ${ARGN})
+ file(APPEND ${bat_file} "${arg} ")
+ endforeach(arg)
+ file(APPEND ${bat_file} "\n")
+
+ add_test(${test_name} ${bat_file})
+ endif(WIN32)
+
+endfunction(GR_ADD_TEST)
diff --git a/grextras b/grextras
-Subproject 12cdd194513ec0fb05292950bfc133587b16685
+Subproject 274b6c3600faf12ef3ccbf9746c4457a465dcdb
diff --git a/include/gras/detail/factory.hpp b/include/gras/detail/factory.hpp
index ac4df6f..551ba9e 100644
--- a/include/gras/detail/factory.hpp
+++ b/include/gras/detail/factory.hpp
@@ -37,10 +37,10 @@ struct FactoryRegistryEntryImpl0 : FactoryRegistryEntry
};
template <typename ReturnType>
-void Factory::register_make(const std::string &name, ReturnType(*fcn)())
+void register_factory(const std::string &path, ReturnType(*fcn)())
{
void *r = new FactoryRegistryEntryImpl0<ReturnType>(fcn);
- Factory::_register_make(name, r);
+ Factory::_register_factory(path, r);
}
/***********************************************************************
@@ -61,10 +61,10 @@ struct FactoryRegistryEntryImpl1 : FactoryRegistryEntry
};
template <typename ReturnType, typename A0>
-void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &))
+void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &))
{
void *r = new FactoryRegistryEntryImpl1<ReturnType, A0>(fcn);
- Factory::_register_make(name, r);
+ Factory::_register_factory(path, r);
}
/***********************************************************************
@@ -85,10 +85,10 @@ struct FactoryRegistryEntryImpl2 : FactoryRegistryEntry
};
template <typename ReturnType, typename A0, typename A1>
-void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &))
+void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &))
{
void *r = new FactoryRegistryEntryImpl2<ReturnType, A0, A1>(fcn);
- Factory::_register_make(name, r);
+ Factory::_register_factory(path, r);
}
/***********************************************************************
@@ -109,10 +109,10 @@ struct FactoryRegistryEntryImpl3 : FactoryRegistryEntry
};
template <typename ReturnType, typename A0, typename A1, typename A2>
-void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &))
+void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &))
{
void *r = new FactoryRegistryEntryImpl3<ReturnType, A0, A1, A2>(fcn);
- Factory::_register_make(name, r);
+ Factory::_register_factory(path, r);
}
/***********************************************************************
@@ -133,10 +133,10 @@ struct FactoryRegistryEntryImpl4 : FactoryRegistryEntry
};
template <typename ReturnType, typename A0, typename A1, typename A2, typename A3>
-void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &))
+void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &))
{
void *r = new FactoryRegistryEntryImpl4<ReturnType, A0, A1, A2, A3>(fcn);
- Factory::_register_make(name, r);
+ Factory::_register_factory(path, r);
}
/***********************************************************************
@@ -157,10 +157,10 @@ struct FactoryRegistryEntryImpl5 : FactoryRegistryEntry
};
template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4>
-void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &))
+void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &))
{
void *r = new FactoryRegistryEntryImpl5<ReturnType, A0, A1, A2, A3, A4>(fcn);
- Factory::_register_make(name, r);
+ Factory::_register_factory(path, r);
}
/***********************************************************************
@@ -181,10 +181,10 @@ struct FactoryRegistryEntryImpl6 : FactoryRegistryEntry
};
template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5>
-void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &))
+void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &))
{
void *r = new FactoryRegistryEntryImpl6<ReturnType, A0, A1, A2, A3, A4, A5>(fcn);
- Factory::_register_make(name, r);
+ Factory::_register_factory(path, r);
}
/***********************************************************************
@@ -205,10 +205,10 @@ struct FactoryRegistryEntryImpl7 : FactoryRegistryEntry
};
template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
-void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &))
+void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &))
{
void *r = new FactoryRegistryEntryImpl7<ReturnType, A0, A1, A2, A3, A4, A5, A6>(fcn);
- Factory::_register_make(name, r);
+ Factory::_register_factory(path, r);
}
/***********************************************************************
@@ -229,10 +229,10 @@ struct FactoryRegistryEntryImpl8 : FactoryRegistryEntry
};
template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
-void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &))
+void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &))
{
void *r = new FactoryRegistryEntryImpl8<ReturnType, A0, A1, A2, A3, A4, A5, A6, A7>(fcn);
- Factory::_register_make(name, r);
+ Factory::_register_factory(path, r);
}
/***********************************************************************
@@ -253,10 +253,10 @@ struct FactoryRegistryEntryImpl9 : FactoryRegistryEntry
};
template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
-void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &))
+void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &))
{
void *r = new FactoryRegistryEntryImpl9<ReturnType, A0, A1, A2, A3, A4, A5, A6, A7, A8>(fcn);
- Factory::_register_make(name, r);
+ Factory::_register_factory(path, r);
}
/***********************************************************************
@@ -277,62 +277,62 @@ struct FactoryRegistryEntryImpl10 : FactoryRegistryEntry
};
template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
-void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &, const A9 &))
+void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &, const A9 &))
{
void *r = new FactoryRegistryEntryImpl10<ReturnType, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9>(fcn);
- Factory::_register_make(name, r);
+ Factory::_register_factory(path, r);
}
/***********************************************************************
* Templated make implementations
**********************************************************************/
inline
-Element *Factory::make(const std::string &name)
+Element *make(const std::string &path)
{
PMCList args(0);
- return Factory::_handle_make(name, PMC_M(args));
+ return Factory::_handle_make(path, PMC_M(args));
}
template <typename A0>
-Element *Factory::make(const std::string &name, const A0 &a0)
+Element *make(const std::string &path, const A0 &a0)
{
PMCList args(1);
args[0] = PMC_M(a0);
- return Factory::_handle_make(name, PMC_M(args));
+ return Factory::_handle_make(path, PMC_M(args));
}
template <typename A0, typename A1>
-Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1)
+Element *make(const std::string &path, const A0 &a0, const A1 &a1)
{
PMCList args(2);
args[0] = PMC_M(a0);
args[1] = PMC_M(a1);
- return Factory::_handle_make(name, PMC_M(args));
+ return Factory::_handle_make(path, PMC_M(args));
}
template <typename A0, typename A1, typename A2>
-Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2)
+Element *make(const std::string &path, const A0 &a0, const A1 &a1, const A2 &a2)
{
PMCList args(3);
args[0] = PMC_M(a0);
args[1] = PMC_M(a1);
args[2] = PMC_M(a2);
- return Factory::_handle_make(name, PMC_M(args));
+ return Factory::_handle_make(path, PMC_M(args));
}
template <typename A0, typename A1, typename A2, typename A3>
-Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3)
+Element *make(const std::string &path, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3)
{
PMCList args(4);
args[0] = PMC_M(a0);
args[1] = PMC_M(a1);
args[2] = PMC_M(a2);
args[3] = PMC_M(a3);
- return Factory::_handle_make(name, PMC_M(args));
+ return Factory::_handle_make(path, PMC_M(args));
}
template <typename A0, typename A1, typename A2, typename A3, typename A4>
-Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4)
+Element *make(const std::string &path, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4)
{
PMCList args(5);
args[0] = PMC_M(a0);
@@ -340,11 +340,11 @@ Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, cons
args[2] = PMC_M(a2);
args[3] = PMC_M(a3);
args[4] = PMC_M(a4);
- return Factory::_handle_make(name, PMC_M(args));
+ return Factory::_handle_make(path, PMC_M(args));
}
template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5>
-Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5)
+Element *make(const std::string &path, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5)
{
PMCList args(6);
args[0] = PMC_M(a0);
@@ -353,11 +353,11 @@ Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, cons
args[3] = PMC_M(a3);
args[4] = PMC_M(a4);
args[5] = PMC_M(a5);
- return Factory::_handle_make(name, PMC_M(args));
+ return Factory::_handle_make(path, PMC_M(args));
}
template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
-Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6)
+Element *make(const std::string &path, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6)
{
PMCList args(7);
args[0] = PMC_M(a0);
@@ -367,11 +367,11 @@ Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, cons
args[4] = PMC_M(a4);
args[5] = PMC_M(a5);
args[6] = PMC_M(a6);
- return Factory::_handle_make(name, PMC_M(args));
+ return Factory::_handle_make(path, PMC_M(args));
}
template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
-Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7)
+Element *make(const std::string &path, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7)
{
PMCList args(8);
args[0] = PMC_M(a0);
@@ -382,11 +382,11 @@ Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, cons
args[5] = PMC_M(a5);
args[6] = PMC_M(a6);
args[7] = PMC_M(a7);
- return Factory::_handle_make(name, PMC_M(args));
+ return Factory::_handle_make(path, PMC_M(args));
}
template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
-Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8)
+Element *make(const std::string &path, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8)
{
PMCList args(9);
args[0] = PMC_M(a0);
@@ -398,11 +398,11 @@ Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, cons
args[6] = PMC_M(a6);
args[7] = PMC_M(a7);
args[8] = PMC_M(a8);
- return Factory::_handle_make(name, PMC_M(args));
+ return Factory::_handle_make(path, PMC_M(args));
}
template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
-Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8, const A9 &a9)
+Element *make(const std::string &path, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8, const A9 &a9)
{
PMCList args(10);
args[0] = PMC_M(a0);
@@ -415,7 +415,7 @@ Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, cons
args[7] = PMC_M(a7);
args[8] = PMC_M(a8);
args[9] = PMC_M(a9);
- return Factory::_handle_make(name, PMC_M(args));
+ return Factory::_handle_make(path, PMC_M(args));
}
}
diff --git a/include/gras/factory.hpp b/include/gras/factory.hpp
index 13524a6..f9403fa 100644
--- a/include/gras/factory.hpp
+++ b/include/gras/factory.hpp
@@ -8,15 +8,6 @@
#include <PMC/PMC.hpp>
#include <string>
-/*!
- * Register a block's factory function:
- * Declare this macro at the global scope in a cpp file.
- * The block will register at static initialization time.
- */
-#define GRAS_REGISTER_FACTORY(name, fcn) \
- GRAS_STATIC_BLOCK(fcn) \
- {gras::Factory::register_make(name, &fcn);}
-
namespace gras
{
@@ -26,7 +17,7 @@ namespace gras
* - Call make() to create element from global factory.
*
* Example register a factory function:
- * gras::Factory::register_make("/proj/my_block", &make_my_block);
+ * gras::Factory::register_factory("/proj/my_block", &make_my_block);
*
* Example call into the factory:
* gras::Element *my_block = gras::Factory::make("/proj/my_block", arg0, arg1);
@@ -34,86 +25,227 @@ namespace gras
struct GRAS_API Factory
{
/*******************************************************************
- * Register API - don't look here, template magic, not helpful
+ * Private registration hooks
******************************************************************/
- template <typename ReturnType>
- static void register_make(const std::string &name, ReturnType(*fcn)());
+ static void _register_factory(const std::string &, void *);
+ static Element *_handle_make(const std::string &, const PMCC &);
+};
- template <typename ReturnType, typename A0>
- static void register_make(const std::string &name, ReturnType(*fcn)(const A0 &));
+/***********************************************************************
+ * Register API - don't look here, template magic, not helpful
+ **********************************************************************/
+template <typename ReturnType>
+static void register_factory(const std::string &path, ReturnType(*fcn)());
- template <typename ReturnType, typename A0, typename A1>
- static void register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &));
+template <typename ReturnType, typename A0>
+static void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &));
- template <typename ReturnType, typename A0, typename A1, typename A2>
- static void register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &));
+template <typename ReturnType, typename A0, typename A1>
+static void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &));
- template <typename ReturnType, typename A0, typename A1, typename A2, typename A3>
- static void register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &));
+template <typename ReturnType, typename A0, typename A1, typename A2>
+static void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &));
- template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4>
- static void register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &));
+template <typename ReturnType, typename A0, typename A1, typename A2, typename A3>
+static void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &));
- template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5>
- static void register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &));
+template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4>
+static void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &));
- template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
- static void register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &));
+template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5>
+static void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &));
- template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
- static void register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &));
+template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
+static void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &));
- template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
- static void register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &));
+template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
+static void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &));
- template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
- static void register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &, const A9 &));
+template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
+static void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &));
- /*******************************************************************
- * Make API - don't look here, template magic, not helpful
- ******************************************************************/;
- inline
- static Element *make(const std::string &name);
+template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
+static void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &, const A9 &));
- template <typename A0>
- static Element *make(const std::string &name, const A0 &);
+/***********************************************************************
+ * Make API - don't look here, template magic, not helpful
+ **********************************************************************/
+inline
+static Element *make(const std::string &path);
- template <typename A0, typename A1>
- static Element *make(const std::string &name, const A0 &, const A1 &);
+template <typename A0>
+static Element *make(const std::string &path, const A0 &);
- template <typename A0, typename A1, typename A2>
- static Element *make(const std::string &name, const A0 &, const A1 &, const A2 &);
+template <typename A0, typename A1>
+static Element *make(const std::string &path, const A0 &, const A1 &);
- template <typename A0, typename A1, typename A2, typename A3>
- static Element *make(const std::string &name, const A0 &, const A1 &, const A2 &, const A3 &);
+template <typename A0, typename A1, typename A2>
+static Element *make(const std::string &path, const A0 &, const A1 &, const A2 &);
- template <typename A0, typename A1, typename A2, typename A3, typename A4>
- static Element *make(const std::string &name, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &);
+template <typename A0, typename A1, typename A2, typename A3>
+static Element *make(const std::string &path, const A0 &, const A1 &, const A2 &, const A3 &);
- template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5>
- static Element *make(const std::string &name, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &);
+template <typename A0, typename A1, typename A2, typename A3, typename A4>
+static Element *make(const std::string &path, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &);
- template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
- static Element *make(const std::string &name, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &);
+template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5>
+static Element *make(const std::string &path, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &);
- template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
- static Element *make(const std::string &name, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &);
+template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
+static Element *make(const std::string &path, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &);
- template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
- static Element *make(const std::string &name, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &);
+template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
+static Element *make(const std::string &path, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &);
- template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
- static Element *make(const std::string &name, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &, const A9 &);
+template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
+static Element *make(const std::string &path, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &);
- /*******************************************************************
- * Private registration hooks
- ******************************************************************/
- static void _register_make(const std::string &, void *);
- static Element *_handle_make(const std::string &, const PMCC &);
-};
+template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
+static Element *make(const std::string &path, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &, const A9 &);
}
+/*!
+ * Register a block's factory function:
+ * Declare this macro at the global scope in a cpp file.
+ * The block will register at static initialization time.
+ */
+#define GRAS_REGISTER_FACTORY(path, fcn) \
+ GRAS_STATIC_BLOCK(fcn) \
+ {gras::register_factory(path, &fcn);}
+
+/*!
+ * Register a block's constructor into the factory:
+ * The arguments to this macro must be the types of each constructor argument.
+ * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t)
+ * Declare this macro at the global scope in a cpp file.
+ * The block will register at static initialization time.
+ */
+#define GRAS_REGISTER_FACTORY0(path, type) \
+ static gras::Element *make_ ## type() \
+ { return new type(); } \
+ GRAS_REGISTER_FACTORY(path, make_##type)
+
+/*!
+ * Register a block's constructor into the factory:
+ * The arguments to this macro must be the types of each constructor argument.
+ * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t)
+ * Declare this macro at the global scope in a cpp file.
+ * The block will register at static initialization time.
+ */
+#define GRAS_REGISTER_FACTORY1(path, type, A0) \
+ static gras::Element *make_ ## type(const A0 &a0) \
+ { return new type(a0); } \
+ GRAS_REGISTER_FACTORY(path, make_##type)
+
+/*!
+ * Register a block's constructor into the factory:
+ * The arguments to this macro must be the types of each constructor argument.
+ * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t)
+ * Declare this macro at the global scope in a cpp file.
+ * The block will register at static initialization time.
+ */
+#define GRAS_REGISTER_FACTORY2(path, type, A0, A1) \
+ static gras::Element *make_ ## type(const A0 &a0, const A1 &a1) \
+ { return new type(a0, a1); } \
+ GRAS_REGISTER_FACTORY(path, make_##type)
+
+/*!
+ * Register a block's constructor into the factory:
+ * The arguments to this macro must be the types of each constructor argument.
+ * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t)
+ * Declare this macro at the global scope in a cpp file.
+ * The block will register at static initialization time.
+ */
+#define GRAS_REGISTER_FACTORY3(path, type, A0, A1, A2) \
+ static gras::Element *make_ ## type(const A0 &a0, const A1 &a1, const A2 &a2) \
+ { return new type(a0, a1, a2); } \
+ GRAS_REGISTER_FACTORY(path, make_##type)
+
+/*!
+ * Register a block's constructor into the factory:
+ * The arguments to this macro must be the types of each constructor argument.
+ * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t)
+ * Declare this macro at the global scope in a cpp file.
+ * The block will register at static initialization time.
+ */
+#define GRAS_REGISTER_FACTORY4(path, type, A0, A1, A2, A3) \
+ static gras::Element *make_ ## type(const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3) \
+ { return new type(a0, a1, a2, a3); } \
+ GRAS_REGISTER_FACTORY(path, make_##type)
+
+/*!
+ * Register a block's constructor into the factory:
+ * The arguments to this macro must be the types of each constructor argument.
+ * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t)
+ * Declare this macro at the global scope in a cpp file.
+ * The block will register at static initialization time.
+ */
+#define GRAS_REGISTER_FACTORY5(path, type, A0, A1, A2, A3, A4) \
+ static gras::Element *make_ ## type(const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4) \
+ { return new type(a0, a1, a2, a3, a4); } \
+ GRAS_REGISTER_FACTORY(path, make_##type)
+
+/*!
+ * Register a block's constructor into the factory:
+ * The arguments to this macro must be the types of each constructor argument.
+ * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t)
+ * Declare this macro at the global scope in a cpp file.
+ * The block will register at static initialization time.
+ */
+#define GRAS_REGISTER_FACTORY6(path, type, A0, A1, A2, A3, A4, A5) \
+ static gras::Element *make_ ## type(const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5) \
+ { return new type(a0, a1, a2, a3, a4, a5); } \
+ GRAS_REGISTER_FACTORY(path, make_##type)
+
+/*!
+ * Register a block's constructor into the factory:
+ * The arguments to this macro must be the types of each constructor argument.
+ * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t)
+ * Declare this macro at the global scope in a cpp file.
+ * The block will register at static initialization time.
+ */
+#define GRAS_REGISTER_FACTORY7(path, type, A0, A1, A2, A3, A4, A5, A6) \
+ static gras::Element *make_ ## type(const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6) \
+ { return new type(a0, a1, a2, a3, a4, a5, a6); } \
+ GRAS_REGISTER_FACTORY(path, make_##type)
+
+/*!
+ * Register a block's constructor into the factory:
+ * The arguments to this macro must be the types of each constructor argument.
+ * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t)
+ * Declare this macro at the global scope in a cpp file.
+ * The block will register at static initialization time.
+ */
+#define GRAS_REGISTER_FACTORY8(path, type, A0, A1, A2, A3, A4, A5, A6, A7) \
+ static gras::Element *make_ ## type(const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7) \
+ { return new type(a0, a1, a2, a3, a4, a5, a6, a7); } \
+ GRAS_REGISTER_FACTORY(path, make_##type)
+
+/*!
+ * Register a block's constructor into the factory:
+ * The arguments to this macro must be the types of each constructor argument.
+ * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t)
+ * Declare this macro at the global scope in a cpp file.
+ * The block will register at static initialization time.
+ */
+#define GRAS_REGISTER_FACTORY9(path, type, A0, A1, A2, A3, A4, A5, A6, A7, A8) \
+ static gras::Element *make_ ## type(const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8) \
+ { return new type(a0, a1, a2, a3, a4, a5, a6, a7, a8); } \
+ GRAS_REGISTER_FACTORY(path, make_##type)
+
+/*!
+ * Register a block's constructor into the factory:
+ * The arguments to this macro must be the types of each constructor argument.
+ * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t)
+ * Declare this macro at the global scope in a cpp file.
+ * The block will register at static initialization time.
+ */
+#define GRAS_REGISTER_FACTORY10(path, type, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9) \
+ static gras::Element *make_ ## type(const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8, const A9 &a9) \
+ { return new type(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } \
+ GRAS_REGISTER_FACTORY(path, make_##type)
+
#include <gras/detail/factory.hpp>
#endif /*INCLUDED_GRAS_FACTORY_HPP*/
diff --git a/lib/callable.cpp b/lib/callable.cpp
index 59ada7f..461eebd 100644
--- a/lib/callable.cpp
+++ b/lib/callable.cpp
@@ -67,5 +67,5 @@ CallableRegistryEntry::~CallableRegistryEntry(void)
void CallableRegistryEntry::arg_check(const PMCList &args, const size_t nargs)
{
if (args.size() != nargs) throw std::runtime_error(str(boost::format(
- "callable expected %u arguments but for %u") % nargs % args.size()));
+ "callable expected %u arguments but got %u") % nargs % args.size()));
}
diff --git a/lib/factory.cpp b/lib/factory.cpp
index e07a2f2..7115197 100644
--- a/lib/factory.cpp
+++ b/lib/factory.cpp
@@ -23,7 +23,7 @@ FactoryRegistryEntry::~FactoryRegistryEntry(void)
void FactoryRegistryEntry::arg_check(const PMCList &args, const size_t nargs)
{
if (args.size() != nargs) throw std::runtime_error(str(boost::format(
- "factory expected %u arguments but for %u") % nargs % args.size()));
+ "factory expected %u arguments but got %u") % nargs % args.size()));
}
typedef std::map<std::string, boost::shared_ptr<FactoryRegistryEntry> > FactoryRegistryType;
@@ -36,22 +36,22 @@ static FactoryRegistryType &get_factory_registry(void)
static boost::mutex mutex;
-void Factory::_register_make(const std::string &name, void *entry)
+void Factory::_register_factory(const std::string &path, void *entry)
{
boost::mutex::scoped_lock l(mutex);
- if (get_factory_registry().count(name) != 0)
+ if (get_factory_registry().count(path) != 0)
{
- std::cerr << "Warning: Factory - function already registered for name: " + name << std::endl;
+ std::cerr << "Warning: Factory - function already registered for path: " + path << std::endl;
}
- get_factory_registry()[name].reset(reinterpret_cast<FactoryRegistryEntry *>(entry));
+ get_factory_registry()[path].reset(reinterpret_cast<FactoryRegistryEntry *>(entry));
}
-Element *Factory::_handle_make(const std::string &name, const PMCC &args)
+Element *Factory::_handle_make(const std::string &path, const PMCC &args)
{
boost::mutex::scoped_lock l(mutex);
- if (get_factory_registry().count(name) == 0)
+ if (get_factory_registry().count(path) == 0)
{
- throw std::invalid_argument("Factory - no function registered for name: " + name);
+ throw std::invalid_argument("Factory - no function registered for path: " + path);
}
- return get_factory_registry()[name]->make(args);
+ return get_factory_registry()[path]->make(args);
}
diff --git a/python/gras/CMakeLists.txt b/python/gras/CMakeLists.txt
index dda4934..766431d 100644
--- a/python/gras/CMakeLists.txt
+++ b/python/gras/CMakeLists.txt
@@ -88,6 +88,7 @@ GR_PYTHON_INSTALL(
FILES
__init__.py
GRAS_Utils.py
+ GRAS_TestUtils.py
${CMAKE_CURRENT_BINARY_DIR}/GRAS_Loader.py
DESTINATION ${GR_PYTHON_DIR}/gras
COMPONENT ${GRAS_COMP_PYTHON}
diff --git a/python/gras/GRAS_Factory.i b/python/gras/GRAS_Factory.i
index 1124963..2740b39 100644
--- a/python/gras/GRAS_Factory.i
+++ b/python/gras/GRAS_Factory.i
@@ -9,7 +9,7 @@
namespace gras
{
- %ignore Factory::register_make;
+ %ignore Factory::register_factory;
%ignore Factory::make;
}
@@ -30,25 +30,18 @@ namespace gras
%pythoncode %{
#TODO we need to register this into the real factory
_py_factory = dict()
-%}
-%extend gras::Factory
-{
- %insert("python")
- %{
- @staticmethod
- def register_make(name, fcn):
- #TODO we need to register this into the real factory
- _py_factory[name] = fcn
-
- @staticmethod
- def make(name, *args, **kwargs):
-
- #first try the local to python py factory #TODO real factory
- if name in _py_factory: return _py_factory[name](*args, **kwargs)
-
- from PMC import PMC_M
- pmcargs = PMC_M(list(args))
- return Factory._handle_make(name, pmcargs)
- %}
-}
+def register_factory(path, fcn):
+ #TODO we need to register this into the real factory
+ _py_factory[path] = fcn
+
+def make(path, *args, **kwargs):
+
+ #first try the local to python py factory #TODO real factory
+ if path in _py_factory: return _py_factory[path](*args, **kwargs)
+
+ from PMC import PMC_M
+ pmcargs = PMC_M(list(args))
+ return Factory._handle_make(path, pmcargs)
+
+%}
diff --git a/python/gras/GRAS_Loader.py b/python/gras/GRAS_Loader.py
index b70bc60..cc73d9b 100644
--- a/python/gras/GRAS_Loader.py
+++ b/python/gras/GRAS_Loader.py
@@ -2,6 +2,7 @@
import os
import sys
+import traceback
#try to import module
#http://effbot.org/zone/import-string.htm
@@ -15,6 +16,7 @@ def __try_module_import(filename):
module = __import__(module_name)
except Exception as ex:
print 'Could not import', filename, ex
+ print traceback.format_exc()
finally:
sys.path[:] = path # restore
diff --git a/tests/demo_blocks.py b/python/gras/GRAS_TestUtils.py
index 8550402..2960a2d 100644
--- a/tests/demo_blocks.py
+++ b/python/gras/GRAS_TestUtils.py
@@ -29,7 +29,7 @@ class VectorSource(gras.Block):
outs[0][:num] = self._vec[:num]
self.produce(0, num)
self._vec = self._vec[num:]
- if not self._vec:
+ if not len(self._vec):
self.mark_done()
class VectorSink(gras.Block):
@@ -37,13 +37,27 @@ class VectorSink(gras.Block):
gras.Block.__init__(self, name='VectorSink', in_sig=[in_sig])
self._vec = list()
- def get_vector(self):
+ def data(self):
return tuple(self._vec)
def work(self, ins, outs):
self._vec.extend(ins[0].copy())
self.consume(0, len(ins[0]))
+class Head(gras.Block):
+ def __init__(self, sig, num_items):
+ gras.Block.__init__(self, name='Head', in_sig=[sig], out_sig=[sig])
+ self._num_items = num_items
+
+ def work(self, ins, outs):
+ n = min(len(ins[0]), len(outs[0]), self._num_items)
+ outs[0][:n] = ins[0][:n]
+ self.consume(0, n)
+ self.produce(0, n)
+ self._num_items -= n
+ if not self._num_items:
+ self.mark_done()
+
class Add2X(gras.Block):
def __init__(self, sig):
gras.Block.__init__(self,
diff --git a/python/gras/__init__.py b/python/gras/__init__.py
index 6dcd4cd..884182c 100644
--- a/python/gras/__init__.py
+++ b/python/gras/__init__.py
@@ -10,7 +10,7 @@ from GRAS_SBuffer import SBufferConfig, SBuffer
from GRAS_Tags import Tag, StreamTag, PacketMsg
from GRAS_TimeTag import TimeTag
from GRAS_Element import Element
-from GRAS_Factory import Factory
+from GRAS_Factory import make, register_factory
import GRAS_Block
import GRAS_HierBlock
import GRAS_TopBlock
@@ -19,3 +19,4 @@ from GRAS_PyHierBlocks import PyHierBlock as HierBlock
from GRAS_PyHierBlocks import PyTopBlock as TopBlock
from GRAS_ThreadPool import ThreadPoolConfig, ThreadPool
import GRAS_Loader
+import GRAS_TestUtils as TestUtils
diff --git a/tests/block_test.py b/tests/block_test.py
index 2f8d91b..614e702 100644
--- a/tests/block_test.py
+++ b/tests/block_test.py
@@ -3,7 +3,7 @@
import unittest
import gras
import numpy
-from demo_blocks import *
+from gras import TestUtils
class BlockTest(unittest.TestCase):
@@ -14,55 +14,55 @@ class BlockTest(unittest.TestCase):
self.tb = None
def test_vector_blocks(self):
- vec_source = VectorSource(numpy.uint32, [0, 9, 8, 7, 6])
- vec_sink = VectorSink(numpy.uint32)
+ vec_source = TestUtils.VectorSource(numpy.uint32, [0, 9, 8, 7, 6])
+ vec_sink = TestUtils.VectorSink(numpy.uint32)
self.tb.connect(vec_source, vec_sink)
self.tb.run()
- self.assertEqual(vec_sink.get_vector(), (0, 9, 8, 7, 6))
+ self.assertEqual(vec_sink.data(), (0, 9, 8, 7, 6))
def test_add_f32(self):
- src0 = VectorSource(numpy.float32, [1, 3, 5, 7, 9])
- src1 = VectorSource(numpy.float32, [0, 2, 4, 6, 8])
- adder = Add2X(numpy.float32)
- sink = VectorSink(numpy.float32)
+ src0 = TestUtils.VectorSource(numpy.float32, [1, 3, 5, 7, 9])
+ src1 = TestUtils.VectorSource(numpy.float32, [0, 2, 4, 6, 8])
+ adder = TestUtils.Add2X(numpy.float32)
+ sink = TestUtils.VectorSink(numpy.float32)
self.tb.connect((src0, 0), (adder, 0))
self.tb.connect((src1, 0), (adder, 1))
self.tb.connect(adder, sink)
self.tb.run()
- self.assertEqual(sink.get_vector(), (1, 5, 9, 13, 17))
+ self.assertEqual(sink.data(), (1, 5, 9, 13, 17))
def test_add_fc32(self):
- src0 = VectorSource(numpy.complex64, [1, 3j, 5, 7j, 9])
- src1 = VectorSource(numpy.complex64, [0, 2j, 4, 6j, 8])
- adder = Add2X(numpy.complex64)
- sink = VectorSink(numpy.complex64)
+ src0 = TestUtils.VectorSource(numpy.complex64, [1, 3j, 5, 7j, 9])
+ src1 = TestUtils.VectorSource(numpy.complex64, [0, 2j, 4, 6j, 8])
+ adder = TestUtils.Add2X(numpy.complex64)
+ sink = TestUtils.VectorSink(numpy.complex64)
self.tb.connect((src0, 0), (adder, 0))
self.tb.connect((src1, 0), (adder, 1))
self.tb.connect(adder, sink)
self.tb.run()
- self.assertEqual(sink.get_vector(), (1, 5j, 9, 13j, 17))
+ self.assertEqual(sink.data(), (1, 5j, 9, 13j, 17))
def test_add_f32_feedback(self):
"""
Feedback adder output to input1 of the adder.
Preload input1 of the adder to set the delay.
"""
- src0 = VectorSource(numpy.float32, [1, 3, 5, 7, 9])
- adder = Add2X(numpy.float32)
+ src0 = TestUtils.VectorSource(numpy.float32, [1, 3, 5, 7, 9])
+ adder = TestUtils.Add2X(numpy.float32)
adder.input_config(1).preload_items = 1 #make this a feedback delay of 1
- sink = VectorSink(numpy.float32)
+ sink = TestUtils.VectorSink(numpy.float32)
self.tb.connect((src0, 0), (adder, 0))
self.tb.connect((adder, 0), (adder, 1))
self.tb.connect(adder, sink)
self.tb.run()
- self.assertEqual(sink.get_vector(), (1, 4, 9, 16, 25))
+ self.assertEqual(sink.data(), (1, 4, 9, 16, 25))
def test_tag_source_sink(self):
values = (0, 'hello', 4.2, True, None, [2, 3, 4], (9, 8, 7), 1j, {2:'d'})
- src = TagSource(values)
- sink = TagSink()
+ src = TestUtils.TagSource(values)
+ sink = TestUtils.TagSink()
self.tb.connect(src, sink)
self.tb.run()
self.assertEqual(sink.get_values(), values)
@@ -79,7 +79,7 @@ class BlockTest(unittest.TestCase):
except: pass
self.consume(0, len(ins[0]))
- source = VectorSource(numpy.uint32, [0, 9, 8, 7, 6])
+ source = TestUtils.VectorSource(numpy.uint32, [0, 9, 8, 7, 6])
sink = BadTouch(numpy.uint32)
self.tb.connect(source, sink)
diff --git a/tests/example_module.cpp b/tests/example_module.cpp
index d0316f8..389cf53 100644
--- a/tests/example_module.cpp
+++ b/tests/example_module.cpp
@@ -26,9 +26,4 @@ struct MyBlock : gras::Block
void work(const InputItems &, const OutputItems &){}
};
-gras::Block *make_my_block(void)
-{
- return new MyBlock();
-}
-
-GRAS_REGISTER_FACTORY("/tests/my_block0", make_my_block)
+GRAS_REGISTER_FACTORY0("/tests/my_block0", MyBlock)
diff --git a/tests/example_module.py b/tests/example_module.py
index 6c29435..3ef73dd 100644
--- a/tests/example_module.py
+++ b/tests/example_module.py
@@ -13,4 +13,4 @@ class MyBlock(gras.Block):
def get_num(self):
return 42
-gras.Factory.register_make("/tests/my_block1", MyBlock)
+gras.register_factory("/tests/my_block1", MyBlock)
diff --git a/tests/factory_test.cpp b/tests/factory_test.cpp
index 999e86e..ca8b5ba 100644
--- a/tests/factory_test.cpp
+++ b/tests/factory_test.cpp
@@ -51,25 +51,25 @@ GRAS_REGISTER_FACTORY("/tests/my_block_args3", make_my_block_args3)
BOOST_AUTO_TEST_CASE(test_register_and_make)
{
- gras::Element *my_block0 = gras::Factory::make("/tests/my_block_args0");
+ gras::Element *my_block0 = gras::make("/tests/my_block_args0");
BOOST_CHECK(dynamic_cast<MyBlock *>(my_block0) != NULL);
BOOST_CHECK_EQUAL(dynamic_cast<MyBlock *>(my_block0)->a0, 0);
BOOST_CHECK_EQUAL(dynamic_cast<MyBlock *>(my_block0)->a1, "");
BOOST_CHECK_EQUAL(dynamic_cast<MyBlock *>(my_block0)->a2, false);
- gras::Element *my_block1 = gras::Factory::make("/tests/my_block_args1", 42);
+ gras::Element *my_block1 = gras::make("/tests/my_block_args1", 42);
BOOST_CHECK(dynamic_cast<MyBlock *>(my_block1) != NULL);
BOOST_CHECK_EQUAL(dynamic_cast<MyBlock *>(my_block1)->a0, 42);
BOOST_CHECK_EQUAL(dynamic_cast<MyBlock *>(my_block1)->a1, "");
BOOST_CHECK_EQUAL(dynamic_cast<MyBlock *>(my_block1)->a2, false);
- gras::Element *my_block2 = gras::Factory::make("/tests/my_block_args2", 1, "foo");
+ gras::Element *my_block2 = gras::make("/tests/my_block_args2", 1, "foo");
BOOST_CHECK(dynamic_cast<MyBlock *>(my_block2) != NULL);
BOOST_CHECK_EQUAL(dynamic_cast<MyBlock *>(my_block2)->a0, 1);
BOOST_CHECK_EQUAL(dynamic_cast<MyBlock *>(my_block2)->a1, "foo");
BOOST_CHECK_EQUAL(dynamic_cast<MyBlock *>(my_block2)->a2, false);
- gras::Element *my_block3 = gras::Factory::make("/tests/my_block_args3", -2, "bar", true);
+ gras::Element *my_block3 = gras::make("/tests/my_block_args3", -2, "bar", true);
BOOST_CHECK(dynamic_cast<MyBlock *>(my_block3) != NULL);
BOOST_CHECK_EQUAL(dynamic_cast<MyBlock *>(my_block3)->a0, -2);
BOOST_CHECK_EQUAL(dynamic_cast<MyBlock *>(my_block3)->a1, "bar");
diff --git a/tests/module_loader_test.py b/tests/module_loader_test.py
index 4a8d64f..34423fd 100644
--- a/tests/module_loader_test.py
+++ b/tests/module_loader_test.py
@@ -6,11 +6,11 @@ import gras
class ModuleLoaderTest(unittest.TestCase):
def test_load_module_cpp(self):
- my_block = gras.Factory.make("/tests/my_block0")
+ my_block = gras.make("/tests/my_block0")
self.assertEqual(my_block.get_num(), 42)
def test_load_module_py(self):
- my_block = gras.Factory.make("/tests/my_block1")
+ my_block = gras.make("/tests/my_block1")
self.assertEqual(my_block.get_num(), 42)
if __name__ == '__main__':
diff --git a/tests/query_test.py b/tests/query_test.py
index 8e5bfaf..f4f45f9 100644
--- a/tests/query_test.py
+++ b/tests/query_test.py
@@ -3,7 +3,7 @@
import unittest
import gras
import numpy
-from demo_blocks import *
+from gras import TestUtils
class MyBlock(gras.Block):
def __init__(self):
@@ -44,13 +44,13 @@ class QueryTest(unittest.TestCase):
self.tb = None
def test_simple(self):
- vec_source = VectorSource(numpy.uint32, [0, 9, 8, 7, 6])
- vec_sink = VectorSink(numpy.uint32)
+ vec_source = TestUtils.VectorSource(numpy.uint32, [0, 9, 8, 7, 6])
+ vec_sink = TestUtils.VectorSink(numpy.uint32)
self.tb.connect(vec_source, vec_sink)
self.tb.run()
- self.assertEqual(vec_sink.get_vector(), (0, 9, 8, 7, 6))
+ self.assertEqual(vec_sink.data(), (0, 9, 8, 7, 6))
#query the block list
blocks_result = self.tb.query(dict(path="/blocks.json"))
@@ -71,8 +71,8 @@ class QueryTest(unittest.TestCase):
self.assertTrue(block_id in stats_result['blocks'])
def test_numeric_query(self):
- vec_source = VectorSource(numpy.uint32, [0, 9, 8, 7, 6])
- vec_sink = VectorSink(numpy.uint32)
+ vec_source = TestUtils.VectorSource(numpy.uint32, [0, 9, 8, 7, 6])
+ vec_sink = TestUtils.VectorSink(numpy.uint32)
block = MyBlock()
block.set_uid("test_numeric_query")
self.tb.connect(vec_source, block, vec_sink)
@@ -120,8 +120,8 @@ class QueryTest(unittest.TestCase):
self.assertEqual(result['value'], '(0,21)')
def test_vector_query(self):
- vec_source = VectorSource(numpy.uint32, [0, 9, 8, 7, 6])
- vec_sink = VectorSink(numpy.uint32)
+ vec_source = TestUtils.VectorSource(numpy.uint32, [0, 9, 8, 7, 6])
+ vec_sink = TestUtils.VectorSink(numpy.uint32)
block = MyBlock()
block.set_uid("test_vector_query")
self.tb.connect(vec_source, block, vec_sink)
diff --git a/tests/thread_pool_test.py b/tests/thread_pool_test.py
index 2765b07..58a00fe 100644
--- a/tests/thread_pool_test.py
+++ b/tests/thread_pool_test.py
@@ -2,7 +2,8 @@
import unittest
import gras
-from demo_blocks import *
+from gras import TestUtils
+import numpy
class ThreadPoolTest(unittest.TestCase):
@@ -26,8 +27,8 @@ class ThreadPoolTest(unittest.TestCase):
def test_migrate_to_thread_pool(self):
tb = gras.TopBlock()
- vec_source = VectorSource(numpy.uint32, [0, 9, 8, 7, 6])
- vec_sink = VectorSink(numpy.uint32)
+ vec_source = TestUtils.VectorSource(numpy.uint32, [0, 9, 8, 7, 6])
+ vec_sink = TestUtils.VectorSink(numpy.uint32)
c = gras.ThreadPoolConfig()
tp = gras.ThreadPool(c)
@@ -36,7 +37,7 @@ class ThreadPoolTest(unittest.TestCase):
tb.connect(vec_source, vec_sink)
tb.run()
- self.assertEqual(vec_sink.get_vector(), (0, 9, 8, 7, 6))
+ self.assertEqual(vec_sink.data(), (0, 9, 8, 7, 6))
if __name__ == '__main__':
unittest.main()
diff --git a/tmpl/factory.tmpl.hpp b/tmpl/factory.tmpl.hpp
index 61a61ba..a8f0b5d 100644
--- a/tmpl/factory.tmpl.hpp
+++ b/tmpl/factory.tmpl.hpp
@@ -8,15 +8,6 @@
#include <PMC/PMC.hpp>
#include <string>
-/*!
- * Register a block's factory function:
- * Declare this macro at the global scope in a cpp file.
- * The block will register at static initialization time.
- */
-#define GRAS_REGISTER_FACTORY(name, fcn) \
- GRAS_STATIC_BLOCK(fcn) \
- {gras::Factory::register_make(name, &fcn);}
-
namespace gras
{
@@ -26,7 +17,7 @@ namespace gras
* - Call make() to create element from global factory.
*
* Example register a factory function:
- * gras::Factory::register_make("/proj/my_block", &make_my_block);
+ * gras::Factory::register_factory("/proj/my_block", &make_my_block);
*
* Example call into the factory:
* gras::Element *my_block = gras::Factory::make("/proj/my_block", arg0, arg1);
@@ -34,30 +25,53 @@ namespace gras
struct GRAS_API Factory
{
/*******************************************************************
- * Register API - don't look here, template magic, not helpful
- ******************************************************************/
- #for $NARGS in range($MAX_ARGS)
- template <typename ReturnType, $expand('typename A%d', $NARGS)>
- static void register_make(const std::string &name, ReturnType(*fcn)($expand('const A%d &', $NARGS)));
-
- #end for
- /*******************************************************************
- * Make API - don't look here, template magic, not helpful
- ******************************************************************/;
- #for $NARGS in range($MAX_ARGS)
- template <$expand('typename A%d', $NARGS)>
- static Element *make(const std::string &name, $expand('const A%d &', $NARGS));
-
- #end for
- /*******************************************************************
* Private registration hooks
******************************************************************/
- static void _register_make(const std::string &, void *);
+ static void _register_factory(const std::string &, void *);
static Element *_handle_make(const std::string &, const PMCC &);
};
+/***********************************************************************
+ * Register API - don't look here, template magic, not helpful
+ **********************************************************************/
+#for $NARGS in range($MAX_ARGS)
+template <typename ReturnType, $expand('typename A%d', $NARGS)>
+static void register_factory(const std::string &path, ReturnType(*fcn)($expand('const A%d &', $NARGS)));
+
+#end for
+/***********************************************************************
+ * Make API - don't look here, template magic, not helpful
+ **********************************************************************/
+#for $NARGS in range($MAX_ARGS)
+template <$expand('typename A%d', $NARGS)>
+static Element *make(const std::string &path, $expand('const A%d &', $NARGS));
+
+#end for
}
+/*!
+ * Register a block's factory function:
+ * Declare this macro at the global scope in a cpp file.
+ * The block will register at static initialization time.
+ */
+#define GRAS_REGISTER_FACTORY(path, fcn) \
+ GRAS_STATIC_BLOCK(fcn) \
+ {gras::register_factory(path, &fcn);}
+
+#for $NARGS in range($MAX_ARGS)
+/*!
+ * Register a block's constructor into the factory:
+ * The arguments to this macro must be the types of each constructor argument.
+ * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t)
+ * Declare this macro at the global scope in a cpp file.
+ * The block will register at static initialization time.
+ */
+#define GRAS_REGISTER_FACTORY$(NARGS)(path, type, $expand('A%d', $NARGS)) \
+ static gras::Element *make_ $('##') type($expand('const A%d &a%d', $NARGS)) \
+ { return new type($expand('a%d', $NARGS)); } \
+ GRAS_REGISTER_FACTORY(path, make_$('##')type)
+
+#end for
#include <gras/detail/factory.hpp>
#endif /*INCLUDED_GRAS_FACTORY_HPP*/
diff --git a/tmpl/factory_detail.tmpl.hpp b/tmpl/factory_detail.tmpl.hpp
index ea30235..660a690 100644
--- a/tmpl/factory_detail.tmpl.hpp
+++ b/tmpl/factory_detail.tmpl.hpp
@@ -38,10 +38,10 @@ struct FactoryRegistryEntryImpl$(NARGS) : FactoryRegistryEntry
};
template <typename ReturnType, $expand('typename A%d', $NARGS)>
-void Factory::register_make(const std::string &name, ReturnType(*fcn)($expand('const A%d &', $NARGS)))
+void register_factory(const std::string &path, ReturnType(*fcn)($expand('const A%d &', $NARGS)))
{
void *r = new FactoryRegistryEntryImpl$(NARGS)<ReturnType, $expand('A%d', $NARGS)>(fcn);
- Factory::_register_make(name, r);
+ Factory::_register_factory(path, r);
}
#end for
@@ -50,13 +50,13 @@ void Factory::register_make(const std::string &name, ReturnType(*fcn)($expand('c
**********************************************************************/
#for $NARGS in range($MAX_ARGS)
template <$expand('typename A%d', $NARGS)>
-Element *Factory::make(const std::string &name, $expand('const A%d &a%d', $NARGS))
+Element *make(const std::string &path, $expand('const A%d &a%d', $NARGS))
{
PMCList args($NARGS);
#for $i in range($NARGS):
args[$i] = PMC_M(a$i);
#end for
- return Factory::_handle_make(name, PMC_M(args));
+ return Factory::_handle_make(path, PMC_M(args));
}
#end for