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
+75 -66
View File
@@ -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__