Building Python Barcode Extension with DBR 5.2 for Linux

Xiao Ling
4 min readSep 18, 2017

According to the statistics of Stack Overflow traffic, Python is the fastest-growing major programming language in high-income countries. Python seems to be promising in the future. I have noticed that many of the developers who would like to use Dynamsoft Barcode Reader SDK for Linux are more interested in Python rather than C/C++ or Java. In this post, I will illustrate how to build the Python barcode extension with DBR 5.2.

Writing Python Barcode Extension in C/C++

Dynamsoft Barcode Reader 5.2 for Linux provides C/C++ APIs, which means you need to create a Python wrapper yourself.

Setting Up Environment

The Ubuntu subsystem is my first choice for developing Linux app on Windows 10.

Download Numpy 1.11.2.

Extract and install Numpy

cd numpy-1.11.2 sudo python setup.py build install

Find the path of ndarraytypes.h:

sudo find /usr -name ndarraytypes.h

Create setup.py and add the header file directory:

from distutils.core import setup, Extensionmodule_dbr = Extension('dbr',sources = ['dbr.c'],include_dirs=["/usr/local/lib/python2.7/dist-packages/numpy-1.11.2-py2.7-linux-x86_64.egg/numpy/core/include/numpy/"],libraries=['DynamsoftBarcodeReader'])setup (name = 'DynamsoftBarcodeReader',version = '1.0',description = 'Python barcode extension',ext_modules = [module_dbr])

Extract dbr_linux_5.2.tar.gz:

tar -xvf dbr_linux_5.2.tar.gz

Create a symlink for libDynamsoftBarcodeReaderx64.so:

sudo ln -s <Your PATH>/libDynamsoftBarcodeReaderx64.so /usr/lib/libDynamsoftBarcodeReader.so

The bridging C/C++ code

Include header files:

#include <Python.h>#include "DynamsoftBarcodeReader.h"#include <ndarraytypes.h>

Define methods and initialize Python module:

static PyMethodDef Methods[] ={{"create", create, METH_VARARGS, NULL},{"destroy", destroy, METH_VARARGS, NULL},{"initLicense", initLicense, METH_VARARGS, NULL},{"decodeFile", decodeFile, METH_VARARGS, NULL},{"decodeBuffer", decodeBuffer, METH_VARARGS, NULL},{NULL, NULL, 0, NULL}};PyMODINIT_FUNCinitdbr(void){(void) Py_InitModule("dbr", Methods);}

Initialize DBR license:

static PyObject *initLicense(PyObject *self, PyObject *args){if (!createDBR()){return NULL;}char *pszLicense;if (!PyArg_ParseTuple(args, "s", &pszLicense)) {return NULL;}int ret = DBR_InitLicenseEx(hBarcode, pszLicense);return Py_BuildValue("i", ret);}

Pass a file name and read barcodes:

/*** Decode barcode from a file*/static PyObject *decodeFile(PyObject *self, PyObject *args){if (!createDBR()){return NULL;}char *pFileName;int iFormat;if (!PyArg_ParseTuple(args, "si", &pFileName, &iFormat)) {return NULL;}// Initialize Dynamsoft Barcode Readerint iMaxCount = 0x7FFFFFFF;SBarcodeResultArray *pResults = NULL;DBR_SetBarcodeFormats(hBarcode, iFormat);DBR_SetMaxBarcodesNumPerPage(hBarcode, iMaxCount);// Barcode detectionint ret = DBR_DecodeFileEx(hBarcode, pFileName, &pResults);// Wrap resultsPyObject *list = createPyResults(pResults);return list;}

Give an image buffer and read barcodes:

/*** Decode barcode from an image buffer.*/static PyObject *decodeBuffer(PyObject *self, PyObject *args){if (!createDBR()){return NULL;}PyObject *o;int iFormat;if (!PyArg_ParseTuple(args, "Oi", &o, &iFormat))return NULL;PyObject *ao = PyObject_GetAttrString(o, "__array_struct__");if ((ao == NULL) || !PyCObject_Check(ao)) {PyErr_SetString(PyExc_TypeError, "object does not have array interface");return NULL;}PyArrayInterface *pai = (PyArrayInterface*)PyCObject_AsVoidPtr(ao);if (pai->two != 2) {PyErr_SetString(PyExc_TypeError, "object does not have array interface");Py_DECREF(ao);return NULL;}// Get image informationchar *buffer = (char*)pai->data; // The address of image dataint width = pai->shape[1];       // image widthint height = pai->shape[0];      // image heightint size = pai->strides[0] * pai->shape[0]; // image size = stride * height// Initialize Dynamsoft Barcode Readerint iMaxCount = 0x7FFFFFFF;SBarcodeResultArray *pResults = NULL;DBR_SetBarcodeFormats(hBarcode, iFormat);DBR_SetMaxBarcodesNumPerPage(hBarcode, iMaxCount);// Detect barcodesint iRet = DBR_DecodeBufferEx(hBarcode, buffer, width, height, width * 3, IPF_RGB_888, &pResults);// Wrap resultsPyObject *list = createPyResults(pResults);Py_DECREF(ao);return list;}

Convert results to Python Object:

static PyObject *createPyResults(SBarcodeResultArray *pResults){// Get barcode resultsint count = pResults->iBarcodeCount;SBarcodeResult** ppBarcodes = pResults->ppBarcodes;SBarcodeResult* tmp = NULL;// Create a Python object to store resultsPyObject* list = PyList_New(count);PyObject* result = NULL;for (int i = 0; i < count; i++){tmp = ppBarcodes[i];result = PyString_FromString(tmp->pBarcodeData);PyList_SetItem(list, i, Py_BuildValue("sN", GetFormatStr(tmp->emBarcodeFormat), result)); // Add results to list}// Release memoryDBR_FreeBarcodeResults(&pResults);return list;}

Build and install the Python barcode extension:

sudo python setup.py build install

A command line barcode app

Read barcodes from a picture file:

import os.pathimport dbrdef initLicense(license):dbr.initLicense(license)def decodeFile(fileName):dbr.initLicense("t0068MgAAAGvV3VqfqOzkuVGi7x/PFfZUQoUyJOakuduaSEoI2Pc8+kMwjrojxQgE5aJphmhagRmq/S9lppTkM4w3qCQezxk=")formats = 0x3FF | 0x2000000 | 0x8000000 | 0x4000000; # 1D, QRCODE, PDF417, DataMatrixresults = dbr.decodeFile(fileName, formats)for result in results:print("barcode format: " + result[0])print("barcode value: " + result[1])if __name__ == "__main__":barcode_image = input("Enter the barcode file: ");if not os.path.isfile(barcode_image):print "It is not a valid file."else:decodeFile(barcode_image);

Run the app:

python test.py

Reference

Source Code

https://github.com/dynamsoft-dbr/linux-barcode-sdk-python-wrapper

Originally published at www.codepool.biz on September 18, 2017.

--

--

Xiao Ling

Manager of Dynamsoft Open Source Projects | Tech Lover