# rpc_core **Repository Path**: shanechang/rpc_core ## Basic Information - **Project Name**: rpc_core - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-16 - **Last Updated**: 2026-07-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # rpc_core [![Build Status](https://github.com/shuai132/rpc_core/workflows/cpp/badge.svg)](https://github.com/shuai132/rpc_core/actions?workflow=cpp) [![Build Status](https://github.com/shuai132/rpc_core/workflows/c/badge.svg)](https://github.com/shuai132/rpc_core/actions?workflow=c) [![Build Status](https://github.com/shuai132/rpc_core/workflows/rust/badge.svg)](https://github.com/shuai132/rpc_core/actions?workflow=rust) [![Build Status](https://github.com/shuai132/rpc_core/workflows/js/badge.svg)](https://github.com/shuai132/rpc_core/actions?workflow=js) [![Build Status](https://github.com/shuai132/rpc_core/workflows/python/badge.svg)](https://github.com/shuai132/rpc_core/actions?workflow=python) [![Release](https://img.shields.io/github/release/shuai132/rpc_core.svg)](https://github.com/shuai132/rpc_core/releases) [![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) a tiny C++14 rpc library, supports all platforms (macOS, Linux, Windows, iOS, Android, etc.) and most microchips ( Arduino, STM32, ESP32/ESP8266, etc.) **C++ TCP options:** this repository includes a small optional C++ TCP adapter, `rpc_core/net/asio_tcp.hpp`, which depends on standalone [Asio](https://think-async.com/Asio/#). It is intended to match the simple TCP helpers provided by the JavaScript, Python, and Rust SDKs. It uses the native C++ serializer by default; enable `RPC_CORE_SERIALIZE_USE_NLOHMANN_JSON` when cross-language JSON payload compatibility is required. For a more complete C++ networking implementation, including reconnect, SSL, UDP, serial, DDS, and discovery support, use [asio_net](https://github.com/shuai132/asio_net). ## Introduction Full-feature rpc frameworks (e.g. `gRPC` and `bRPC`) are very complex and not suitable for use on embedded platforms. This project offers a lightweight and user-friend rpc library that is better suited for one-to-one rpc calls. It supports all platforms and a wide range of microchips, including Arduino, STM32, ESP32/ESP8266, and more. Note: The default C++ include path only offers the protocol layer and API. TCP support is available as an optional standalone Asio adapter in `rpc_core/net/asio_tcp.hpp`; it is not included by `rpc_core.hpp`. ## Features * Header-Only * No-Schema * Support performance-limited platforms including microchips * Support any connection type (`tcp socket`, `serial port`, etc.) * High Performance Serialization, support most STL containers and user type * Serialization plugins implementations for `flatbuffers` and `nlohmann::json` * Support `co_await`, depend on `C++20` and `asio`, or custom implementation * Support subscribe async callback, async coroutine, and custom scheduler * RAII-based `dispose` for automatic cancel request * Support timeout, retry, cancel api * Comprehensive unittests ## TCP-based implementations * C++ built-in adapter - [./cpp](./cpp): notes for C++ users. `rpc_core/net/asio_tcp.hpp` provides the built-in lightweight TCP adapter and requires standalone [Asio](https://think-async.com/Asio/#). It uses the native C++ serializer by default; JSON variants are available for cross-language testing. * C++ full networking layer - [asio_net](https://github.com/shuai132/asio_net): complete C++ networking implementation for reconnect, SSL, UDP, serial, DDS, discovery, and related production features. * Rust - [./rust](./rust): based on [tokio](https://github.com/tokio-rs/tokio) Support callback and async/await, details: [README.md](./rust/README.md) * JavaScript / TypeScript - [./js](./js): browser-safe core SDK with WebSocket adapter and a separate Node TCP adapter Uses the same RPC wire header and JSON payloads, details: [README.md](./js/README.md) * Python - [./python](./python): asyncio-friendly SDK with loopback and TCP stream helpers Uses the same RPC wire header and JSON payloads, details: [README.md](./python/README.md) * C - [./c](./c): dependency-free C SDK with raw/text/json payload helpers and TCP adapters for POSIX and Windows. Uses the same RPC wire header and stream framing, details: [README.md](./c/README.md) ## Cross-language RPC For cross-language RPC, use JSON as the shared payload serialization format. The RPC protocol itself is still binary: `seq(u32 LE) + cmd_len(u16 LE) + cmd + type(u8) + payload`. This keeps the framing compact and efficient while allowing each language to choose a flexible, widely supported data format for request and response bodies. The protocol uses `type` bit 6 (`0x40`) to mark JSON payloads. Receivers still accept unmarked JSON packets for backward compatibility, while the marker helps diagnose native-vs-JSON payload mismatches. JavaScript, Python, and Rust SDKs use JSON payloads by default. C++ uses the native binary serializer by default, including the built-in C++ TCP adapter. For cross-language RPC, define `RPC_CORE_SERIALIZE_USE_NLOHMANN_JSON` and make `nlohmann/json.hpp` available in the include path: ```shell cmake -S . -B build -DRPC_CORE_SERIALIZE_USE_NLOHMANN_JSON=ON ``` When this option is enabled, C++ `msg` and `rsp` payloads use the nlohmann/json serializer path, making them compatible with the JS, Python, and Rust SDKs as long as all sides use matching JSON object shapes and value types. ## Requirements * C++14 * Provide your connection implementation: [connection](include/rpc_core/connection.hpp) NOTICE: complete data packets are required for data transmission, such as `websocket`. If using `tcp socket`, `serial port`, etc., message pack and unpack need to be implemented. Or you can use [stream_connection](include/rpc_core/connection.hpp), or the optional standalone Asio TCP adapter [asio_tcp.hpp](include/rpc_core/net/asio_tcp.hpp). * Optional: C++20 (for coroutine api, co_await co_call) ## Usage * basic usage: notice: both sender and receiver can use `subscribe` and `call` apis ```c++ // receiver rpc->subscribe("cmd", [](const std::string& msg) -> std::string { assert(msg == "hello"); return "world"; }); // sender rpc->cmd("cmd") ->msg(std::string("hello")) ->rsp([](const std::string& rsp) { assert(rsp == "world"); }) ->call(); // or: rpc->call("cmd", std::string("hello"), [](const std::string& rsp) {}); ``` * async response: just use `request_response<>` type, with `scheduler` support ```c++ rpc->subscribe("cmd", [&](request_response rr) { assert(rr->req == "hello"); rr->rsp("world"); // call rr->rsp() when data is ready }, scheduler); ``` * async call and response using c++20 coroutine: here is an example using asio, custom async/coroutine implementation is supported ```c++ // receiver rpc->subscribe("cmd", [&](request_response rr) -> asio::awaitable { assert(rr->req == "hello"); asio::steady_timer timer(context); timer.expires_after(std::chrono::seconds(1)); co_await timer.async_wait(); rr->rsp("world"); }, scheduler_asio_coroutine); // sender // use C++20 co_await with asio, or you can use custom async implementation, and co_await it! auto rsp = co_await rpc->cmd("cmd")->msg(std::string("hello"))->co_call(); // or: auto rsp = co_await rpc->co_call("cmd", std::string("hello")); assert(rsp.data == "world"); ``` Inspect the code for more details: [rpc_s_coroutine.cpp](https://github.com/shuai132/asio_net/blob/main/test/rpc_s_coroutine.cpp) and [rpc_c_coroutine.cpp](https://github.com/shuai132/asio_net/blob/main/test/rpc_c_coroutine.cpp) * Addition: 1. `msg` and `rsp` support any serializable type, refer to [Serialization](#Serialization). 2. Detailed usages and unittests can be found here: [rpc_test.cpp](cpp/test/test_rpc.cpp) 3. There is an example shows custom async impl: [rpc_c_coroutine.hpp](https://github.com/shuai132/asio_net/blob/main/test/rpc_c_coroutine.hpp) ## Serialization High-performance and memory-saving binary serialization. * api is very simple to use: [include/rpc_core/serialize_api.hpp](include/rpc_core/serialize_api.hpp) * usage and comprehensive unittest: [cpp/test/test_serialize.cpp](cpp/test/test_serialize.cpp) * the design balance cpu and memory usage, and zero-copy if possible. * std::string is used as inner data container, it's serialize/deserialize is zero-overhead. so, it is recommended to use std::string whenever possible, using it to store binary data is also a good choice. ### Why design a new serialization Fist of all, I want to keep `rpc_core` library standalone, without any dependencies, except for STL. Moreover, these serialization libraries do not align with my design goals: * protobuf library is too large for some platforms, and it's Varint, Zigzag, and GZIP will use a lot of cpu. * msgpack has similarity reason to protobuf. * flatbuffers serialized data is too large. Of course, when communicating across languages, it is recommended to use the above serialization libraries! Finally, it also provides a way to use thirdparty serialization libraries directly, refer to [Serialization Plugins](#Serialization-Plugins). ### Usage For example, user data: ```c++ struct Type { uint8_t id = 1; uint8_t age = 18; std::string name = "test"; }; ``` json: `{"id":1,"age":18,"name":"test"}` | library | bytes | |-------------|:-----:| | json | 31 | | flatbuffers | 44 | | protobuf | 10 | | msgpack | 20 | | rpc_core | 8 | - [x] [std::string](https://en.cppreference.com/w/cpp/string/basic_string) - [x] [std::wstring](https://en.cppreference.com/w/cpp/string/basic_string) - [x] [std::array](https://en.cppreference.com/w/cpp/container/array) - [x] [std::vector](https://en.cppreference.com/w/cpp/container/vector) - [x] [std::list](https://en.cppreference.com/w/cpp/container/list) - [x] [std::forward_list](https://en.cppreference.com/w/cpp/container/forward_list) - [x] [std::deque](https://en.cppreference.com/w/cpp/container/deque) - [x] [std::pair](https://en.cppreference.com/w/cpp/utility/pair) - [x] [std::tuple](https://en.cppreference.com/w/cpp/utility/tuple) - [x] [std::map](https://en.cppreference.com/w/cpp/container/map) - [x] [std::unordered_map](https://en.cppreference.com/w/cpp/container/unordered_map) - [x] [std::multimap](https://en.cppreference.com/w/cpp/container/multimap) - [x] [std::unordered_multimap](https://en.cppreference.com/w/cpp/container/unordered_multimap) - [x] [std::set](https://en.cppreference.com/w/cpp/container/set) - [x] [std::unordered_set](https://en.cppreference.com/w/cpp/container/unordered_set) - [x] [std::multiset](https://en.cppreference.com/w/cpp/container/multiset) - [x] [std::unordered_multiset](https://en.cppreference.com/w/cpp/container/unordered_multiset) - [x] [std::stack](https://en.cppreference.com/w/cpp/container/stack) - [x] [std::queue](https://en.cppreference.com/w/cpp/container/queue) - [x] [std::priority_queue](https://en.cppreference.com/w/cpp/container/priority_queue) - [x] [std::bitset](https://en.cppreference.com/w/cpp/utility/bitset) - [x] [std::complex](https://en.cppreference.com/w/cpp/numeric/complex) - [x] [std::chrono::duration](https://en.cppreference.com/w/cpp/chrono/duration) - [x] [std::chrono::time_point](https://en.cppreference.com/w/cpp/chrono/time_point) - [x] [std::unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr) - [x] [std::shared_ptr](https://en.cppreference.com/w/cpp/memory/shared_ptr) - [x] [rpc_core::binary_wrap](include/rpc_core/serialize/binary_wrap.hpp) - [x] [custom struct/class](cpp/test/serialize/CustomType.h) ```c++ #include "rpc_core/serialize.hpp" struct TestStruct { uint8_t a; std::string b; OtherType c // RPC_CORE_DEFINE_TYPE_INNER(a, b, c); }; RPC_CORE_DEFINE_TYPE(TestStruct, a, b, c); ``` choose `RPC_CORE_DEFINE_TYPE` or `RPC_CORE_DEFINE_TYPE_INNER` for private member variable. ## Serialization Plugins * [flatbuffers.hpp](include/rpc_core/plugin/flatbuffers.hpp) Supports using types generated by `flatbuffers` directly as message (add the option `--gen-object-api` when using `flatc`) * [json_msg.hpp](include/rpc_core/plugin/json_msg.hpp) Supports using types supported by [nlohmann/json](https://github.com/nlohmann/json) directly as message (the `to_json/from_json` rules in `nlohmann/json` need to be satisfied, and use `DEFINE_JSON_CLASS`). * [json.hpp](include/rpc_core/plugin/json.hpp) A flexible way to use `nlohmann/json` # License This project is licensed under the [MIT license](LICENSE). # Links * Implementation based on asio: [asio_net](https://github.com/shuai132/asio_net) * Implementation suitable for ESP8266: [esp_rpc](https://github.com/shuai132/esp_rpc)