对比Windows,Linux上实现PHP扩展要简单轻松的多。
参考原文:How to Make PHP Barcode Reader on Linux
作者:Xiao Ling
翻译:yushulx
安装DBR。
要构建PHP扩展,一定要使用对应版本的源码:
php –v
下载PHP源码。
解压代码,切换到ext目录:
cd ~/Downloads/php-5.5.9/ext
创建扩展dbr:
./ext_skel --extname=dbr cd dbr
编辑config.m4,添加头文件和库文件路径:
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
编辑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); } }
要独立构建PHP扩展模块,需要使用phpize。安装开发包:
sudo apt-get install php5-dev
构建PHP扩展模块:
phpize ./configure make
C90规范不支持布尔类型。如果看到错误“unknown type name ‘bool’”,加上头文件:
#include <stdbool.h>
动态链接库dbr.so会自动生成到目录modules下面:
创建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"; } ?>
安装刚才编译出来的扩展:
sudo make install
把安装之后的路径(/usr/lib/php5/20121212/dbr.so)加入到php.ini文件中:
locate php.ini
通过命令找寻php.ini文件会发现有好几个相关的。到底用哪个呢?可以随便选一个或者新建一个。我选择了php.ini-production :
extension=/usr/lib/php5/20121212/dbr.so
运行PHP barcode reader,记得带上php.ini的文件路径:
php -c /usr/share/php5/php.ini-production reader.php
https://github.com/dynamsoftlabs/linux-php-barcode-reader-