Skip to content

Instantly share code, notes, and snippets.

@symisc
Last active April 2, 2026 18:45
Show Gist options
  • Select an option

  • Save symisc/e628cd94d4f68d2dda3e4fbc876d43f2 to your computer and use it in GitHub Desktop.

Select an option

Save symisc/e628cd94d4f68d2dda3e4fbc876d43f2 to your computer and use it in GitHub Desktop.
Symisc syNumpy C++ usage sample program - https://pixlab.io/numpy-cpp-library - A Modern C++17 Library for NumPy Arrays
/* Symisc syNumpy: C++ usage sample program.
* Copyright (C) 2026, Symisc Systems https://pixlab.io/numpy-cpp-library
* Version 1.9.7
* For information on licensing, redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES
* please contact Symisc Systems via:
* [email protected]
* [email protected]
* [email protected]
* or visit:
* https://pixlab.io/numpy-cpp-library
*/
/*
* Copyright (C) 2026 Symisc Systems, S.U.A.R.L [M.I.A.G Mrad Chams Eddine <[email protected]>].
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SYMISC SYSTEMS ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
* NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SYMISC SYSTEMS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* $SymiscID: example.cpp v1.9.7 Win11 2026-04-01 stable <[email protected]> $ */
#include "synumpy.hpp"
#include <cstdint>
#include <fstream>
#include <iostream>
#include <iterator>
#include <vector>
namespace {
void printShape(const syNumpy::NpyArray& array) {
std::cout << "shape=(";
for (std::size_t i = 0; i < array.shape().size(); ++i) {
if (i != 0) {
std::cout << ", ";
}
std::cout << array.shape()[i];
}
std::cout << ")\n";
} // namespace
template <typename T>
void printValues(const std::vector<T>& values, const char* label) {
std::cout << label << ": ";
for (const T& value : values) {
std::cout << value << ' ';
}
std::cout << "\n";
}
}
int main() {
try {
const char* float_path = "floats.npy";
const char* matrix_path = "matrix.npy";
// 1) Save a one-dimensional float array.
const std::vector<float> floats = {1.0f, 2.0f, 3.0f};
syNumpy::saveNpy(float_path, floats);
// 2) Load the array back from disk and access it as typed values.
const syNumpy::NpyArray loaded_floats = syNumpy::loadNpy(float_path);
std::cout << "Loaded " << float_path << "\n";
std::cout << "dtype=" << loaded_floats.dtypeDescr() << "\n";
printShape(loaded_floats);
printValues(loaded_floats.asVector<float>(), "values");
// 3) Load the same file from a raw memory buffer.
std::ifstream input(float_path, std::ios::binary);
if (!input) {
throw std::runtime_error("failed to open floats.npy for buffer example");
}
const std::vector<std::uint8_t> file_bytes{
std::istreambuf_iterator<char>(input),
std::istreambuf_iterator<char>()
};
const syNumpy::NpyArray buffer_loaded = syNumpy::loadNpyBuffer(file_bytes.data(), file_bytes.size());
printValues(buffer_loaded.asVector<float>(), "buffer values");
// 4) Append more data along axis 0.
const std::vector<float> more_floats = {4.0f, 5.0f};
syNumpy::saveNpy(float_path, more_floats, "a");
const syNumpy::NpyArray appended = syNumpy::loadNpy(float_path);
printValues(appended.asVector<float>(), "appended values");
// 5) Save and load a 2D matrix using an explicit shape.
const std::vector<std::int32_t> matrix = {
1, 2, 3,
4, 5, 6
};
syNumpy::saveNpy(matrix_path, matrix, std::vector<std::size_t>{2, 3});
const syNumpy::NpyArray loaded_matrix = syNumpy::loadNpy(matrix_path);
std::cout << "Loaded " << matrix_path << "\n";
std::cout << "dtype=" << loaded_matrix.dtypeDescr() << "\n";
printShape(loaded_matrix);
printValues(loaded_matrix.asVector<std::int32_t>(), "matrix values");
return 0;
} catch (const syNumpy::Error& error) {
std::cerr << "syNumpy error: " << error.what() << "\n";
return 1;
} catch (const std::exception& error) {
std::cerr << "Unexpected error: " << error.what() << "\n";
return 2;
}
}
@symisc
Copy link
Copy Markdown
Author

symisc commented Apr 2, 2026

syNumpy

syNumpy is a standalone C++17 library from Symisc Systems for reading and writing NumPy .npy files.

Project homepage and documentation: https://pixlab.io/numpy-cpp-library

Production Usage

syNumpy is used internally by Symisc/PixLab production systems.

  • It is used by FACEIO for internal facial features extraction workflows.
  • It is used by PixLab document and visual search workloads behind the DocScan Mobile App and StreetLens mobile app integrations built on top of the PixLab API Endpoints ecosystem.
  • It also integrates naturally with the DOCSCAN ID Scan API, which is designed to scan and extract structured data from identity documents worldwide.

Highlights

  • Single public header and single implementation file: synumpy.hpp and synumpy.cpp
  • C++17 API with no external runtime dependency
  • Core parser centered on syNumpy::loadNpyBuffer()
  • Load .npy arrays from disk or directly from a memory buffer
  • Save typed vectors and raw buffers to .npy
  • Append mode for extending the first dimension of an existing array
  • Strict validation for malformed headers, truncated payloads, and unsupported dtype/layout combinations

Scope Of This Release

This public release focuses on robust .npy support.

  • Supported: scalar numeric and complex NumPy dtypes that map cleanly to native C++ types
  • Supported: shape metadata, payload loading, file loading, memory-buffer loading, and append-on-axis-0
  • Supported: explicit dtype-based raw save through syNumpy::saveNpyRaw()
  • Not implemented in this release: .npz archive support
  • Endianness is validated explicitly; cross-endian payloads are rejected rather than silently byte-swapped

Repository Layout

  • synumpy.hpp: public C++ API
  • synumpy.cpp: implementation
  • example.cpp: minimal usage sample
  • CMakeLists.txt: CMake build integration
  • Makefile: simple Unix-style build integration

Build & Integration

The easiest way to integrate syNumpy is to drop synumpy.hpp and synumpy.cpp directly into your codebase and compile them as part of your project. No complex build scripts, generators, or external runtime dependencies are required.

CMake

cmake -S . -B build
cmake --build build --config Release

To install:

cmake --install build --config Release

Make

make

This builds:

  • build/libsynumpy.a
  • build/example

To install:

make install

Direct Compilation

MSVC:

cl /std:c++17 /EHsc /W4 synumpy.cpp example.cpp

GCC or Clang:

c++ -std=c++17 -O2 -Wall -Wextra -Wpedantic synumpy.cpp example.cpp -o example

Quick Start

Include the public header:

#include "synumpy.hpp"

The main entry points are:

  • syNumpy::NpyArray
  • syNumpy::loadNpyBuffer()
  • syNumpy::loadNpy()
  • syNumpy::saveNpy()
  • syNumpy::saveNpyRaw()

Minimal Example

#include "synumpy.hpp"

#include <cstdint>
#include <fstream>
#include <iterator>
#include <vector>

int main() {
    const std::vector<float> values = {1.0f, 2.0f, 3.0f};

    syNumpy::saveNpy("floats.npy", values);

    syNumpy::NpyArray loaded = syNumpy::loadNpy("floats.npy");
    std::vector<float> roundtrip = loaded.asVector<float>();

    std::ifstream input("floats.npy", std::ios::binary);
    std::vector<std::uint8_t> bytes{
        std::istreambuf_iterator<char>(input),
        std::istreambuf_iterator<char>()
    };

    syNumpy::NpyArray from_buffer = syNumpy::loadNpyBuffer(bytes.data(), bytes.size());
    std::vector<float> in_memory = from_buffer.asVector<float>();

    return 0;
}

See example.cpp for a fuller sample covering:

  • file save/load
  • memory-buffer loading
  • append mode
  • shaped matrix output

C++ API Interface

The C++ interface is intentionally small and source-oriented. The public declarations live in synumpy.hpp, and that header should be treated as the immediate source of truth during integration.

This README does not attempt to fully document every API detail. For project updates, integration notes, and the official documentation path, use:

Related Products

License

BSD 3-Clause. See the LICENSE file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment