Thanks to visit codestin.com
Credit goes to fory.apache.org

Skip to main content
Version: 0.14

C++ Serialization Guide

Apache Fory™ is a blazing fast multi-language serialization framework powered by JIT compilation and zero-copy techniques, providing up to ultra-fast performance while maintaining ease of use and safety.

The C++ implementation provides high-performance serialization with compile-time type safety using modern C++17 features and template metaprogramming.

Why Apache Fory™ C++?

  • 🔥 Blazingly Fast: Fast serialization and optimized binary protocols
  • 🌍 Cross-Language: Seamlessly serialize/deserialize data across Java, Python, C++, Go, JavaScript, and Rust
  • 🎯 Type-Safe: Compile-time type checking with macro-based struct registration
  • 🔄 Reference Tracking: Automatic tracking of shared and circular references
  • 📦 Schema Evolution: Compatible mode for independent schema changes
  • ⚡ Two Formats: Object graph serialization and zero-copy row-based format
  • 🧵 Thread Safety: Both single-threaded (fastest) and thread-safe variants

Installation

The C++ implementation supports both CMake and Bazel build systems.

Prerequisites

  • CMake 3.16+ (for CMake build) or Bazel 8+ (for Bazel build)
  • C++17 compatible compiler (GCC 7+, Clang 5+, MSVC 2017+)

The easiest way to use Fory is with CMake's FetchContent module:

cmake_minimum_required(VERSION 3.16)
project(my_project LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

include(FetchContent)
FetchContent_Declare(
fory
GIT_REPOSITORY https://github.com/apache/fory.git
GIT_TAG v0.14.0
SOURCE_SUBDIR cpp
)
FetchContent_MakeAvailable(fory)

add_executable(my_app main.cc)
target_link_libraries(my_app PRIVATE fory::serialization)

Then build and run:

mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build . --parallel
./my_app

Using Bazel

Create a MODULE.bazel file in your project root:

module(
name = "my_project",
version = "1.0.0",
)

bazel_dep(name = "rules_cc", version = "0.1.1")

bazel_dep(name = "fory", version = "0.14.0")
git_override(
module_name = "fory",
remote = "https://github.com/apache/fory.git",
commit = "v0.14.0", # Or use a specific commit hash for reproducibility
)

Create a BUILD file for your application:

cc_binary(
name = "my_app",
srcs = ["main.cc"],
deps = ["@fory//cpp/fory/serialization:fory_serialization"],
)

Then build and run:

bazel build //:my_app
bazel run //:my_app

For local development, you can use local_path_override instead:

bazel_dep(name = "fory", version = "0.14.0")
local_path_override(
module_name = "fory",
path = "/path/to/fory",
)

Examples

See the examples/cpp directory for complete working examples:

Quick Start

Basic Example

#include "fory/serialization/fory.h"

using namespace fory::serialization;

// Define a struct
struct Person {
std::string name;
int32_t age;
std::vector<std::string> hobbies;

bool operator==(const Person &other) const {
return name == other.name && age == other.age && hobbies == other.hobbies;
}
};

// Register the struct with Fory (must be in the same namespace)
FORY_STRUCT(Person, name, age, hobbies);

int main() {
// Create a Fory instance
auto fory = Fory::builder()
.xlang(true) // Enable cross-language mode
.track_ref(false) // Disable reference tracking for simple types
.build();

// Register the type with a unique ID
fory.register_struct<Person>(1);

// Create an object
Person person{"Alice", 30, {"reading", "coding"}};

// Serialize
auto result = fory.serialize(person);
if (!result.ok()) {
// Handle error
return 1;
}
std::vector<uint8_t> bytes = std::move(result).value();

// Deserialize
auto deser_result = fory.deserialize<Person>(bytes);
if (!deser_result.ok()) {
// Handle error
return 1;
}
Person decoded = std::move(deser_result).value();

assert(person == decoded);
return 0;
}

Thread Safety

Apache Fory™ C++ provides two variants for different threading needs:

Single-Threaded (Fastest)

// Single-threaded Fory - fastest, NOT thread-safe
auto fory = Fory::builder()
.xlang(true)
.build();

Thread-Safe

// Thread-safe Fory - uses context pools
auto fory = Fory::builder()
.xlang(true)
.build_thread_safe();

// Can be used from multiple threads safely
std::thread t1([&]() {
auto result = fory.serialize(obj1);
});
std::thread t2([&]() {
auto result = fory.serialize(obj2);
});

Tip: Perform type registrations before spawning threads so every worker sees the same metadata.

Use Cases

Object Serialization

  • Complex data structures with nested objects and references
  • Cross-language communication in microservices
  • General-purpose serialization with full type safety
  • Schema evolution with compatible mode

Row-Based Serialization

  • High-throughput data processing
  • Analytics workloads requiring fast field access
  • Memory-constrained environments
  • Zero-copy scenarios

Next Steps