node_app_api/ffi.rs
1//! C ABI definitions for native app loading
2//!
3//! All structs in this module use `#[repr(C)]` for stable ABI across
4//! Rust, Go, C, C++, and Zig compiled shared libraries.
5
6use std::ffi::c_char;
7use std::os::raw::c_void;
8
9/// Symbol name for the app entry point function in shared libraries.
10/// Native apps must export this symbol.
11pub const NODE_APP_ENTRY_SYMBOL: &[u8] = b"_node_app_entry\0";
12
13/// Result type returned by FFI functions
14#[repr(C)]
15#[derive(Debug)]
16pub struct FfiResult {
17 /// Whether the operation succeeded
18 pub success: bool,
19 /// Error code (0 = no error, negative = app-defined error)
20 pub error_code: i32,
21 /// Pointer to response data (JSON bytes, caller must free with host_free)
22 pub data: *mut u8,
23 /// Length of the response data in bytes
24 pub data_len: usize,
25}
26
27impl FfiResult {
28 /// Create a successful result with no data
29 pub fn ok() -> Self {
30 Self {
31 success: true,
32 error_code: 0,
33 data: std::ptr::null_mut(),
34 data_len: 0,
35 }
36 }
37
38 /// Create an error result
39 pub fn error(code: i32) -> Self {
40 Self {
41 success: false,
42 error_code: code,
43 data: std::ptr::null_mut(),
44 data_len: 0,
45 }
46 }
47}
48
49/// App metadata returned by the entry point function
50#[repr(C)]
51pub struct NodeAppMetadata {
52 /// API version (must match host API_VERSION)
53 pub api_version: u32,
54 /// App name (null-terminated UTF-8 string, owned by app)
55 pub name: *const c_char,
56 /// App version (null-terminated UTF-8 string, owned by app)
57 pub version: *const c_char,
58 /// Author (null-terminated UTF-8 string, owned by app)
59 pub author: *const c_char,
60 /// Description (null-terminated UTF-8 string, owned by app)
61 pub description: *const c_char,
62 /// Capability flags (bitwise OR of Capabilities values)
63 pub capabilities: u32,
64}
65
66/// VTable of function pointers for app operations.
67/// Returned by the `_node_app_entry` symbol.
68#[repr(C)]
69pub struct NodeAppVTable {
70 /// App metadata
71 pub metadata: NodeAppMetadata,
72 /// Initialize the app with the host context.
73 /// Called once after loading. Returns FfiResult.
74 pub init: unsafe extern "C" fn(ctx: *const c_void) -> FfiResult,
75 /// Shut down the app gracefully.
76 /// Called before unloading the shared library.
77 pub shutdown: unsafe extern "C" fn() -> FfiResult,
78 /// Handle an HTTP request.
79 /// `request_json` is a pointer to UTF-8 JSON bytes of length `request_len`.
80 /// Returns FfiResult with response JSON in `data`/`data_len`.
81 pub handle_request:
82 unsafe extern "C" fn(request_json: *const u8, request_len: usize) -> FfiResult,
83 /// Handle a domain event.
84 /// `event_json` is a pointer to UTF-8 JSON bytes of length `event_len`.
85 /// Returns FfiResult (data is typically empty for events).
86 pub handle_event: unsafe extern "C" fn(event_json: *const u8, event_len: usize) -> FfiResult,
87 /// Handle a capability invocation from the capability router.
88 /// `request_json` is a pointer to UTF-8 JSON bytes (CapabilityRequest) of length `request_len`.
89 /// Returns FfiResult with CapabilityResponse JSON in `data`/`data_len`.
90 /// Response is limited to 16MB.
91 pub handle_capability:
92 unsafe extern "C" fn(request_json: *const u8, request_len: usize) -> FfiResult,
93 /// Free memory allocated by the app (for response data).
94 /// The host calls this to release `FfiResult.data`.
95 pub free: unsafe extern "C" fn(ptr: *mut u8, len: usize),
96}
97
98// Safety: NodeAppMetadata contains *const c_char pointers that point to
99// static CStrings owned by the plugin. They are effectively immutable
100// once the vtable is constructed and valid for the process lifetime.
101unsafe impl Send for NodeAppMetadata {}
102unsafe impl Sync for NodeAppMetadata {}
103
104// Safety: NodeAppVTable contains function pointers (inherently thread-safe)
105// and a NodeAppMetadata with static CString pointers. Once constructed,
106// the vtable is immutable and safe to share across threads.
107unsafe impl Send for NodeAppVTable {}
108unsafe impl Sync for NodeAppVTable {}
109
110/// Type signature for the `_node_app_entry` function exported by native apps.
111/// Returns a pointer to a static NodeAppVTable.
112pub type NodeAppEntryFn = unsafe extern "C" fn(ctx: *const c_void) -> *const NodeAppVTable;