Skip to content

Commit d2852e7

Browse files
authored
feat: add C bindings for Client type (#92)
1 parent 4e3cf00 commit d2852e7

36 files changed

+1071
-68
lines changed

apps/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#add_subdirectory(hello-c)
21
add_subdirectory(sse-contract-tests)
32
add_subdirectory(sdk-contract-tests)
43
add_subdirectory(hello-cpp)
4+
add_subdirectory(hello-c)

apps/hello-c/CMakeLists.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Required for Apple Silicon support.
2+
cmake_minimum_required(VERSION 3.19)
3+
4+
project(
5+
LaunchDarklyHelloCClient
6+
VERSION 0.1
7+
DESCRIPTION "LaunchDarkly Hello C Client"
8+
LANGUAGES C
9+
)
10+
11+
set(THREADS_PREFER_PTHREAD_FLAG ON)
12+
find_package(Threads REQUIRED)
13+
14+
add_executable(hello-c main.c)
15+
target_link_libraries(hello-c PRIVATE launchdarkly::client launchdarkly::sse launchdarkly::common Threads::Threads)

apps/hello-c/main.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#include <launchdarkly/client_side/bindings/c/sdk.h>
2+
3+
#include <launchdarkly/bindings/c/config/builder.h>
4+
#include <launchdarkly/bindings/c/context_builder.h>
5+
6+
#include <stdio.h>
7+
#include <stdlib.h>
8+
9+
int main() {
10+
char const* key = getenv("STG_SDK_KEY");
11+
if (!key) {
12+
printf("Set environment variable STG_SDK_KEY to the sdk key\n");
13+
return 1;
14+
}
15+
16+
LDClientConfigBuilder builder = LDClientConfigBuilder_New(key);
17+
18+
LDClientConfigBuilder_ServiceEndpoints_PollingBaseURL(
19+
builder, "http://sdk.launchdarkly.com");
20+
LDClientConfigBuilder_ServiceEndpoints_StreamingBaseURL(
21+
builder, "https://stream.launchdarkly.com");
22+
LDClientConfigBuilder_ServiceEndpoints_EventsBaseURL(
23+
builder, "https://events.launchdarkly.com");
24+
25+
LDClientConfigBuilder_Events_FlushIntervalMs(builder, 5000);
26+
27+
LDClientConfigBuilder_DataSource_UseReport(builder, true);
28+
LDClientConfigBuilder_DataSource_WithReasons(builder, true);
29+
30+
LDDataSourcePollBuilder poll_builder = LDDataSourcePollBuilder_New();
31+
LDDataSourcePollBuilder_IntervalS(poll_builder, 30);
32+
LDClientConfigBuilder_DataSource_MethodPoll(builder, poll_builder);
33+
34+
LDClientConfig config;
35+
LDStatus status = LDClientConfigBuilder_Build(builder, &config);
36+
37+
if (!LDStatus_Ok(status)) {
38+
printf("%s\n", LDStatus_Error(status));
39+
return 1;
40+
}
41+
42+
LDContextBuilder context_builder = LDContextBuilder_New();
43+
LDContextBuilder_AddKind(context_builder, "user", "ryan");
44+
45+
LDContext context = LDContextBuilder_Build(context_builder);
46+
47+
LDClientSDK client = LDClientSDK_New(config, context);
48+
//
49+
// std::cout << "Initial Status: " << client.DataSourceStatus().Status()
50+
// << std::endl;
51+
//
52+
// client.DataSourceStatus().OnDataSourceStatusChange([](auto status) {
53+
// std::cout << "Got status: " << status << std::endl;
54+
// });
55+
//
56+
// client.FlagNotifier().OnFlagChange("my-boolean-flag", [](auto event) {
57+
// std::cout << "Got flag change: " << *event << std::endl;
58+
// });
59+
//
60+
// client.WaitForReadySync(std::chrono::seconds(30));
61+
62+
LDEvalDetail detail;
63+
if (LDClientSDK_BoolVariationDetail(client, "my-boolean-flag", false,
64+
&detail)) {
65+
printf("Value was: true\n");
66+
} else {
67+
printf("Value was: false\n");
68+
}
69+
70+
LDEvalReason reason;
71+
if (LDEvalDetail_Reason(detail, &reason)) {
72+
printf("Reason was: %d\n", LDEvalReason_Kind(reason));
73+
}
74+
75+
// Sit around.
76+
printf("Press enter to exit\n\n");
77+
getchar();
78+
}
Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
// NOLINTBEGIN modernize-use-using
2+
3+
#pragma once
4+
5+
#include <launchdarkly/bindings/c/config/config.h>
6+
#include <launchdarkly/bindings/c/context.h>
7+
#include <launchdarkly/bindings/c/data/evaluation_detail.h>
8+
#include <launchdarkly/bindings/c/export.h>
9+
#include <launchdarkly/bindings/c/memory_routines.h>
10+
#include <launchdarkly/bindings/c/status.h>
11+
#include <launchdarkly/bindings/c/value.h>
12+
#include <stddef.h>
13+
14+
#ifdef __cplusplus
15+
extern "C" { // only need to export C interface if
16+
// used by C++ source code
17+
#endif
18+
19+
typedef struct _LDClientSDK* LDClientSDK;
20+
21+
#define LD_NONBLOCKING -1
22+
#define LD_DISCARD_DETAIL NULL
23+
24+
/**
25+
* Constructs a new client-side LaunchDarkly SDK from a configuration and
26+
* context.
27+
* @param config The configuration. Must not be NULL.
28+
* @param context The initial context. Must not be NULL.
29+
* @return New SDK instance.
30+
*/
31+
LD_EXPORT(LDClientSDK)
32+
LDClientSDK_New(LDClientConfig config, LDContext context);
33+
34+
/**
35+
* Returns a boolean value indicating LaunchDarkly connection and flag state
36+
* within the client.
37+
*
38+
* [TODO Need to make WaitForReadyAsync, offline]
39+
* When you first start the client, once WaitForReadySync has returned or
40+
* WaitForReadyAsync has completed, Initialized should return true if
41+
* and only if either 1. it connected to LaunchDarkly and successfully
42+
* retrieved flags, or 2. it started in offline mode so there's no need to
43+
* connect to LaunchDarkly. If the client timed out trying to connect to LD,
44+
* then Initialized returns false (even if we do have cached flags).
45+
* If the client connected and got a 401 error, Initialized is
46+
* will return false. This serves the purpose of letting the app know that
47+
* there was a problem of some kind.
48+
*
49+
* @param sdk SDK. Must not be NULL.
50+
* @return True if initialized.
51+
*/
52+
LD_EXPORT(bool) LDClientSDK_Initialized(LDClientSDK sdk);
53+
54+
/**
55+
* Tracks that the current context performed an event for the given event name.
56+
* @param sdk SDK. Must not be NULL.
57+
* @param event_name Name of the event. Must not be NULL.
58+
*/
59+
LD_EXPORT(void) LDClientSDK_TrackEvent(LDClientSDK sdk, char const* event_name);
60+
61+
/**
62+
* Tracks that the current context performed an event for the given event
63+
* name, and associates it with a numeric metric and value.
64+
*
65+
* @param sdk SDK. Must not be NULL.
66+
* @param event_name The name of the event. Must not be NULL.
67+
* @param metric_value this value is used by the LaunchDarkly experimentation
68+
* feature in numeric custom metrics, and will also be returned as part of the
69+
* custom event for Data Export.
70+
* @param data A JSON value containing additional data associated with the
71+
* event. Must not be NULL.
72+
*/
73+
LD_EXPORT(void)
74+
LDClientSDK_TrackMetric(LDClientSDK sdk,
75+
char const* event_name,
76+
double metric_value,
77+
LDValue data);
78+
79+
/**
80+
* Tracks that the current context performed an event for the given event
81+
* name, with additional JSON data.
82+
* @param sdk SDK. Must not be NULL.
83+
* @param event_name Must not be NULL.
84+
* @param data A JSON value containing additional data associated with the
85+
* event. Must not be NULL.
86+
*/
87+
LD_EXPORT(void)
88+
LDClientSDK_TrackData(LDClientSDK sdk, char const* event_name, LDValue data);
89+
90+
/**
91+
* Requests delivery of all pending analytic events (if any).
92+
*
93+
* Pass LD_NONBLOCKING as the second parameter.
94+
*
95+
* @param sdk SDK. Must not be NULL.
96+
* @param milliseconds Must pass LD_NONBLOCKING.
97+
*/
98+
LD_EXPORT(void)
99+
LDClientSDK_Flush(LDClientSDK sdk, int reserved);
100+
101+
/**
102+
* Changes the current evaluation context, requests flags for that context
103+
* from LaunchDarkly if online, and generates an analytics event to
104+
* tell LaunchDarkly about the context.
105+
*
106+
* Only one Identify call can be in progress at once; calling it
107+
* concurrently invokes undefined behavior.
108+
*
109+
* To block until the identify operation is complete or a timeout is reached,
110+
* pass a non-negative milliseconds parameter. Otherwise to return immediately,
111+
* pass LD_NONBLOCKING.
112+
*
113+
* @param sdk SDK. Must not be NULL.
114+
* @param context The new evaluation context.
115+
* @param milliseconds How long to wait for the identify to complete, or
116+
* LD_NONBLOCKING to return immediately.
117+
*/
118+
LD_EXPORT(void)
119+
LDClientSDK_Identify(LDClientSDK sdk, LDContext context, int milliseconds);
120+
121+
/**
122+
* Returns the boolean value of a feature flag for a given flag key.
123+
* @param sdk SDK. Must not be NULL.
124+
* @param flag_key The unique key for the feature flag. Must not be NULL.
125+
* @param default_value The default value of the flag.
126+
* @return The variation for the current context, or default_value if the
127+
* flag is disabled in the LaunchDarkly control panel.
128+
*/
129+
LD_EXPORT(bool)
130+
LDClientSDK_BoolVariation(LDClientSDK sdk,
131+
char const* flag_key,
132+
bool default_value);
133+
134+
/**
135+
* Returns the boolean value of a feature flag for a given flag key, and details
136+
* that also describes the way the value was determined.
137+
* @param sdk SDK. Must not be NULL.
138+
* @param flag_key The unique key for the feature flag. Must not be NULL.
139+
* @param default_value The default value of the flag.
140+
* @param detail Out parameter to store the details. May pass LD_DISCARD_DETAILS
141+
* or NULL to discard the details. The details object must be freed with
142+
* LDEvalDetail_Free.
143+
* @return The variation for the current context, or default_value if the
144+
* flag is disabled in the LaunchDarkly control panel.
145+
*/
146+
LD_EXPORT(bool)
147+
LDClientSDK_BoolVariationDetail(LDClientSDK sdk,
148+
char const* flag_key,
149+
bool default_value,
150+
LDEvalDetail* out_detail);
151+
152+
/**
153+
* Returns the string value of a feature flag for a given flag key. Ensure the
154+
* string is freed with LDMemory_FreeString.
155+
* @param sdk SDK. Must not be NULL.
156+
* @param flag_key The unique key for the feature flag. Must not be NULL.
157+
* @param default_value The default value of the flag.
158+
* @return The variation for the current context, or a copy of default_value if
159+
* the flag is disabled in the LaunchDarkly control panel. Must be freed with
160+
* LDMemory_FreeString.
161+
*/
162+
LD_EXPORT(char*)
163+
LDClientSDK_StringVariation(LDClientSDK sdk,
164+
char const* flag_key,
165+
char const* default_value);
166+
167+
/**
168+
* Returns the string value of a feature flag for a given flag key, and details
169+
* that also describes the way the value was determined. Ensure the
170+
* string is freed with LDMemory_FreeString.
171+
* @param sdk SDK. Must not be NULL.
172+
* @param flag_key The unique key for the feature flag. Must not be NULL.
173+
* @param default_value The default value of the flag.
174+
* @param detail Out parameter to store the details. May pass LD_DISCARD_DETAILS
175+
* or NULL to discard the details. The details object must be freed with
176+
* LDEvalDetail_Free.
177+
* @return The variation for the current context, or a copy of default_value if
178+
* the flag is disabled in the LaunchDarkly control panel. Must be freed with
179+
* LDMemory_FreeString.
180+
*/
181+
LD_EXPORT(char*)
182+
LDClientSDK_StringVariationDetail(LDClientSDK sdk,
183+
char const* flag_key,
184+
char const* default_value,
185+
LDEvalDetail* out_detail);
186+
187+
/**
188+
* Returns the int value of a feature flag for a given flag key.
189+
* @param sdk SDK. Must not be NULL.
190+
* @param flag_key The unique key for the feature flag. Must not be NULL.
191+
* @param default_value The default value of the flag.
192+
* @return The variation for the current context, or default_value if the
193+
* flag is disabled in the LaunchDarkly control panel.
194+
*/
195+
LD_EXPORT(int)
196+
LDClientSDK_IntVariation(LDClientSDK sdk,
197+
char const* flag_key,
198+
int default_value);
199+
200+
/**
201+
* Returns the int value of a feature flag for a given flag key, and details
202+
* that also describes the way the value was determined.
203+
* @param sdk SDK. Must not be NULL.
204+
* @param flag_key The unique key for the feature flag. Must not be NULL.
205+
* @param default_value The default value of the flag.
206+
* @param detail Out parameter to store the details. May pass LD_DISCARD_DETAILS
207+
* or NULL to discard the details. The details object must be freed with
208+
* LDEvalDetail_Free.
209+
* @return The variation for the current context, or default_value if the
210+
* flag is disabled in the LaunchDarkly control panel.
211+
*/
212+
LD_EXPORT(int)
213+
LDClientSDK_IntVariationDetail(LDClientSDK sdk,
214+
char const* flag_key,
215+
int default_value,
216+
LDEvalDetail* out_detail);
217+
218+
/**
219+
* Returns the double value of a feature flag for a given flag key.
220+
* @param sdk SDK. Must not be NULL.
221+
* @param flag_key The unique key for the feature flag. Must not be NULL.
222+
* @param default_value The default value of the flag.
223+
* @return The variation for the current context, or default_value if the
224+
* flag is disabled in the LaunchDarkly control panel.
225+
*/
226+
LD_EXPORT(int)
227+
LDClientSDK_DoubleVariation(LDClientSDK sdk,
228+
char const* flag_key,
229+
double default_value);
230+
231+
/**
232+
* Returns the double value of a feature flag for a given flag key, and details
233+
* that also describes the way the value was determined.
234+
* @param sdk SDK. Must not be NULL.
235+
* @param flag_key The unique key for the feature flag. Must not be NULL.
236+
* @param default_value The default value of the flag.
237+
* @param detail Out parameter to store the details. May pass LD_DISCARD_DETAILS
238+
* or NULL to discard the details. The details object must be freed with
239+
* LDEvalDetail_Free.
240+
* @return The variation for the current context, or default_value if the
241+
* flag is disabled in the LaunchDarkly control panel.
242+
*/
243+
LD_EXPORT(int)
244+
LDClientSDK_DoubleVariationDetail(LDClientSDK sdk,
245+
char const* flag_key,
246+
double default_value,
247+
LDEvalDetail* out_detail);
248+
249+
/**
250+
* Returns the JSON value of a feature flag for a given flag key.
251+
* @param sdk SDK. Must not be NULL.
252+
* @param flag_key The unique key for the feature flag. Must not be NULL.
253+
* @param default_value The default value of the flag. The value is copied.
254+
* @return The variation for the current context, or a copy of default_value if
255+
* the flag is disabled in the LaunchDarkly control panel. The returned value
256+
* must be freed using LDValue_Free.
257+
*/
258+
LD_EXPORT(LDValue)
259+
LDClientSDK_JsonVariation(LDClientSDK sdk,
260+
char const* flag_key,
261+
LDValue default_value);
262+
263+
/**
264+
* Returns the JSON value of a feature flag for a given flag key, and details
265+
* that also describes the way the value was determined.
266+
* @param sdk SDK. Must not be NULL.
267+
* @param flag_key The unique key for the feature flag. Must not be NULL.
268+
* @param default_value The default value of the flag. The value is copied.
269+
* @param detail Out parameter to store the details. May pass LD_DISCARD_DETAILS
270+
* or NULL to discard the details. The details object must be freed with
271+
* LDEvalDetail_Free.
272+
* @return The variation for the current context, or a copy of default_value if
273+
* the flag is disabled in the LaunchDarkly control panel. The returned value
274+
* must be freed using LDValue_Free.
275+
*/
276+
LD_EXPORT(LDValue)
277+
LDClientSDK_JsonVariationDetail(LDClientSDK sdk,
278+
char const* flag_key,
279+
LDValue default_value,
280+
LDEvalDetail* out_detail);
281+
282+
/**
283+
* Frees the SDK's resources, shutting down any connections. May block.
284+
* @param sdk SDK.
285+
*/
286+
LD_EXPORT(void) LDClientSDK_Free(LDClientSDK sdk);
287+
288+
#ifdef __cplusplus
289+
}
290+
#endif
291+
292+
// NOLINTEND modernize-use-using

0 commit comments

Comments
 (0)