# ncnn C API vs C++ API: When to Use Each Interface

> Master ncnn API choices. Use the ncnn C++ API for modern C++ features and the ncnn C API for cross-language bindings or pure C projects. Optimize your integration.

- Repository: [Tencent/ncnn](https://github.com/tencent/ncnn)
- Tags: comparison
- Published: 2026-02-23

---

**Choose the ncnn C++ API for native C++ projects requiring modern features like RAII and templates, and select the ncnn C API when building cross-language bindings or working in pure C environments that must avoid C++ runtime dependencies.**

Tencent's ncnn is a high-performance neural network inference framework optimized for mobile and edge devices. While the library is implemented in modern C++, it provides a thin ncnn C API wrapper that offers identical runtime performance with different ergonomics. Understanding when to use each interface depends on your project's language constraints, build environment, and integration requirements.

## Key Differences Between ncnn C API and C++ API

The primary distinction lies in language integration and memory management models. Both APIs ultimately call the same core engine code in [`src/net.cpp`](https://github.com/Tencent/ncnn/blob/main/src/net.cpp) and [`src/mat.cpp`](https://github.com/Tencent/ncnn/blob/main/src/mat.cpp), so inference performance is identical.

**Language Integration**
- **C++ API**: Native to C++ projects. Supports templates, function overloads, STL containers, and exception handling. Classes like `ncnn::Net` and `ncnn::Mat` in [`src/net.h`](https://github.com/Tencent/ncnn/blob/main/src/net.h) and [`src/mat.h`](https://github.com/Tencent/ncnn/blob/main/src/mat.h) provide idiomatic C++ interfaces.
- **C API**: Exposes a C-compatible ABI via opaque handles (`ncnn_net_t`, `ncnn_mat_t`) defined in [`src/c_api.h`](https://github.com/Tencent/ncnn/blob/main/src/c_api.h). Callable from pure C, Python ctypes, Rust FFI, Go, and Java JNI.

**Compilation Requirements**
- **C++ API**: Requires a C++ compiler and the C++ standard library. Headers in [`src/net.h`](https://github.com/Tencent/ncnn/blob/main/src/net.h) use C++ features like classes and namespaces.
- **C API**: Only needs a C compiler. The implementation in [`src/c_api.cpp`](https://github.com/Tencent/ncnn/blob/main/src/c_api.cpp) wraps C++ objects but exposes only C linkage, eliminating name-mangling issues and C++ runtime dependencies.

**Memory Management**
- **C++ API**: Uses **RAII** (Resource Acquisition Is Initialization). `ncnn::Mat` automatically releases memory in its destructor. `ncnn::Net` cleans up layers automatically when it goes out of scope.
- **C API**: Requires **manual lifecycle management**. You must call `ncnn_net_create`/`ncnn_net_destroy` and `ncnn_mat_create`/`ncnn_mat_destroy` explicitly. The C implementation internally calls `new Net()` and `delete net` as shown in [`src/c_api.cpp`](https://github.com/Tencent/ncnn/blob/main/src/c_api.cpp).

**Feature Exposure**
- **C++ API**: Full access to all class members, inline helpers, and overloads. For example, `ncnn::Mat` provides `reshape`, `clone`, and pixel conversion methods directly.
- **C API**: Exposes a subset of functionality most useful across language borders—primarily network creation, parameter loading, and tensor extraction. Advanced features require C++ API access.

**ABI Stability**
- **C++ API**: Changing class layout in [`src/net.h`](https://github.com/Tencent/ncnn/blob/main/src/net.h) or [`src/mat.h`](https://github.com/Tencent/ncnn/blob/main/src/mat.h) breaks binary compatibility; consumers must recompile.
- **C API**: Designed for stable binary interface. The layout of opaque structs never changes; only the implementation in [`src/c_api.cpp`](https://github.com/Tencent/ncnn/blob/main/src/c_api.cpp) is modified.

## When to Choose the ncnn C++ API

Select the C++ API when your project is built with C++ and you want maximum ergonomics and feature completeness.

### Native C++ Development

If your codebase is C++-only, the C++ API provides idiomatic syntax that integrates seamlessly with modern C++ features. You can use `ncnn::Net` and `ncnn::Mat` directly from [`src/net.h`](https://github.com/Tencent/ncnn/blob/main/src/net.h) and [`src/mat.h`](https://github.com/Tencent/ncnn/blob/main/src/mat.h), leverage STL containers to manage multiple networks, and rely on RAII for automatic memory management without explicit cleanup calls.

### Advanced Features and Ergonomics

The C++ API exposes the full surface area of the library. You can access Vulkan pipeline configurations through `ncnn::Option`, implement custom layer factories by inheriting from `ncnn::Layer`, and use template-based utilities. Method overloading allows convenient pixel format conversions via `ncnn::Mat::from_pixels_resize`, which would require multiple explicit function calls in the C API.

## When to Choose the ncnn C API

Use the C API when you need language interoperability or must avoid C++ toolchain dependencies.

### Cross-Language Bindings

The C API is the foundation for creating bindings in other languages. Because [`src/c_api.h`](https://github.com/Tencent/ncnn/blob/main/src/c_api.h) exposes opaque handles (`ncnn_net_t`, `ncnn_mat_t`) with C linkage, you can interface with Python using ctypes, with Rust via FFI, or with Go using cgo. The implementation in [`src/c_api.cpp`](https://github.com/Tencent/ncnn/blob/main/src/c_api.cpp) handles the translation between C handles and C++ objects (e.g., `ncnn_net_create` calls `new Net()`), allowing other languages to leverage ncnn's optimized inference engine without writing C++ wrapper code.

### C-Only Build Environments

If your project must compile with a pure C toolchain or you need to minimize binary footprint by avoiding C++ runtime libraries, the C API is the correct choice. The [`src/c_api.cpp`](https://github.com/Tencent/ncnn/blob/main/src/c_api.cpp) wrapper compiles the C++ implementation into a library that presents only a C interface, eliminating name-mangling issues and C++ standard library dependencies in the consuming application. This is critical for embedded systems with limited storage or when integrating with legacy C codebases.

## Code Examples

### C++ API Implementation

The following example demonstrates idiomatic C++ usage with RAII-based resource management. This code uses `ncnn::Net` and `ncnn::Mat` from [`src/net.h`](https://github.com/Tencent/ncnn/blob/main/src/net.h) and [`src/mat.h`](https://github.com/Tencent/ncnn/blob/main/src/mat.h):

```cpp
#include <ncnn/net.h>

int main() {
    ncnn::Net net;
    // Configure options directly on the object
    net.opt.num_threads = 4;

    // Load model parameters and weights
    net.load_param("mobilenetv2.param");
    net.load_model("mobilenetv2.bin");

    // Create input tensor using static factory method
    ncnn::Mat in = ncnn::Mat::from_pixels_resize(
        image_data, ncnn::Mat::PIXEL_BGR, img_w, img_h, 224, 224);

    // Inference with automatic resource cleanup
    ncnn::Extractor ex = net.create_extractor();
    ex.input("data", in);
    ncnn::Mat out;
    ex.extract("prob", out);

    // Resources automatically freed when objects go out of scope
    return 0;
}

```

### C API Implementation

This example shows the explicit lifecycle management required when using the C API from [`src/c_api.h`](https://github.com/Tencent/ncnn/blob/main/src/c_api.h). Note how every `create` call requires a corresponding `destroy` call:

```c
#include "c_api.h"

int main() {
    // Explicit creation of opaque handles
    ncnn_net_t net = ncnn_net_create();
    
    // Configure options through getter/setter functions
    ncnn_option_t opt = ncnn_net_get_option(net);
    ncnn_option_set_num_threads(opt, 4);
    ncnn_net_set_option(net, opt);

    // Load model data
    ncnn_net_load_param(net, "mobilenetv2.param");
    ncnn_net_load_model(net, "mobilenetv2.bin");

    // Create extractor and input tensor
    ncnn_extractor_t ex = ncnn_extractor_create(net);
    ncnn_mat_t in = ncnn_mat_create();
    // ... populate input data ...

    ncnn_extractor_input(ex, "data", in);
    
    ncnn_mat_t out;
    ncnn_extractor_extract(ex, "prob", &out);

    // Manual cleanup required for every created object
    ncnn_mat_destroy(in);
    ncnn_mat_destroy(out);
    ncnn_extractor_destroy(ex);
    ncnn_net_destroy(net);
    
    return 0;
}

```

## Summary

- **Runtime performance is identical** between the C++ and C APIs because both call the same core engine implementation in [`src/net.cpp`](https://github.com/Tencent/ncnn/blob/main/src/net.cpp) and [`src/mat.cpp`](https://github.com/Tencent/ncnn/blob/main/src/mat.cpp).
- **Choose the C++ API** when working in C++ environments to benefit from RAII automatic memory management, STL integration, and full access to advanced features like custom layer factories and Vulkan configurations.
- **Choose the C API** when building language bindings for Python, Rust, or Go, or when compiling in pure C environments that must avoid C++ runtime dependencies and name-mangling issues.
- **Memory management differs significantly**: C++ uses destructors (`~Net()`, `~Mat()`), while C requires explicit `ncnn_net_destroy()` and `ncnn_mat_destroy()` calls as implemented in [`src/c_api.cpp`](https://github.com/Tencent/ncnn/blob/main/src/c_api.cpp).

## Frequently Asked Questions

### Is the ncnn C API slower than the C++ API?

No, the ncnn C API provides identical inference performance to the C++ API because it is a thin wrapper that forwards calls to the same underlying C++ objects. The implementation in [`src/c_api.cpp`](https://github.com/Tencent/ncnn/blob/main/src/c_api.cpp) simply translates C handles (like `ncnn_net_t`) into C++ object pointers (like `Net*`) and invokes the native methods, adding negligible overhead.

### Can I mix C++ and C API calls in the same project?

Yes, you can mix both APIs in the same application because they operate on the same underlying data structures. The C API opaque handles (defined in [`src/c_api.h`](https://github.com/Tencent/ncnn/blob/main/src/c_api.h)) are essentially pointers to C++ objects, so you can create a network with `ncnn::Net` and pass its internal pointer to C functions, or vice versa, provided you manage object lifetimes carefully to avoid double-free errors.

### Which API should I use for Python bindings?

You should use the **ncnn C API** for Python bindings because Python's `ctypes` module can directly interface with C functions and opaque pointers without requiring C++ compiler tooling. The C API in [`src/c_api.h`](https://github.com/Tencent/ncnn/blob/main/src/c_api.h) exposes functions like `ncnn_net_create()` and `ncnn_extractor_extract()` that map cleanly to Python function calls, whereas binding to the C++ API would require complex wrapper generators like pybind11 or SWIG.

### Does the ncnn C API support Vulkan GPU acceleration?

Yes, the ncnn C API supports Vulkan GPU acceleration because it exposes the same `ncnn_option_t` configuration structure used to enable GPU inference. You can call `ncnn_option_set_use_vulkan_compute(opt, 1)` on the option object retrieved via `ncnn_net_get_option()`, allowing the underlying C++ engine to utilize Vulkan pipelines exactly as it would through the C++ API's `opt.use_vulkan_compute` flag.