diff --git a/hcore/include/opts.h b/hcore/include/opts.h index 8b85761..2b2ec92 100644 --- a/hcore/include/opts.h +++ b/hcore/include/opts.h @@ -16,6 +16,12 @@ public: void dumpOptions() const; std::string getUsage() const; + static OptionParser &getOptions(void) + { + static OptionParser options; + return options; + } + public: std::string senseApiLibPath; std::vector senseApiLibs; diff --git a/hcore/include/senseApis/senseApiLib.h b/hcore/include/senseApis/senseApiLib.h index 116fce3..1d4fbff 100644 --- a/hcore/include/senseApis/senseApiLib.h +++ b/hcore/include/senseApis/senseApiLib.h @@ -39,7 +39,7 @@ public: class SenseApiLib { public: - typedef const CSenseApiDesc *(SenseApiDescGetterFn)(void); + typedef const CSenseApiDesc* (SenseApiDescGetterFn)(void); public: SenseApiLib(const std::string& path) @@ -58,7 +58,7 @@ public: * This getter function should be visible to dlsym() so that Harikoff can * find it in the lib after loading it, and call it. */ - SenseApiDescGetterFn *getSenseApiDescriptor; + std::function getSenseApiDescriptor; /** * @brief Harikoff will call the `getSenseApiDescriptor` getter function and diff --git a/hcore/senseApis/senseApiManager.cpp b/hcore/senseApis/senseApiManager.cpp index c8c9f23..445ea89 100644 --- a/hcore/senseApis/senseApiManager.cpp +++ b/hcore/senseApis/senseApiManager.cpp @@ -1,19 +1,63 @@ #include #include #include +#include #include #include +#include +#include + +namespace fs = std::filesystem; namespace hk { namespace sense_api { +static std::optional findLibraryPath( + const std::string& libraryPath) +{ + std::vector searchPaths = { + OptionParser::getOptions().senseApiLibPath, + fs::current_path().string(), + fs::path("/proc/self/exe").parent_path().string() + }; + + for (const auto& path : searchPaths) + { + fs::path fullPath = fs::path(path) / libraryPath; + if (fs::exists(fullPath)) + { + return fullPath.string(); + } + } + + std::cerr << std::string(__func__) + ": library '" + + libraryPath + "' isn't in search bespoke search paths: "; + for (const auto& path : searchPaths) + { + std::cerr << path << " "; + } + std::cerr << std::endl; + std::cerr << "Trying to load " + libraryPath + " from system default search " + "paths\n"; + + return std::nullopt; +} + SenseApiLib& SenseApiManager::loadSenseApiLib(const std::string& libraryPath) { - auto lib = std::make_unique(libraryPath); + std::optional fullPath = findLibraryPath(libraryPath); + auto lib = std::make_unique(fullPath.value_or(libraryPath)); // Clear any existing error dlerror(); - lib->handle.reset(dlopen(libraryPath.c_str(), RTLD_LAZY)); + lib->handle.reset(dlopen(lib->libraryPath.c_str(), RTLD_LAZY)); + if (!lib->handle && fullPath.has_value()) + { + // Fallback to using the supplied libraryPath + dlerror(); + lib->handle.reset(dlopen(libraryPath.c_str(), RTLD_LAZY)); + } + if (!lib->handle) { std::string error = dlerror() @@ -25,6 +69,18 @@ SenseApiLib& SenseApiManager::loadSenseApiLib(const std::string& libraryPath) + error); } + // Initialize getSenseApiDescriptor + auto func = reinterpret_cast( + dlsym(lib->handle.get(), HK_SENSE_API_DESC_GETTER_FN_NAME)); + if (!func) + { + throw std::runtime_error( + std::string(__func__) + ": dlsym(" + HK_SENSE_API_DESC_GETTER_FN_NAME ") failed for library '" + + lib->libraryPath + "'"); + } + lib->getSenseApiDescriptor = func; + senseApiLibs.push_back(std::move(lib)); return *senseApiLibs.back(); } diff --git a/main.cpp b/main.cpp index 1a069be..0e12b97 100644 --- a/main.cpp +++ b/main.cpp @@ -4,10 +4,11 @@ #include #include + int main(int argc, char **argv) { try { - OptionParser options; + OptionParser &options = OptionParser::getOptions(); hk::Mind mind; std::cout << PACKAGE_NAME << " " << PACKAGE_VERSION << std::endl;