From 8866afe8ee318701eb4e12a389d066e11a6d189c Mon Sep 17 00:00:00 2001 From: Howard Butler Date: Fri, 5 Jul 2013 11:43:22 -0500 Subject: [PATCH] provide implementation for plugin versioning #154 --- include/pdal/Utils.hpp | 5 ++++- include/pdal/pdal_config.hpp | 1 + include/pdal/pdal_error.hpp | 9 +++++++++ include/pdal/pdal_macros.hpp | 9 +++++++++ pdal_defines.h.in | 2 ++ src/StageFactory.cpp | 11 ++++++++--- src/Utils.cpp | 24 +++++++++++++++++++++--- 7 files changed, 54 insertions(+), 7 deletions(-) diff --git a/include/pdal/Utils.hpp b/include/pdal/Utils.hpp index a25345c547..41308065f1 100644 --- a/include/pdal/Utils.hpp +++ b/include/pdal/Utils.hpp @@ -193,7 +193,10 @@ class PDAL_DLL Utils } - static void registerPlugin(void* stageFactoryPtr, std::string const& filename, std::string const& method); + static void* registerPlugin( void* stageFactoryPtr, + std::string const& filename, + std::string const& registerMethodName, + std::string const& versionMethodName); static char* getenv(const char* env); static std::string getenv(std::string const& name); diff --git a/include/pdal/pdal_config.hpp b/include/pdal/pdal_config.hpp index a2ced7eb2b..2311e0844f 100644 --- a/include/pdal/pdal_config.hpp +++ b/include/pdal/pdal_config.hpp @@ -66,6 +66,7 @@ PDAL_DLL int GetVersionPatch(); + } // namespace pdal #endif diff --git a/include/pdal/pdal_error.hpp b/include/pdal/pdal_error.hpp index 6ec89375db..f83db7d2f4 100644 --- a/include/pdal/pdal_error.hpp +++ b/include/pdal/pdal_error.hpp @@ -299,6 +299,15 @@ class python_error : public std::runtime_error {} }; +class plugin_error : public std::runtime_error +{ +public: + plugin_error(std::string const& msg) + : std::runtime_error(msg) + {} +}; + + } // namespace pdal #endif // PDAL_EXCEPTION_HPP_INCLUDED diff --git a/include/pdal/pdal_macros.hpp b/include/pdal/pdal_macros.hpp index 1e769f16d7..347f891fc2 100644 --- a/include/pdal/pdal_macros.hpp +++ b/include/pdal/pdal_macros.hpp @@ -107,4 +107,13 @@ } \ PDAL_C_END +#define SET_PLUGIN_VERSION(DriverName) \ + PDAL_C_START PDAL_DLL int PDALRegister_version_##DriverName() \ + { \ + return PDAL_PLUGIN_VERSION; \ + } \ + PDAL_C_END + + #endif + diff --git a/pdal_defines.h.in b/pdal_defines.h.in index b5fab3baf7..2f43b275a5 100644 --- a/pdal_defines.h.in +++ b/pdal_defines.h.in @@ -17,6 +17,8 @@ #define PDAL_VERSION_STRING "@PDAL_VERSION_STRING@" +#define PDAL_PLUGIN_VERSION 1 + /* (note this will look yucky until we get to major>=1) */ #define PDAL_VERSION_INTEGER ((PDAL_VERSION_MAJOR*100*100)+(PDAL_VERSION_MINOR*100)+PDAL_VERSION_PATCH) diff --git a/src/StageFactory.cpp b/src/StageFactory.cpp index 3639ff25a9..517eb8c037 100644 --- a/src/StageFactory.cpp +++ b/src/StageFactory.cpp @@ -527,7 +527,6 @@ void StageFactory::loadPlugins() { using namespace boost::filesystem; - typedef boost::tokenizer > tokenizer; std::string driver_path("PDAL_DRIVER_PATH"); std::string pluginDir = Utils::getenv(driver_path); @@ -636,8 +635,14 @@ void StageFactory::registerPlugin(std::string const& filename) } } - std::string methodName = "PDALRegister_" + boost::algorithm::ireplace_first_copy(basename.string(), "libpdal_plugin_", ""); - Utils::registerPlugin((void*)this, filename, methodName); + std::string base = basename.string(); + + std::string registerMethodName = "PDALRegister_" + \ + boost::algorithm::ireplace_first_copy(base, "libpdal_plugin_", ""); + + std::string versionMethodName = "PDALRegister_version_" + base.substr( base.find_last_of("_")+1, base.size()); + + Utils::registerPlugin((void*)this, filename, registerMethodName, versionMethodName); } diff --git a/src/Utils.cpp b/src/Utils.cpp index 7dd59d6507..e02d379221 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -75,20 +75,38 @@ double Utils::random(double minimum, double maximum) return t; } -void Utils::registerPlugin(void* stageFactoryPtr, std::string const& filename, std::string const& method) +void* Utils::registerPlugin( void* stageFactoryPtr, + std::string const& filename, + std::string const& registerMethod, + std::string const& versionMethod) { void* pRegister; + void* pVersion; - pRegister = Utils::getDLLSymbol(filename, method); + pVersion = Utils::getDLLSymbol(filename, versionMethod); + + int plugins_version = ((int (*)()) pVersion)(); + + if (plugins_version != PDAL_PLUGIN_VERSION) + { + std::ostringstream oss; + oss << "Unable to register shared library '" << filename << "' with method name '" << registerMethod << "' version of plugin, '" << plugins_version << "' did not match PDALs version '" << PDAL_PLUGIN_VERSION << "'"; + throw pdal_error(oss.str()); + } + + + pRegister = Utils::getDLLSymbol(filename, registerMethod); if (pRegister != NULL) { ((void (*)(void*)) pRegister)(stageFactoryPtr); } else { std::ostringstream oss; - oss << "Unable to register shared library '" << filename << "' with method name '" << method << "'"; + oss << "Unable to register shared library '" << filename << "' with method name '" << registerMethod << "'"; throw pdal_error(oss.str()); } + + return pRegister; }