-
Notifications
You must be signed in to change notification settings - Fork 13
Description
I've been looking into the C API definitions in dave.h and noticed a significant limitation regarding callback handling.
Currently, the callback typedefs (like DAVEMLSFailureCallback and DAVEPairwiseFingerprintCallback) are defined as plain function pointers without a user context parameter:
Lines 61 to 67 in 74979cb
| typedef void (*DAVEMLSFailureCallback)(const char* source, const char* reason); | |
| typedef void (*DAVEPairwiseFingerprintCallback)(const uint8_t* fingerprint, size_t length); | |
| typedef void (*DAVEEncryptorProtocolVersionChangedCallback)(void); | |
| typedef void (*DAVELogSinkCallback)(DAVELoggingSeverity severity, | |
| const char* file, | |
| int line, | |
| const char* message); |
And the registration functions do not accept a context pointer to pass through:
Lines 91 to 93 in 74979cb
| DAVE_EXPORT DAVESessionHandle daveSessionCreate(void* context, | |
| const char* authSessionId, | |
| DAVEMLSFailureCallback callback); |
The Problem
While the underlying C++ implementation uses std::function (which supports capturing state/this), the C API strips this context away.
This makes it effectively impossible to map a callback invocation back to a specific session instance or language-level object without resorting to unsafe global state or thread-local storage.
For consumers using C++ or things like JNI, this isn't strictly a blocker because we can wrap the C++ API directly. However, for any consumer attempting to use the C API via FFI mechanisms (like Java's JNA/Project Panama, C# P/Invoke, Python ctypes, or Rust bindgen), this is a major pain point.
To make this work currently with FFI, one would have to resort to extreme hacks, like JIT-compiling a unique trampoline function for every session instance just to bake the instance pointer into the instruction stream.
Suggested Fix
Add a void* user_data argument to every callback type definition and any function consuming the callback.
The signatures should ideally look something like this:
typedef void (*DAVEMLSFailureCallback)(void* user_data, const char* source, const char* reason);
DAVE_EXPORT DAVESessionHandle daveSessionCreate(void* context,
const char* authSessionId,
DAVEMLSFailureCallback callback,
void* user_data); // <--- Passed back to callback