This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git


The following commit(s) were added to refs/heads/main by this push:
     new 42bb30502 feat(c++): add cmake build support and add cpp examples 
(#2942)
42bb30502 is described below

commit 42bb3050232632ecbb80e3158130df132f94bdc8
Author: Shawn Yang <[email protected]>
AuthorDate: Thu Nov 27 20:43:48 2025 +0800

    feat(c++): add cmake build support and add cpp examples (#2942)
    
    ## Why?
    
    Cmake is used wildy, many users don't use bazel
    
    ## What does this PR do?
    
    - add cmake build support
    - add cpp examples
    
    ## Related issues
    
    #2906
    Closes #2921
    
    ## Does this PR introduce any user-facing change?
    
    <!--
    If any user-facing interface changes, please [open an
    issue](https://github.com/apache/fory/issues/new/choose) describing the
    need to do so and update the document if necessary.
    
    Delete section if not applicable.
    -->
    
    - [ ] Does this PR introduce any public API change?
    - [ ] Does this PR introduce any binary protocol compatibility change?
    
    ## Benchmark
    
    <!--
    When the PR has an impact on performance (if you don't know whether the
    PR will have an impact on performance, you can submit the PR first, and
    if it will have impact on performance, the code reviewer will explain
    it), be sure to attach a benchmark data here.
    
    Delete section if not applicable.
    -->
---
 .github/workflows/ci.yml                           |  14 +
 .gitignore                                         |   1 +
 AGENTS.md                                          |  32 ++
 cpp/CMakeLists.txt                                 | 181 ++++++++++++
 cpp/cmake/ForyConfig.cmake.in                      |  39 +++
 cpp/fory/encoder/CMakeLists.txt                    |  39 +++
 cpp/fory/meta/CMakeLists.txt                       |  70 +++++
 cpp/fory/row/CMakeLists.txt                        |  58 ++++
 cpp/fory/serialization/CMakeLists.txt              |  94 ++++++
 cpp/fory/thirdparty/CMakeLists.txt                 |  32 ++
 cpp/fory/type/CMakeLists.txt                       |  35 +++
 cpp/fory/util/CMakeLists.txt                       |  90 ++++++
 examples/cpp/cmake_example/CMakeLists.txt          |  78 +++++
 examples/cpp/cmake_example/README.md               | 168 +++++++++++
 examples/cpp/cmake_example/row_format_example.cc   | 260 ++++++++++++++++
 examples/cpp/cmake_example/run.sh                  |  66 +++++
 .../cpp/cmake_example/serialization_example.cc     | 327 +++++++++++++++++++++
 17 files changed, 1584 insertions(+)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6030a666b..87a2c8558 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -420,6 +420,20 @@ jobs:
           cd fory-core
           mvn -T16 --no-transfer-progress test 
-Dtest=org.apache.fory.CPPXlangTest
 
+  cpp_example:
+    name: C++ Example
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v5
+      - name: Set up Python
+        uses: actions/setup-python@v5
+        with:
+          python-version: '3.11'
+      - name: Build and run C++ CMake examples
+        run: |
+          cd examples/cpp/cmake_example
+          ./run.sh
+
   python:
     name: Python CI
     runs-on: ${{ matrix.os }}
diff --git a/.gitignore b/.gitignore
index c79bd6f31..558badab6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -80,3 +80,4 @@ dist/
 **/.pytest_cache
 .venv
 **/.idea
+examples/cpp/cmake_example/build
\ No newline at end of file
diff --git a/AGENTS.md b/AGENTS.md
index 87b72e9c4..707965ec9 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -548,6 +548,38 @@ Fory rust provides macro-based serialization and 
deserialization. Fory rust cons
 - **`lint.yml`**: Code formatting and linting
 - **`pr-lint.yml`**: PR-specific checks
 
+### Fixing GitHub CI Errors
+
+Use the GitHub CLI (`gh`) to inspect and fix CI failures:
+
+```bash
+# List all checks for a PR and their status
+gh pr checks <PR_NUMBER> --repo apache/fory
+
+# View failed job logs (get job ID from pr checks output)
+gh run view <RUN_ID> --repo apache/fory --job <JOB_ID> --log-failed
+
+# View full job logs
+gh run view <RUN_ID> --repo apache/fory --job <JOB_ID> --log
+
+# Example workflow for fixing CI errors:
+# 1. List checks to find failing jobs
+gh pr checks 2942 --repo apache/fory
+
+# 2. Get the failed job logs (RUN_ID and JOB_ID from step 1)
+gh run view 19735911308 --repo apache/fory --job 56547673283 --log-failed
+
+# 3. Fix the issues based on error messages
+# 4. Commit and push fixes
+```
+
+Common CI failures and fixes:
+
+- **Code Style Check**: Run formatters (`clang-format`, `prettier`, 
`spotless:apply`, etc.)
+- **Markdown Lint**: Run `prettier --write <file>` for markdown files
+- **C++ Build Errors**: Check for missing dependencies or header includes
+- **Test Failures**: Run tests locally to reproduce and fix
+
 ## Commit Message Format
 
 Use conventional commits with language scope:
diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
new file mode 100644
index 000000000..ef368623f
--- /dev/null
+++ b/cpp/CMakeLists.txt
@@ -0,0 +1,181 @@
+# 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.
+
+cmake_minimum_required(VERSION 3.16)
+
+project(fory
+    VERSION 0.14.0
+    DESCRIPTION "Apache Fory - A blazingly fast multi-language serialization 
framework"
+    LANGUAGES CXX
+)
+
+# C++ standard
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS OFF)
+
+# Options
+option(FORY_BUILD_TESTS "Build Fory tests" OFF)
+option(FORY_BUILD_SHARED "Build shared libraries" ON)
+option(FORY_BUILD_STATIC "Build static libraries" ON)
+option(FORY_USE_AVX2 "Enable AVX2 optimizations on x86_64" ON)
+
+# Set default build type if not specified
+if(NOT CMAKE_BUILD_TYPE)
+    set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
+endif()
+
+# Output directories
+set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+
+# Platform detection
+if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64|amd64")
+    set(FORY_IS_X86_64 TRUE)
+else()
+    set(FORY_IS_X86_64 FALSE)
+endif()
+
+# Compiler flags
+if(MSVC)
+    add_compile_options(/W4)
+    if(FORY_USE_AVX2 AND FORY_IS_X86_64)
+        add_compile_options(/arch:AVX2)
+    endif()
+else()
+    add_compile_options(-Wall -Wextra -Wpedantic)
+    if(FORY_USE_AVX2 AND FORY_IS_X86_64)
+        add_compile_options(-mavx2)
+    endif()
+endif()
+
+# Set Fory root directory for include paths (important when used as 
subdirectory)
+set(FORY_CPP_ROOT ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH "Fory C++ root 
directory")
+
+# Fetch Abseil (required for debugging support)
+message(STATUS "Fetching Abseil via FetchContent")
+include(FetchContent)
+set(ABSL_PROPAGATE_CXX_STD ON)
+set(ABSL_BUILD_TESTING OFF)
+set(ABSL_ENABLE_INSTALL ON)
+FetchContent_Declare(
+    abseil-cpp
+    GIT_REPOSITORY https://github.com/abseil/abseil-cpp.git
+    GIT_TAG 20240722.0
+)
+FetchContent_MakeAvailable(abseil-cpp)
+
+# Add subdirectories
+add_subdirectory(fory/thirdparty)
+add_subdirectory(fory/util)
+add_subdirectory(fory/type)
+add_subdirectory(fory/meta)
+add_subdirectory(fory/serialization)
+add_subdirectory(fory/row)
+add_subdirectory(fory/encoder)
+
+# Create main fory_serialization interface library (for users who only need 
serialization)
+add_library(fory_serialization_lib INTERFACE)
+target_link_libraries(fory_serialization_lib INTERFACE fory_serialization)
+add_library(fory::serialization ALIAS fory_serialization_lib)
+
+# Create main fory_row_format interface library (for users who need row format)
+add_library(fory_row_format_lib INTERFACE)
+target_link_libraries(fory_row_format_lib INTERFACE fory_row_format 
fory_encoder)
+add_library(fory::row_format ALIAS fory_row_format_lib)
+
+# Create main fory interface library (includes everything)
+add_library(fory_lib INTERFACE)
+target_link_libraries(fory_lib INTERFACE fory_serialization fory_row_format 
fory_encoder)
+add_library(fory::fory ALIAS fory_lib)
+
+# Tests
+if(FORY_BUILD_TESTS)
+    enable_testing()
+    find_package(GTest REQUIRED)
+    include(GoogleTest)
+    add_subdirectory(tests)
+endif()
+
+# Installation
+include(GNUInstallDirs)
+include(CMakePackageConfigHelpers)
+
+# Install headers
+install(DIRECTORY fory/
+    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/fory
+    FILES_MATCHING
+    PATTERN "*.h"
+    PATTERN "*_test.cc" EXCLUDE
+    PATTERN "python" EXCLUDE
+)
+
+# Install libraries
+install(TARGETS
+    fory_thirdparty
+    fory_util
+    fory_type
+    fory_meta
+    fory_serialization
+    fory_row_format
+    fory_encoder
+    fory_serialization_lib
+    fory_row_format_lib
+    fory_lib
+    EXPORT ForyTargets
+    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+    INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
+)
+
+# Generate and install package config files
+write_basic_package_version_file(
+    "${CMAKE_CURRENT_BINARY_DIR}/ForyConfigVersion.cmake"
+    VERSION ${PROJECT_VERSION}
+    COMPATIBILITY SameMajorVersion
+)
+
+configure_package_config_file(
+    "${CMAKE_CURRENT_SOURCE_DIR}/cmake/ForyConfig.cmake.in"
+    "${CMAKE_CURRENT_BINARY_DIR}/ForyConfig.cmake"
+    INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/fory
+)
+
+install(EXPORT ForyTargets
+    FILE ForyTargets.cmake
+    NAMESPACE fory::
+    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/fory
+)
+
+install(FILES
+    "${CMAKE_CURRENT_BINARY_DIR}/ForyConfig.cmake"
+    "${CMAKE_CURRENT_BINARY_DIR}/ForyConfigVersion.cmake"
+    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/fory
+)
+
+# Print configuration summary
+message(STATUS "")
+message(STATUS "Fory Configuration Summary:")
+message(STATUS "  Version:        ${PROJECT_VERSION}")
+message(STATUS "  Build type:     ${CMAKE_BUILD_TYPE}")
+message(STATUS "  C++ standard:   ${CMAKE_CXX_STANDARD}")
+message(STATUS "  Install prefix: ${CMAKE_INSTALL_PREFIX}")
+message(STATUS "  Build tests:    ${FORY_BUILD_TESTS}")
+message(STATUS "  AVX2 enabled:   ${FORY_USE_AVX2} (x86_64: 
${FORY_IS_X86_64})")
+message(STATUS "")
diff --git a/cpp/cmake/ForyConfig.cmake.in b/cpp/cmake/ForyConfig.cmake.in
new file mode 100644
index 000000000..f14844247
--- /dev/null
+++ b/cpp/cmake/ForyConfig.cmake.in
@@ -0,0 +1,39 @@
+# 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.
+
+@PACKAGE_INIT@
+
+include(CMakeFindDependencyMacro)
+
+# Check for Abseil (optional)
+find_package(absl CONFIG QUIET)
+
+include("${CMAKE_CURRENT_LIST_DIR}/ForyTargets.cmake")
+
+# Provide convenient component targets
+# Users can use:
+#   find_package(Fory REQUIRED)
+#   target_link_libraries(myapp fory::serialization)  # For serialization only
+#   target_link_libraries(myapp fory::row_format)     # For row format
+#   target_link_libraries(myapp fory::fory)           # For everything
+
+check_required_components(Fory)
+
+# Print found message
+if(NOT Fory_FIND_QUIETLY)
+    message(STATUS "Found Fory: ${CMAKE_CURRENT_LIST_DIR}")
+endif()
diff --git a/cpp/fory/encoder/CMakeLists.txt b/cpp/fory/encoder/CMakeLists.txt
new file mode 100644
index 000000000..2a4f687d2
--- /dev/null
+++ b/cpp/fory/encoder/CMakeLists.txt
@@ -0,0 +1,39 @@
+# 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.
+
+# fory_encoder is a header-only library
+add_library(fory_encoder INTERFACE)
+add_library(fory::encoder ALIAS fory_encoder)
+
+target_include_directories(fory_encoder
+    INTERFACE
+        $<BUILD_INTERFACE:${FORY_CPP_ROOT}>
+        $<INSTALL_INTERFACE:include>
+)
+
+target_link_libraries(fory_encoder
+    INTERFACE
+        fory_row_format
+        fory_meta
+)
+
+# Tests
+if(FORY_BUILD_TESTS)
+    add_executable(fory_encoder_test row_encoder_test.cc 
row_encode_trait_test.cc)
+    target_link_libraries(fory_encoder_test fory_encoder GTest::gtest)
+    gtest_discover_tests(fory_encoder_test)
+endif()
diff --git a/cpp/fory/meta/CMakeLists.txt b/cpp/fory/meta/CMakeLists.txt
new file mode 100644
index 000000000..36d6bf0ad
--- /dev/null
+++ b/cpp/fory/meta/CMakeLists.txt
@@ -0,0 +1,70 @@
+# 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.
+
+set(FORY_META_SOURCES
+    meta_string.cc
+)
+
+set(FORY_META_HEADERS
+    enum_info.h
+    field_info.h
+    meta_string.h
+    preprocessor.h
+    type_traits.h
+)
+
+add_library(fory_meta ${FORY_META_SOURCES})
+add_library(fory::meta ALIAS fory_meta)
+
+target_include_directories(fory_meta
+    PUBLIC
+        $<BUILD_INTERFACE:${FORY_CPP_ROOT}>
+        $<INSTALL_INTERFACE:include>
+)
+
+target_link_libraries(fory_meta
+    PUBLIC
+        fory_util
+)
+
+set_target_properties(fory_meta PROPERTIES
+    POSITION_INDEPENDENT_CODE ON
+    OUTPUT_NAME fory_meta
+)
+
+# Tests
+if(FORY_BUILD_TESTS)
+    add_executable(fory_meta_preprocessor_test preprocessor_test.cc)
+    target_link_libraries(fory_meta_preprocessor_test fory_meta GTest::gtest)
+    gtest_discover_tests(fory_meta_preprocessor_test)
+
+    add_executable(fory_meta_field_info_test field_info_test.cc)
+    target_link_libraries(fory_meta_field_info_test fory_meta GTest::gtest)
+    gtest_discover_tests(fory_meta_field_info_test)
+
+    add_executable(fory_meta_enum_info_test enum_info_test.cc)
+    target_link_libraries(fory_meta_enum_info_test fory_meta GTest::gtest)
+    gtest_discover_tests(fory_meta_enum_info_test)
+
+    add_executable(fory_meta_type_traits_test type_traits_test.cc)
+    target_link_libraries(fory_meta_type_traits_test fory_meta GTest::gtest)
+    gtest_discover_tests(fory_meta_type_traits_test)
+
+    add_executable(fory_meta_string_test meta_string_test.cc)
+    target_link_libraries(fory_meta_string_test fory_meta GTest::gtest 
GTest::gtest_main)
+    gtest_discover_tests(fory_meta_string_test)
+endif()
diff --git a/cpp/fory/row/CMakeLists.txt b/cpp/fory/row/CMakeLists.txt
new file mode 100644
index 000000000..bf450f386
--- /dev/null
+++ b/cpp/fory/row/CMakeLists.txt
@@ -0,0 +1,58 @@
+# 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.
+
+set(FORY_ROW_SOURCES
+    row.cc
+    schema.cc
+    type.cc
+    writer.cc
+)
+
+set(FORY_ROW_HEADERS
+    row.h
+    schema.h
+    type.h
+    writer.h
+)
+
+add_library(fory_row_format ${FORY_ROW_SOURCES})
+add_library(fory::row_format_impl ALIAS fory_row_format)
+
+target_include_directories(fory_row_format
+    PUBLIC
+        $<BUILD_INTERFACE:${FORY_CPP_ROOT}>
+        $<INSTALL_INTERFACE:include>
+)
+
+target_link_libraries(fory_row_format
+    PUBLIC
+        fory_serialization
+        fory_type
+        fory_util
+)
+
+set_target_properties(fory_row_format PROPERTIES
+    POSITION_INDEPENDENT_CODE ON
+    OUTPUT_NAME fory_row_format
+)
+
+# Tests
+if(FORY_BUILD_TESTS)
+    add_executable(fory_row_test row_test.cc)
+    target_link_libraries(fory_row_test fory_row_format GTest::gtest)
+    gtest_discover_tests(fory_row_test)
+endif()
diff --git a/cpp/fory/serialization/CMakeLists.txt 
b/cpp/fory/serialization/CMakeLists.txt
new file mode 100644
index 000000000..8bd0330c8
--- /dev/null
+++ b/cpp/fory/serialization/CMakeLists.txt
@@ -0,0 +1,94 @@
+# 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.
+
+set(FORY_SERIALIZATION_SOURCES
+    context.cc
+    skip.cc
+    type_resolver.cc
+)
+
+set(FORY_SERIALIZATION_HEADERS
+    array_serializer.h
+    basic_serializer.h
+    collection_serializer.h
+    config.h
+    context.h
+    enum_serializer.h
+    fory.h
+    map_serializer.h
+    ref_resolver.h
+    serializer.h
+    serializer_traits.h
+    skip.h
+    smart_ptr_serializers.h
+    struct_serializer.h
+    temporal_serializers.h
+    type_info.h
+    type_resolver.h
+)
+
+add_library(fory_serialization ${FORY_SERIALIZATION_SOURCES})
+add_library(fory::serialization_impl ALIAS fory_serialization)
+
+target_include_directories(fory_serialization
+    PUBLIC
+        $<BUILD_INTERFACE:${FORY_CPP_ROOT}>
+        $<INSTALL_INTERFACE:include>
+)
+
+target_link_libraries(fory_serialization
+    PUBLIC
+        fory_meta
+        fory_type
+        fory_util
+        fory_thirdparty
+)
+
+set_target_properties(fory_serialization PROPERTIES
+    POSITION_INDEPENDENT_CODE ON
+    OUTPUT_NAME fory_serialization
+)
+
+# Tests
+if(FORY_BUILD_TESTS)
+    add_executable(fory_serialization_test serialization_test.cc)
+    target_link_libraries(fory_serialization_test fory_serialization 
GTest::gtest GTest::gtest_main)
+    gtest_discover_tests(fory_serialization_test)
+
+    add_executable(fory_serialization_struct_test struct_test.cc)
+    target_link_libraries(fory_serialization_struct_test fory_serialization 
GTest::gtest GTest::gtest_main)
+    gtest_discover_tests(fory_serialization_struct_test)
+
+    add_executable(fory_serialization_struct_compatible_test 
struct_compatible_test.cc)
+    target_link_libraries(fory_serialization_struct_compatible_test 
fory_serialization GTest::gtest GTest::gtest_main)
+    gtest_discover_tests(fory_serialization_struct_compatible_test)
+
+    add_executable(fory_serialization_smart_ptr_test 
smart_ptr_serializer_test.cc)
+    target_link_libraries(fory_serialization_smart_ptr_test fory_serialization 
GTest::gtest GTest::gtest_main)
+    gtest_discover_tests(fory_serialization_smart_ptr_test)
+
+    add_executable(fory_serialization_map_test map_serializer_test.cc)
+    target_link_libraries(fory_serialization_map_test fory_serialization 
GTest::gtest GTest::gtest_main)
+    gtest_discover_tests(fory_serialization_map_test)
+endif()
+
+# xlang test binary
+add_executable(fory_xlang_test_main xlang_test_main.cc)
+target_link_libraries(fory_xlang_test_main fory_serialization fory_thirdparty)
+set_target_properties(fory_xlang_test_main PROPERTIES
+    EXCLUDE_FROM_ALL TRUE
+)
diff --git a/cpp/fory/thirdparty/CMakeLists.txt 
b/cpp/fory/thirdparty/CMakeLists.txt
new file mode 100644
index 000000000..048922fae
--- /dev/null
+++ b/cpp/fory/thirdparty/CMakeLists.txt
@@ -0,0 +1,32 @@
+# 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.
+
+add_library(fory_thirdparty
+    MurmurHash3.cc
+)
+add_library(fory::thirdparty ALIAS fory_thirdparty)
+
+target_include_directories(fory_thirdparty
+    PUBLIC
+        $<BUILD_INTERFACE:${FORY_CPP_ROOT}>
+        $<INSTALL_INTERFACE:include>
+)
+
+set_target_properties(fory_thirdparty PROPERTIES
+    POSITION_INDEPENDENT_CODE ON
+    OUTPUT_NAME fory_thirdparty
+)
diff --git a/cpp/fory/type/CMakeLists.txt b/cpp/fory/type/CMakeLists.txt
new file mode 100644
index 000000000..5dde8464a
--- /dev/null
+++ b/cpp/fory/type/CMakeLists.txt
@@ -0,0 +1,35 @@
+# 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.
+
+# fory_type is a header-only library
+add_library(fory_type INTERFACE)
+add_library(fory::type ALIAS fory_type)
+
+target_include_directories(fory_type
+    INTERFACE
+        $<BUILD_INTERFACE:${FORY_CPP_ROOT}>
+        $<INSTALL_INTERFACE:include>
+)
+
+# Enable AVX2 on x86_64 if configured
+if(FORY_USE_AVX2 AND FORY_IS_X86_64)
+    if(MSVC)
+        target_compile_options(fory_type INTERFACE /arch:AVX2)
+    else()
+        target_compile_options(fory_type INTERFACE -mavx2)
+    endif()
+endif()
diff --git a/cpp/fory/util/CMakeLists.txt b/cpp/fory/util/CMakeLists.txt
new file mode 100644
index 000000000..0668d4a40
--- /dev/null
+++ b/cpp/fory/util/CMakeLists.txt
@@ -0,0 +1,90 @@
+# 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.
+
+set(FORY_UTIL_SOURCES
+    buffer.cc
+    error.cc
+    logging.cc
+    string_util.cc
+    time_util.cc
+)
+
+set(FORY_UTIL_HEADERS
+    bit_util.h
+    buffer.h
+    error.h
+    lock.h
+    logging.h
+    platform.h
+    pool.h
+    result.h
+    string_util.h
+    time_util.h
+)
+
+add_library(fory_util ${FORY_UTIL_SOURCES})
+add_library(fory::util ALIAS fory_util)
+
+target_include_directories(fory_util
+    PUBLIC
+        $<BUILD_INTERFACE:${FORY_CPP_ROOT}>
+        $<INSTALL_INTERFACE:include>
+)
+
+# Link Abseil for debugging support
+target_link_libraries(fory_util
+    PUBLIC
+        absl::failure_signal_handler
+        absl::stacktrace
+        absl::symbolize
+)
+
+set_target_properties(fory_util PROPERTIES
+    POSITION_INDEPENDENT_CODE ON
+    OUTPUT_NAME fory_util
+)
+
+# Tests
+if(FORY_BUILD_TESTS)
+    add_executable(fory_util_buffer_test buffer_test.cc)
+    target_link_libraries(fory_util_buffer_test fory_util GTest::gtest 
GTest::gtest_main)
+    gtest_discover_tests(fory_util_buffer_test)
+
+    add_executable(fory_util_error_test error_test.cc)
+    target_link_libraries(fory_util_error_test fory_util GTest::gtest)
+    gtest_discover_tests(fory_util_error_test)
+
+    add_executable(fory_util_logging_test logging_test.cc)
+    target_link_libraries(fory_util_logging_test fory_util GTest::gtest)
+    gtest_discover_tests(fory_util_logging_test)
+
+    add_executable(fory_util_pool_test pool_test.cc)
+    target_link_libraries(fory_util_pool_test fory_util GTest::gtest 
GTest::gtest_main)
+    gtest_discover_tests(fory_util_pool_test)
+
+    add_executable(fory_util_result_test result_test.cc)
+    target_link_libraries(fory_util_result_test fory_util GTest::gtest)
+    gtest_discover_tests(fory_util_result_test)
+
+    add_executable(fory_util_string_util_test string_util_test.cc)
+    target_link_libraries(fory_util_string_util_test fory_util GTest::gtest)
+    gtest_discover_tests(fory_util_string_util_test)
+
+    add_executable(fory_util_time_util_test time_util_test.cc)
+    target_link_libraries(fory_util_time_util_test fory_util GTest::gtest 
GTest::gtest_main)
+    gtest_discover_tests(fory_util_time_util_test)
+endif()
diff --git a/examples/cpp/cmake_example/CMakeLists.txt 
b/examples/cpp/cmake_example/CMakeLists.txt
new file mode 100644
index 000000000..219f77a4d
--- /dev/null
+++ b/examples/cpp/cmake_example/CMakeLists.txt
@@ -0,0 +1,78 @@
+# 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.
+
+cmake_minimum_required(VERSION 3.16)
+
+project(fory_cmake_example
+    VERSION 1.0.0
+    DESCRIPTION "Example project demonstrating Fory C++ CMake integration"
+    LANGUAGES CXX
+)
+
+# C++17 required for Fory
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+# =============================================================================
+# Fory Integration Options (choose one)
+# =============================================================================
+
+# Option 1: Use FetchContent (recommended for external projects)
+# This is similar to how abseil or gtest are commonly used
+include(FetchContent)
+
+# For production use: fetch from GitHub
+# FetchContent_Declare(
+#     fory
+#     GIT_REPOSITORY https://github.com/apache/fory.git
+#     GIT_TAG        main
+#     SOURCE_SUBDIR  cpp
+# )
+
+# For local development: use local source directory
+FetchContent_Declare(
+    fory
+    SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../cpp"
+)
+
+FetchContent_MakeAvailable(fory)
+
+# Option 2: Use find_package if Fory is installed system-wide
+# find_package(Fory REQUIRED)
+
+# Option 3: Add Fory as a subdirectory with explicit path
+# set(FORY_CPP_DIR "/path/to/fory/cpp" CACHE PATH "Path to Fory C++ directory")
+# add_subdirectory(${FORY_CPP_DIR} ${CMAKE_BINARY_DIR}/fory)
+
+# Serialization example executable
+add_executable(serialization_example
+    ${CMAKE_CURRENT_SOURCE_DIR}/serialization_example.cc
+)
+target_link_libraries(serialization_example PRIVATE fory::serialization)
+
+# Row format example executable
+add_executable(row_format_example
+    ${CMAKE_CURRENT_SOURCE_DIR}/row_format_example.cc
+)
+target_link_libraries(row_format_example PRIVATE fory::row_format)
+
+# Print build info
+message(STATUS "")
+message(STATUS "Fory CMake Example Configuration:")
+message(STATUS "  C++ standard:   ${CMAKE_CXX_STANDARD}")
+message(STATUS "  Build type:     ${CMAKE_BUILD_TYPE}")
+message(STATUS "")
diff --git a/examples/cpp/cmake_example/README.md 
b/examples/cpp/cmake_example/README.md
new file mode 100644
index 000000000..fa129fcd5
--- /dev/null
+++ b/examples/cpp/cmake_example/README.md
@@ -0,0 +1,168 @@
+# Fory C++ CMake Example
+
+This example demonstrates how to integrate Fory C++ into your CMake-based 
project.
+
+## Prerequisites
+
+- CMake 3.16 or higher
+- C++17 compatible compiler (GCC 7+, Clang 5+, MSVC 2017+)
+
+## Using Fory in Your CMake Project
+
+### Option 1: FetchContent (Recommended)
+
+The easiest way to use Fory is with CMake's `FetchContent` module, similar to 
how you might use Abseil or GoogleTest:
+
+```cmake
+include(FetchContent)
+FetchContent_Declare(
+    fory
+    GIT_REPOSITORY https://github.com/apache/fory.git
+    GIT_TAG        main  # or a specific version tag
+    SOURCE_SUBDIR  cpp
+)
+FetchContent_MakeAvailable(fory)
+
+# Link to your target
+target_link_libraries(your_app PRIVATE fory::serialization)
+```
+
+### Option 2: find_package (System Installation)
+
+If Fory is installed system-wide:
+
+```cmake
+find_package(Fory REQUIRED)
+target_link_libraries(your_app PRIVATE fory::serialization)
+```
+
+To install Fory system-wide:
+
+```bash
+cd fory/cpp
+mkdir build && cd build
+cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local
+cmake --build .
+cmake --install .
+```
+
+### Option 3: add_subdirectory (Local Source)
+
+For development or when you have Fory source locally:
+
+```cmake
+add_subdirectory(/path/to/fory/cpp ${CMAKE_BINARY_DIR}/fory)
+target_link_libraries(your_app PRIVATE fory::serialization)
+```
+
+## Building This Example
+
+```bash
+cd examples/cpp/cmake_example
+mkdir build && cd build
+cmake ..
+cmake --build .
+```
+
+Or use the provided script:
+
+```bash
+./run.sh
+```
+
+## Running the Examples
+
+After building:
+
+```bash
+# Run serialization example
+./serialization_example
+
+# Run row format example
+./row_format_example
+```
+
+## Example Overview
+
+### serialization_example.cpp
+
+Demonstrates Fory's high-performance serialization:
+
+- Primitive types (int, float, string)
+- Collections (vector, map)
+- Custom structs with `FORY_STRUCT` macro
+- Nested structs
+- Enums
+
+Key concepts:
+
+- Use `FORY_STRUCT(StructName, field1, field2, ...)` to register struct fields
+- Create Fory instance with `Fory::builder().xlang(true).build()`
+- Register struct types with `fory.register_struct<Type>(type_id)`
+- Serialize with `fory.serialize(obj)`
+- Deserialize with `fory.deserialize<Type>(data, size)`
+
+### row_format_example.cpp
+
+Demonstrates Fory's row format for random access:
+
+- Manual row writing with schema
+- Automatic encoding with `RowEncoder`
+- Nested struct encoding
+- Array encoding
+- Direct array creation from vectors
+
+Key concepts:
+
+- Use `FORY_FIELD_INFO(StructName, field1, field2, ...)` for row encoding
+- Create schema with `schema({field("name", type()), ...})`
+- Write rows with `RowWriter`
+- Encode structs automatically with `encoder::RowEncoder<T>`
+- Read fields with `row->GetString(index)`, `row->GetInt32(index)`, etc.
+
+## Using Fory in Your Project
+
+### Linking to Fory Libraries
+
+Fory provides three main CMake targets:
+
+```cmake
+# For serialization only
+target_link_libraries(your_app PRIVATE fory::serialization)
+
+# For row format (includes serialization)
+target_link_libraries(your_app PRIVATE fory::row_format)
+
+# For everything
+target_link_libraries(your_app PRIVATE fory::fory)
+```
+
+### Including Headers
+
+```cpp
+// For serialization
+#include "fory/serialization/fory.h"
+
+// For row format
+#include "fory/row/row.h"
+#include "fory/row/schema.h"
+#include "fory/row/writer.h"
+#include "fory/encoder/row_encoder.h"
+#include "fory/encoder/row_encode_trait.h"
+```
+
+## Build Options
+
+When building Fory, you can configure these options:
+
+| Option              | Default | Description            |
+| ------------------- | ------- | ---------------------- |
+| `FORY_BUILD_TESTS`  | OFF     | Build Fory tests       |
+| `FORY_BUILD_SHARED` | ON      | Build shared libraries |
+| `FORY_BUILD_STATIC` | ON      | Build static libraries |
+
+Example:
+
+```bash
+cmake -DFORY_BUILD_TESTS=ON ..
+```
diff --git a/examples/cpp/cmake_example/row_format_example.cc 
b/examples/cpp/cmake_example/row_format_example.cc
new file mode 100644
index 000000000..4d888590f
--- /dev/null
+++ b/examples/cpp/cmake_example/row_format_example.cc
@@ -0,0 +1,260 @@
+/*
+ * 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.
+ */
+
+/**
+ * Fory C++ Row Format Example
+ *
+ * This example demonstrates how to use Fory's row format for
+ * cache-friendly binary random access. Row format is ideal for
+ * scenarios where you need:
+ * - Partial serialization/deserialization
+ * - Random field access without full deserialization
+ * - Interoperability with columnar formats
+ */
+
+#include <cstdint>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "fory/encoder/row_encode_trait.h"
+#include "fory/encoder/row_encoder.h"
+#include "fory/row/row.h"
+#include "fory/row/schema.h"
+#include "fory/row/writer.h"
+
+// Define a struct for the encoder example
+struct Employee {
+  std::string name;
+  int32_t id;
+  float salary;
+};
+
+// Register field info for automatic encoding
+FORY_FIELD_INFO(Employee, name, id, salary);
+
+// Define a nested struct
+struct Department {
+  std::string dept_name;
+  Employee manager;
+  std::vector<Employee> employees;
+};
+
+FORY_FIELD_INFO(Department, dept_name, manager, employees);
+
+int main() {
+  std::cout << "=== Fory C++ Row Format Example ===" << std::endl << std::endl;
+
+  // 
============================================================================
+  // Example 1: Manual Row Writing with Schema
+  // 
============================================================================
+  std::cout << "--- Example 1: Manual Row Writing ---" << std::endl;
+  {
+    using namespace fory::row;
+
+    // Define schema with fields
+    auto name_field = field("name", utf8());
+    auto age_field = field("age", int32());
+    auto score_field = field("score", float32());
+    auto tags_field = field("tags", list(utf8()));
+
+    std::vector<FieldPtr> fields = {name_field, age_field, score_field,
+                                    tags_field};
+    auto row_schema = schema(fields);
+
+    // Create a row writer
+    RowWriter writer(row_schema);
+    writer.Reset();
+
+    // Write primitive fields
+    writer.WriteString(0, "Alice");
+    writer.Write(1, static_cast<int32_t>(25));
+    writer.Write(2, 95.5f);
+
+    // Write array field
+    writer.SetNotNullAt(3);
+    int array_start = writer.cursor();
+    auto list_type = std::dynamic_pointer_cast<ListType>(utf8());
+    ArrayWriter array_writer(list(utf8()), &writer);
+    array_writer.Reset(3);
+    array_writer.WriteString(0, "developer");
+    array_writer.WriteString(1, "team-lead");
+    array_writer.WriteString(2, "mentor");
+    writer.SetOffsetAndSize(3, array_start, writer.cursor() - array_start);
+
+    // Convert to row and read back
+    auto row = writer.ToRow();
+
+    std::cout << "Written row:" << std::endl;
+    std::cout << "  name: " << row->GetString(0) << std::endl;
+    std::cout << "  age: " << row->GetInt32(1) << std::endl;
+    std::cout << "  score: " << row->GetFloat(2) << std::endl;
+
+    auto tags_array = row->GetArray(3);
+    std::cout << "  tags: [";
+    for (int i = 0; i < tags_array->num_elements(); ++i) {
+      std::cout << tags_array->GetString(i);
+      if (i < tags_array->num_elements() - 1)
+        std::cout << ", ";
+    }
+    std::cout << "]" << std::endl;
+
+    // Print full row string representation
+    std::cout << "  Full row: " << row->ToString() << std::endl;
+  }
+  std::cout << std::endl;
+
+  // 
============================================================================
+  // Example 2: Using RowEncoder for Automatic Encoding
+  // 
============================================================================
+  std::cout << "--- Example 2: Automatic Encoding with RowEncoder ---"
+            << std::endl;
+  {
+    using namespace fory::row;
+
+    // Create an employee
+    Employee emp{"Bob", 1001, 75000.0f};
+
+    // Create encoder and encode
+    encoder::RowEncoder<Employee> enc;
+    enc.Encode(emp);
+
+    // Get the schema (automatically generated from struct)
+    auto &schema = enc.GetSchema();
+    std::cout << "Generated schema fields: ";
+    for (const auto &name : schema.field_names()) {
+      std::cout << name << " ";
+    }
+    std::cout << std::endl;
+
+    // Read back from encoded row
+    auto row = enc.GetWriter().ToRow();
+    std::cout << "Encoded employee:" << std::endl;
+    std::cout << "  name: " << row->GetString(0) << std::endl;
+    std::cout << "  id: " << row->GetInt32(1) << std::endl;
+    std::cout << "  salary: " << row->GetFloat(2) << std::endl;
+  }
+  std::cout << std::endl;
+
+  // 
============================================================================
+  // Example 3: Nested Struct Encoding
+  // 
============================================================================
+  std::cout << "--- Example 3: Nested Struct Encoding ---" << std::endl;
+  {
+    using namespace fory::row;
+
+    // Create a department with nested employees
+    Department dept{"Engineering",
+                    {"Alice", 1000, 120000.0f}, // manager
+                    {
+                        {"Bob", 1001, 75000.0f},
+                        {"Carol", 1002, 80000.0f},
+                        {"Dave", 1003, 70000.0f},
+                    }};
+
+    // Encode using RowEncoder
+    encoder::RowEncoder<Department> enc;
+    enc.Encode(dept);
+
+    auto &schema = enc.GetSchema();
+    std::cout << "Department schema fields: ";
+    for (const auto &name : schema.field_names()) {
+      std::cout << name << " ";
+    }
+    std::cout << std::endl;
+
+    // Read back
+    auto row = enc.GetWriter().ToRow();
+    std::cout << "Encoded department:" << std::endl;
+    std::cout << "  dept_name: " << row->GetString(0) << std::endl;
+
+    // Access nested manager struct
+    auto manager_row = row->GetStruct(1);
+    std::cout << "  manager: {name=" << manager_row->GetString(0)
+              << ", id=" << manager_row->GetInt32(1)
+              << ", salary=" << manager_row->GetFloat(2) << "}" << std::endl;
+
+    // Access employees array
+    auto employees_array = row->GetArray(2);
+    std::cout << "  employees (" << employees_array->num_elements()
+              << " total):" << std::endl;
+    for (int i = 0; i < employees_array->num_elements(); ++i) {
+      auto emp_row = employees_array->GetStruct(i);
+      std::cout << "    - {name=" << emp_row->GetString(0)
+                << ", id=" << emp_row->GetInt32(1)
+                << ", salary=" << emp_row->GetFloat(2) << "}" << std::endl;
+    }
+  }
+  std::cout << std::endl;
+
+  // 
============================================================================
+  // Example 4: Array Encoding
+  // 
============================================================================
+  std::cout << "--- Example 4: Array Encoding ---" << std::endl;
+  {
+    using namespace fory::row;
+
+    // Encode a vector of employees
+    std::vector<Employee> employees = {
+        {"Eve", 2001, 65000.0f},
+        {"Frank", 2002, 68000.0f},
+    };
+
+    encoder::RowEncoder<decltype(employees)> enc;
+    enc.Encode(employees);
+
+    auto &type = enc.GetType();
+    std::cout << "Type name: " << type.name() << std::endl;
+
+    // Get array data
+    auto array_data = enc.GetWriter().CopyToArrayData();
+    std::cout << "Encoded " << array_data->num_elements()
+              << " employees:" << std::endl;
+
+    for (int i = 0; i < array_data->num_elements(); ++i) {
+      auto emp_row = array_data->GetStruct(i);
+      std::cout << "  [" << i << "] {name=" << emp_row->GetString(0)
+                << ", id=" << emp_row->GetInt32(1)
+                << ", salary=" << emp_row->GetFloat(2) << "}" << std::endl;
+    }
+  }
+  std::cout << std::endl;
+
+  // 
============================================================================
+  // Example 5: Creating Arrays from Vectors
+  // 
============================================================================
+  std::cout << "--- Example 5: Direct Array Creation ---" << std::endl;
+  {
+    using namespace fory::row;
+
+    // Create array directly from vector
+    std::vector<int32_t> numbers = {10, 20, 30, 40, 50};
+    auto array = ArrayData::From(numbers);
+
+    std::cout << "Created array with " << array->num_elements()
+              << " elements:" << std::endl;
+    std::cout << "  " << array->ToString() << std::endl;
+  }
+  std::cout << std::endl;
+
+  std::cout << "=== All examples completed successfully! ===" << std::endl;
+
+  return 0;
+}
diff --git a/examples/cpp/cmake_example/run.sh 
b/examples/cpp/cmake_example/run.sh
new file mode 100755
index 000000000..8afa4698b
--- /dev/null
+++ b/examples/cpp/cmake_example/run.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+
+# 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.
+
+set -e
+
+pip install cmake
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+BUILD_DIR="${SCRIPT_DIR}/build"
+
+echo "=== Fory C++ CMake Example Build Script ==="
+echo ""
+
+# Clean previous build if requested
+if [[ "$1" == "clean" ]]; then
+    echo "Cleaning build directory..."
+    rm -rf "${BUILD_DIR}"
+    echo "Done."
+    exit 0
+fi
+
+# Create build directory
+mkdir -p "${BUILD_DIR}"
+cd "${BUILD_DIR}"
+
+# Configure
+echo "Configuring with CMake..."
+cmake .. -DCMAKE_BUILD_TYPE=Release
+
+# Build
+echo ""
+echo "Building..."
+cmake --build . --parallel
+
+echo ""
+echo "=== Build successful! ==="
+echo ""
+
+# Run examples
+echo "=== Running serialization_example ==="
+echo ""
+./serialization_example
+
+echo ""
+echo "=== Running row_format_example ==="
+echo ""
+./row_format_example
+
+echo ""
+echo "=== All examples completed! ==="
diff --git a/examples/cpp/cmake_example/serialization_example.cc 
b/examples/cpp/cmake_example/serialization_example.cc
new file mode 100644
index 000000000..875ea82b7
--- /dev/null
+++ b/examples/cpp/cmake_example/serialization_example.cc
@@ -0,0 +1,327 @@
+/*
+ * 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.
+ */
+
+/**
+ * Fory C++ Serialization Example
+ *
+ * This example demonstrates how to use Fory for high-performance
+ * serialization and deserialization of C++ objects.
+ */
+
+#include <cstdint>
+#include <iostream>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "fory/serialization/fory.h"
+
+// Define a simple struct with primitive fields
+struct Point {
+  int32_t x;
+  int32_t y;
+
+  bool operator==(const Point &other) const {
+    return x == other.x && y == other.y;
+  }
+};
+
+// Register struct fields with Fory using FORY_STRUCT macro
+FORY_STRUCT(Point, x, y);
+
+// Define a more complex struct with various field types
+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;
+  }
+};
+
+FORY_STRUCT(Person, name, age, hobbies);
+
+// Define a nested struct
+struct Team {
+  std::string team_name;
+  std::vector<Person> members;
+  Point headquarters;
+
+  bool operator==(const Team &other) const {
+    return team_name == other.team_name && members == other.members &&
+           headquarters == other.headquarters;
+  }
+};
+
+FORY_STRUCT(Team, team_name, members, headquarters);
+
+// Define an enum
+enum class Status { PENDING, ACTIVE, COMPLETED };
+
+// Helper function to print bytes
+void print_bytes(const std::vector<uint8_t> &bytes) {
+  std::cout << "Serialized bytes (" << bytes.size() << " bytes): ";
+  for (size_t i = 0; i < std::min(bytes.size(), size_t(20)); ++i) {
+    printf("%02x ", bytes[i]);
+  }
+  if (bytes.size() > 20) {
+    std::cout << "...";
+  }
+  std::cout << std::endl;
+}
+
+int main() {
+  std::cout << "=== Fory C++ Serialization Example ===" << std::endl
+            << std::endl;
+
+  // Create a Fory instance with xlang (cross-language) mode enabled
+  auto fory = fory::serialization::Fory::builder()
+                  .xlang(true)      // Enable cross-language serialization
+                  .track_ref(false) // Disable reference tracking for 
simplicity
+                  .build();
+
+  // Register struct types (required for struct serialization)
+  fory.register_struct<Point>(1);
+  fory.register_struct<Person>(2);
+  fory.register_struct<Team>(3);
+
+  // 
============================================================================
+  // Example 1: Primitive types
+  // 
============================================================================
+  std::cout << "--- Example 1: Primitive Types ---" << std::endl;
+  {
+    int32_t original = 42;
+    auto bytes_result = fory.serialize(original);
+    if (bytes_result.ok()) {
+      auto bytes = bytes_result.value();
+      print_bytes(bytes);
+
+      auto result = fory.deserialize<int32_t>(bytes.data(), bytes.size());
+      if (result.ok()) {
+        std::cout << "Original: " << original
+                  << ", Deserialized: " << result.value() << std::endl;
+      }
+    }
+  }
+  std::cout << std::endl;
+
+  // 
============================================================================
+  // Example 2: String
+  // 
============================================================================
+  std::cout << "--- Example 2: String ---" << std::endl;
+  {
+    std::string original = "Hello, Fory!";
+    auto bytes_result = fory.serialize(original);
+    if (bytes_result.ok()) {
+      auto bytes = bytes_result.value();
+      print_bytes(bytes);
+
+      auto result = fory.deserialize<std::string>(bytes.data(), bytes.size());
+      if (result.ok()) {
+        std::cout << "Original: \"" << original << "\", Deserialized: \""
+                  << result.value() << "\"" << std::endl;
+      }
+    }
+  }
+  std::cout << std::endl;
+
+  // 
============================================================================
+  // Example 3: Vector
+  // 
============================================================================
+  std::cout << "--- Example 3: Vector ---" << std::endl;
+  {
+    std::vector<int32_t> original = {1, 2, 3, 4, 5};
+    auto bytes_result = fory.serialize(original);
+    if (bytes_result.ok()) {
+      auto bytes = bytes_result.value();
+      print_bytes(bytes);
+
+      auto result =
+          fory.deserialize<std::vector<int32_t>>(bytes.data(), bytes.size());
+      if (result.ok()) {
+        std::cout << "Original: [";
+        for (size_t i = 0; i < original.size(); ++i) {
+          std::cout << original[i] << (i < original.size() - 1 ? ", " : "");
+        }
+        std::cout << "], Deserialized: [";
+        auto &v = result.value();
+        for (size_t i = 0; i < v.size(); ++i) {
+          std::cout << v[i] << (i < v.size() - 1 ? ", " : "");
+        }
+        std::cout << "]" << std::endl;
+      }
+    }
+  }
+  std::cout << std::endl;
+
+  // 
============================================================================
+  // Example 4: Map
+  // 
============================================================================
+  std::cout << "--- Example 4: Map ---" << std::endl;
+  {
+    std::map<std::string, int32_t> original = {
+        {"apple", 1}, {"banana", 2}, {"cherry", 3}};
+    auto bytes_result = fory.serialize(original);
+    if (bytes_result.ok()) {
+      auto bytes = bytes_result.value();
+      print_bytes(bytes);
+
+      auto result = fory.deserialize<std::map<std::string, int32_t>>(
+          bytes.data(), bytes.size());
+      if (result.ok()) {
+        std::cout << "Original: {";
+        for (auto it = original.begin(); it != original.end(); ++it) {
+          std::cout << "\"" << it->first << "\": " << it->second;
+          if (std::next(it) != original.end())
+            std::cout << ", ";
+        }
+        std::cout << "}" << std::endl;
+
+        auto &m = result.value();
+        std::cout << "Deserialized: {";
+        for (auto it = m.begin(); it != m.end(); ++it) {
+          std::cout << "\"" << it->first << "\": " << it->second;
+          if (std::next(it) != m.end())
+            std::cout << ", ";
+        }
+        std::cout << "}" << std::endl;
+      }
+    }
+  }
+  std::cout << std::endl;
+
+  // 
============================================================================
+  // Example 5: Simple Struct
+  // 
============================================================================
+  std::cout << "--- Example 5: Simple Struct ---" << std::endl;
+  {
+    Point original{10, 20};
+    auto bytes_result = fory.serialize(original);
+    if (bytes_result.ok()) {
+      auto bytes = bytes_result.value();
+      print_bytes(bytes);
+
+      auto result = fory.deserialize<Point>(bytes.data(), bytes.size());
+      if (result.ok()) {
+        auto &p = result.value();
+        std::cout << "Original: Point{x=" << original.x << ", y=" << original.y
+                  << "}" << std::endl;
+        std::cout << "Deserialized: Point{x=" << p.x << ", y=" << p.y << "}"
+                  << std::endl;
+        std::cout << "Equal: " << (original == p ? "true" : "false")
+                  << std::endl;
+      }
+    }
+  }
+  std::cout << std::endl;
+
+  // 
============================================================================
+  // Example 6: Complex Struct
+  // 
============================================================================
+  std::cout << "--- Example 6: Complex Struct ---" << std::endl;
+  {
+    Person original{"Alice", 30, {"reading", "coding", "hiking"}};
+    auto bytes_result = fory.serialize(original);
+    if (bytes_result.ok()) {
+      auto bytes = bytes_result.value();
+      print_bytes(bytes);
+
+      auto result = fory.deserialize<Person>(bytes.data(), bytes.size());
+      if (result.ok()) {
+        auto &p = result.value();
+        std::cout << "Original: Person{name=\"" << original.name
+                  << "\", age=" << original.age << ", hobbies=[";
+        for (size_t i = 0; i < original.hobbies.size(); ++i) {
+          std::cout << "\"" << original.hobbies[i] << "\""
+                    << (i < original.hobbies.size() - 1 ? ", " : "");
+        }
+        std::cout << "]}" << std::endl;
+
+        std::cout << "Deserialized: Person{name=\"" << p.name
+                  << "\", age=" << p.age << ", hobbies=[";
+        for (size_t i = 0; i < p.hobbies.size(); ++i) {
+          std::cout << "\"" << p.hobbies[i] << "\""
+                    << (i < p.hobbies.size() - 1 ? ", " : "");
+        }
+        std::cout << "]}" << std::endl;
+        std::cout << "Equal: " << (original == p ? "true" : "false")
+                  << std::endl;
+      }
+    }
+  }
+  std::cout << std::endl;
+
+  // 
============================================================================
+  // Example 7: Nested Struct
+  // 
============================================================================
+  std::cout << "--- Example 7: Nested Struct ---" << std::endl;
+  {
+    Team original{"Engineering",
+                  {{"Bob", 25, {"gaming"}}, {"Carol", 28, {"music", "art"}}},
+                  {100, 200}};
+    auto bytes_result = fory.serialize(original);
+    if (bytes_result.ok()) {
+      auto bytes = bytes_result.value();
+      print_bytes(bytes);
+
+      auto result = fory.deserialize<Team>(bytes.data(), bytes.size());
+      if (result.ok()) {
+        auto &t = result.value();
+        std::cout << "Original team: \"" << original.team_name << "\" with "
+                  << original.members.size() << " members" << std::endl;
+        std::cout << "Deserialized team: \"" << t.team_name << "\" with "
+                  << t.members.size() << " members" << std::endl;
+        std::cout << "Headquarters: (" << t.headquarters.x << ", "
+                  << t.headquarters.y << ")" << std::endl;
+        std::cout << "Equal: " << (original == t ? "true" : "false")
+                  << std::endl;
+      }
+    }
+  }
+  std::cout << std::endl;
+
+  // 
============================================================================
+  // Example 8: Enum
+  // 
============================================================================
+  std::cout << "--- Example 8: Enum ---" << std::endl;
+  {
+    Status original = Status::ACTIVE;
+    auto bytes_result = fory.serialize(original);
+    if (bytes_result.ok()) {
+      auto bytes = bytes_result.value();
+      print_bytes(bytes);
+
+      auto result = fory.deserialize<Status>(bytes.data(), bytes.size());
+      if (result.ok()) {
+        std::cout << "Original: " << static_cast<int>(original)
+                  << ", Deserialized: " << static_cast<int>(result.value())
+                  << std::endl;
+        std::cout << "Equal: "
+                  << (original == result.value() ? "true" : "false")
+                  << std::endl;
+      }
+    }
+  }
+  std::cout << std::endl;
+
+  std::cout << "=== All examples completed successfully! ===" << std::endl;
+
+  return 0;
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to