Skip to content

Commit b4dd766

Browse files
committed
Add C URL opener example and instance-based C API
Add a new examples/url_opener_c_example (CMakeLists + main.c) and include it in the top-level CMakeLists. Change the C API to use an opaque native_url_opener_t instance: add native_url_opener_create() and native_url_opener_destroy(), update native_url_opener_is_supported() and native_url_opener_open() to accept the instance, and add FFI_PLUGIN_EXPORT for symbol visibility. Implement GetUrlOpener helper, improve null checks and error handling in src/capi/url_opener_c.cpp, and keep the existing result cleanup API.
1 parent 1b42dae commit b4dd766

File tree

5 files changed

+104
-7
lines changed

5 files changed

+104
-7
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ add_subdirectory(examples/storage_example)
2626
add_subdirectory(examples/storage_c_example)
2727
add_subdirectory(examples/tray_icon_example)
2828
add_subdirectory(examples/tray_icon_c_example)
29+
add_subdirectory(examples/url_opener_c_example)
2930
add_subdirectory(examples/window_c_example)
3031
add_subdirectory(examples/window_example)
3132

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
cmake_minimum_required(VERSION 3.10)
2+
3+
project(url_opener_c_example)
4+
5+
set(CMAKE_C_STANDARD 11)
6+
set(CMAKE_C_STANDARD_REQUIRED ON)
7+
8+
add_executable(url_opener_c_example main.c)
9+
10+
target_link_libraries(url_opener_c_example nativeapi)
11+
12+
target_include_directories(url_opener_c_example PRIVATE ../../include)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include <nativeapi.h>
2+
#include <stdio.h>
3+
4+
int main(void) {
5+
printf("URL Opener C API Example\n");
6+
printf("========================\n\n");
7+
8+
native_url_opener_t opener = native_url_opener_create();
9+
if (!opener) {
10+
fprintf(stderr, "Failed to create URL opener instance.\n");
11+
return 1;
12+
}
13+
14+
if (!native_url_opener_is_supported(opener)) {
15+
printf("URL opening is not supported on this platform.\n");
16+
native_url_opener_destroy(opener);
17+
return 0;
18+
}
19+
20+
printf("URL opening is supported.\n");
21+
printf("Opening https://example.com ...\n");
22+
23+
native_url_open_result_t result = native_url_opener_open(opener, "https://example.com");
24+
if (result.success) {
25+
printf("URL opened successfully.\n");
26+
} else {
27+
fprintf(stderr, "Failed to open URL.\n");
28+
fprintf(stderr, "Error code: %d\n", (int)result.error_code);
29+
fprintf(stderr, "Message: %s\n", result.error_message ? result.error_message : "(none)");
30+
}
31+
32+
native_url_open_result_free(&result);
33+
native_url_opener_destroy(opener);
34+
return result.success ? 0 : 1;
35+
}

src/capi/url_opener_c.cpp

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ using namespace nativeapi;
1010

1111
namespace {
1212

13+
UrlOpener* GetUrlOpener(native_url_opener_t opener) {
14+
return static_cast<UrlOpener*>(opener);
15+
}
16+
1317
native_url_open_error_code_t ToCErrorCode(UrlOpenErrorCode code) {
1418
switch (code) {
1519
case UrlOpenErrorCode::kNone:
@@ -41,22 +45,41 @@ native_url_open_result_t MakeResult(bool success,
4145

4246
} // namespace
4347

44-
bool native_url_opener_is_supported(void) {
48+
native_url_opener_t native_url_opener_create(void) {
49+
try {
50+
return static_cast<native_url_opener_t>(new UrlOpener());
51+
} catch (...) {
52+
return nullptr;
53+
}
54+
}
55+
56+
void native_url_opener_destroy(native_url_opener_t opener) {
57+
delete GetUrlOpener(opener);
58+
}
59+
60+
bool native_url_opener_is_supported(native_url_opener_t opener) {
61+
if (!opener) {
62+
return false;
63+
}
64+
4565
try {
4666
return UrlOpener::IsSupported();
4767
} catch (...) {
4868
return false;
4969
}
5070
}
5171

52-
native_url_open_result_t native_url_opener_open(const char* url) {
72+
native_url_open_result_t native_url_opener_open(native_url_opener_t opener, const char* url) {
73+
if (!opener) {
74+
return MakeResult(false, NATIVE_URL_OPEN_ERROR_INVOCATION_FAILED, "URL opener is null.");
75+
}
76+
5377
if (!url) {
5478
return MakeResult(false, NATIVE_URL_OPEN_ERROR_INVALID_URL_EMPTY, "URL is empty.");
5579
}
5680

5781
try {
58-
UrlOpener opener;
59-
const UrlOpenResult result = opener.Open(std::string(url));
82+
const UrlOpenResult result = GetUrlOpener(opener)->Open(std::string(url));
6083
return MakeResult(result.success, ToCErrorCode(result.error_code), result.error_message);
6184
} catch (const std::exception& e) {
6285
return MakeResult(false, NATIVE_URL_OPEN_ERROR_INVOCATION_FAILED, e.what());

src/capi/url_opener_c.h

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
11
#pragma once
22

3+
#include <stdbool.h>
4+
5+
#if _WIN32
6+
#define FFI_PLUGIN_EXPORT __declspec(dllexport)
7+
#else
8+
#define FFI_PLUGIN_EXPORT
9+
#endif
10+
311
#ifdef __cplusplus
412
extern "C" {
513
#endif
614

7-
#include <stdbool.h>
15+
/**
16+
* @brief Opaque handle for a URL opener instance.
17+
*/
18+
typedef void* native_url_opener_t;
819

920
/**
1021
* @brief Error codes returned by URL opening APIs.
@@ -27,21 +38,36 @@ typedef struct {
2738
char* error_message;
2839
} native_url_open_result_t;
2940

41+
/**
42+
* @brief Create a URL opener instance.
43+
*/
44+
FFI_PLUGIN_EXPORT
45+
native_url_opener_t native_url_opener_create(void);
46+
47+
/**
48+
* @brief Destroy a URL opener instance.
49+
*/
50+
FFI_PLUGIN_EXPORT
51+
void native_url_opener_destroy(native_url_opener_t opener);
52+
3053
/**
3154
* @brief Check whether URL opening is supported on this platform.
3255
*/
33-
bool native_url_opener_is_supported(void);
56+
FFI_PLUGIN_EXPORT
57+
bool native_url_opener_is_supported(native_url_opener_t opener);
3458

3559
/**
3660
* @brief Attempt to open URL with the system default browser.
3761
*
3862
* Caller must release result.error_message via native_url_open_result_free().
3963
*/
40-
native_url_open_result_t native_url_opener_open(const char* url);
64+
FFI_PLUGIN_EXPORT
65+
native_url_open_result_t native_url_opener_open(native_url_opener_t opener, const char* url);
4166

4267
/**
4368
* @brief Free owned memory inside a native_url_open_result_t.
4469
*/
70+
FFI_PLUGIN_EXPORT
4571
void native_url_open_result_free(native_url_open_result_t* result);
4672

4773
#ifdef __cplusplus

0 commit comments

Comments
 (0)