Skip to content

Feature request: expose service discovery to the C API #346

Description

@TPfitzer

Summary

Add a C-API entry point that lets a participant be notified whenever a service
(controller, link, pub/sub, RPC endpoint, …) is created or removed anywhere in
the simulation
.

SIL Kit already has this capability internally
(SilKit::Core::Discovery::IServiceDiscovery::RegisterServiceDiscoveryHandler).
However, it lives in internal headers (SilKit/source/core/service/…) and is not reachable from the public C or C++
API. This request is to surface it through the public C API.

Motivation / use case

Tools and integrations built on top of SIL Kit often need to know which
controllers exist in a running simulation
— not from each participant's static
configuration, but from what is actually present at runtime (participants join and
leave dynamically, and the configuration is not always available to the consumer).

Today the options for a C-API integrator are:

  • SystemMonitor participant connect/disconnect — too coarse. It is
    participant-level, not service-level; it does not indicate which
    CAN/LIN/Ethernet controllers or pub/sub/RPC endpoints a participant exposes.
  • Parsing participant configuration files — brittle, requires the consumer to
    have every config, and does not reflect runtime reality.
  • Reaching into internal headers (IServiceDiscovery.hpp,
    IParticipantInternal.hpp) — not supportable across versions and not available
    to C-API-only consumers.

A service-level discovery callback solves this directly and matches what the
internal machinery already provides.

Proposed API

// silkit/capi/ServiceDiscovery.h

typedef uint32_t SilKit_NetworkType;            // Undefined/Invalid/CAN/LIN/Ethernet/FlexRay/Data/RPC
typedef uint32_t SilKit_ServiceType;            // Undefined/Link/Controller/SimulatedController/InternalController
typedef uint32_t SilKit_ServiceDiscoveryEventType; // Invalid/ServiceCreated/ServiceRemoved

typedef struct
{
    SilKit_StructHeader structHeader;
    const char* participantName;
    const char* networkName;
    const char* serviceName;
    SilKit_NetworkType               networkType;
    SilKit_ServiceType               serviceType;
    SilKit_ServiceDiscoveryEventType eventType;
} SilKit_ServiceDiscoveryEvent;

typedef void (SilKitFPTR* SilKit_ServiceDiscoveryHandler_t)(
    void* context,
    SilKit_Participant* participant,
    const SilKit_ServiceDiscoveryEvent* discoveryEvent);

SilKitAPI SilKit_ReturnCode SilKitCALL
SilKit_Participant_SetServiceDiscoveryHandler(
    SilKit_Participant* participant,
    void* context,
    SilKit_ServiceDiscoveryHandler_t handler);

Behaviour

  • On registration, the handler is invoked immediately for every service already
    known to the participant (consistent with the internal
    RegisterServiceDiscoveryHandler semantics).
  • Afterwards it is invoked on every ServiceCreated / ServiceRemoved event.
  • Callbacks arrive on the I/O worker thread, so handlers should be lightweight —
    this should be documented on the function.
  • The event exposes participant name, network name, service name, network type,
    service type, and the event type, mapped from the internal ServiceDescriptor.

Implementation notes

We have a working implementation and would be glad to open a PR if there is
interest:

  • A new public header SilKit/include/silkit/capi/ServiceDiscovery.h (above).
  • A translation unit implementing
    SilKit_Participant_SetServiceDiscoveryHandler: it resolves the participant to
    IParticipantInternal, obtains the IServiceDiscovery, registers a handler,
    and marshals each ServiceDescriptor + event type into the C struct.

The change is additive — it exposes existing internal functionality and does not
alter current behaviour.

Open questions for maintainers

  1. Is exposing service discovery through the public C API acceptable? If you would
    rather keep it internal, is there a recommended supported way to enumerate
    services at runtime from the C API?
  2. Preferred naming / placement if you would shape it differently.
  3. Should a snapshot accessor (the internal GetServices()) also be exposed, in
    addition to the event-driven handler?
  4. Is a matching public C++ API desired alongside the C binding?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions