Ubuntu上轻松实现PHP扩展

co518248 8年前

来自: http://my.oschina.net/yushulx/blog/626498


对比Windows,Linux上实现PHP扩展要简单轻松的多。

参考原文:How to Make PHP Barcode Reader on Linux

作者:Xiao Ling

翻译:yushulx

几步构建PHP Barcode扩展

安装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下面:

 

简单的PHP Barcode应用

创建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-