When developing a web barcode reader app in PHP, you can either use some JavaScript barcode libraries to recognize barcode images on client-side or read the barcode images on server-side with some PHP extensions that capable of reading 1D and 2D barcode. In this post, I will demonstrate how to create a PHP barcode reader with DBR (Dynamsoft Barcode Reader for Linux) on Ubuntu 14.04.
How to Make PHP Extension with C Source Code and Shared Library
Install DBR.
To build PHP extension, you need to use the source code. Before download, you have to check which PHP version used:
php –v
Download the corresponding source code of PHP.
Extract the package and change to the ext folder. Here is mine:
cd ~/Downloads/php-5.5.9/ext
Create an extension dbr:
./ext_skel --extname=dbr
Change directory to dbr:
cd dbr
Edit config.m4 to configure the paths of include and library:
PHP_ARG_ENABLE(dbr, whether to enable dbr support, dnl Make sure that the comment is aligned: [ --enable-dbr Enable dbr support]) if test "$PHP_DBR" != "no"; then PHP_ADD_LIBRARY_WITH_PATH(DynamsoftBarcodeReaderx64, /home/xiao/Dynamsoft/BarcodeReader4.0/Redist, DBR_SHARED_LIBADD) PHP_ADD_INCLUDE(/home/xiao/Dynamsoft/BarcodeReader4.0/Include) PHP_SUBST(DBR_SHARED_LIBADD) PHP_NEW_EXTENSION(dbr, dbr.c, $ext_shared) fi
Edit dbr.c:
#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" #include "php_dbr.h" #include "If_DBR.h" #include "BarcodeFormat.h" #include "BarcodeStructs.h" #include "ErrorCode.h" #include <stdbool.h> /* If you declare any globals in php_dbr.h uncomment this: ZEND_DECLARE_MODULE_GLOBALS(dbr) */ /* True global resources - no need for thread safety here */ static int le_dbr; /* {{{ dbr_functions[] * * Every user visible function must have an entry in dbr_functions[]. */ const zend_function_entry dbr_functions[] = { PHP_FE(DecodeBarcodeFile, NULL) /* For testing, remove later. */ PHP_FE_END /* Must be the last line in dbr_functions[] */ }; /* }}} */ /* {{{ dbr_module_entry */ zend_module_entry dbr_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif "dbr", dbr_functions, PHP_MINIT(dbr), PHP_MSHUTDOWN(dbr), PHP_RINIT(dbr), /* Replace with NULL if there's nothing to do at request start */ PHP_RSHUTDOWN(dbr), /* Replace with NULL if there's nothing to do at request end */ PHP_MINFO(dbr), #if ZEND_MODULE_API_NO >= 20010901 PHP_DBR_VERSION, #endif STANDARD_MODULE_PROPERTIES }; /* }}} */ #ifdef COMPILE_DL_DBR ZEND_GET_MODULE(dbr) #endif /* {{{ PHP_INI */ /* Remove comments and fill if you need to have entries in php.ini PHP_INI_BEGIN() STD_PHP_INI_ENTRY("dbr.global_value", "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_dbr_globals, dbr_globals) STD_PHP_INI_ENTRY("dbr.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_dbr_globals, dbr_globals) PHP_INI_END() */ /* }}} */ /* {{{ php_dbr_init_globals */ /* Uncomment this function if you have INI entries static void php_dbr_init_globals(zend_dbr_globals *dbr_globals) { dbr_globals->global_value = 0; dbr_globals->global_string = NULL; } */ /* }}} */ /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(dbr) { /* If you have INI entries, uncomment these lines REGISTER_INI_ENTRIES(); */ return SUCCESS; } /* }}} */ /* {{{ PHP_MSHUTDOWN_FUNCTION */ PHP_MSHUTDOWN_FUNCTION(dbr) { /* uncomment this line if you have INI entries UNREGISTER_INI_ENTRIES(); */ return SUCCESS; } /* }}} */ /* Remove if there's nothing to do at request start */ /* {{{ PHP_RINIT_FUNCTION */ PHP_RINIT_FUNCTION(dbr) { return SUCCESS; } /* }}} */ /* Remove if there's nothing to do at request end */ /* {{{ PHP_RSHUTDOWN_FUNCTION */ PHP_RSHUTDOWN_FUNCTION(dbr) { return SUCCESS; } /* }}} */ /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(dbr) { php_info_print_table_start(); php_info_print_table_header(2, "dbr support", "enabled"); php_info_print_table_end(); /* Remove comments if you have entries in php.ini DISPLAY_INI_ENTRIES(); */ } /* }}} */ // Barcode format const char * GetFormatStr(__int64 format) { if (format == CODE_39) return "CODE_39"; if (format == CODE_128) return "CODE_128"; if (format == CODE_93) return "CODE_93"; if (format == CODABAR) return "CODABAR"; if (format == ITF) return "ITF"; if (format == UPC_A) return "UPC_A"; if (format == UPC_E) return "UPC_E"; if (format == EAN_13) return "EAN_13"; if (format == EAN_8) return "EAN_8"; if (format == INDUSTRIAL_25) return "INDUSTRIAL_25"; if (format == QR_CODE) return "QR_CODE"; if (format == PDF417) return "PDF417"; if (format == DATAMATRIX) return "DATAMATRIX"; return "UNKNOWN"; } PHP_FUNCTION(DecodeBarcodeFile) { array_init(return_value); // Get Barcode image path char* pFileName = NULL; int barcodeType = 0; int iLen = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &pFileName, &iLen, &barcodeType) == FAILURE) { RETURN_STRING("Invalid parameters", true); } // Dynamsoft Barcode Reader: init __int64 llFormat = barcodeType > 0 ? barcodeType : (OneD | QR_CODE | PDF417 | DATAMATRIX); int iMaxCount = 0x7FFFFFFF; int iIndex = 0; ReaderOptions ro = {0}; pBarcodeResultArray pResults = NULL; int iRet = -1; char * pszTemp = NULL; // Initialize license iRet = DBR_InitLicense("84D34246FC1BC4BDD4078D71FCB5A3AA"); printf("DBR_InitLicense ret: %d\n", iRet); ro.llBarcodeFormat = llFormat; ro.iMaxBarcodesNumPerPage = iMaxCount; // Decode barcode image int ret = DBR_DecodeFile(pFileName, &ro, &pResults); if (ret == DBR_OK) { int count = pResults->iBarcodeCount; pBarcodeResult* ppBarcodes = pResults->ppBarcodes; pBarcodeResult tmp = NULL; char result[2048] = {0}; int i = 0; if (count == 0) { add_next_index_string(return_value, "No Barcode detected", true); } // loop all results for (; i llFormat), true); add_next_index_string(tmp_array, tmp->pBarcodeData, true); // Add result to returned array add_next_index_zval(return_value, tmp_array); } } // Dynamsoft Barcode Reader: release memory DBR_FreeBarcodeResults(&pResults); } else { add_next_index_string(return_value, "No Barcode detected", true); } }
To build PHP extension independently, you need to use phpize, which is a shell script to prepare PHP extension for compiling. Install the dev package as follows:
sudo apt-get install php5-dev
Build the extension with following commands:
phpize ./configure make
C90 does not support the boolean data type. If you see the error “unknown type name ‘bool’”, please include the header file:
#include <stdbool.h>
A shared library dbr.so is generated under folder modules:
Simple PHP Barcode Reader
Create reader.php:
<?php $filename = "/home/xiao/Dynamsoft/BarcodeReader4.0/Images/AllSupportedBarcodeTypes.tif"; if (file_exists($filename)) { echo "Barcode file: $filename \n"; $resultArray = DecodeBarcodeFile($filename, 0); if (is_array($resultArray[0])) { $resultCount = count($resultArray); echo "Total count: $resultCount\n"; for($i = 0; $i < $resultCount ; $i++) { $result = $resultArray[$i]; echo "Barcode format: $result[0], value: $result[1]\n"; } } else { echo "$resultArray[0]"; } } else { echo "The file $filename does not exist"; } ?>
Install the PHP Barcode extension:
sudo make install
To load the custom extension, you have to add the library path (e.g. /usr/lib/php5/20121212/dbr.so ) into php.ini:
locate php.ini
You may ask which php.ini file should be used? The answer is that you can modify any php.ini file or make it yourself. When executing PHP script, you can designate the php.ini file. I picked php.ini-production and then added the following line:
extension=/usr/lib/php5/20121212/dbr.so
Test the simple PHP barcode reader:
php -c /usr/share/php5/php.ini-production reader.php