How to Make PHP Barcode Reader on Linux
How to make PHP barcode reader on Linux
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 are 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 downloading, you have to check which PHP version is 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;
bool isNativeOuput = false;
bool isLogOn = false;
int iLen = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"sb|b", &pFileName, &iLen, &isNativeOuput, &isLogOn) == FAILURE) {
RETURN_STRING("Invalid parameters", true);
}
if (isLogOn)
{
printf("params: %s, %d, %d\n", pFileName, iLen, isNativeOuput);
}
// Dynamsoft Barcode Reader: init
__int64 llFormat = (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 < count; i++)
{
char barcodeResult[1024];
// A barcode result.
tmp = ppBarcodes[i];
{
// Working with PHP array:
// http://php.net/manual/en/internals2.variables.arrays.php
zval *tmp_array;
// Initialize zval
MAKE_STD_ZVAL(tmp_array);
array_init(tmp_array);
// Add format & value to an array
add_next_index_string(tmp_array, GetFormatStr(tmp->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);
if (isLogOn && isNativeOuput)
{
printf("Native result: %s\n", result);
}
if (isNativeOuput)
{
add_next_index_string(return_value, result, true);
}
}
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 the 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";
/*
* Description:
* array DecodeBarcodeFile( string $filename , bool $isNativeOutput [, bool $isLogOn ] )
*
* Return Values:
* If barcode detected, $array[0] is an array.
*/
$resultArray = DecodeBarcodeFile($filename, false);
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