summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2010-03-21 16:53:50 -0700
committerJosh Blum <josh@joshknows.com>2010-03-21 16:53:50 -0700
commitd66efda608db9f6a1c2ab64659556b53810d87b7 (patch)
treeedee79716e8a29cb3f21ebb148d2a6f6bbed347a
parentd1ecc555e53770f1a5608000352f56f48c36c310 (diff)
downloaduhd-d66efda608db9f6a1c2ab64659556b53810d87b7.tar.gz
uhd-d66efda608db9f6a1c2ab64659556b53810d87b7.tar.bz2
uhd-d66efda608db9f6a1c2ab64659556b53810d87b7.zip
Added ability to load modules at runtime
(specified by environment variable path). Added a demo test module as well.
-rw-r--r--host/lib/CMakeLists.txt21
-rw-r--r--host/lib/load_modules.cpp117
-rw-r--r--host/lib/simple_device.cpp1
-rw-r--r--host/test/CMakeLists.txt11
-rw-r--r--host/test/module_test.cpp26
5 files changed, 171 insertions, 5 deletions
diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt
index 563ffb340..22fbde265 100644
--- a/host/lib/CMakeLists.txt
+++ b/host/lib/CMakeLists.txt
@@ -22,6 +22,7 @@ SET(libuhd_sources
device.cpp
device_addr.cpp
gain_handler.cpp
+ load_modules.cpp
metadata.cpp
simple_device.cpp
time_spec.cpp
@@ -56,11 +57,29 @@ LIST(APPEND libuhd_sources
)
########################################################################
+# Setup defines for module loading
+########################################################################
+INCLUDE(CheckIncludeFileCXX)
+
+CHECK_INCLUDE_FILE_CXX(dlfcn.h HAVE_DLFCN_H)
+CHECK_INCLUDE_FILE_CXX(Winbase.h HAVE_WINBASE_H)
+
+IF(HAVE_DLFCN_H)
+ MESSAGE(STATUS "Module loading supported through dlopen...")
+ ADD_DEFINITIONS(-DHAVE_DLFCN_H)
+ELSEIF(HAVE_WINBASE_H)
+ MESSAGE(STATUS "Module loading supported through LoadLibrary...")
+ ADD_DEFINITIONS(-DHAVE_WINBASE_H)
+ELSE(HAVE_DLFCN_H)
+ MESSAGE(STATUS "Module loading not supported...")
+ENDIF(HAVE_DLFCN_H)
+
+########################################################################
# Setup libuhd library
########################################################################
ADD_LIBRARY(uhd SHARED ${libuhd_sources})
-TARGET_LINK_LIBRARIES(uhd ${Boost_LIBRARIES})
+TARGET_LINK_LIBRARIES(uhd ${Boost_LIBRARIES} ${CMAKE_DL_LIBS})
SET_TARGET_PROPERTIES(uhd PROPERTIES DEFINE_SYMBOL "UHD_DLL_EXPORTS")
diff --git a/host/lib/load_modules.cpp b/host/lib/load_modules.cpp
new file mode 100644
index 000000000..700afcd3f
--- /dev/null
+++ b/host/lib/load_modules.cpp
@@ -0,0 +1,117 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program 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 of the License, or
+// (at your option) any later version.
+//
+// This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils.hpp>
+#include <boost/format.hpp>
+#include <boost/foreach.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/filesystem.hpp>
+#include <iostream>
+#include <stdexcept>
+#include <cstdlib>
+
+namespace fs = boost::filesystem;
+
+/***********************************************************************
+ * Module Load Function
+ **********************************************************************/
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+
+static void load_module(const std::string &file_name){
+ if (dlopen(file_name.c_str(), RTLD_LAZY) == NULL){
+ throw std::runtime_error(str(
+ boost::format("dlopen failed to load \"%s\"") % file_name
+ ));
+ }
+}
+
+#elif HAVE_WINBASE_H
+#include <Winbase.h>
+
+static void load_module(const std::string &file_name){
+ if (LoadLibrary(file_name.c_str()) == NULL){
+ throw std::runtime_error(str(
+ boost::format("LoadLibrary failed to load \"%s\"") % file_name
+ ));
+ }
+}
+
+#else
+
+static void load_module(const std::string &file_name){
+ throw std::runtime_error(str(
+ boost::format("Module loading not supported: Cannot load \"%s\"") % file_name
+ ));
+}
+
+#endif
+
+/***********************************************************************
+ * Load Modules
+ **********************************************************************/
+/*!
+ * Load all modules in a given path.
+ * This will recurse into sub-directories.
+ * Does not throw, prints to std error.
+ * \param path the filesystem path
+ */
+static void load_path(const fs::path &path){
+ if (not fs::exists(path)){
+ std::cerr << boost::format("Module path \"%s\" not found.") % path.file_string() << std::endl;
+ return;
+ }
+
+ //try to load the files in this path
+ if (fs::is_directory(path)){
+ for(
+ fs::directory_iterator dir_itr(path);
+ dir_itr != fs::directory_iterator();
+ ++dir_itr
+ ){
+ load_path(dir_itr->path());
+ }
+ return;
+ }
+
+ //its not a directory, try to load it
+ try{
+ load_module(path.file_string());
+ }
+ catch(const std::exception &err){
+ std::cerr << boost::format("Error: %s") % err.what() << std::endl;
+ }
+}
+
+/*!
+ * Load all the modules given by the module path enviroment variable.
+ * The path variable may be several paths split by path separators.
+ */
+STATIC_BLOCK(load_modules){
+ //get the environment variable module path
+ char *env_module_path = std::getenv("UHD_MODULE_PATH");
+ if (env_module_path == NULL) return;
+
+ //split the path at the path separators
+ std::vector<std::string> module_paths;
+ boost::split(module_paths, env_module_path, boost::is_any_of(":;"));
+
+ //load modules in each path
+ BOOST_FOREACH(const std::string &module_path, module_paths){
+ load_path(fs::system_complete(fs::path(module_path)));
+ }
+}
diff --git a/host/lib/simple_device.cpp b/host/lib/simple_device.cpp
index 045318c6b..ba1966e0d 100644
--- a/host/lib/simple_device.cpp
+++ b/host/lib/simple_device.cpp
@@ -21,7 +21,6 @@
#include <uhd/props.hpp>
#include <uhd/types.hpp>
#include <boost/algorithm/string.hpp>
-#include <boost/algorithm/string/trim.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <stdexcept>
diff --git a/host/test/CMakeLists.txt b/host/test/CMakeLists.txt
index b1d5924c7..1791d9082 100644
--- a/host/test/CMakeLists.txt
+++ b/host/test/CMakeLists.txt
@@ -15,7 +15,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-
+########################################################################
+# unit test suite
+########################################################################
ADD_EXECUTABLE(main_test
main_test.cpp
addr_test.cpp
@@ -23,7 +25,10 @@ ADD_EXECUTABLE(main_test
vrt_test.cpp
wax_test.cpp
)
-
TARGET_LINK_LIBRARIES(main_test uhd)
-
ADD_TEST(test main_test)
+
+########################################################################
+# demo of a loadable module
+########################################################################
+ADD_LIBRARY(module_test MODULE module_test.cpp)
diff --git a/host/test/module_test.cpp b/host/test/module_test.cpp
new file mode 100644
index 000000000..71721ef90
--- /dev/null
+++ b/host/test/module_test.cpp
@@ -0,0 +1,26 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program 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 of the License, or
+// (at your option) any later version.
+//
+// This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils.hpp>
+#include <iostream>
+
+STATIC_BLOCK(module_test){
+ std::cout << "---------------------------------------" << std::endl;
+ std::cout << "-- Good news, everyone!" << std::endl;
+ std::cout << "-- The test module has been loaded." << std::endl;
+ std::cout << "---------------------------------------" << std::endl;
+}