Opts: Make singleton; senseApi: check senseApiLibPath, get senseApiDescFn pointer.

* OptionsParser now has a singleton.
* We now use the cmdline opt -p <senseApiLibPath>, and search for
  the specified library in:
  * senseApiLibPath, then CWD, then the place where our executable
    is running from, and then finally we let the hosting OS do
    its own search.
* We now call dlsym() on dlopen()'d libs to to get the senseApiDescFn
  pointer.
This commit is contained in:
2025-01-08 13:43:44 -04:00
parent b40790ee4a
commit bffa2b837c
4 changed files with 68 additions and 5 deletions
+58 -2
View File
@@ -1,19 +1,63 @@
#include <iostream>
#include <stdexcept>
#include <optional>
#include <filesystem>
#include <senseApis/senseApiManager.h>
#include <senseApis/senseApiLib.h>
#include <opts.h>
#include <user/senseApiDesc.h>
namespace fs = std::filesystem;
namespace hk {
namespace sense_api {
static std::optional<std::string> findLibraryPath(
const std::string& libraryPath)
{
std::vector<std::string> 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<SenseApiLib>(libraryPath);
std::optional<std::string> fullPath = findLibraryPath(libraryPath);
auto lib = std::make_unique<SenseApiLib>(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<SenseApiLib::SenseApiDescGetterFn*>(
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();
}