score-back/openwiki/c-api.md
Artur Mukhamadiev 71c3d930d9
All checks were successful
Verification / Is-Buildable (push) Successful in 3m8s
feat(docs) added openwiki to the project
:Release Notes:
-

:Detailed Notes:
-

:Testing Performed:
- was not verified, to be fair :D

:QA Notes:
- generated by glm-5.2

:Issues Addressed:
TG-3
2026-07-03 01:47:34 +03:00

6.3 KiB

C API for Unity Integration

The C API allows Unity (or any C/C++ consumer) to embed the RPC server as a shared library, register custom RPC handlers as C function pointers, and manage the server lifecycle without touching C++ directly.

Two C API surfaces exist:

API Header Library Purpose
Server API include/server_api.h libcloud_point_rpc Start/stop the TCP server, register RPC methods
Test API include/test_api.h test_cloud_point Internal test harness: register methods, schedule calls, auto-call loop

Both APIs use the rpc_string type and callback_t function pointer typedef.

Export macros

include/export.h defines CRPC_EXPORT. On Windows, it resolves to __declspec(dllexport) when CRPC_SERVER_API_EXPORT is defined (set in src/meson.build) and __declspec(dllimport) otherwise. On GCC/Clang, it uses __attribute__((visibility("default"))). This allows the same headers to be used when building the library and when consuming it.

rpc_string

Defined in include/cloud_point_rpc/rpc_server.hpp inside an extern "C" block:

struct rpc_string {
    std::string s;  // C++ std::string, but the struct is C-ABI compatible
};

Although the struct contains a std::string, it is allocated and managed by the library. Consumers interact with it through opaque pointers and accessor functions:

Function Description
crpc_str_create(data, size) Allocate a new rpc_string with the given data. Tracked by internal GC.
crpc_str_destroy(ptr) Manually free a rpc_string.
crpc_str_get_data(ptr) Get the raw C string pointer.
crpc_str_get_size(ptr) Get the string length.

Garbage collector

src/server_api.cpp maintains a static std::list<std::unique_ptr<rpc_string>> gc protected by gc_mtx. All crpc_str_create allocations are tracked in this list. crpc_deinit() clears the entire list. crpc_str_destroy removes a specific entry. This prevents memory leaks if Unity forgets to call destroy, though manual destruction is recommended to avoid excessive memory usage.

Important

: rpc_string pointers returned from callbacks are owned by the library's GC. Do not free() them — use crpc_str_destroy().

Server API (server_api.h)

Lifecycle

// Initialize and start the server from a config file
crpc_init("config.yaml");

// Or initialize with an explicit address (no config file needed)
crpc_init_with_address("127.0.0.1", 9095);

// ... register methods and serve ...

// Stop server and free all GC-tracked rpc_strings
crpc_deinit();
  • crpc_init(config_path) — Loads YAML config via ConfigLoader, creates a TcpServer with the configured IP/port, and starts it. Initializes Google Logging if not already initialized. See Architecture → Config.
  • crpc_init_with_address(ip, port) — Same but without a config file. Used when the consumer wants to set the address directly.
  • crpc_deinit() — Stops the server (resets the TcpServer unique_ptr) and clears the rpc_string GC list.

Registering methods

rpc_string* my_handler(rpc_string* params_json) {
    // params_json->s contains the JSON params as a string
    // Build your result (JSON or raw string)
    return crpc_str_create("{\"key\":\"value\"}", 15);
}

rpc_string method_name;
method_name.s = "my-method";
crpc_add_method(my_handler, &method_name);
  • callback_t is rpc_string* (*)(rpc_string*) — a C function pointer.
  • The callback receives the JSON params object serialized as a string in rpc_string->s.
  • The callback returns a rpc_string* whose string is parsed as JSON if possible, or used as a raw string in the result field. See RPC Protocol → Handler registration.
  • crpc_add_method is guarded by server_mtx and registers the callback on the global RpcServer.

Global state

server_api.cpp uses file-level statics: rpc_server (the global RpcServer), server (the TcpServer unique_ptr), gc (the string GC list), and two mutexes (gc_mtx, server_mtx). This means only one server instance is supported per process.

Test API (test_api.h)

The test API is built into a separate shared library (test_cloud_point) and provides a TestThread class (in src/test_api.cpp) that runs a background std::jthread for testing registered methods without a real TCP connection.

Lifecycle

crpc_test_init();       // Start the test thread + Google Logging
// ... register methods, schedule calls ...
crpc_test_deinit();     // Stop thread, call crpc_deinit(), reset state

Methods

Function Description
crpc_test_add_method(cb, name) Register a method on the test RpcServer. Duplicates are ignored.
crpc_test_remove_method(name) Remove a registered method. Returns 0 on success, -1 if not found.
crpc_test_schedule_call(name) Enqueue a one-shot call to the named method (processed by the test thread).
crpc_test_change_duration(ms) Set the auto-call sleep interval (default 50ms).
crpc_test_duration() Get the current sleep interval.
crpc_test_auto_call(state) Enable (1) or disable (0) auto-calling registered methods on each sleep cycle.

Test thread behavior

The TestThread::routine() loop:

  1. If there are queued one-shot calls, process them (build a JSON-RPC request and call server.process()).
  2. If auto-call is enabled and methods exist, call the next method in round-robin order.
  3. If auto-call is enabled and the queue is empty, wait on a condition variable for the configured duration (or until stop is requested).
  4. Stop when jthread stop is requested via crpc_test_deinit().

Note

: The test API does not start a TCP server. It processes JSON-RPC requests directly through RpcServer::process(), logging results. It is designed for testing handler registration and callback behavior in C, as demonstrated in tests/test_c_api.cpp and tests/test_c_api_edge_cases.cpp.

Source references

  • include/server_api.h — Server C API declarations
  • src/server_api.cpp — Server C API implementation, rpc_string GC
  • include/test_api.h — Test C API declarations
  • src/test_api.cppTestThread implementation and test C API
  • include/export.hCRPC_EXPORT macro
  • include/cloud_point_rpc/rpc_server.hpprpc_string struct and callback_t typedef