title: C++ Serialization Guide sidebar_position: 0 id: cpp_serialization_index license: | Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

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+)

Using CMake (Recommended)

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)
if(MSVC)
    add_compile_options(/Zc:preprocessor)
endif()
include(FetchContent)
FetchContent_Declare(
    fory
    GIT_REPOSITORY https://github.com/apache/fory.git
    GIT_TAG        v0.14.1
    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.1")
git_override(
    module_name = "fory",
    remote = "https://github.com/apache/fory.git",
    commit = "v0.14.1",  # 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.1")
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