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:
+75
-66
@@ -5,24 +5,18 @@
|
||||
#include <stdbool.h>
|
||||
#include <user/senseDeviceSpec.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
namespace hk {
|
||||
namespace sense_api {
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
struct CExportedImplexorApiDesc
|
||||
{
|
||||
const char *name;
|
||||
};
|
||||
|
||||
typedef int (sal_mho_initializeRdyFn)(void);
|
||||
typedef int (sal_mho_finalizeRdyFn)(void);
|
||||
typedef int (sal_mho_attachDeviceAckFn)(const CSenseDeviceSpec *const desc);
|
||||
typedef int (sal_mho_detachDeviceAckFn)(const CSenseDeviceSpec *const desc);
|
||||
typedef int (sal_mho_attachDeviceAckFn)(const device::SenseDeviceSpec *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.
|
||||
sal_mho_initializeRdyFn *initializeRdy;
|
||||
@@ -36,10 +30,10 @@ struct Csal_mgmt_hkOps
|
||||
|
||||
typedef int (sal_mlo_initializeIndFn)(void);
|
||||
typedef int (sal_mlo_finalizeIndFn)(void);
|
||||
typedef int (sal_mlo_attachDeviceReqFn)(const CSenseDeviceSpec *const desc);
|
||||
typedef int (sal_mlo_detachDeviceReqFn)(const CSenseDeviceSpec *const desc);
|
||||
typedef int (sal_mlo_attachDeviceReqFn)(const device::SenseDeviceSpec *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
|
||||
* 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;
|
||||
// When this returns, the device should be detached.
|
||||
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
|
||||
* provider.
|
||||
*/
|
||||
const char *name;
|
||||
/* These are the implexors whose APIs this lib exports.
|
||||
*/
|
||||
uint32_t numExportedImplexorApis;
|
||||
CExportedImplexorApiDesc *exportedImplexorApis;
|
||||
/* Sub-API for managing the lib. Library role within the API.
|
||||
*/
|
||||
Csal_mgmt_libOps *sal_mgmt_libOps;
|
||||
public:
|
||||
class ExportedImplexorApiDesc
|
||||
{
|
||||
public:
|
||||
ExportedImplexorApiDesc(const std::string name)
|
||||
// The caller should sanity check before calling this constructor.
|
||||
: name(name)
|
||||
{}
|
||||
|
||||
static bool sanityCheck(const ExportedImplexorApiDesc &desc)
|
||||
{
|
||||
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_STR \
|
||||
HK_QUOTE(HK_GET_SENSE_API_DESC_FN_NAME)
|
||||
|
||||
typedef const CSenseApiDesc *(getSenseApiDescFn)(void);
|
||||
typedef const SenseApiDesc &(getSenseApiDescFn)(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
} // namespace sense_api
|
||||
} // namespace hk
|
||||
|
||||
#endif // __USER_SENSE_API_LIB_H__
|
||||
|
||||
+35
-155
@@ -1,19 +1,32 @@
|
||||
#ifndef SENSORDEVICESPEC_H
|
||||
#define SENSORDEVICESPEC_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#endif // __cplusplus
|
||||
|
||||
#ifdef __cplusplus
|
||||
struct SenseDeviceSpec
|
||||
namespace hk {
|
||||
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;
|
||||
std::string implexor;
|
||||
std::string api;
|
||||
@@ -22,168 +35,35 @@ struct SenseDeviceSpec
|
||||
std::vector<std::string> providerParams;
|
||||
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::ostringstream os;
|
||||
os << "Device: " << sensorType << ", Implexor: "
|
||||
<< (implexor ? implexor : "NULL") << ", API: "
|
||||
<< (api ? api : "NULL") << ", API Params: (";
|
||||
if (apiParams)
|
||||
<< implexor << ", API: " << api << ", API Params: (";
|
||||
for (const auto& param : apiParams)
|
||||
{
|
||||
for (size_t i = 0; apiParams[i] != nullptr; ++i)
|
||||
{
|
||||
os << apiParams[i] << (apiParams[i + 1] == nullptr ? "" : " ");
|
||||
}
|
||||
os << param << " ";
|
||||
}
|
||||
os << "), Provider: " << (provider ? provider : "NULL")
|
||||
<< ", Provider Params: (";
|
||||
if (providerParams)
|
||||
os << "), Provider: " << provider << ", Provider Params: (";
|
||||
for (const auto& param : providerParams)
|
||||
{
|
||||
for (size_t i = 0; providerParams[i] != nullptr; ++i)
|
||||
{
|
||||
os << providerParams[i] << (providerParams[i + 1] == nullptr ? "" : " ");
|
||||
}
|
||||
os << param << " ";
|
||||
}
|
||||
os << "), Device Selector: "
|
||||
<< (deviceSelector ? deviceSelector : "NULL") << std::endl;
|
||||
os << "), Device Selector: " << deviceSelector << std::endl;
|
||||
|
||||
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
|
||||
}
|
||||
#endif
|
||||
class ExtrospectorDeviceSpec : public SenseDeviceSpec
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace device
|
||||
} // namespace hk
|
||||
|
||||
#endif // SENSORDEVICESPEC_H
|
||||
|
||||
Reference in New Issue
Block a user