Skip to content

Commit d761937

Browse files
committed
Add C API memory cleanup and improve display info handling
1 parent 6379dc0 commit d761937

File tree

5 files changed

+154
-19
lines changed

5 files changed

+154
-19
lines changed

examples/display_example/main.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -231,13 +231,27 @@ int main() {
231231

232232
std::cout << "\n✅ Display information retrieved successfully!" << std::endl;
233233

234+
// Test C API
235+
std::cout << "\n=== Testing C API ===" << std::endl;
234236
native_display_list_t display_list = native_display_manager_get_all();
235237

236-
std::cout << "C API - Found " << display_list.count
237-
<< " display(s):" << std::endl;
238-
for (size_t i = 0; i < display_list.count; ++i) {
239-
std::cout << "Display " << (i + 1)
240-
<< " Name: " << display_list.displays[i].name << std::endl;
238+
if (display_list.displays != nullptr && display_list.count > 0) {
239+
std::cout << "C API - Found " << display_list.count
240+
<< " display(s):" << std::endl;
241+
for (size_t i = 0; i < display_list.count; ++i) {
242+
const native_display_t& display = display_list.displays[i];
243+
std::cout << "Display " << (i + 1) << ":" << std::endl;
244+
std::cout << " Name: " << (display.name ? display.name : "Unknown") << std::endl;
245+
std::cout << " ID: " << (display.id ? display.id : "Unknown") << std::endl;
246+
std::cout << " Size: " << display.size.width << " x " << display.size.height << std::endl;
247+
std::cout << " Primary: " << (display.is_primary ? "Yes" : "No") << std::endl;
248+
std::cout << std::endl;
249+
}
250+
251+
// Clean up memory
252+
native_display_list_free(&display_list);
253+
} else {
254+
std::cout << "C API - No displays found or error occurred" << std::endl;
241255
}
242256

243257
return 0;

src/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
1818
file(GLOB COMMON_SOURCES "*.cpp")
1919
list(FILTER COMMON_SOURCES EXCLUDE REGEX "platform/*")
2020

21+
# C API source files
22+
file(GLOB CAPI_SOURCES "capi/*.cpp" "capi/*.c")
23+
2124
# Platform-specific source files
2225
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
2326
file(GLOB PLATFORM_SOURCES "platform/linux/*_linux.cpp")
@@ -38,6 +41,7 @@ endif()
3841
add_library(libnativeapi STATIC
3942
${COMMON_SOURCES}
4043
${PLATFORM_SOURCES}
44+
${CAPI_SOURCES}
4145
)
4246

4347
# Set library properties

src/capi/display_c.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ typedef struct {
4646
char* serial_number; // Display serial number (if available)
4747
} native_display_t;
4848

49+
/**
50+
* Representation of a list of displays
51+
*/
4952
typedef struct {
5053
native_display_t* displays;
5154
long count;

src/capi/display_manager_c.cpp

Lines changed: 125 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include <string.h>
22
#include <iostream>
3+
#include <vector>
34

45
#include "../display.h"
56
#include "../display_manager.h"
@@ -10,44 +11,154 @@
1011

1112
using namespace nativeapi;
1213

14+
native_display_orientation_t to_native_orientation(
15+
DisplayOrientation orientation) {
16+
switch (orientation) {
17+
case DisplayOrientation::kPortrait:
18+
return NATIVE_DISPLAY_ORIENTATION_PORTRAIT;
19+
case DisplayOrientation::kLandscape:
20+
return NATIVE_DISPLAY_ORIENTATION_LANDSCAPE;
21+
case DisplayOrientation::kPortraitFlipped:
22+
return NATIVE_DISPLAY_ORIENTATION_PORTRAIT_FLIPPED;
23+
case DisplayOrientation::kLandscapeFlipped:
24+
return NATIVE_DISPLAY_ORIENTATION_LANDSCAPE_FLIPPED;
25+
default:
26+
return NATIVE_DISPLAY_ORIENTATION_PORTRAIT;
27+
}
28+
}
29+
1330
native_display_t to_native_display(const Display& raw_display) {
14-
native_display_t display;
31+
native_display_t display = {};
32+
33+
// Allocate and copy strings
1534
display.id = strdup(raw_display.id.c_str());
1635
display.name = strdup(raw_display.name.c_str());
36+
display.manufacturer = raw_display.manufacturer.empty()
37+
? nullptr
38+
: strdup(raw_display.manufacturer.c_str());
39+
display.model =
40+
raw_display.model.empty() ? nullptr : strdup(raw_display.model.c_str());
41+
display.serial_number = nullptr; // Not available in the C++ API
42+
43+
// Copy position
44+
display.position.x = raw_display.position.x;
45+
display.position.y = raw_display.position.y;
46+
47+
// Copy size
1748
display.size.width = raw_display.size.width;
1849
display.size.height = raw_display.size.height;
50+
51+
// Copy work area
1952
display.work_area.x = raw_display.workArea.x;
2053
display.work_area.y = raw_display.workArea.y;
2154
display.work_area.width = raw_display.workArea.width;
2255
display.work_area.height = raw_display.workArea.height;
56+
57+
// Copy other properties
2358
display.scale_factor = raw_display.scaleFactor;
59+
display.is_primary = raw_display.isPrimary;
60+
display.orientation = to_native_orientation(raw_display.orientation);
61+
display.refresh_rate = raw_display.refreshRate;
62+
display.bit_depth = raw_display.bitDepth;
63+
2464
return display;
2565
}
2666

2767
DisplayManager g_display_manager = DisplayManager();
2868

2969
FFI_PLUGIN_EXPORT
3070
native_display_list_t native_display_manager_get_all() {
31-
auto displays = g_display_manager.GetAll();
32-
native_display_list_t list;
33-
list.count = displays.size();
34-
for (size_t i = 0; i < displays.size(); i++) {
35-
list.displays[i] = to_native_display(displays[i]);
71+
try {
72+
auto displays = g_display_manager.GetAll();
73+
native_display_list_t list = {};
74+
75+
list.count = displays.size();
76+
if (list.count > 0) {
77+
// Allocate array for displays
78+
list.displays =
79+
(native_display_t*)malloc(sizeof(native_display_t) * list.count);
80+
if (list.displays != nullptr) {
81+
for (size_t i = 0; i < displays.size(); i++) {
82+
list.displays[i] = to_native_display(displays[i]);
83+
}
84+
} else {
85+
list.count = 0;
86+
}
87+
} else {
88+
list.displays = nullptr;
89+
}
90+
91+
return list;
92+
} catch (const std::exception& e) {
93+
std::cerr << "Error in native_display_manager_get_all: " << e.what()
94+
<< std::endl;
95+
native_display_list_t empty_list = {};
96+
empty_list.count = 0;
97+
empty_list.displays = nullptr;
98+
return empty_list;
3699
}
37-
return list;
38100
}
39101

40102
FFI_PLUGIN_EXPORT
41103
native_display_t native_display_manager_get_primary() {
42-
auto display = g_display_manager.GetPrimary();
43-
return to_native_display(display);
104+
try {
105+
auto display = g_display_manager.GetPrimary();
106+
return to_native_display(display);
107+
} catch (const std::exception& e) {
108+
std::cerr << "Error in native_display_manager_get_primary: " << e.what()
109+
<< std::endl;
110+
native_display_t empty_display = {};
111+
return empty_display;
112+
}
44113
}
45114

46115
FFI_PLUGIN_EXPORT
47116
native_point_t native_display_manager_get_cursor_position() {
48-
auto cursor_position = g_display_manager.GetCursorPosition();
49-
native_point_t point;
50-
point.x = cursor_position.x;
51-
point.y = cursor_position.y;
52-
return point;
117+
try {
118+
auto cursor_position = g_display_manager.GetCursorPosition();
119+
native_point_t point;
120+
point.x = cursor_position.x;
121+
point.y = cursor_position.y;
122+
return point;
123+
} catch (const std::exception& e) {
124+
std::cerr << "Error in native_display_manager_get_cursor_position: "
125+
<< e.what() << std::endl;
126+
native_point_t point = {0.0, 0.0};
127+
return point;
128+
}
129+
}
130+
131+
FFI_PLUGIN_EXPORT
132+
void native_display_list_free(native_display_list_t* list) {
133+
if (list != nullptr && list->displays != nullptr) {
134+
// Free individual display strings
135+
for (size_t i = 0; i < list->count; i++) {
136+
native_display_t* display = &list->displays[i];
137+
if (display->id != nullptr) {
138+
free(display->id);
139+
display->id = nullptr;
140+
}
141+
if (display->name != nullptr) {
142+
free(display->name);
143+
display->name = nullptr;
144+
}
145+
if (display->manufacturer != nullptr) {
146+
free(display->manufacturer);
147+
display->manufacturer = nullptr;
148+
}
149+
if (display->model != nullptr) {
150+
free(display->model);
151+
display->model = nullptr;
152+
}
153+
if (display->serial_number != nullptr) {
154+
free(display->serial_number);
155+
display->serial_number = nullptr;
156+
}
157+
}
158+
159+
// Free the displays array
160+
free(list->displays);
161+
list->displays = nullptr;
162+
list->count = 0;
163+
}
53164
}

src/capi/display_manager_c.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ native_display_t native_display_manager_get_primary();
2222
FFI_PLUGIN_EXPORT
2323
native_point_t native_display_manager_get_cursor_position();
2424

25+
FFI_PLUGIN_EXPORT
26+
void native_display_list_free(native_display_list_t* list);
27+
2528
#ifdef __cplusplus
2629
}
2730
#endif

0 commit comments

Comments
 (0)