TensorFlow Lite
C++ API
Inference
Machine Learning
Programming Example

TensorFlow Lite C API example for inference

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

TensorFlow Lite ships a small C API that is useful when you want minimal dependencies or need to call inference code from C or another native environment. The workflow is straightforward: load the model, create an interpreter, allocate tensors, copy input data into the input tensor, invoke the interpreter, and copy the output back out.

The important part is matching your buffers to the model's tensor types and sizes. The API is low level, so it will not guess shapes or convert data for you.

Basic Inference Flow With the C API

A minimal inference program looks like this:

c
1#include <stdio.h>
2#include <stdlib.h>
3#include <tensorflow/lite/c/c_api.h>
4
5int main(void) {
6    const char* model_path = "model.tflite";
7
8    TfLiteModel* model = TfLiteModelCreateFromFile(model_path);
9    if (!model) {
10        fprintf(stderr, "failed to load model
11");
12        return 1;
13    }
14
15    TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate();
16    TfLiteInterpreterOptionsSetNumThreads(options, 1);
17
18    TfLiteInterpreter* interpreter = TfLiteInterpreterCreate(model, options);
19    if (!interpreter) {
20        fprintf(stderr, "failed to create interpreter
21");
22        TfLiteInterpreterOptionsDelete(options);
23        TfLiteModelDelete(model);
24        return 1;
25    }
26
27    if (TfLiteInterpreterAllocateTensors(interpreter) != kTfLiteOk) {
28        fprintf(stderr, "failed to allocate tensors
29");
30        TfLiteInterpreterDelete(interpreter);
31        TfLiteInterpreterOptionsDelete(options);
32        TfLiteModelDelete(model);
33        return 1;
34    }
35
36    TfLiteTensor* input = TfLiteInterpreterGetInputTensor(interpreter, 0);
37    float input_data[4] = {5.1f, 3.5f, 1.4f, 0.2f};
38
39    if (TfLiteTensorType(input) != kTfLiteFloat32) {
40        fprintf(stderr, "unexpected input type
41");
42        return 1;
43    }
44
45    if (TfLiteTensorByteSize(input) != sizeof(input_data)) {
46        fprintf(stderr, "unexpected input size
47");
48        return 1;
49    }
50
51    if (TfLiteTensorCopyFromBuffer(input, input_data, sizeof(input_data)) != kTfLiteOk) {
52        fprintf(stderr, "failed to copy input buffer
53");
54        return 1;
55    }
56
57    if (TfLiteInterpreterInvoke(interpreter) != kTfLiteOk) {
58        fprintf(stderr, "inference failed
59");
60        return 1;
61    }
62
63    const TfLiteTensor* output = TfLiteInterpreterGetOutputTensor(interpreter, 0);
64    float output_data[3] = {0};
65
66    if (TfLiteTensorCopyToBuffer(output, output_data, sizeof(output_data)) != kTfLiteOk) {
67        fprintf(stderr, "failed to copy output buffer
68");
69        return 1;
70    }
71
72    for (int i = 0; i < 3; ++i) {
73        printf("output[%d] = %f
74", i, output_data[i]);
75    }
76
77    TfLiteInterpreterDelete(interpreter);
78    TfLiteInterpreterOptionsDelete(options);
79    TfLiteModelDelete(model);
80    return 0;
81}

That example assumes a float input tensor of four values and a float output tensor of length three. Replace those sizes with the shapes from your own model.

Understand the Responsibilities of Each Step

The model object holds the parsed .tflite file. The interpreter object owns the execution state and tensors. TfLiteInterpreterAllocateTensors must happen before you read or write input and output buffers, because tensor memory is not ready until allocation completes.

After that, the flow is simple:

  • get the input tensor
  • confirm its type and byte size
  • copy your input bytes into it
  • call TfLiteInterpreterInvoke
  • copy the output bytes back into your own buffer

The API is intentionally explicit. That is useful for performance and embedding, but it means shape mismatches are your responsibility to catch.

Check Tensor Metadata Before Copying Buffers

One common mistake is assuming the model input type from training code. A model might be quantized even if the original training graph used floats. Before writing the buffer, inspect the tensor:

  • 'TfLiteTensorType tells you the raw element type'
  • 'TfLiteTensorByteSize tells you how large the input buffer must be'
  • tensor dimensions can be inspected if you need to validate shape at runtime

That is especially important for int8 or uint8 models, where feeding float data directly will fail or produce nonsense.

Common Pitfalls

  • Forgetting TfLiteInterpreterAllocateTensors before touching the input tensor.
  • Assuming a float model when the deployed .tflite file is actually quantized.
  • Copying the wrong number of bytes into the input tensor.
  • Ignoring the return value from TfLiteInterpreterInvoke and then trying to read invalid outputs.
  • Leaking the interpreter, options, or model objects on early-return error paths.

Summary

  • The TensorFlow Lite C API inference loop is load model, create interpreter, allocate tensors, copy input, invoke, and copy output.
  • Always validate tensor type and byte size against your application buffers.
  • The API does not perform convenient conversions for you, so buffer correctness matters.
  • Treat allocation and cleanup as part of the normal inference path, not as optional extras.
  • Once the tensor metadata matches your buffers, the C API is a small and reliable way to run native inference.

Course illustration
Course illustration

All Rights Reserved.