tessl install tessl/github-zxing-cpp--zxing-cpp@2.3.0Open-source, multi-format linear/matrix barcode image processing library implemented in C++
ZXing-C++ provides a complete C API wrapper (ZXingC.h) that exposes all C++ functionality through C-compatible functions. This enables use from C code and simplifies FFI (Foreign Function Interface) integration with other languages.
The C API wraps all major C++ types and functions:
_new() and _delete() functions#include "ZXing/ZXingC.h"The C API is available when the library is built with ZXING_C_API CMake option enabled.
All C++ classes are wrapped as opaque pointer types:
// Core types
typedef struct ZXing_Barcode ZXing_Barcode;
typedef struct ZXing_Barcodes ZXing_Barcodes;
typedef struct ZXing_ImageView ZXing_ImageView;
typedef struct ZXing_Image ZXing_Image;
typedef struct ZXing_ReaderOptions ZXing_ReaderOptions;
// Experimental types (requires ZXING_EXPERIMENTAL_API)
#ifdef ZXING_EXPERIMENTAL_API
typedef struct ZXing_CreatorOptions ZXing_CreatorOptions;
typedef struct ZXing_WriterOptions ZXing_WriterOptions;
#endif
// Enums are used directly (same as C++)
typedef enum ZXing_BarcodeFormat ZXing_BarcodeFormat;
typedef enum ZXing_ImageFormat ZXing_ImageFormat;
typedef enum ZXing_ContentType ZXing_ContentType;
// ... etc// Read single barcode
ZXing_Barcode* ZXing_ReadBarcode(
const ZXing_ImageView* iv,
const ZXing_ReaderOptions* opts
);Example:
#include "ZXing/ZXingC.h"
void read_barcode(const uint8_t* data, int width, int height) {
// Create ImageView
ZXing_ImageView* iv = ZXing_ImageView_new(
data, width, height, ZXing_ImageFormat_Lum, 0, 0
);
// Create options (NULL for defaults)
ZXing_ReaderOptions* opts = ZXing_ReaderOptions_new();
ZXing_ReaderOptions_setFormats(opts, ZXing_BarcodeFormat_QRCode);
// Read barcode
ZXing_Barcode* barcode = ZXing_ReadBarcode(iv, opts);
// Check validity
if (ZXing_Barcode_isValid(barcode)) {
// Get text
char* text = ZXing_Barcode_text(barcode);
printf("Barcode: %s\n", text);
free(text); // Free returned string
} else {
// Get error
char* errorMsg = ZXing_Barcode_errorMsg(barcode);
printf("Error: %s\n", errorMsg);
free(errorMsg);
}
// Cleanup
ZXing_Barcode_delete(barcode);
ZXing_ReaderOptions_delete(opts);
ZXing_ImageView_delete(iv);
}// Read multiple barcodes
ZXing_Barcodes* ZXing_ReadBarcodes(
const ZXing_ImageView* iv,
const ZXing_ReaderOptions* opts
);
// Get count of barcodes
int ZXing_Barcodes_size(const ZXing_Barcodes* barcodes);
// Get barcode at index
ZXing_Barcode* ZXing_Barcodes_at(const ZXing_Barcodes* barcodes, int index);Example:
void read_multiple(const uint8_t* data, int width, int height) {
ZXing_ImageView* iv = ZXing_ImageView_new(
data, width, height, ZXing_ImageFormat_Lum, 0, 0
);
ZXing_ReaderOptions* opts = ZXing_ReaderOptions_new();
// Read all barcodes
ZXing_Barcodes* barcodes = ZXing_ReadBarcodes(iv, opts);
// Iterate results
int count = ZXing_Barcodes_size(barcodes);
printf("Found %d barcodes\n", count);
for (int i = 0; i < count; i++) {
ZXing_Barcode* bc = ZXing_Barcodes_at(barcodes, i);
if (ZXing_Barcode_isValid(bc)) {
char* text = ZXing_Barcode_text(bc);
printf("%d: %s\n", i + 1, text);
free(text);
}
}
// Cleanup
ZXing_Barcodes_delete(barcodes);
ZXing_ReaderOptions_delete(opts);
ZXing_ImageView_delete(iv);
}// Create ImageView
ZXing_ImageView* ZXing_ImageView_new(
const uint8_t* data,
int width,
int height,
ZXing_ImageFormat format,
int rowStride,
int pixStride
);
// Create ImageView with size checking
ZXing_ImageView* ZXing_ImageView_new_checked(
const uint8_t* data,
int size,
int width,
int height,
ZXing_ImageFormat format,
int rowStride,
int pixStride
);
// Delete ImageView
void ZXing_ImageView_delete(ZXing_ImageView* iv);Example:
// Grayscale image
ZXing_ImageView* iv = ZXing_ImageView_new(
data, width, height,
ZXing_ImageFormat_Lum,
0, // Auto-calculate row stride
0 // Auto-calculate pixel stride
);
// RGB image
ZXing_ImageView* iv_rgb = ZXing_ImageView_new(
rgb_data, width, height,
ZXing_ImageFormat_RGB,
0, 0
);
ZXing_ImageView_delete(iv);
ZXing_ImageView_delete(iv_rgb);// Create options
ZXing_ReaderOptions* ZXing_ReaderOptions_new(void);
// Delete options
void ZXing_ReaderOptions_delete(ZXing_ReaderOptions* opts);
// Setters
void ZXing_ReaderOptions_setFormats(ZXing_ReaderOptions* opts,
ZXing_BarcodeFormats formats);
void ZXing_ReaderOptions_setTryHarder(ZXing_ReaderOptions* opts, bool tryHarder);
void ZXing_ReaderOptions_setTryRotate(ZXing_ReaderOptions* opts, bool tryRotate);
void ZXing_ReaderOptions_setTryInvert(ZXing_ReaderOptions* opts, bool tryInvert);
void ZXing_ReaderOptions_setTryDownscale(ZXing_ReaderOptions* opts, bool try);
void ZXing_ReaderOptions_setBinarizer(ZXing_ReaderOptions* opts,
ZXing_Binarizer binarizer);
void ZXing_ReaderOptions_setIsPure(ZXing_ReaderOptions* opts, bool isPure);
void ZXing_ReaderOptions_setMaxNumberOfSymbols(ZXing_ReaderOptions* opts,
uint8_t n);
void ZXing_ReaderOptions_setTextMode(ZXing_ReaderOptions* opts,
ZXing_TextMode mode);
// Getters
ZXing_BarcodeFormats ZXing_ReaderOptions_getFormats(const ZXing_ReaderOptions* opts);
bool ZXing_ReaderOptions_getTryHarder(const ZXing_ReaderOptions* opts);
// ... etcExample:
ZXing_ReaderOptions* opts = ZXing_ReaderOptions_new();
// Configure options
ZXing_ReaderOptions_setFormats(opts,
ZXing_BarcodeFormat_QRCode | ZXing_BarcodeFormat_DataMatrix);
ZXing_ReaderOptions_setTryHarder(opts, true);
ZXing_ReaderOptions_setTryRotate(opts, true);
ZXing_ReaderOptions_setMaxNumberOfSymbols(opts, 10);
// Use options
ZXing_Barcodes* barcodes = ZXing_ReadBarcodes(iv, opts);
// Cleanup
ZXing_ReaderOptions_delete(opts);// Delete barcode
void ZXing_Barcode_delete(ZXing_Barcode* barcode);
// Validity
bool ZXing_Barcode_isValid(const ZXing_Barcode* barcode);
// Content
char* ZXing_Barcode_text(const ZXing_Barcode* barcode);
uint8_t* ZXing_Barcode_bytes(const ZXing_Barcode* barcode, int* size);
char* ZXing_Barcode_ecLevel(const ZXing_Barcode* barcode);
// Format
ZXing_BarcodeFormat ZXing_Barcode_format(const ZXing_Barcode* barcode);
// Position (corners)
void ZXing_Barcode_position(const ZXing_Barcode* barcode,
ZXing_PointI* topLeft,
ZXing_PointI* topRight,
ZXing_PointI* bottomRight,
ZXing_PointI* bottomLeft);
// Orientation
int ZXing_Barcode_orientation(const ZXing_Barcode* barcode);
// Error
ZXing_ErrorType ZXing_Barcode_errorType(const ZXing_Barcode* barcode);
char* ZXing_Barcode_errorMsg(const ZXing_Barcode* barcode);
// Metadata
char* ZXing_Barcode_symbologyIdentifier(const ZXing_Barcode* barcode);
int ZXing_Barcode_sequenceSize(const ZXing_Barcode* barcode);
int ZXing_Barcode_sequenceIndex(const ZXing_Barcode* barcode);
bool ZXing_Barcode_isPartOfSequence(const ZXing_Barcode* barcode);All string-returning functions allocate memory that must be freed:
// Get text - allocates string
char* text = ZXing_Barcode_text(barcode);
if (text) {
printf("Text: %s\n", text);
free(text); // Must free!
}
// Get error message - allocates string
char* errorMsg = ZXing_Barcode_errorMsg(barcode);
if (errorMsg) {
printf("Error: %s\n", errorMsg);
free(errorMsg); // Must free!
}ZXing_PointI tl, tr, br, bl;
ZXing_Barcode_position(barcode, &tl, &tr, &br, &bl);
printf("Corners:\n");
printf(" Top-Left: (%d, %d)\n", tl.x, tl.y);
printf(" Top-Right: (%d, %d)\n", tr.x, tr.y);
printf(" Bottom-Right: (%d, %d)\n", br.x, br.y);
printf(" Bottom-Left: (%d, %d)\n", bl.x, bl.y);#ifdef ZXING_EXPERIMENTAL_API
// Create barcode from text
ZXing_Barcode* ZXing_CreateBarcodeFromText(
const char* data,
int size,
const ZXing_CreatorOptions* opts
);
// Create barcode from bytes
ZXing_Barcode* ZXing_CreateBarcodeFromBytes(
const uint8_t* data,
int size,
const ZXing_CreatorOptions* opts
);
// Write to SVG
char* ZXing_WriteBarcodeToSVG(
const ZXing_Barcode* barcode,
const ZXing_WriterOptions* opts
);
// Write to UTF-8 string
char* ZXing_WriteBarcodeToUtf8(
const ZXing_Barcode* barcode,
const ZXing_WriterOptions* opts
);
// Write to image
ZXing_Image* ZXing_WriteBarcodeToImage(
const ZXing_Barcode* barcode,
const ZXing_WriterOptions* opts
);
#endifExample:
#ifdef ZXING_EXPERIMENTAL_API
void create_qr_code(const char* text) {
// Create options
ZXing_CreatorOptions* createOpts =
ZXing_CreatorOptions_new(ZXing_BarcodeFormat_QRCode);
ZXing_CreatorOptions_setEcLevel(createOpts, "H");
// Create barcode
ZXing_Barcode* barcode = ZXing_CreateBarcodeFromText(
text, -1, createOpts
);
if (ZXing_Barcode_isValid(barcode)) {
// Write to SVG
ZXing_WriterOptions* writeOpts = ZXing_WriterOptions_new();
ZXing_WriterOptions_setScale(writeOpts, 4);
char* svg = ZXing_WriteBarcodeToSVG(barcode, writeOpts);
printf("SVG:\n%s\n", svg);
free(svg);
ZXing_WriterOptions_delete(writeOpts);
}
ZXing_Barcode_delete(barcode);
ZXing_CreatorOptions_delete(createOpts);
}
#endif// Get version
const char* ZXing_Version(void);
// Get supported formats (experimental)
#ifdef ZXING_EXPERIMENTAL_API
ZXing_BarcodeFormats ZXing_SupportedBarcodeFormats(ZXing_Operation op);
#endifExample:
// Print version
printf("ZXing-C++ version: %s\n", ZXing_Version());
#ifdef ZXING_EXPERIMENTAL_API
// Check supported formats
ZXing_BarcodeFormats readFormats =
ZXing_SupportedBarcodeFormats(ZXing_Operation_Read);
if (readFormats & ZXing_BarcodeFormat_QRCode) {
printf("QR Code reading supported\n");
}
#endifAll C++ enums are available in C with the same values:
// BarcodeFormat
ZXing_BarcodeFormat_None
ZXing_BarcodeFormat_Aztec
ZXing_BarcodeFormat_Codabar
ZXing_BarcodeFormat_Code39
ZXing_BarcodeFormat_Code93
ZXing_BarcodeFormat_Code128
ZXing_BarcodeFormat_DataBar
ZXing_BarcodeFormat_DataBarExpanded
ZXing_BarcodeFormat_DataBarLimited
ZXing_BarcodeFormat_DataMatrix
ZXing_BarcodeFormat_EAN8
ZXing_BarcodeFormat_EAN13
ZXing_BarcodeFormat_ITF
ZXing_BarcodeFormat_MaxiCode
ZXing_BarcodeFormat_PDF417
ZXing_BarcodeFormat_QRCode
ZXing_BarcodeFormat_UPCA
ZXing_BarcodeFormat_UPCE
ZXing_BarcodeFormat_MicroQRCode
ZXing_BarcodeFormat_RMQRCode
ZXing_BarcodeFormat_DXFilmEdge
ZXing_BarcodeFormat_LinearCodes
ZXing_BarcodeFormat_MatrixCodes
ZXing_BarcodeFormat_Any
// ImageFormat
ZXing_ImageFormat_None
ZXing_ImageFormat_Lum
ZXing_ImageFormat_LumA
ZXing_ImageFormat_RGB
ZXing_ImageFormat_BGR
ZXing_ImageFormat_RGBA
ZXing_ImageFormat_ARGB
ZXing_ImageFormat_BGRA
ZXing_ImageFormat_ABGR
// TextMode
ZXing_TextMode_Plain
ZXing_TextMode_ECI
ZXing_TextMode_HRI
ZXing_TextMode_Hex
ZXing_TextMode_Escaped
// ErrorType
ZXing_ErrorType_None
ZXing_ErrorType_Format
ZXing_ErrorType_Checksum
ZXing_ErrorType_Unsupported
// Binarizer
ZXing_Binarizer_LocalAverage
ZXing_Binarizer_GlobalHistogram
ZXing_Binarizer_FixedThreshold
ZXing_Binarizer_BoolCast#include "ZXing/ZXingC.h"
#include <stdio.h>
#include <stdlib.h>
void process_image(const uint8_t* data, int width, int height) {
printf("Processing image: %dx%d\n", width, height);
printf("ZXing-C++ version: %s\n", ZXing_Version());
// Create ImageView
ZXing_ImageView* iv = ZXing_ImageView_new(
data, width, height,
ZXing_ImageFormat_Lum,
0, 0
);
if (!iv) {
fprintf(stderr, "Failed to create ImageView\n");
return;
}
// Create options
ZXing_ReaderOptions* opts = ZXing_ReaderOptions_new();
ZXing_ReaderOptions_setFormats(opts, ZXing_BarcodeFormat_Any);
ZXing_ReaderOptions_setTryHarder(opts, true);
ZXing_ReaderOptions_setTryRotate(opts, true);
ZXing_ReaderOptions_setMaxNumberOfSymbols(opts, 255);
// Read all barcodes
ZXing_Barcodes* barcodes = ZXing_ReadBarcodes(iv, opts);
int count = ZXing_Barcodes_size(barcodes);
printf("Found %d barcode(s)\n", count);
// Process each barcode
for (int i = 0; i < count; i++) {
ZXing_Barcode* bc = ZXing_Barcodes_at(barcodes, i);
printf("\nBarcode %d:\n", i + 1);
if (ZXing_Barcode_isValid(bc)) {
// Get format
ZXing_BarcodeFormat format = ZXing_Barcode_format(bc);
printf(" Format: %d\n", format);
// Get text
char* text = ZXing_Barcode_text(bc);
printf(" Text: %s\n", text);
free(text);
// Get position
ZXing_PointI tl, tr, br, bl;
ZXing_Barcode_position(bc, &tl, &tr, &br, &bl);
printf(" Position: TL(%d,%d) TR(%d,%d) BR(%d,%d) BL(%d,%d)\n",
tl.x, tl.y, tr.x, tr.y, br.x, br.y, bl.x, bl.y);
// Get orientation
int orientation = ZXing_Barcode_orientation(bc);
printf(" Orientation: %d degrees\n", orientation);
// Check for structured append
if (ZXing_Barcode_isPartOfSequence(bc)) {
int index = ZXing_Barcode_sequenceIndex(bc);
int size = ZXing_Barcode_sequenceSize(bc);
printf(" Sequence: %d of %d\n", index + 1, size);
}
} else {
// Get error
ZXing_ErrorType errType = ZXing_Barcode_errorType(bc);
char* errMsg = ZXing_Barcode_errorMsg(bc);
printf(" Error (type %d): %s\n", errType, errMsg);
free(errMsg);
}
}
// Cleanup
ZXing_Barcodes_delete(barcodes);
ZXing_ReaderOptions_delete(opts);
ZXing_ImageView_delete(iv);
printf("\nDone\n");
}
int main(void) {
// Load image data (example)
int width = 640;
int height = 480;
uint8_t* data = load_image("barcode.png", &width, &height);
if (data) {
process_image(data, width, height);
free(data);
}
return 0;
}# Enable C API when building ZXing
set(ZXING_C_API ON)
add_executable(my_app main.c)
target_link_libraries(my_app ZXing::ZXing)# Compile C code
gcc -c main.c -I/path/to/zxing/include
# Link with ZXing library
gcc -o my_app main.o -L/path/to/zxing/lib -lZXing -lstdc++Note: You must link with C++ standard library even when using C API, as the implementation is C++.
The C API has the same thread safety guarantees as the C++ API:
// These functions are thread-safe:
ZXing_ReadBarcode()
ZXing_ReadBarcodes()
// These objects should not be shared between threads without synchronization:
ZXing_ReaderOptions
ZXing_CreatorOptions
ZXing_WriterOptions
// Results (Barcode objects) can be read from multiple threads
// but should not be modified concurrentlyC API uses return values and validity checks instead of exceptions:
// Always check validity
ZXing_Barcode* barcode = ZXing_ReadBarcode(iv, opts);
if (ZXing_Barcode_isValid(barcode)) {
// Success - safe to use
char* text = ZXing_Barcode_text(barcode);
process_text(text);
free(text);
} else {
// Failure - check error
char* errorMsg = ZXing_Barcode_errorMsg(barcode);
fprintf(stderr, "Error: %s\n", errorMsg);
free(errorMsg);
}
// Always cleanup
ZXing_Barcode_delete(barcode);// These functions allocate strings that must be freed:
char* text = ZXing_Barcode_text(barcode);
char* error = ZXing_Barcode_errorMsg(barcode);
char* ecLevel = ZXing_Barcode_ecLevel(barcode);
char* svg = ZXing_WriteBarcodeToSVG(barcode, opts);
// Always free after use
free(text);
free(error);
free(ecLevel);
free(svg);// Create
ZXing_ImageView* iv = ZXing_ImageView_new(...);
ZXing_ReaderOptions* opts = ZXing_ReaderOptions_new();
ZXing_Barcode* barcode = ZXing_ReadBarcode(...);
// Use...
// Delete
ZXing_ImageView_delete(iv);
ZXing_ReaderOptions_delete(opts);
ZXing_Barcode_delete(barcode);ZXing_Barcode* barcode = ZXing_ReadBarcode(iv, opts);
if (!barcode) {
// Very rare - allocation failure or null input
fprintf(stderr, "Failed to read barcode\n");
return;
}
// Use barcode...
ZXing_Barcode_delete(barcode);// Point structures can be on stack
ZXing_PointI topLeft, topRight, bottomRight, bottomLeft;
ZXing_Barcode_position(barcode, &topLeft, &topRight, &bottomRight, &bottomLeft);
// No need to free - automatic cleanup