Skip to content

Commit 6c263dd

Browse files
authored
fix: initialization of LDFlagListener (#218)
This commit moves the definition and implementation of `LDFlagListener` into `common`, so it can be easily shared with the server. Additionally, it fixes a bug in the specification of the `LDFlagListener_Init` method. It previously took `LDFlagListener` by value; now it takes a pointer. The impact would be if a user forgot to initialize the struct, then the member(s) would be undefined.
1 parent ef2a597 commit 6c263dd

File tree

6 files changed

+81
-53
lines changed

6 files changed

+81
-53
lines changed

libs/client-sdk/include/launchdarkly/client_side/bindings/c/sdk.h

Lines changed: 1 addition & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <launchdarkly/bindings/c/context.h>
1010
#include <launchdarkly/bindings/c/data/evaluation_detail.h>
1111
#include <launchdarkly/bindings/c/export.h>
12+
#include <launchdarkly/bindings/c/flag_listener.h>
1213
#include <launchdarkly/bindings/c/listener_connection.h>
1314
#include <launchdarkly/bindings/c/memory_routines.h>
1415
#include <launchdarkly/bindings/c/status.h>
@@ -412,52 +413,6 @@ LDClientSDK_AllFlags(LDClientSDK sdk);
412413
*/
413414
LD_EXPORT(void) LDClientSDK_Free(LDClientSDK sdk);
414415

415-
typedef void (*FlagChangedCallbackFn)(char const* flag_key,
416-
LDValue new_value,
417-
LDValue old_value,
418-
bool deleted,
419-
void* user_data);
420-
421-
/**
422-
* Defines a feature flag listener which may be used to listen for flag changes.
423-
* The struct should be initialized using LDFlagListener_Init before use.
424-
*/
425-
struct LDFlagListener {
426-
/**
427-
* Callback function which is invoked for flag changes.
428-
*
429-
* The provided pointers are only valid for the duration of the function
430-
* call (excluding UserData, whose lifetime is controlled by the caller).
431-
*
432-
* @param flag_key The name of the flag that changed.
433-
* @param new_value The new value of the flag. If there was not an new
434-
* value, because the flag was deleted, then the LDValue will be of a null
435-
* type. Check the deleted parameter to see if a flag was deleted.
436-
* @param old_value The old value of the flag. If there was not an old
437-
* value, for instance a newly created flag, then the Value will be of a
438-
* null type.
439-
* @param deleted True if the flag has been deleted.
440-
*/
441-
FlagChangedCallbackFn FlagChanged;
442-
443-
/**
444-
* UserData is forwarded into callback functions.
445-
*/
446-
void* UserData;
447-
};
448-
449-
/**
450-
* Initializes a flag listener. Must be called before passing the listener
451-
* to LDClientSDK_FlagNotifier_OnFlagChange.
452-
*
453-
* Create the struct, initialize the struct, set the FlagChanged handler
454-
* and optionally UserData, and then pass the struct to
455-
* LDClientSDK_FlagNotifier_OnFlagChange.
456-
*
457-
* @param listener Listener to initialize.
458-
*/
459-
LD_EXPORT(void) LDFlagListener_Init(struct LDFlagListener listener);
460-
461416
/**
462417
* Listen for changes for the specific flag.
463418
*

libs/client-sdk/src/bindings/c/sdk.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -377,11 +377,6 @@ LD_EXPORT(time_t) LDDataSourceStatus_StateSince(LDDataSourceStatus status) {
377377
.count();
378378
}
379379

380-
LD_EXPORT(void) LDFlagListener_Init(struct LDFlagListener listener) {
381-
listener.FlagChanged = nullptr;
382-
listener.UserData = nullptr;
383-
}
384-
385380
LD_EXPORT(LDDataSourceStatus_ErrorKind)
386381
LDDataSourceStatus_ErrorInfo_GetKind(LDDataSourceStatus_ErrorInfo info) {
387382
LD_ASSERT_NOT_NULL(info);

libs/client-sdk/tests/client_c_bindings_test.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,15 @@ TEST(ClientBindings, RegisterFlagListener) {
5959
LDClientSDK_Start(sdk, 3000, &success);
6060
EXPECT_TRUE(success);
6161

62-
struct LDFlagListener listener {};
63-
LDFlagListener_Init(listener);
62+
struct LDFlagListener listener {
63+
reinterpret_cast<FlagChangedCallbackFn>(0x123),
64+
reinterpret_cast<void*>(0x456)
65+
};
66+
67+
LDFlagListener_Init(&listener);
68+
ASSERT_EQ(listener.FlagChanged, nullptr);
69+
ASSERT_EQ(listener.UserData, nullptr);
70+
6471
listener.UserData = const_cast<char*>("Potato");
6572
listener.FlagChanged = FlagListenerFunction;
6673

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/** @file */
2+
// NOLINTBEGIN modernize-use-using
3+
4+
#pragma once
5+
6+
#include <launchdarkly/bindings/c/export.h>
7+
#include <launchdarkly/bindings/c/value.h>
8+
9+
#ifdef __cplusplus
10+
extern "C" { // only need to export C interface if
11+
// used by C++ source code
12+
#endif
13+
14+
typedef void (*FlagChangedCallbackFn)(char const* flag_key,
15+
LDValue new_value,
16+
LDValue old_value,
17+
bool deleted,
18+
void* user_data);
19+
20+
/**
21+
* Defines a feature flag listener which may be used to listen for flag changes.
22+
* The struct should be initialized using LDFlagListener_Init before use.
23+
*/
24+
struct LDFlagListener {
25+
/**
26+
* Callback function which is invoked for flag changes.
27+
*
28+
* The provided pointers are only valid for the duration of the function
29+
* call (excluding UserData, whose lifetime is controlled by the caller).
30+
*
31+
* @param flag_key The name of the flag that changed.
32+
* @param new_value The new value of the flag. If there was not an new
33+
* value, because the flag was deleted, then the LDValue will be of a null
34+
* type. Check the deleted parameter to see if a flag was deleted.
35+
* @param old_value The old value of the flag. If there was not an old
36+
* value, for instance a newly created flag, then the Value will be of a
37+
* null type.
38+
* @param deleted True if the flag has been deleted.
39+
*/
40+
FlagChangedCallbackFn FlagChanged;
41+
42+
/**
43+
* UserData is forwarded into callback functions.
44+
*/
45+
void* UserData;
46+
};
47+
48+
/**
49+
* Initializes a flag listener. Must be called before passing the listener
50+
* to LDClientSDK_FlagNotifier_OnFlagChange.
51+
*
52+
* Create the struct, initialize the struct, set the FlagChanged handler
53+
* and optionally UserData, and then pass the struct to
54+
* LDClientSDK_FlagNotifier_OnFlagChange.
55+
*
56+
* @param listener Listener to initialize.
57+
*/
58+
LD_EXPORT(void) LDFlagListener_Init(struct LDFlagListener* listener);
59+
60+
#ifdef __cplusplus
61+
}
62+
#endif
63+
64+
// NOLINTEND modernize-use-using

libs/common/src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ add_library(${LIBNAME} OBJECT
4646
bindings/c/config/logging_builder.cpp
4747
bindings/c/data/evaluation_detail.cpp
4848
bindings/c/listener_connection.cpp
49+
bindings/c/flag_listener.cpp
4950
bindings/c/memory_routines.cpp
5051
log_level.cpp
5152
config/persistence_builder.cpp
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include <launchdarkly/bindings/c/flag_listener.h>
2+
3+
LD_EXPORT(void) LDFlagListener_Init(struct LDFlagListener* listener) {
4+
listener->FlagChanged = nullptr;
5+
listener->UserData = nullptr;
6+
}

0 commit comments

Comments
 (0)