What is syNumpy?
syNumpy is a standalone C++17 library from Symisc Systems ↗ for reading and writing NumPy .npy files.
It gives native C++ applications a straightforward way to exchange array data with Python-based workflows without pulling in a large runtime dependency chain. The library is released under the 3-Clause BSD License, and the source code is available on GitHub ↗.
Production Usage
syNumpy is used internally by FACEIO ↗ for facial feature extraction workflows and by PixLab systems behind the DocScan mobile app, internal visual search and document processing workflows, the PixLab API endpoints, and the DOCSCAN API for passports, driver licenses, visas, residence permits, and other identity documents.
Core Features
syNumpy focuses on reliable .npy support for scalar numeric and complex dtypes. The main parser entry point is syNumpy::loadNpyBuffer(), the file APIs are thin wrappers around that parser, and malformed headers or truncated payloads fail explicitly.
Stores shape metadata, dtype descriptors, Fortran-order flags, and raw payload bytes in a compact in-memory container.
Use syNumpy::loadNpy() for file input, or syNumpy::loadNpyBuffer() to parse an in-memory NumPy payload directly.
syNumpy::saveNpyRaw() exposes explicit dtype control, while saveNpy() overloads cover common native C++ workflows with less setup.
Set mode = "a" to extend axis 0. Headers, endianness, and trailing dimensions are validated before append operations proceed.
Build & Integration
The simplest integration path is to copy synumpy.hpp and synumpy.cpp into your source tree and build them with your existing C++17 target.
- Public files synumpy.hpp, synumpy.cpp
- Language requirement C++17
- Runtime dependencies None
- Alternative build files CMakeLists.txt, Makefile
Minimal Example
C++17 API Reference Guide
The following reference covers the current public interface exported by synumpy.hpp.
Version Constants
syNumpy::kVersionMajor syNumpy::kVersionMinor syNumpy::kVersionPatch syNumpy::kVersionStringclass syNumpy::Error
explicit Error(const std::string& message)
message - The exception text.std::runtime_error-derived exception object used for parse, validation, and I/O failures.class syNumpy::NpyArray
NpyArray() = default
NpyArray(std::vector<std::size_t> shape, std::string dtype_descr, bool fortran_order)
.npy array in memory together with its shape, dtype metadata, Fortran-order flag, and payload bytes.shape, dtype_descr, and fortran_order for the materializing constructor.shape(),dtypeDescr(),wordSize(),fortranOrder(),numValues(), andnumBytes()expose array metadata.bytes()returns raw payload bytes.is<T>(),data<T>(), andasVector<T>()provide typed access and throwsyNumpy::Erroron dtype mismatch.
function syNumpy::loadNpyBuffer()
NpyArray loadNpyBuffer(const void* buffer, std::size_t size)
.npy image that is already loaded in memory. This is the core parser entry point used by the file-loading path.buffer - A pointer to the first byte of a complete .npy image.size - The total available byte count.
syNumpy::NpyArray.syNumpy::Error on malformed headers, truncated payloads, unsupported dtypes, or unsupported endianness.function syNumpy::loadNpy()
NpyArray loadNpy(const std::filesystem::path& path)
.npy file from disk, reads its contents, and returns the parsed array as a syNumpy::NpyArray.path - The filesystem path to a .npy file.syNumpy::NpyArray.function syNumpy::saveNpyRaw()
void saveNpyRaw(const std::filesystem::path& path, const void* data, std::size_t byte_count, const std::vector<std::size_t>& shape,
std::string_view dtype_descr, std::string_view mode = "w")
.npy file from raw bytes and an explicit NumPy dtype descriptor. It is the low-level save path behind the typed overloads and also supports compatible append mode.path, data, byte_count, shape, and dtype_descr.mode = "w" or "wb" to overwrite or create, and mode = "a" or "ab" to append along axis 0 when the existing file is compatible.function syNumpy::saveNpy() Typed Overloads
template <typename T> void saveNpy(const std::filesystem::path& path, const T* data, const std::vector<std::size_t>& shape, std::string_view mode = "w")
template <typename T> void saveNpy(const std::filesystem::path& path, const std::vector<T>& data, const
std::vector<std::size_t>& shape, std::string_view mode = "w")
template <typename T> void saveNpy(const std::filesystem::path& path, const std::vector<T>& data, std::string_view mode =
"w")
data.size() to match the element count implied by the provided shape. The vector-only overload automatically infers a one-dimensional shape equal to {data.size()}.Supported Native Types
bool, 8/16/32/64-bit signed and unsigned integers, float, double, long double, and std::complex<T> for the supported floating-point scalar families.Full Usage Example
The following example combines direct integration, save and load round-trips, explicit shapes, buffer parsing, and append mode in one place.