Eliminate the C FFI; Namespace lib API and DeviceManager
We decided to get rid of the C FFI for libs. It was becoming too intricate and complicated. It was becoming a technical burden and expanding into too much extra code. It's unfortunate, but we'll have to give up on getting out-of-tree hot-loadable libraries the easy way. It's possible to still do it with cross compilation or by keeping track of the libstdc++ version that the running harikoff binary was compiled against. Then we can ensure that our loadable lib code is linked against that same libstdc++ code and this should ensure ABI stability.
This commit is contained in:
@@ -8,6 +8,9 @@
|
||||
#include <opts.h>
|
||||
#include <deviceManager/deviceManager.h>
|
||||
|
||||
namespace hk {
|
||||
namespace device {
|
||||
|
||||
std::vector<std::shared_ptr<InteroceptorDeviceSpec>>
|
||||
DeviceManager::interoceptorDeviceSpecs;
|
||||
std::vector<std::shared_ptr<ExtrospectorDeviceSpec>>
|
||||
@@ -20,12 +23,15 @@ const std::string DeviceManager::stringifyDeviceSpecs(void)
|
||||
std::ostringstream oss;
|
||||
|
||||
for (const auto& spec : DeviceManager::interoceptorDeviceSpecs) {
|
||||
oss << "Interoceptor " << CSenseDeviceSpec(*spec);
|
||||
oss << "Interoceptor " << spec->stringify();
|
||||
}
|
||||
|
||||
for (const auto& spec : DeviceManager::extrospectorDeviceSpecs) {
|
||||
oss << "Extrospector " << CSenseDeviceSpec(*spec);
|
||||
oss << "Extrospector " << spec->stringify();
|
||||
}
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
} // namespace device
|
||||
} // namespace hk
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
#include "deviceSpecp.hh"
|
||||
#include "deviceSpecl.hh"
|
||||
|
||||
namespace hk {
|
||||
namespace device {
|
||||
|
||||
std::string DeviceManager::readDeviceFile(const std::string& filename)
|
||||
{
|
||||
std::ifstream file(filename);
|
||||
@@ -61,3 +64,6 @@ void DeviceManager::parseAllDeviceSpecs(void)
|
||||
"Check specs for errors");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace device
|
||||
} // namespace hk
|
||||
|
||||
@@ -39,9 +39,9 @@ void yyerror(const char *message)
|
||||
%union {
|
||||
char* str;
|
||||
char chr;
|
||||
SenseDeviceSpec* sensorSpec;
|
||||
InteroceptorDeviceSpec* interoceptorSpec;
|
||||
ExtrospectorDeviceSpec* extrospectorSpec;
|
||||
hk::device::SenseDeviceSpec* sensorSpec;
|
||||
hk::device::InteroceptorDeviceSpec* interoceptorSpec;
|
||||
hk::device::ExtrospectorDeviceSpec* extrospectorSpec;
|
||||
std::vector<std::string>* stringVector;
|
||||
}
|
||||
|
||||
@@ -73,12 +73,12 @@ sensor_spec:
|
||||
|
||||
interoceptor_spec:
|
||||
KEYWORD_SPECTYPE_INTEROSPECTOR PIPE spec_body {
|
||||
auto spec = std::make_shared<InteroceptorDeviceSpec>(
|
||||
*static_cast<InteroceptorDeviceSpec *>($3));
|
||||
auto spec = std::make_shared<hk::device::InteroceptorDeviceSpec>(
|
||||
*static_cast<hk::device::InteroceptorDeviceSpec *>($3));
|
||||
|
||||
spec->sensorType = $1;
|
||||
DeviceManager::interoceptorDeviceSpecs.push_back(spec);
|
||||
DeviceManager::senseDeviceSpecs.push_back(spec);
|
||||
hk::device::DeviceManager::interoceptorDeviceSpecs.push_back(spec);
|
||||
hk::device::DeviceManager::senseDeviceSpecs.push_back(spec);
|
||||
|
||||
delete $3;
|
||||
}
|
||||
@@ -86,12 +86,12 @@ interoceptor_spec:
|
||||
|
||||
extrospector_spec:
|
||||
KEYWORD_SPECTYPE_EXTROSPECTOR PIPE spec_body {
|
||||
auto spec = std::make_shared<ExtrospectorDeviceSpec>(
|
||||
*static_cast<ExtrospectorDeviceSpec *>($3));
|
||||
auto spec = std::make_shared<hk::device::ExtrospectorDeviceSpec>(
|
||||
*static_cast<hk::device::ExtrospectorDeviceSpec *>($3));
|
||||
|
||||
spec->sensorType = $1;
|
||||
DeviceManager::extrospectorDeviceSpecs.push_back(spec);
|
||||
DeviceManager::senseDeviceSpecs.push_back(spec);
|
||||
hk::device::DeviceManager::extrospectorDeviceSpecs.push_back(spec);
|
||||
hk::device::DeviceManager::senseDeviceSpecs.push_back(spec);
|
||||
|
||||
delete $3;
|
||||
}
|
||||
@@ -99,7 +99,7 @@ extrospector_spec:
|
||||
|
||||
spec_body:
|
||||
STRING PIPE STRING LPAREN opt_params RPAREN PIPE STRING LPAREN opt_params RPAREN PIPE STRING {
|
||||
$$ = new SenseDeviceSpec();
|
||||
$$ = new hk::device::SenseDeviceSpec();
|
||||
$$->sensorType = '\0';
|
||||
$$->implexor = std::string($1);
|
||||
$$->api = std::string($3);
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
#include <iostream>
|
||||
#include <user/senseDeviceSpec.h>
|
||||
|
||||
namespace hk {
|
||||
namespace device {
|
||||
|
||||
class DeviceManager
|
||||
{
|
||||
public:
|
||||
@@ -39,4 +42,7 @@ public:
|
||||
senseDeviceSpecs;
|
||||
};
|
||||
|
||||
} // namespace device
|
||||
} // namespace hk
|
||||
|
||||
#endif // DEVICEMANAGER_H
|
||||
|
||||
@@ -11,59 +11,6 @@
|
||||
namespace hk {
|
||||
namespace sense_api {
|
||||
|
||||
/* C++ version of the C struct above, which Harikoff uses to manage the
|
||||
* lib and connect implexors to it.
|
||||
*/
|
||||
class SenseApiDesc
|
||||
{
|
||||
public:
|
||||
class ExportedImplexorApiDesc
|
||||
{
|
||||
public:
|
||||
ExportedImplexorApiDesc(const CExportedImplexorApiDesc& cDesc)
|
||||
// The caller should sanity check before calling this constructor.
|
||||
: name(cDesc.name)
|
||||
{}
|
||||
|
||||
const std::string name;
|
||||
};
|
||||
|
||||
public:
|
||||
SenseApiDesc() = default;
|
||||
SenseApiDesc(const CSenseApiDesc& cDesc)
|
||||
// The caller should sanity check before calling this constructor.
|
||||
: name(cDesc.name),
|
||||
sal_mgmt_libOps(cDesc.sal_mgmt_libOps)
|
||||
{
|
||||
for (uint32_t i = 0; i < cDesc.numExportedImplexorApis; ++i)
|
||||
{
|
||||
if (!CExportedImplexorApiDesc_sanityCheck(
|
||||
&cDesc.exportedImplexorApis[i]))
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"Sanity check failed for exported implexor API descriptor");
|
||||
}
|
||||
|
||||
exportedImplexorApis.push_back(
|
||||
ExportedImplexorApiDesc(cDesc.exportedImplexorApis[i]));
|
||||
}
|
||||
}
|
||||
|
||||
std::string name;
|
||||
// These are the implexors whose APIs this lib exports.
|
||||
std::vector<ExportedImplexorApiDesc> exportedImplexorApis;
|
||||
Csal_mgmt_libOps* sal_mgmt_libOps;
|
||||
|
||||
std::string stringify() const {
|
||||
std::string result = "Name: " + name + "\n";
|
||||
result += "Exported Implexor APIs:\n";
|
||||
for (const auto& api : exportedImplexorApis) {
|
||||
result += " - " + api.name + "\n";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
class SenseApiLib
|
||||
{
|
||||
private:
|
||||
@@ -86,27 +33,16 @@ public:
|
||||
HK_GET_SENSE_API_DESC_FN_NAME(descFn)
|
||||
{}
|
||||
|
||||
void setSenseApiDesc(const CSenseApiDesc* desc)
|
||||
void setSenseApiDesc(const SenseApiDesc &desc)
|
||||
{
|
||||
if (!CSenseApiDesc_sanityCheck(desc) ||
|
||||
!Csal_mgmt_libOps_sanityCheck(desc->sal_mgmt_libOps))
|
||||
if (!SenseApiDesc::sanityCheck(desc))
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": Sanity check failed for sense API "
|
||||
"descriptor in library '" + libraryPath + "'");
|
||||
}
|
||||
for (uint32_t i = 0; i < desc->numExportedImplexorApis; ++i)
|
||||
{
|
||||
if (!CExportedImplexorApiDesc_sanityCheck(
|
||||
&desc->exportedImplexorApis[i]))
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": Sanity check failed for "
|
||||
"exported implexor API descriptor in library '"
|
||||
+ libraryPath + "'");
|
||||
}
|
||||
}
|
||||
new (&senseApiDesc) SenseApiDesc(*desc); // Placement new
|
||||
|
||||
senseApiDesc = desc;
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -119,7 +55,7 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Every sense API lib is required to provide a function that returns
|
||||
* a CSenseApiDesc struct. This struct states which API the lib uses to
|
||||
* a SenseApiDesc struct. This struct states which API the lib uses to
|
||||
* connect Harikoff to the sense provider it supports.
|
||||
*
|
||||
* This getter function should be visible to dlsym() so that Harikoff can
|
||||
|
||||
@@ -38,8 +38,8 @@ public:
|
||||
void finalizeAllSenseApiLibs(void);
|
||||
|
||||
void attachAllSenseDevicesFromSpecs(void);
|
||||
void attachSenseDevice(const SenseDeviceSpec& spec);
|
||||
void detachSenseDevice(const SenseDeviceSpec& spec);
|
||||
void attachSenseDevice(const device::SenseDeviceSpec& spec);
|
||||
void detachSenseDevice(const device::SenseDeviceSpec& spec);
|
||||
void detachAllSenseDevices(void);
|
||||
|
||||
std::string stringifyLibs() const;
|
||||
|
||||
@@ -38,20 +38,18 @@ static std::optional<std::string> findLibraryPath(
|
||||
|
||||
std::cerr << std::string(__func__) + ": library '"
|
||||
+ libraryPath + "' isn't in search bespoke search paths: ";
|
||||
for (const auto& path : searchPaths)
|
||||
{
|
||||
for (const auto& path : searchPaths) {
|
||||
std::cerr << path << " ";
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "Trying to load " + libraryPath + " from system default search "
|
||||
"paths\n";
|
||||
std::cerr << "Trying to load " + libraryPath + " from system default "
|
||||
"search paths\n";
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
SenseApiLib& SenseApiManager::loadSenseApiLib(const std::string& libraryPath)
|
||||
{
|
||||
const CSenseApiDesc *libApiDesc;
|
||||
std::optional<std::string> fullPath = findLibraryPath(libraryPath);
|
||||
std::string resolvedPath = fullPath.value_or(libraryPath);
|
||||
|
||||
@@ -90,14 +88,7 @@ SenseApiLib& SenseApiManager::loadSenseApiLib(const std::string& libraryPath)
|
||||
+ libraryPath + "'");
|
||||
}
|
||||
|
||||
libApiDesc = func();
|
||||
if (!libApiDesc)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": getSenseApiDesc() returned NULL for "
|
||||
"library '" + libraryPath + "'");
|
||||
}
|
||||
|
||||
const SenseApiDesc &libApiDesc = func();
|
||||
auto lib = std::make_unique<SenseApiLib>(
|
||||
libraryPath, dlopen_handle.release(), func);
|
||||
lib->setSenseApiDesc(libApiDesc);
|
||||
@@ -173,24 +164,24 @@ std::string SenseApiManager::stringifyLibs() const
|
||||
|
||||
void SenseApiManager::initializeSenseApiLib(SenseApiLib& lib)
|
||||
{
|
||||
if (!lib.senseApiDesc.sal_mgmt_libOps->initializeInd)
|
||||
if (!lib.senseApiDesc.sal_mgmt_libOps.initializeInd)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": initializeInd() is NULL for library '"
|
||||
+ lib.libraryPath + "'");
|
||||
}
|
||||
lib.senseApiDesc.sal_mgmt_libOps->initializeInd();
|
||||
lib.senseApiDesc.sal_mgmt_libOps.initializeInd();
|
||||
}
|
||||
|
||||
void SenseApiManager::finalizeSenseApiLib(SenseApiLib& lib)
|
||||
{
|
||||
if (!lib.senseApiDesc.sal_mgmt_libOps->finalizeInd)
|
||||
if (!lib.senseApiDesc.sal_mgmt_libOps.finalizeInd)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": finalizeInd() is NULL for library '"
|
||||
+ lib.libraryPath + "'");
|
||||
}
|
||||
lib.senseApiDesc.sal_mgmt_libOps->finalizeInd();
|
||||
lib.senseApiDesc.sal_mgmt_libOps.finalizeInd();
|
||||
}
|
||||
|
||||
void SenseApiManager::initializeAllSenseApiLibs(void)
|
||||
@@ -207,7 +198,7 @@ void SenseApiManager::finalizeAllSenseApiLibs(void)
|
||||
}
|
||||
}
|
||||
|
||||
void SenseApiManager::attachSenseDevice(const SenseDeviceSpec& spec)
|
||||
void SenseApiManager::attachSenseDevice(const device::SenseDeviceSpec& spec)
|
||||
{
|
||||
auto libOpt = getSenseApiLibByApiName(spec.api);
|
||||
if (!libOpt)
|
||||
@@ -217,17 +208,16 @@ void SenseApiManager::attachSenseDevice(const SenseDeviceSpec& spec)
|
||||
+ spec.api + "'");
|
||||
}
|
||||
auto& lib = libOpt.value().get();
|
||||
if (!lib.senseApiDesc.sal_mgmt_libOps->attachDeviceReq)
|
||||
if (!lib.senseApiDesc.sal_mgmt_libOps.attachDeviceReq)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": attachDeviceReq() is NULL for library '"
|
||||
+ lib.libraryPath + "'");
|
||||
}
|
||||
CSenseDeviceSpec cSpec(spec);
|
||||
lib.senseApiDesc.sal_mgmt_libOps->attachDeviceReq(&cSpec);
|
||||
lib.senseApiDesc.sal_mgmt_libOps.attachDeviceReq(&spec);
|
||||
}
|
||||
|
||||
void SenseApiManager::detachSenseDevice(const SenseDeviceSpec& spec)
|
||||
void SenseApiManager::detachSenseDevice(const device::SenseDeviceSpec& spec)
|
||||
{
|
||||
auto libOpt = getSenseApiLibByApiName(spec.api);
|
||||
if (!libOpt)
|
||||
@@ -237,26 +227,25 @@ void SenseApiManager::detachSenseDevice(const SenseDeviceSpec& spec)
|
||||
+ spec.api + "'");
|
||||
}
|
||||
auto& lib = libOpt.value().get();
|
||||
if (!lib.senseApiDesc.sal_mgmt_libOps->detachDeviceReq)
|
||||
if (!lib.senseApiDesc.sal_mgmt_libOps.detachDeviceReq)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": detachDeviceReq() is NULL for library '"
|
||||
+ lib.libraryPath + "'");
|
||||
}
|
||||
CSenseDeviceSpec cSpec(spec);
|
||||
lib.senseApiDesc.sal_mgmt_libOps->detachDeviceReq(&cSpec);
|
||||
lib.senseApiDesc.sal_mgmt_libOps.detachDeviceReq(&spec);
|
||||
}
|
||||
|
||||
void SenseApiManager::attachAllSenseDevicesFromSpecs(void)
|
||||
{
|
||||
for (const auto& spec : DeviceManager::senseDeviceSpecs) {
|
||||
for (const auto& spec : device::DeviceManager::senseDeviceSpecs) {
|
||||
attachSenseDevice(*spec);
|
||||
}
|
||||
}
|
||||
|
||||
void SenseApiManager::detachAllSenseDevices(void)
|
||||
{
|
||||
for (const auto& spec : DeviceManager::senseDeviceSpecs) {
|
||||
for (const auto& spec : device::DeviceManager::senseDeviceSpecs) {
|
||||
detachSenseDevice(*spec);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user