Skip to content

Commit 62ed26f

Browse files
committed
Refactor C API string getters to return allocated strings
Changed native_menu_item_get_label, native_menu_item_get_icon, native_menu_item_get_tooltip, and native_keyboard_accelerator_to_string to return newly allocated C strings instead of writing to caller-provided buffers. Updated documentation and example usage to reflect new memory management requirements. This improves usability and safety for string handling in the C API.
1 parent 5d6299e commit 62ed26f

File tree

3 files changed

+89
-90
lines changed

3 files changed

+89
-90
lines changed

examples/tray_icon_c_example/main.c

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@
1111
// Include individual C API headers instead of the full nativeapi.h
1212
#include "../../src/capi/menu_c.h"
1313
#include "../../src/capi/run_example_app_c.h"
14+
#include "../../src/capi/string_utils_c.h"
1415
#include "../../src/capi/tray_icon_c.h"
1516
#include "../../src/capi/tray_manager_c.h"
1617

1718
// Event callback functions
1819
void on_menu_item_clicked(const void* event, void* user_data) {
19-
const native_menu_item_clicked_event_t* clicked_event = (const native_menu_item_clicked_event_t*)event;
20+
const native_menu_item_clicked_event_t* clicked_event =
21+
(const native_menu_item_clicked_event_t*)event;
2022
printf("Menu item clicked: ID=%ld, Text='%s'\n", clicked_event->item_id,
2123
clicked_event->item_text);
2224

@@ -29,28 +31,35 @@ void on_menu_item_clicked(const void* event, void* user_data) {
2931
}
3032

3133
void on_tray_clicked(const void* event, void* user_data) {
32-
const native_tray_icon_clicked_event_t* clicked_event = (const native_tray_icon_clicked_event_t*)event;
33-
printf("Tray icon clicked! ID=%ld, Button='%s'\n", clicked_event->tray_icon_id,
34-
clicked_event->button);
34+
const native_tray_icon_clicked_event_t* clicked_event =
35+
(const native_tray_icon_clicked_event_t*)event;
36+
printf("Tray icon clicked! ID=%ld, Button='%s'\n",
37+
clicked_event->tray_icon_id, clicked_event->button);
3538
}
3639

3740
void on_tray_right_clicked(const void* event, void* user_data) {
38-
const native_tray_icon_right_clicked_event_t* right_clicked_event = (const native_tray_icon_right_clicked_event_t*)event;
39-
printf("Tray icon right clicked! ID=%ld\n", right_clicked_event->tray_icon_id);
41+
const native_tray_icon_right_clicked_event_t* right_clicked_event =
42+
(const native_tray_icon_right_clicked_event_t*)event;
43+
printf("Tray icon right clicked! ID=%ld\n",
44+
right_clicked_event->tray_icon_id);
4045
}
4146

4247
void on_tray_double_clicked(const void* event, void* user_data) {
43-
const native_tray_icon_double_clicked_event_t* double_clicked_event = (const native_tray_icon_double_clicked_event_t*)event;
44-
printf("Tray icon double clicked! ID=%ld\n", double_clicked_event->tray_icon_id);
48+
const native_tray_icon_double_clicked_event_t* double_clicked_event =
49+
(const native_tray_icon_double_clicked_event_t*)event;
50+
printf("Tray icon double clicked! ID=%ld\n",
51+
double_clicked_event->tray_icon_id);
4552
}
4653

4754
void on_menu_opened(const void* event, void* user_data) {
48-
const native_menu_opened_event_t* open_event = (const native_menu_opened_event_t*)event;
55+
const native_menu_opened_event_t* open_event =
56+
(const native_menu_opened_event_t*)event;
4957
printf("Menu opened: ID=%ld\n", open_event->menu_id);
5058
}
5159

5260
void on_menu_closed(const void* event, void* user_data) {
53-
const native_menu_closed_event_t* close_event = (const native_menu_closed_event_t*)event;
61+
const native_menu_closed_event_t* close_event =
62+
(const native_menu_closed_event_t*)event;
5463
printf("Menu closed: ID=%ld\n", close_event->menu_id);
5564
}
5665

@@ -104,10 +113,14 @@ int main() {
104113
native_menu_item_set_state(checkbox, NATIVE_MENU_ITEM_STATE_CHECKED);
105114

106115
// Set up event listeners using new API
107-
native_menu_item_add_listener(item1, NATIVE_MENU_ITEM_EVENT_CLICKED, on_menu_item_clicked, NULL);
108-
native_menu_item_add_listener(item2, NATIVE_MENU_ITEM_EVENT_CLICKED, on_menu_item_clicked, NULL);
109-
native_menu_item_add_listener(exit_item, NATIVE_MENU_ITEM_EVENT_CLICKED, on_menu_item_clicked, NULL);
110-
native_menu_item_add_listener(checkbox, NATIVE_MENU_ITEM_EVENT_CLICKED, on_menu_item_clicked, NULL);
116+
native_menu_item_add_listener(item1, NATIVE_MENU_ITEM_EVENT_CLICKED,
117+
on_menu_item_clicked, NULL);
118+
native_menu_item_add_listener(item2, NATIVE_MENU_ITEM_EVENT_CLICKED,
119+
on_menu_item_clicked, NULL);
120+
native_menu_item_add_listener(exit_item, NATIVE_MENU_ITEM_EVENT_CLICKED,
121+
on_menu_item_clicked, NULL);
122+
native_menu_item_add_listener(checkbox, NATIVE_MENU_ITEM_EVENT_CLICKED,
123+
on_menu_item_clicked, NULL);
111124

112125
// Add items to menu
113126
native_menu_add_item(menu, item1);
@@ -119,8 +132,10 @@ int main() {
119132
printf("Added %zu items to menu\n", native_menu_get_item_count(menu));
120133

121134
// Set menu event listeners using new API
122-
native_menu_add_listener(menu, NATIVE_MENU_EVENT_OPENED, on_menu_opened, NULL);
123-
native_menu_add_listener(menu, NATIVE_MENU_EVENT_CLOSED, on_menu_closed, NULL);
135+
native_menu_add_listener(menu, NATIVE_MENU_EVENT_OPENED, on_menu_opened,
136+
NULL);
137+
native_menu_add_listener(menu, NATIVE_MENU_EVENT_CLOSED, on_menu_closed,
138+
NULL);
124139

125140
// Create a submenu example
126141
native_menu_t submenu = native_menu_create();
@@ -164,9 +179,13 @@ int main() {
164179
native_tray_icon_set_context_menu(tray_icon, menu);
165180

166181
// Set up tray icon event listeners using new API
167-
native_tray_icon_add_listener(tray_icon, NATIVE_TRAY_ICON_EVENT_CLICKED, on_tray_clicked, NULL);
168-
native_tray_icon_add_listener(tray_icon, NATIVE_TRAY_ICON_EVENT_RIGHT_CLICKED, on_tray_right_clicked, NULL);
169-
native_tray_icon_add_listener(tray_icon, NATIVE_TRAY_ICON_EVENT_DOUBLE_CLICKED, on_tray_double_clicked, NULL);
182+
native_tray_icon_add_listener(tray_icon, NATIVE_TRAY_ICON_EVENT_CLICKED,
183+
on_tray_clicked, NULL);
184+
native_tray_icon_add_listener(tray_icon, NATIVE_TRAY_ICON_EVENT_RIGHT_CLICKED,
185+
on_tray_right_clicked, NULL);
186+
native_tray_icon_add_listener(tray_icon,
187+
NATIVE_TRAY_ICON_EVENT_DOUBLE_CLICKED,
188+
on_tray_double_clicked, NULL);
170189

171190
// Show the tray icon
172191
if (native_tray_icon_show(tray_icon)) {
@@ -191,10 +210,10 @@ int main() {
191210
// Get accelerator info
192211
native_keyboard_accelerator_t accel;
193212
if (native_menu_item_get_accelerator(found_item, &accel)) {
194-
char accel_str[64];
195-
if (native_keyboard_accelerator_to_string(&accel, accel_str,
196-
sizeof(accel_str)) > 0) {
213+
char* accel_str = native_keyboard_accelerator_to_string(&accel);
214+
if (accel_str) {
197215
printf("Exit item accelerator: %s\n", accel_str);
216+
free_c_str(accel_str); // Free the allocated string
198217
}
199218
}
200219
}

src/capi/menu_c.cpp

Lines changed: 40 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -231,25 +231,22 @@ void native_menu_item_set_label(native_menu_item_t item, const char* label) {
231231
}
232232
}
233233

234-
int native_menu_item_get_label(native_menu_item_t item,
235-
char* buffer,
236-
size_t buffer_size) {
237-
if (!item || !buffer || buffer_size == 0)
238-
return -1;
234+
char* native_menu_item_get_label(native_menu_item_t item) {
235+
if (!item)
236+
return nullptr;
239237

240238
try {
241239
auto menu_item = static_cast<MenuItem*>(item);
242240
std::string text = menu_item->GetLabel();
243-
244-
if (text.length() >= buffer_size) {
245-
return -1;
241+
242+
// Allocate C string and copy content
243+
char* result = static_cast<char*>(malloc(text.length() + 1));
244+
if (result) {
245+
strcpy(result, text.c_str());
246246
}
247-
248-
strncpy(buffer, text.c_str(), buffer_size - 1);
249-
buffer[buffer_size - 1] = '\0';
250-
return static_cast<int>(text.length());
247+
return result;
251248
} catch (...) {
252-
return -1;
249+
return nullptr;
253250
}
254251
}
255252

@@ -265,25 +262,22 @@ void native_menu_item_set_icon(native_menu_item_t item, const char* icon) {
265262
}
266263
}
267264

268-
int native_menu_item_get_icon(native_menu_item_t item,
269-
char* buffer,
270-
size_t buffer_size) {
271-
if (!item || !buffer || buffer_size == 0)
272-
return -1;
265+
char* native_menu_item_get_icon(native_menu_item_t item) {
266+
if (!item)
267+
return nullptr;
273268

274269
try {
275270
auto menu_item = static_cast<MenuItem*>(item);
276271
std::string icon = menu_item->GetIcon();
277-
278-
if (icon.length() >= buffer_size) {
279-
return -1;
272+
273+
// Allocate C string and copy content
274+
char* result = static_cast<char*>(malloc(icon.length() + 1));
275+
if (result) {
276+
strcpy(result, icon.c_str());
280277
}
281-
282-
strncpy(buffer, icon.c_str(), buffer_size - 1);
283-
buffer[buffer_size - 1] = '\0';
284-
return static_cast<int>(icon.length());
278+
return result;
285279
} catch (...) {
286-
return -1;
280+
return nullptr;
287281
}
288282
}
289283

@@ -300,25 +294,22 @@ void native_menu_item_set_tooltip(native_menu_item_t item,
300294
}
301295
}
302296

303-
int native_menu_item_get_tooltip(native_menu_item_t item,
304-
char* buffer,
305-
size_t buffer_size) {
306-
if (!item || !buffer || buffer_size == 0)
307-
return -1;
297+
char* native_menu_item_get_tooltip(native_menu_item_t item) {
298+
if (!item)
299+
return nullptr;
308300

309301
try {
310302
auto menu_item = static_cast<MenuItem*>(item);
311303
std::string tooltip = menu_item->GetTooltip();
312-
313-
if (tooltip.length() >= buffer_size) {
314-
return -1;
304+
305+
// Allocate C string and copy content
306+
char* result = static_cast<char*>(malloc(tooltip.length() + 1));
307+
if (result) {
308+
strcpy(result, tooltip.c_str());
315309
}
316-
317-
strncpy(buffer, tooltip.c_str(), buffer_size - 1);
318-
buffer[buffer_size - 1] = '\0';
319-
return static_cast<int>(tooltip.length());
310+
return result;
320311
} catch (...) {
321-
return -1;
312+
return nullptr;
322313
}
323314
}
324315

@@ -1140,26 +1131,23 @@ void native_menu_cleanup_all(void) {
11401131
cleanup_at_exit();
11411132
}
11421133

1143-
int native_keyboard_accelerator_to_string(
1144-
const native_keyboard_accelerator_t* accelerator,
1145-
char* buffer,
1146-
size_t buffer_size) {
1147-
if (!accelerator || !buffer || buffer_size == 0)
1148-
return -1;
1134+
char* native_keyboard_accelerator_to_string(
1135+
const native_keyboard_accelerator_t* accelerator) {
1136+
if (!accelerator)
1137+
return nullptr;
11491138

11501139
try {
11511140
KeyboardAccelerator cpp_accelerator =
11521141
convert_keyboard_accelerator(accelerator);
11531142
std::string str = cpp_accelerator.ToString();
11541143

1155-
if (str.length() >= buffer_size) {
1156-
return -1;
1144+
// Allocate C string and copy content
1145+
char* result = static_cast<char*>(malloc(str.length() + 1));
1146+
if (result) {
1147+
strcpy(result, str.c_str());
11571148
}
1158-
1159-
strncpy(buffer, str.c_str(), buffer_size - 1);
1160-
buffer[buffer_size - 1] = '\0';
1161-
return static_cast<int>(str.length());
1149+
return result;
11621150
} catch (...) {
1163-
return -1;
1151+
return nullptr;
11641152
}
11651153
}

src/capi/menu_c.h

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -190,12 +190,10 @@ void native_menu_item_set_label(native_menu_item_t item, const char* label);
190190
/**
191191
* Get the label of a menu item
192192
* @param item The menu item
193-
* @param buffer Buffer to store the label (caller allocated)
194-
* @param buffer_size Size of the buffer
195-
* @return Length of the label, or -1 if buffer too small
193+
* @return The label string (caller must free), or NULL if item is invalid
196194
*/
197195
FFI_PLUGIN_EXPORT
198-
int native_menu_item_get_label(native_menu_item_t item, char* buffer, size_t buffer_size);
196+
char* native_menu_item_get_label(native_menu_item_t item);
199197

200198
/**
201199
* Set the icon of a menu item
@@ -208,12 +206,10 @@ void native_menu_item_set_icon(native_menu_item_t item, const char* icon);
208206
/**
209207
* Get the icon of a menu item
210208
* @param item The menu item
211-
* @param buffer Buffer to store the icon path/data (caller allocated)
212-
* @param buffer_size Size of the buffer
213-
* @return Length of the icon string, or -1 if buffer too small
209+
* @return The icon path/data string (caller must free), or NULL if item is invalid or no icon set
214210
*/
215211
FFI_PLUGIN_EXPORT
216-
int native_menu_item_get_icon(native_menu_item_t item, char* buffer, size_t buffer_size);
212+
char* native_menu_item_get_icon(native_menu_item_t item);
217213

218214
/**
219215
* Set the tooltip of a menu item
@@ -226,12 +222,10 @@ void native_menu_item_set_tooltip(native_menu_item_t item, const char* tooltip);
226222
/**
227223
* Get the tooltip of a menu item
228224
* @param item The menu item
229-
* @param buffer Buffer to store the tooltip (caller allocated)
230-
* @param buffer_size Size of the buffer
231-
* @return Length of the tooltip, or -1 if buffer too small
225+
* @return The tooltip string (caller must free), or NULL if item is invalid or no tooltip set
232226
*/
233227
FFI_PLUGIN_EXPORT
234-
int native_menu_item_get_tooltip(native_menu_item_t item, char* buffer, size_t buffer_size);
228+
char* native_menu_item_get_tooltip(native_menu_item_t item);
235229

236230
/**
237231
* Set the keyboard accelerator for a menu item
@@ -613,12 +607,10 @@ void native_menu_item_list_free(native_menu_item_list_t list);
613607
/**
614608
* Convert keyboard accelerator to string representation
615609
* @param accelerator The accelerator
616-
* @param buffer Buffer to store the string (caller allocated)
617-
* @param buffer_size Size of the buffer
618-
* @return Length of the string, or -1 if buffer too small
610+
* @return The string representation (caller must free), or NULL if accelerator is invalid
619611
*/
620612
FFI_PLUGIN_EXPORT
621-
int native_keyboard_accelerator_to_string(const native_keyboard_accelerator_t* accelerator, char* buffer, size_t buffer_size);
613+
char* native_keyboard_accelerator_to_string(const native_keyboard_accelerator_t* accelerator);
622614

623615
#ifdef __cplusplus
624616
}

0 commit comments

Comments
 (0)