From 197bd5f7e412c070c1430abcba7e70fea5f0b709 Mon Sep 17 00:00:00 2001 From: Casey Waldren Date: Mon, 28 Aug 2023 14:14:29 -0700 Subject: [PATCH 1/3] extract LDFlagListener from client to common bindings --- .../launchdarkly/client_side/bindings/c/sdk.h | 47 +------------- .../launchdarkly/bindings/c/flag_listener.h | 63 +++++++++++++++++++ 2 files changed, 64 insertions(+), 46 deletions(-) create mode 100644 libs/common/include/launchdarkly/bindings/c/flag_listener.h diff --git a/libs/client-sdk/include/launchdarkly/client_side/bindings/c/sdk.h b/libs/client-sdk/include/launchdarkly/client_side/bindings/c/sdk.h index 2ca8eeb1a..67ab29330 100644 --- a/libs/client-sdk/include/launchdarkly/client_side/bindings/c/sdk.h +++ b/libs/client-sdk/include/launchdarkly/client_side/bindings/c/sdk.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -412,52 +413,6 @@ LDClientSDK_AllFlags(LDClientSDK sdk); */ LD_EXPORT(void) LDClientSDK_Free(LDClientSDK sdk); -typedef void (*FlagChangedCallbackFn)(char const* flag_key, - LDValue new_value, - LDValue old_value, - bool deleted, - void* user_data); - -/** - * Defines a feature flag listener which may be used to listen for flag changes. - * The struct should be initialized using LDFlagListener_Init before use. - */ -struct LDFlagListener { - /** - * Callback function which is invoked for flag changes. - * - * The provided pointers are only valid for the duration of the function - * call (excluding UserData, whose lifetime is controlled by the caller). - * - * @param flag_key The name of the flag that changed. - * @param new_value The new value of the flag. If there was not an new - * value, because the flag was deleted, then the LDValue will be of a null - * type. Check the deleted parameter to see if a flag was deleted. - * @param old_value The old value of the flag. If there was not an old - * value, for instance a newly created flag, then the Value will be of a - * null type. - * @param deleted True if the flag has been deleted. - */ - FlagChangedCallbackFn FlagChanged; - - /** - * UserData is forwarded into callback functions. - */ - void* UserData; -}; - -/** - * Initializes a flag listener. Must be called before passing the listener - * to LDClientSDK_FlagNotifier_OnFlagChange. - * - * Create the struct, initialize the struct, set the FlagChanged handler - * and optionally UserData, and then pass the struct to - * LDClientSDK_FlagNotifier_OnFlagChange. - * - * @param listener Listener to initialize. - */ -LD_EXPORT(void) LDFlagListener_Init(struct LDFlagListener listener); - /** * Listen for changes for the specific flag. * diff --git a/libs/common/include/launchdarkly/bindings/c/flag_listener.h b/libs/common/include/launchdarkly/bindings/c/flag_listener.h new file mode 100644 index 000000000..e7e87572a --- /dev/null +++ b/libs/common/include/launchdarkly/bindings/c/flag_listener.h @@ -0,0 +1,63 @@ +/** @file */ +// NOLINTBEGIN modernize-use-using + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { // only need to export C interface if +// used by C++ source code +#endif + +typedef void (*FlagChangedCallbackFn)(char const* flag_key, + LDValue new_value, + LDValue old_value, + bool deleted, + void* user_data); + +/** + * Defines a feature flag listener which may be used to listen for flag changes. + * The struct should be initialized using LDFlagListener_Init before use. + */ +struct LDFlagListener { + /** + * Callback function which is invoked for flag changes. + * + * The provided pointers are only valid for the duration of the function + * call (excluding UserData, whose lifetime is controlled by the caller). + * + * @param flag_key The name of the flag that changed. + * @param new_value The new value of the flag. If there was not an new + * value, because the flag was deleted, then the LDValue will be of a null + * type. Check the deleted parameter to see if a flag was deleted. + * @param old_value The old value of the flag. If there was not an old + * value, for instance a newly created flag, then the Value will be of a + * null type. + * @param deleted True if the flag has been deleted. + */ + FlagChangedCallbackFn FlagChanged; + + /** + * UserData is forwarded into callback functions. + */ + void* UserData; +}; + +/** + * Initializes a flag listener. Must be called before passing the listener + * to LDClientSDK_FlagNotifier_OnFlagChange. + * + * Create the struct, initialize the struct, set the FlagChanged handler + * and optionally UserData, and then pass the struct to + * LDClientSDK_FlagNotifier_OnFlagChange. + * + * @param listener Listener to initialize. + */ +LD_EXPORT(void) LDFlagListener_Init(struct LDFlagListener listener); + +#ifdef __cplusplus +} +#endif + +// NOLINTEND modernize-use-using From 9f17050e77e725fbfd30bdead05b5ef99cc29579 Mon Sep 17 00:00:00 2001 From: Casey Waldren Date: Mon, 28 Aug 2023 14:39:05 -0700 Subject: [PATCH 2/3] move implementation & fix LDFlagListener_Init --- libs/client-sdk/src/bindings/c/sdk.cpp | 5 ----- libs/common/include/launchdarkly/bindings/c/flag_listener.h | 3 ++- libs/common/src/CMakeLists.txt | 1 + libs/common/src/bindings/c/flag_listener.cpp | 6 ++++++ 4 files changed, 9 insertions(+), 6 deletions(-) create mode 100644 libs/common/src/bindings/c/flag_listener.cpp diff --git a/libs/client-sdk/src/bindings/c/sdk.cpp b/libs/client-sdk/src/bindings/c/sdk.cpp index ec68b396a..8020971b0 100644 --- a/libs/client-sdk/src/bindings/c/sdk.cpp +++ b/libs/client-sdk/src/bindings/c/sdk.cpp @@ -377,11 +377,6 @@ LD_EXPORT(time_t) LDDataSourceStatus_StateSince(LDDataSourceStatus status) { .count(); } -LD_EXPORT(void) LDFlagListener_Init(struct LDFlagListener listener) { - listener.FlagChanged = nullptr; - listener.UserData = nullptr; -} - LD_EXPORT(LDDataSourceStatus_ErrorKind) LDDataSourceStatus_ErrorInfo_GetKind(LDDataSourceStatus_ErrorInfo info) { LD_ASSERT_NOT_NULL(info); diff --git a/libs/common/include/launchdarkly/bindings/c/flag_listener.h b/libs/common/include/launchdarkly/bindings/c/flag_listener.h index e7e87572a..2e930129c 100644 --- a/libs/common/include/launchdarkly/bindings/c/flag_listener.h +++ b/libs/common/include/launchdarkly/bindings/c/flag_listener.h @@ -4,6 +4,7 @@ #pragma once #include +#include #ifdef __cplusplus extern "C" { // only need to export C interface if @@ -54,7 +55,7 @@ struct LDFlagListener { * * @param listener Listener to initialize. */ -LD_EXPORT(void) LDFlagListener_Init(struct LDFlagListener listener); +LD_EXPORT(void) LDFlagListener_Init(struct LDFlagListener* listener); #ifdef __cplusplus } diff --git a/libs/common/src/CMakeLists.txt b/libs/common/src/CMakeLists.txt index febb4a9fb..790f86516 100644 --- a/libs/common/src/CMakeLists.txt +++ b/libs/common/src/CMakeLists.txt @@ -46,6 +46,7 @@ add_library(${LIBNAME} OBJECT bindings/c/config/logging_builder.cpp bindings/c/data/evaluation_detail.cpp bindings/c/listener_connection.cpp + bindings/c/flag_listener.cpp bindings/c/memory_routines.cpp log_level.cpp config/persistence_builder.cpp diff --git a/libs/common/src/bindings/c/flag_listener.cpp b/libs/common/src/bindings/c/flag_listener.cpp new file mode 100644 index 000000000..edd10e7ae --- /dev/null +++ b/libs/common/src/bindings/c/flag_listener.cpp @@ -0,0 +1,6 @@ +#include + +LD_EXPORT(void) LDFlagListener_Init(struct LDFlagListener* listener) { + listener->FlagChanged = nullptr; + listener->UserData = nullptr; +} From 7674e3410dd6d0fa47ebe9c3bcf919613ad6b41e Mon Sep 17 00:00:00 2001 From: Casey Waldren Date: Mon, 28 Aug 2023 14:44:59 -0700 Subject: [PATCH 3/3] fix bug in LDFlagListener initialization --- libs/client-sdk/tests/client_c_bindings_test.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libs/client-sdk/tests/client_c_bindings_test.cpp b/libs/client-sdk/tests/client_c_bindings_test.cpp index 5c184a95a..052217b60 100644 --- a/libs/client-sdk/tests/client_c_bindings_test.cpp +++ b/libs/client-sdk/tests/client_c_bindings_test.cpp @@ -59,8 +59,15 @@ TEST(ClientBindings, RegisterFlagListener) { LDClientSDK_Start(sdk, 3000, &success); EXPECT_TRUE(success); - struct LDFlagListener listener {}; - LDFlagListener_Init(listener); + struct LDFlagListener listener { + reinterpret_cast(0x123), + reinterpret_cast(0x456) + }; + + LDFlagListener_Init(&listener); + ASSERT_EQ(listener.FlagChanged, nullptr); + ASSERT_EQ(listener.UserData, nullptr); + listener.UserData = const_cast("Potato"); listener.FlagChanged = FlagListenerFunction;