SenseApiLib, SenseApiDesc improvements, new Sense API Mgmt Lib Ops role

SenseApiDesc:
* Use a number count for num exported implexor APIs instead of
  NULL-terminated list.
* Add sanity checker functions for structs.

SenseApiLib:
* Invoke the new sanity checkers on new Lib objects.
* SenseApiDesc is now a member object instead of being
  pointed to.

SenseApiManager:
* loadSenseApiLib now calls the SenseApiDesc getter function.
* loadSenseApiLib now fills out the SenseApiLib class object.

New Sense API Mgmt Sub-API:

This sub-api (metalanguage, some might call it) is used to initialize
the lib's connection to the provider. After this call, the lib should
be ready to attach new devices to its provider on behalf of Hk.
This commit is contained in:
2025-01-09 06:03:43 -04:00
parent 2a397ae064
commit 53583e5735
4 changed files with 196 additions and 25 deletions
+28 -8
View File
@@ -12,6 +12,14 @@ namespace fs = std::filesystem;
namespace hk {
namespace sense_api {
struct DlCloser {
void operator()(void* handle) const {
if (handle) {
dlclose(handle);
}
}
};
static std::optional<std::string> findLibraryPath(
const std::string& libraryPath)
{
@@ -50,20 +58,22 @@ static std::optional<std::string> findLibraryPath(
SenseApiLib& SenseApiManager::loadSenseApiLib(const std::string& libraryPath)
{
const CSenseApiDesc *libApiDesc;
std::optional<std::string> fullPath = findLibraryPath(libraryPath);
auto lib = std::make_unique<SenseApiLib>(fullPath.value_or(libraryPath));
std::string resolvedPath = fullPath.value_or(libraryPath);
// Clear any existing error
dlerror();
lib->handle.reset(dlopen(lib->libraryPath.c_str(), RTLD_LAZY));
if (!lib->handle && fullPath.has_value())
auto dlopen_handle = std::unique_ptr<void, DlCloser>(
dlopen(resolvedPath.c_str(), RTLD_LAZY));
if (!dlopen_handle && fullPath.has_value())
{
// Fallback to using the supplied libraryPath
dlerror();
lib->handle.reset(dlopen(libraryPath.c_str(), RTLD_LAZY));
dlopen_handle.reset(dlopen(libraryPath.c_str(), RTLD_LAZY));
}
if (!lib->handle)
if (!dlopen_handle)
{
const char *dlerr = dlerror();
@@ -78,16 +88,26 @@ SenseApiLib& SenseApiManager::loadSenseApiLib(const std::string& libraryPath)
// Initialize getSenseApiDescriptor
auto func = reinterpret_cast<getSenseApiDescFn *>(
dlsym(lib->handle.get(), HK_GET_SENSE_API_DESC_FN_NAME_STR));
dlsym(dlopen_handle.get(), HK_GET_SENSE_API_DESC_FN_NAME_STR));
if (!func)
{
throw std::runtime_error(
std::string(__func__) + ": dlsym('"
HK_GET_SENSE_API_DESC_FN_NAME_STR "') failed for library '"
+ lib->libraryPath + "'");
+ libraryPath + "'");
}
lib->getSenseApiDescriptor = func;
libApiDesc = func();
if (!libApiDesc)
{
throw std::runtime_error(
std::string(__func__) + ": getSenseApiDesc() returned NULL for "
"library '" + libraryPath + "'");
}
auto lib = std::make_unique<SenseApiLib>(
libraryPath, dlopen_handle.release(), func);
lib->setSenseApiDesc(libApiDesc);
senseApiLibs.push_back(std::move(lib));
return *senseApiLibs.back();
}