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:
2025-01-13 21:57:11 -04:00
parent a4f96c8dfa
commit 09caf314f1
11 changed files with 197 additions and 377 deletions
+8 -2
View File
@@ -8,6 +8,9 @@
#include <opts.h> #include <opts.h>
#include <deviceManager/deviceManager.h> #include <deviceManager/deviceManager.h>
namespace hk {
namespace device {
std::vector<std::shared_ptr<InteroceptorDeviceSpec>> std::vector<std::shared_ptr<InteroceptorDeviceSpec>>
DeviceManager::interoceptorDeviceSpecs; DeviceManager::interoceptorDeviceSpecs;
std::vector<std::shared_ptr<ExtrospectorDeviceSpec>> std::vector<std::shared_ptr<ExtrospectorDeviceSpec>>
@@ -20,12 +23,15 @@ const std::string DeviceManager::stringifyDeviceSpecs(void)
std::ostringstream oss; std::ostringstream oss;
for (const auto& spec : DeviceManager::interoceptorDeviceSpecs) { for (const auto& spec : DeviceManager::interoceptorDeviceSpecs) {
oss << "Interoceptor " << CSenseDeviceSpec(*spec); oss << "Interoceptor " << spec->stringify();
} }
for (const auto& spec : DeviceManager::extrospectorDeviceSpecs) { for (const auto& spec : DeviceManager::extrospectorDeviceSpecs) {
oss << "Extrospector " << CSenseDeviceSpec(*spec); oss << "Extrospector " << spec->stringify();
} }
return oss.str(); return oss.str();
} }
} // namespace device
} // namespace hk
+6
View File
@@ -10,6 +10,9 @@
#include "deviceSpecp.hh" #include "deviceSpecp.hh"
#include "deviceSpecl.hh" #include "deviceSpecl.hh"
namespace hk {
namespace device {
std::string DeviceManager::readDeviceFile(const std::string& filename) std::string DeviceManager::readDeviceFile(const std::string& filename)
{ {
std::ifstream file(filename); std::ifstream file(filename);
@@ -61,3 +64,6 @@ void DeviceManager::parseAllDeviceSpecs(void)
"Check specs for errors"); "Check specs for errors");
} }
} }
} // namespace device
} // namespace hk
+12 -12
View File
@@ -39,9 +39,9 @@ void yyerror(const char *message)
%union { %union {
char* str; char* str;
char chr; char chr;
SenseDeviceSpec* sensorSpec; hk::device::SenseDeviceSpec* sensorSpec;
InteroceptorDeviceSpec* interoceptorSpec; hk::device::InteroceptorDeviceSpec* interoceptorSpec;
ExtrospectorDeviceSpec* extrospectorSpec; hk::device::ExtrospectorDeviceSpec* extrospectorSpec;
std::vector<std::string>* stringVector; std::vector<std::string>* stringVector;
} }
@@ -73,12 +73,12 @@ sensor_spec:
interoceptor_spec: interoceptor_spec:
KEYWORD_SPECTYPE_INTEROSPECTOR PIPE spec_body { KEYWORD_SPECTYPE_INTEROSPECTOR PIPE spec_body {
auto spec = std::make_shared<InteroceptorDeviceSpec>( auto spec = std::make_shared<hk::device::InteroceptorDeviceSpec>(
*static_cast<InteroceptorDeviceSpec *>($3)); *static_cast<hk::device::InteroceptorDeviceSpec *>($3));
spec->sensorType = $1; spec->sensorType = $1;
DeviceManager::interoceptorDeviceSpecs.push_back(spec); hk::device::DeviceManager::interoceptorDeviceSpecs.push_back(spec);
DeviceManager::senseDeviceSpecs.push_back(spec); hk::device::DeviceManager::senseDeviceSpecs.push_back(spec);
delete $3; delete $3;
} }
@@ -86,12 +86,12 @@ interoceptor_spec:
extrospector_spec: extrospector_spec:
KEYWORD_SPECTYPE_EXTROSPECTOR PIPE spec_body { KEYWORD_SPECTYPE_EXTROSPECTOR PIPE spec_body {
auto spec = std::make_shared<ExtrospectorDeviceSpec>( auto spec = std::make_shared<hk::device::ExtrospectorDeviceSpec>(
*static_cast<ExtrospectorDeviceSpec *>($3)); *static_cast<hk::device::ExtrospectorDeviceSpec *>($3));
spec->sensorType = $1; spec->sensorType = $1;
DeviceManager::extrospectorDeviceSpecs.push_back(spec); hk::device::DeviceManager::extrospectorDeviceSpecs.push_back(spec);
DeviceManager::senseDeviceSpecs.push_back(spec); hk::device::DeviceManager::senseDeviceSpecs.push_back(spec);
delete $3; delete $3;
} }
@@ -99,7 +99,7 @@ extrospector_spec:
spec_body: spec_body:
STRING PIPE STRING LPAREN opt_params RPAREN PIPE STRING LPAREN opt_params RPAREN PIPE STRING { STRING PIPE STRING LPAREN opt_params RPAREN PIPE STRING LPAREN opt_params RPAREN PIPE STRING {
$$ = new SenseDeviceSpec(); $$ = new hk::device::SenseDeviceSpec();
$$->sensorType = '\0'; $$->sensorType = '\0';
$$->implexor = std::string($1); $$->implexor = std::string($1);
$$->api = std::string($3); $$->api = std::string($3);
@@ -9,6 +9,9 @@
#include <iostream> #include <iostream>
#include <user/senseDeviceSpec.h> #include <user/senseDeviceSpec.h>
namespace hk {
namespace device {
class DeviceManager class DeviceManager
{ {
public: public:
@@ -39,4 +42,7 @@ public:
senseDeviceSpecs; senseDeviceSpecs;
}; };
} // namespace device
} // namespace hk
#endif // DEVICEMANAGER_H #endif // DEVICEMANAGER_H
+5 -69
View File
@@ -11,59 +11,6 @@
namespace hk { namespace hk {
namespace sense_api { 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 class SenseApiLib
{ {
private: private:
@@ -86,27 +33,16 @@ public:
HK_GET_SENSE_API_DESC_FN_NAME(descFn) HK_GET_SENSE_API_DESC_FN_NAME(descFn)
{} {}
void setSenseApiDesc(const CSenseApiDesc* desc) void setSenseApiDesc(const SenseApiDesc &desc)
{ {
if (!CSenseApiDesc_sanityCheck(desc) || if (!SenseApiDesc::sanityCheck(desc))
!Csal_mgmt_libOps_sanityCheck(desc->sal_mgmt_libOps))
{ {
throw std::runtime_error( throw std::runtime_error(
std::string(__func__) + ": Sanity check failed for sense API " std::string(__func__) + ": Sanity check failed for sense API "
"descriptor in library '" + libraryPath + "'"); "descriptor in library '" + libraryPath + "'");
} }
for (uint32_t i = 0; i < desc->numExportedImplexorApis; ++i)
{ senseApiDesc = desc;
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
} }
public: public:
@@ -119,7 +55,7 @@ public:
/** /**
* @brief Every sense API lib is required to provide a function that returns * @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. * connect Harikoff to the sense provider it supports.
* *
* This getter function should be visible to dlsym() so that Harikoff can * This getter function should be visible to dlsym() so that Harikoff can
+2 -2
View File
@@ -38,8 +38,8 @@ public:
void finalizeAllSenseApiLibs(void); void finalizeAllSenseApiLibs(void);
void attachAllSenseDevicesFromSpecs(void); void attachAllSenseDevicesFromSpecs(void);
void attachSenseDevice(const SenseDeviceSpec& spec); void attachSenseDevice(const device::SenseDeviceSpec& spec);
void detachSenseDevice(const SenseDeviceSpec& spec); void detachSenseDevice(const device::SenseDeviceSpec& spec);
void detachAllSenseDevices(void); void detachAllSenseDevices(void);
std::string stringifyLibs() const; std::string stringifyLibs() const;
+16 -27
View File
@@ -38,20 +38,18 @@ static std::optional<std::string> findLibraryPath(
std::cerr << std::string(__func__) + ": library '" std::cerr << std::string(__func__) + ": library '"
+ libraryPath + "' isn't in search bespoke search paths: "; + libraryPath + "' isn't in search bespoke search paths: ";
for (const auto& path : searchPaths) for (const auto& path : searchPaths) {
{
std::cerr << path << " "; std::cerr << path << " ";
} }
std::cerr << std::endl; std::cerr << std::endl;
std::cerr << "Trying to load " + libraryPath + " from system default search " std::cerr << "Trying to load " + libraryPath + " from system default "
"paths\n"; "search paths\n";
return std::nullopt; return std::nullopt;
} }
SenseApiLib& SenseApiManager::loadSenseApiLib(const std::string& libraryPath) SenseApiLib& SenseApiManager::loadSenseApiLib(const std::string& libraryPath)
{ {
const CSenseApiDesc *libApiDesc;
std::optional<std::string> fullPath = findLibraryPath(libraryPath); std::optional<std::string> fullPath = findLibraryPath(libraryPath);
std::string resolvedPath = fullPath.value_or(libraryPath); std::string resolvedPath = fullPath.value_or(libraryPath);
@@ -90,14 +88,7 @@ SenseApiLib& SenseApiManager::loadSenseApiLib(const std::string& libraryPath)
+ libraryPath + "'"); + libraryPath + "'");
} }
libApiDesc = func(); const SenseApiDesc &libApiDesc = func();
if (!libApiDesc)
{
throw std::runtime_error(
std::string(__func__) + ": getSenseApiDesc() returned NULL for "
"library '" + libraryPath + "'");
}
auto lib = std::make_unique<SenseApiLib>( auto lib = std::make_unique<SenseApiLib>(
libraryPath, dlopen_handle.release(), func); libraryPath, dlopen_handle.release(), func);
lib->setSenseApiDesc(libApiDesc); lib->setSenseApiDesc(libApiDesc);
@@ -173,24 +164,24 @@ std::string SenseApiManager::stringifyLibs() const
void SenseApiManager::initializeSenseApiLib(SenseApiLib& lib) void SenseApiManager::initializeSenseApiLib(SenseApiLib& lib)
{ {
if (!lib.senseApiDesc.sal_mgmt_libOps->initializeInd) if (!lib.senseApiDesc.sal_mgmt_libOps.initializeInd)
{ {
throw std::runtime_error( throw std::runtime_error(
std::string(__func__) + ": initializeInd() is NULL for library '" std::string(__func__) + ": initializeInd() is NULL for library '"
+ lib.libraryPath + "'"); + lib.libraryPath + "'");
} }
lib.senseApiDesc.sal_mgmt_libOps->initializeInd(); lib.senseApiDesc.sal_mgmt_libOps.initializeInd();
} }
void SenseApiManager::finalizeSenseApiLib(SenseApiLib& lib) void SenseApiManager::finalizeSenseApiLib(SenseApiLib& lib)
{ {
if (!lib.senseApiDesc.sal_mgmt_libOps->finalizeInd) if (!lib.senseApiDesc.sal_mgmt_libOps.finalizeInd)
{ {
throw std::runtime_error( throw std::runtime_error(
std::string(__func__) + ": finalizeInd() is NULL for library '" std::string(__func__) + ": finalizeInd() is NULL for library '"
+ lib.libraryPath + "'"); + lib.libraryPath + "'");
} }
lib.senseApiDesc.sal_mgmt_libOps->finalizeInd(); lib.senseApiDesc.sal_mgmt_libOps.finalizeInd();
} }
void SenseApiManager::initializeAllSenseApiLibs(void) 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); auto libOpt = getSenseApiLibByApiName(spec.api);
if (!libOpt) if (!libOpt)
@@ -217,17 +208,16 @@ void SenseApiManager::attachSenseDevice(const SenseDeviceSpec& spec)
+ spec.api + "'"); + spec.api + "'");
} }
auto& lib = libOpt.value().get(); auto& lib = libOpt.value().get();
if (!lib.senseApiDesc.sal_mgmt_libOps->attachDeviceReq) if (!lib.senseApiDesc.sal_mgmt_libOps.attachDeviceReq)
{ {
throw std::runtime_error( throw std::runtime_error(
std::string(__func__) + ": attachDeviceReq() is NULL for library '" std::string(__func__) + ": attachDeviceReq() is NULL for library '"
+ lib.libraryPath + "'"); + lib.libraryPath + "'");
} }
CSenseDeviceSpec cSpec(spec); lib.senseApiDesc.sal_mgmt_libOps.attachDeviceReq(&spec);
lib.senseApiDesc.sal_mgmt_libOps->attachDeviceReq(&cSpec);
} }
void SenseApiManager::detachSenseDevice(const SenseDeviceSpec& spec) void SenseApiManager::detachSenseDevice(const device::SenseDeviceSpec& spec)
{ {
auto libOpt = getSenseApiLibByApiName(spec.api); auto libOpt = getSenseApiLibByApiName(spec.api);
if (!libOpt) if (!libOpt)
@@ -237,26 +227,25 @@ void SenseApiManager::detachSenseDevice(const SenseDeviceSpec& spec)
+ spec.api + "'"); + spec.api + "'");
} }
auto& lib = libOpt.value().get(); auto& lib = libOpt.value().get();
if (!lib.senseApiDesc.sal_mgmt_libOps->detachDeviceReq) if (!lib.senseApiDesc.sal_mgmt_libOps.detachDeviceReq)
{ {
throw std::runtime_error( throw std::runtime_error(
std::string(__func__) + ": detachDeviceReq() is NULL for library '" std::string(__func__) + ": detachDeviceReq() is NULL for library '"
+ lib.libraryPath + "'"); + lib.libraryPath + "'");
} }
CSenseDeviceSpec cSpec(spec); lib.senseApiDesc.sal_mgmt_libOps.detachDeviceReq(&spec);
lib.senseApiDesc.sal_mgmt_libOps->detachDeviceReq(&cSpec);
} }
void SenseApiManager::attachAllSenseDevicesFromSpecs(void) void SenseApiManager::attachAllSenseDevicesFromSpecs(void)
{ {
for (const auto& spec : DeviceManager::senseDeviceSpecs) { for (const auto& spec : device::DeviceManager::senseDeviceSpecs) {
attachSenseDevice(*spec); attachSenseDevice(*spec);
} }
} }
void SenseApiManager::detachAllSenseDevices(void) void SenseApiManager::detachAllSenseDevices(void)
{ {
for (const auto& spec : DeviceManager::senseDeviceSpecs) { for (const auto& spec : device::DeviceManager::senseDeviceSpecs) {
detachSenseDevice(*spec); detachSenseDevice(*spec);
} }
} }
+75 -66
View File
@@ -5,24 +5,18 @@
#include <stdbool.h> #include <stdbool.h>
#include <user/senseDeviceSpec.h> #include <user/senseDeviceSpec.h>
#ifdef __cplusplus namespace hk {
extern "C" { namespace sense_api {
#endif
/* Exported by all sense API Libraries to tell Harikoff what API the lib uses /* Exported by all sense API Libraries to tell Harikoff what API the lib uses
* to connect to providers; and also to state which implexor APIs it exports. * to connect to providers; and also to state which implexor APIs it exports.
*/ */
struct CExportedImplexorApiDesc
{
const char *name;
};
typedef int (sal_mho_initializeRdyFn)(void); typedef int (sal_mho_initializeRdyFn)(void);
typedef int (sal_mho_finalizeRdyFn)(void); typedef int (sal_mho_finalizeRdyFn)(void);
typedef int (sal_mho_attachDeviceAckFn)(const CSenseDeviceSpec *const desc); typedef int (sal_mho_attachDeviceAckFn)(const device::SenseDeviceSpec *const desc);
typedef int (sal_mho_detachDeviceAckFn)(const CSenseDeviceSpec *const desc); typedef int (sal_mho_detachDeviceAckFn)(const device::SenseDeviceSpec *const desc);
struct Csal_mgmt_hkOps struct Sal_Mgmt_HkOps
{ {
// Lib calls this function to notify Harikoff that it's done initializing. // Lib calls this function to notify Harikoff that it's done initializing.
sal_mho_initializeRdyFn *initializeRdy; sal_mho_initializeRdyFn *initializeRdy;
@@ -36,10 +30,10 @@ struct Csal_mgmt_hkOps
typedef int (sal_mlo_initializeIndFn)(void); typedef int (sal_mlo_initializeIndFn)(void);
typedef int (sal_mlo_finalizeIndFn)(void); typedef int (sal_mlo_finalizeIndFn)(void);
typedef int (sal_mlo_attachDeviceReqFn)(const CSenseDeviceSpec *const desc); typedef int (sal_mlo_attachDeviceReqFn)(const device::SenseDeviceSpec *const desc);
typedef int (sal_mlo_detachDeviceReqFn)(const CSenseDeviceSpec *const desc); typedef int (sal_mlo_detachDeviceReqFn)(const device::SenseDeviceSpec *const desc);
struct Csal_mgmt_libOps struct Sal_Mgmt_LibOps
{ {
/* When Harikoff loads a sense API lib, it calls this function to initialize /* When Harikoff loads a sense API lib, it calls this function to initialize
* the lib. When this returns, the lib should be ready to attach devices. * the lib. When this returns, the lib should be ready to attach devices.
@@ -55,67 +49,82 @@ struct Csal_mgmt_libOps
sal_mlo_attachDeviceReqFn *attachDeviceReq; sal_mlo_attachDeviceReqFn *attachDeviceReq;
// When this returns, the device should be detached. // When this returns, the device should be detached.
sal_mlo_detachDeviceReqFn *detachDeviceReq; sal_mlo_detachDeviceReqFn *detachDeviceReq;
static bool sanityCheck(const Sal_Mgmt_LibOps &ops)
{
if (!ops.initializeInd || !ops.finalizeInd
|| !ops.attachDeviceReq || !ops.detachDeviceReq)
{
return false;
}
return true;
}
}; };
struct CSenseApiDesc /* C++ version of the C struct above, which Harikoff uses to manage the
* lib and connect implexors to it.
*/
class SenseApiDesc
{ {
/* Shortname that identifies the API used by this lib to talk to the sense public:
* provider. class ExportedImplexorApiDesc
*/ {
const char *name; public:
/* These are the implexors whose APIs this lib exports. ExportedImplexorApiDesc(const std::string name)
*/ // The caller should sanity check before calling this constructor.
uint32_t numExportedImplexorApis; : name(name)
CExportedImplexorApiDesc *exportedImplexorApis; {}
/* Sub-API for managing the lib. Library role within the API.
*/ static bool sanityCheck(const ExportedImplexorApiDesc &desc)
Csal_mgmt_libOps *sal_mgmt_libOps; {
if (desc.name.empty()) { return false; }
return true;
}
public:
std::string name;
};
public:
SenseApiDesc() = default;
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;
}
static bool sanityCheck(const SenseApiDesc &desc)
{
if (desc.name.empty() || desc.exportedImplexorApis.empty()) {
return false;
}
for (const auto& api : desc.exportedImplexorApis) {
if (!ExportedImplexorApiDesc::sanityCheck(api)) { return false; }
}
return Sal_Mgmt_LibOps::sanityCheck(desc.sal_mgmt_libOps);
}
std::string name;
// These are the implexors whose APIs this lib exports.
std::vector<ExportedImplexorApiDesc> exportedImplexorApis;
Sal_Mgmt_LibOps sal_mgmt_libOps;
}; };
static bool CSenseApiDesc_sanityCheck(const CSenseApiDesc *desc)
{
(void)CSenseApiDesc_sanityCheck;
if (!desc || !desc->name || desc->numExportedImplexorApis < 1
||!desc->exportedImplexorApis || !desc->sal_mgmt_libOps)
{
return false;
}
return true;
}
static bool CExportedImplexorApiDesc_sanityCheck(
const CExportedImplexorApiDesc *desc)
{
(void)CExportedImplexorApiDesc_sanityCheck;
if (!desc || !desc->name)
{
return false;
}
return true;
}
static bool Csal_mgmt_libOps_sanityCheck(const Csal_mgmt_libOps *ops)
{
(void)Csal_mgmt_libOps_sanityCheck;
if (!ops || !ops->initializeInd || !ops->finalizeInd
|| !ops->attachDeviceReq || !ops->detachDeviceReq)
{
return false;
}
return true;
}
#define HK_GET_SENSE_API_DESC_FN_NAME getSenseApiDesc #define HK_GET_SENSE_API_DESC_FN_NAME getSenseApiDesc
#define HK_GET_SENSE_API_DESC_FN_NAME_STR \ #define HK_GET_SENSE_API_DESC_FN_NAME_STR \
HK_QUOTE(HK_GET_SENSE_API_DESC_FN_NAME) HK_QUOTE(HK_GET_SENSE_API_DESC_FN_NAME)
typedef const CSenseApiDesc *(getSenseApiDescFn)(void); typedef const SenseApiDesc &(getSenseApiDescFn)(void);
#ifdef __cplusplus } // namespace sense_api
} } // namespace hk
#endif
#endif // __USER_SENSE_API_LIB_H__ #endif // __USER_SENSE_API_LIB_H__
+35 -155
View File
@@ -1,19 +1,32 @@
#ifndef SENSORDEVICESPEC_H #ifndef SENSORDEVICESPEC_H
#define SENSORDEVICESPEC_H #define SENSORDEVICESPEC_H
#include <stdlib.h>
#include <string.h>
#ifdef __cplusplus
#include <vector> #include <vector>
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#endif // __cplusplus
#ifdef __cplusplus namespace hk {
struct SenseDeviceSpec namespace device {
class SenseDeviceSpec
{ {
public:
friend std::ostream& operator<<(
std::ostream& os, const SenseDeviceSpec& spec)
{
os << spec.stringify();
return os;
}
bool operator==(const SenseDeviceSpec& other) const
{
return sensorType == other.sensorType &&
provider == other.provider &&
deviceSelector == other.deviceSelector;
}
public:
char sensorType; char sensorType;
std::string implexor; std::string implexor;
std::string api; std::string api;
@@ -22,168 +35,35 @@ struct SenseDeviceSpec
std::vector<std::string> providerParams; std::vector<std::string> providerParams;
std::string deviceSelector; std::string deviceSelector;
friend std::ostream& operator<<(
std::ostream& os, const SenseDeviceSpec& spec);
bool operator==(const SenseDeviceSpec& other) const
{
return sensorType == other.sensorType &&
provider == other.provider &&
deviceSelector == other.deviceSelector;
}
};
struct InteroceptorDeviceSpec : public SenseDeviceSpec
{
};
struct ExtrospectorDeviceSpec : public SenseDeviceSpec
{
};
#endif // __cplusplus
#ifdef __cplusplus
extern "C" {
#endif
struct CSenseDeviceSpec
{
#ifdef __cplusplus
CSenseDeviceSpec(const SenseDeviceSpec& spec)
: sensorType(spec.sensorType),
implexor(strdup(spec.implexor.c_str())),
api(strdup(spec.api.c_str())),
provider(strdup(spec.provider.c_str())),
deviceSelector(strdup(spec.deviceSelector.c_str()))
{
apiParams = new char*[spec.apiParams.size() + 1];
for (size_t i = 0; i < spec.apiParams.size(); ++i)
{
apiParams[i] = strdup(spec.apiParams[i].c_str());
}
apiParams[spec.apiParams.size()] = nullptr;
providerParams = new char*[spec.providerParams.size() + 1];
for (size_t i = 0; i < spec.providerParams.size(); ++i)
{
providerParams[i] = strdup(spec.providerParams[i].c_str());
}
providerParams[spec.providerParams.size()] = nullptr;
}
CSenseDeviceSpec(const CSenseDeviceSpec& other)
: sensorType(other.sensorType),
implexor(strdup(other.implexor)),
api(strdup(other.api)),
provider(strdup(other.provider)),
deviceSelector(strdup(other.deviceSelector))
{
if (other.apiParams) {
size_t apiParamsSize = 0;
while (other.apiParams[apiParamsSize] != nullptr) {
++apiParamsSize;
}
apiParams = new char*[apiParamsSize + 1];
for (size_t i = 0; i < apiParamsSize; ++i) {
apiParams[i] = strdup(other.apiParams[i]);
}
apiParams[apiParamsSize] = nullptr;
} else {
apiParams = nullptr;
}
if (other.providerParams) {
size_t providerParamsSize = 0;
while (other.providerParams[providerParamsSize] != nullptr) {
++providerParamsSize;
}
providerParams = new char*[providerParamsSize + 1];
for (size_t i = 0; i < providerParamsSize; ++i) {
providerParams[i] = strdup(other.providerParams[i]);
}
providerParams[providerParamsSize] = nullptr;
} else {
providerParams = nullptr;
}
}
~CSenseDeviceSpec(void)
{
free(implexor);
free(api);
free(provider);
free(deviceSelector);
if (apiParams)
{
for (size_t i = 0; apiParams[i] != nullptr; ++i) {
free(apiParams[i]);
}
}
delete[] apiParams;
if (providerParams)
{
for (size_t i = 0; providerParams[i] != nullptr; ++i) {
free(providerParams[i]);
}
}
delete[] providerParams;
}
std::string stringify() const std::string stringify() const
{ {
std::ostringstream os; std::ostringstream os;
os << "Device: " << sensorType << ", Implexor: " os << "Device: " << sensorType << ", Implexor: "
<< (implexor ? implexor : "NULL") << ", API: " << implexor << ", API: " << api << ", API Params: (";
<< (api ? api : "NULL") << ", API Params: ("; for (const auto& param : apiParams)
if (apiParams)
{ {
for (size_t i = 0; apiParams[i] != nullptr; ++i) os << param << " ";
{
os << apiParams[i] << (apiParams[i + 1] == nullptr ? "" : " ");
}
} }
os << "), Provider: " << (provider ? provider : "NULL") os << "), Provider: " << provider << ", Provider Params: (";
<< ", Provider Params: ("; for (const auto& param : providerParams)
if (providerParams)
{ {
for (size_t i = 0; providerParams[i] != nullptr; ++i) os << param << " ";
{
os << providerParams[i] << (providerParams[i + 1] == nullptr ? "" : " ");
}
} }
os << "), Device Selector: " os << "), Device Selector: " << deviceSelector << std::endl;
<< (deviceSelector ? deviceSelector : "NULL") << std::endl;
return os.str(); return os.str();
} }
bool operator==(const CSenseDeviceSpec& other) const
{
return sensorType == other.sensorType &&
strcmp(provider, other.provider) == 0 &&
strcmp(deviceSelector, other.deviceSelector) == 0;
}
#endif
char sensorType;
char *implexor;
char *api;
char **apiParams;
char *provider;
char **providerParams;
char *deviceSelector;
}; };
inline std::ostream& operator<<(std::ostream& os, const CSenseDeviceSpec& spec) class InteroceptorDeviceSpec : public SenseDeviceSpec
{ {
os << spec.stringify(); };
return os;
}
#ifdef __cplusplus class ExtrospectorDeviceSpec : public SenseDeviceSpec
} {
#endif };
} // namespace device
} // namespace hk
#endif // SENSORDEVICESPEC_H #endif // SENSORDEVICESPEC_H
+3 -3
View File
@@ -86,9 +86,9 @@ static int initializeHarikoff(int argc, char **argv, char **envp)
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
DeviceManager::getInstance().collateAllDeviceSpecs(); device::DeviceManager::getInstance().collateAllDeviceSpecs();
DeviceManager::getInstance().parseAllDeviceSpecs(); device::DeviceManager::getInstance().parseAllDeviceSpecs();
std::cout << DeviceManager::stringifyDeviceSpecs() << std::endl; std::cout << device::DeviceManager::stringifyDeviceSpecs() << std::endl;
sense_api::SenseApiManager::getInstance().loadAllSenseApiLibsFromOptions(); sense_api::SenseApiManager::getInstance().loadAllSenseApiLibsFromOptions();
std::cout << sense_api::SenseApiManager::getInstance().stringifyLibs() std::cout << sense_api::SenseApiManager::getInstance().stringifyLibs()
<< std::endl; << std::endl;
+29 -41
View File
@@ -3,23 +3,25 @@
#include <stdexcept> #include <stdexcept>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <user/senseDeviceSpec.h>
#include <user/senseApiDesc.h>
#include <xcb/xcb.h> #include <xcb/xcb.h>
#include "xcbXorg.h" #include "xcbXorg.h"
class AttachedDevice { class AttachedDevice {
public: public:
AttachedDevice(const CSenseDeviceSpec &spec) : deviceSpec(spec) {} AttachedDevice(const hk::device::SenseDeviceSpec &spec)
: deviceSpec(spec)
{}
const CSenseDeviceSpec& getSpec() const { const hk::device::SenseDeviceSpec& getSpec() const {
return deviceSpec; return deviceSpec;
} }
private: private:
CSenseDeviceSpec deviceSpec; hk::device::SenseDeviceSpec deviceSpec;
}; };
static std::vector<AttachedDevice> attachedDevices;
struct XcbConnectionInfo { struct XcbConnectionInfo {
std::unique_ptr<xcb_connection_t, decltype(&xcb_disconnect)> connection; std::unique_ptr<xcb_connection_t, decltype(&xcb_disconnect)> connection;
int screenNumber; int screenNumber;
@@ -29,44 +31,33 @@ struct XcbConnectionInfo {
}; };
static XcbConnectionInfo xcbConn; static XcbConnectionInfo xcbConn;
static std::vector<AttachedDevice> attachedDevices;
static CExportedImplexorApiDesc xcbXorgExportedImplexorApis[] = static hk::sense_api::sal_mlo_initializeIndFn xcbXorg_initializeInd;
static hk::sense_api::sal_mlo_finalizeIndFn xcbXorg_finalizeInd;
static hk::sense_api::sal_mlo_attachDeviceReqFn xcbXorg_attachDeviceReq;
static hk::sense_api::sal_mlo_detachDeviceReqFn xcbXorg_detachDeviceReq;
static hk::sense_api::SenseApiDesc xcbXorgApiDesc =
{ {
{ .name = "xcb-xorg",
.name = "video-implexor" .exportedImplexorApis = { { "video-implexor" } },
.sal_mgmt_libOps = {
.initializeInd = xcbXorg_initializeInd,
.finalizeInd = xcbXorg_finalizeInd,
.attachDeviceReq = xcbXorg_attachDeviceReq,
.detachDeviceReq = xcbXorg_detachDeviceReq
} }
}; };
static sal_mlo_initializeIndFn xcbXorg_initializeInd; extern HK_UNMANGLED hk::sense_api::getSenseApiDescFn
static sal_mlo_finalizeIndFn xcbXorg_finalizeInd; HK_GET_SENSE_API_DESC_FN_NAME;
static sal_mlo_attachDeviceReqFn xcbXorg_attachDeviceReq;
static sal_mlo_detachDeviceReqFn xcbXorg_detachDeviceReq;
static Csal_mgmt_libOps xcbXorgMgmtLibOps = const hk::sense_api::SenseApiDesc &HK_GET_SENSE_API_DESC_FN_NAME(void)
{ {
.initializeInd = xcbXorg_initializeInd, return xcbXorgApiDesc;
.finalizeInd = xcbXorg_finalizeInd,
.attachDeviceReq = xcbXorg_attachDeviceReq,
.detachDeviceReq = xcbXorg_detachDeviceReq
};
static CSenseApiDesc xcbXorgApiDesc =
{
.name = "xcb-xorg",
.numExportedImplexorApis = sizeof(xcbXorgExportedImplexorApis) /
sizeof(*xcbXorgExportedImplexorApis),
.exportedImplexorApis = xcbXorgExportedImplexorApis,
.sal_mgmt_libOps = &xcbXorgMgmtLibOps
};
extern HK_UNMANGLED getSenseApiDescFn HK_GET_SENSE_API_DESC_FN_NAME;
const CSenseApiDesc *HK_GET_SENSE_API_DESC_FN_NAME(void)
{
return &xcbXorgApiDesc;
} }
static sal_mlo_initializeIndFn xcbXorg_initializeInd;
int xcbXorg_initializeInd(void) int xcbXorg_initializeInd(void)
{ {
xcbConn.connection.reset( xcbConn.connection.reset(
@@ -83,7 +74,6 @@ int xcbXorg_initializeInd(void)
return 0; return 0;
} }
static sal_mlo_finalizeIndFn xcbXorg_finalizeInd;
int xcbXorg_finalizeInd(void) int xcbXorg_finalizeInd(void)
{ {
if (!xcbConn.connection) { if (!xcbConn.connection) {
@@ -94,22 +84,20 @@ int xcbXorg_finalizeInd(void)
return 0; return 0;
} }
static sal_mlo_attachDeviceReqFn xcbXorg_attachDeviceReq; int xcbXorg_attachDeviceReq(const hk::device::SenseDeviceSpec *const desc)
int xcbXorg_attachDeviceReq(const CSenseDeviceSpec *const desc)
{ {
attachedDevices.emplace_back(*desc); attachedDevices.emplace_back(*desc);
std::ostringstream os; std::ostringstream os;
for (const auto& device : attachedDevices) { for (const auto& device : attachedDevices) {
os << device.getSpec(); os << device.getSpec().stringify();
} }
std::cout << __func__ << ": >>>> Attaching device spec: " << *desc << "\n" std::cout << __func__ << ": >>>> Attaching device spec: " << desc->stringify() << "\n"
<< " >>>> Current attached devices:\n" << os.str(); << " >>>> Current attached devices:\n" << os.str();
return 0; return 0;
} }
static sal_mlo_detachDeviceReqFn xcbXorg_detachDeviceReq; int xcbXorg_detachDeviceReq(const hk::device::SenseDeviceSpec *const spec)
int xcbXorg_detachDeviceReq(const CSenseDeviceSpec *const spec)
{ {
auto it = std::remove_if(attachedDevices.begin(), attachedDevices.end(), auto it = std::remove_if(attachedDevices.begin(), attachedDevices.end(),
[spec](const AttachedDevice &device) { [spec](const AttachedDevice &device) {