π libnpy: Easily Read and Write NumPy Data Files with C++
Have you encountered the following scenarios while developing C++ projects?
“How do I load model weights trained with NumPy in Python into C++?”
“How can a C++ program read sensor data in.npyformat?”
“Is there a simple way to share array data between C++ and Python?”
Today, we will introduce a lightweight, dependency-free, header-only C++ library β libnpy.
It allows you to easily:
- β
Read
.npyfiles (NumPy single array) - β
Read
.npzfiles (NumPy multi-array compressed package) - β
Write
.npyand.npzfiles - β Seamlessly exchange numerical data between C++ and Python
Project address: https://github.com/llohse/libnpy
License: MIT (commercial use allowed)
π What is libnpy?
libnpy is an open-source C++ library developed by Lars LΓΆhhse, designed specifically for reading and writing NumPy’s .npy and .npz file formats.
β Core Features
| Feature | Description |
|---|---|
| π§© Header-only | Simply include one .hpp file, no compilation needed |
| π¦ No external dependencies | No reliance on large libraries like Boost or Eigen |
| π§ Automatic type inference | Automatically recognizes NumPy data types (float32, int64, etc.) |
| π Supports multi-dimensional arrays | Supports 1D to 7D arrays (NumPy limitation) |
| πΎ Supports .npz compressed packages | Reads multiple arrays from .npz |
| π MIT License | Can be used for commercial projects |
β οΈ Note: It does not support complex NumPy types like
datetimeorobject, focusing on numerical arrays (int, float).
π οΈ Installation and Integration
Method 1: Directly Download the Header File (Recommended)
wget https://raw.githubusercontent.com/llohse/libnpy/master/include/npy.hpp
Then in your C++ code:
#include "npy.hpp"
It’s that simple! No compilation, no linking required.
π‘ First Example: Generate .npy File with Python
First, create a test file using Python:
β
create_data.py
import numpy as np
# Create a 3x4 float array
data = np.random.rand(3, 4).astype(np.float32)
print("Data in Python:")
print(data)
# Save as .npy file
np.save("data.npy", data)
# You can also save multiple arrays to .npz
np.savez("data.npz", array1=data, array2=np.array([1, 2, 3]))
Run it:
python create_data.py
This will generate data.npy and data.npz.
π‘ Second Example: Read .npy File with C++
β
read_npy.cpp
#include "npy.hpp"
#include <iostream>
#include <vector>
int main() {
// 1. Read .npy file
auto array = npy::read_npy<float>("data.npy");
// 2. Get array information
std::cout << "Dimensions: ";
for (auto dim : array.shape) {
std::cout << dim << " ";
}
std::cout << "\nData type: " << array.fortran_order << "\n";
// 3. Access data (row-major order)
std::cout << "Data read in C++:\n";
for (size_t i = 0; i < array.shape[0]; ++i) {
for (size_t j = 0; j < array.shape[1]; ++j) {
// Calculate index: row-major order
size_t idx = i * array.shape[1] + j;
std::cout << array.data[idx] << " ";
}
std::cout << "\n";
}
return 0;
}
β Compile and Run
g++ read_npy.cpp -o read_npy
./read_npy
π Sample Output:
Dimensions: 3 4
Data type: 0
Data read in C++:
0.123 0.456 0.789 0.234
0.567 0.890 0.345 0.678
0.901 0.234 0.567 0.890
Perfectly matches the data generated in Python!
π₯ Write to .npy File
β
write_npy.cpp
#include "npy.hpp"
#include <vector>
int main() {
// Create a 2x3 array
std::vector<float> data = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
std::vector<size_t> shape = {2, 3};
// Write to .npy file
npy::save_npy("output.npy", data.data(), shape, false); // false = not fortran order
std::cout << "Saved output.npy\n";
return 0;
}
Verify with Python:
import numpy as np
loaded = np.load("output.npy")
print(loaded)
# Output: [[1. 2. 3.]
# [4. 5. 6.]]
π¦ Read .npz File (Multiple Arrays)
.npz is a ZIP compressed package containing multiple .npy files.
β
read_npz.cpp
#include "npy.hpp"
#include <iostream>
int main() {
// Read .npz file
auto archive = npy::read_npz("data.npz");
std::cout << "Found " << archive.size() << " arrays\n";
for (const auto& pair : archive) {
const std::string& name = pair.first;
const auto& array = pair.second;
std::cout << "Array name: " << name << "\n";
std::cout << "Shape: ";
for (auto dim : array.shape) {
std::cout << dim << " ";
}
std::cout << "\n";
// Print the first element (example)
if (!array.data.empty()) {
std::cout << "First element: " << array.data[0] << "\n";
}
}
return 0;
}
π Supported Data Types
libnpy automatically maps NumPy types to C++ types:
| NumPy Type | C++ Type |
|---|---|
int8 |
int8_t |
int16 |
int16_t |
int32 |
int32_t |
int64 |
int64_t |
uint8 |
uint8_t |
float32 |
float |
float64 |
double |
complex64 |
std::complex<float> |
complex128 |
std::complex<double> |
When using, simply specify the template parameter, such as
npy::read_npy<float>().
π§© Advanced Tips
1. Integration with Eigen (Common Requirement)
Although libnpy does not directly depend on Eigen, you can easily convert:
#include <Eigen/Dense>
// ...
auto array = npy::read_npy<float>("matrix.npy");
Eigen::Map<Eigen::MatrixXf> mat(array.data.data(), array.shape[0], array.shape[1]);
2. Memory Safety
array.dataisstd::vector<T>, automatically managing memory.- No need to manually
free.
π Real-world Applications
| Scenario | Description |
|---|---|
| AI Inference | Loading weights trained in Python with C++ |
| Scientific Computing | Sharing experimental data |
| Embedded Systems | Loading calibration parameters |
| Game Development | Loading precomputed numerical tables |
| Cross-language Projects | Python processing + C++ high-performance computing |
β Why Choose libnpy?
| Comparison Item | libnpy | Manual Parsing | Other Libraries (e.g., cnpy) |
|---|---|---|---|
| Ease of Use | β Header-only | β Complex | β οΈ May require compilation |
| Dependencies | β None | β | May depend on zlib |
| Functionality | β .npy + .npz | Limited | Similar |
| Maintainability | β Active | β | Depends on the project |
π Learning Resources
- GitHub Repository: https://github.com/llohse/libnpy
- Example Code:
examples/directory - NumPy File Format Documentation: https://numpy.org/doc/stable/reference/generated/numpy.lib.format.html
β Summary
libnpy is a bridge for C++ developers to seamlessly connect with the Python scientific computing ecosystem.
It:
π§© Minimal integration
π¦ Zero dependencies
π Efficient exchange
π Free to use
Whether you are working on AI, simulation, or data processing, as long as your workflow involves data generated by Python and processed by C++, libnpy is an indispensable tool for you.
“Let data flow freely between languages.”
Now add it to your C++ project and start your cross-language collaboration journey!