bloomberg/blazingmq

C Client API (Wrapper over the C++ API)

kaikulimu opened this issue · 7 comments

Is there an existing proposal for this?

  • I have searched the existing proposals

Is your feature request related to a problem?

C API is very useful in general, and can become a bridge for API in other languages as well.

Describe the solution you'd like

Since implementing a C API from ground-up would be too much effort, we plan to write a C wrapper over the existing C++ API.

Alternatives you considered

No response

@Simon-Sandrew and @jonathanadotey77 expressed interest in working on this project. They will be working on a basic wrapper on Q3/Q4 2023.

@hallfox For your awareness

Some points of note to get started:

  1. The bindings should be created in a new group called z_bmq
  2. The best component to start with is a set of headers for bmqa_session.h.
  3. There should be an opaque struct to manage the state of each class paired with a set of functions. Here's a sketch of what I'd expect:
// z_bmqa_session.h

#if defined(__cplusplus)
extern "C" {
#endif   /* __cplusplus */

typedef struct z_bmqa_Session z_bmqa_Session;

typedef struct z_bmqt_SessionOptions z_bmqt_SessionOptions;

typedef void* dummy_t;

// Just going to gloss over what this type should be for now.
typedef dummy_t z_bmqt_TimeInterval;

z_bmqa_Session* z_bmqa_Session__create(z_bmqa_Session** session, z_bmqt_SessionOptions* options);

int z_bmqa_Session__start(z_bmqa_Session* session, z_bmqt_TimeInterval timeout);
int z_bmqa_Session__stop(z_bmqa_Session* session, z_bmqt_TimeInterval timeout);

void z_bmqa_Session__destroy(z_bmqa_Session* session);

// z_bmqa_session.cpp

#include <bmqt_sessionoptions.h>
#include <bmqa_session.h>

z_bmqa_Session* z_bmqa_Session__create(z_bmqa_Session** session, z_bmqt_SessionOptions* options) {
    bmqt::Session* real_session = new bmqt::Session(reinterpret_cast<bmqt::SessionOptions>(options));

    // Constructors could fail in a number of ways. One thing we won't do in bmq is throw exceptions, so you
    // generally don't have to check for that. Still good to be aware of though.
    if (!session_is_valid(real_session)) {
        delete real_session;
        return NULL;
    }
    
    *session = reinterpret_cast<z_bmqa_Session*>(real_session);
    return *session;
}

void z_bmqa_Session__destroy(z_bmqa_Session* session) {
    delete session;
}

int z_bmqa_Session__start(z_bmqa_Session* session, z_bmqt_TimeInterval timeout) {
    // Stub
    return -1;
}

int z_bmqa_Session__stop(z_bmqa_Session* session, z_bmqt_TimeInterval timeout) {
    // Stub
    return -1;
}

// More member functions...
// We shouldn't be implementing wrapper functions for anything marked DEPRECATED

// Example usage
int main() {
    z_bmqa_Session* session = NULL;
    z_bmqt_SessionOptions* options = ...;

    z_bmqa_Session__create(&session, options);
    if (session == NULL) {
        // fail state
    }

    return 0;
}

#if defined(__cplusplus)
}
#endif   /* __cplusplus */

For session and message events:

typedef void(*z_bmqa_OnSessionEvent)(const z_bmqa_SessionEvent* event);
typedef void(*z_bmqa_OnMessageEvent)(const z_bmqa_MessageEvent* event);

struct z_bmqa_SessionEventHandler {
    z_bmqa_OnSessionEvent event_cb;
    z_bmqa_OnMessageEvent message_cb;
};

z_bmqa_SessionEventHandler event_handler = {
    .event_cb = my_event_fp,
    .message_cb = my_message_fp
};

z_bmqa_Session__create(&my_session, &event_handler, options);

@Simon-Sandrew and @jonathanadotey77 expressed interest in working on this project. They will be working on a basic wrapper on Q3/Q4 2023.

Has work on this issue begun ? I would be interested in contributing here.

Simon and Jon has been working on this project under Taylor and my guidance.

Me and Simon are pushing to this repository for now.