使用C/C++编写PHP Extension

和Python,JavaScript等高级语言一样,PHP也可以通过C/C++编写扩展功能。这里分享下如何构建一个简单的PHP扩展,以及如何调用第三方DLL库。

参考原文:Making PHP Barcode Extension with Dynamsoft Barcode SDK

使用Visual Studio 2012构建PHP扩展

Windows PHP的安装包本身不包涵头文件,所以要构建PHP扩展,必须下载PHP的源码。在Windows上,要编译PHP,以及构建PHP扩展都必须使用对应的Visual Studio,不然会出现大量的错误。在这里我们使用Visual Studio 2012去构建PHP 5.6的扩展。步骤如下:

  1. 下载PHP 5.6的源码以及VC11 build版本。

  2. 创建一个空的Win32工程,应用类型选择DLL。

  3. 添加头文件路径:

    ?
    1
    2
    3
    4
    5
    F:\php_pack\php-5.6.10-src
    F:\php_pack\php-5.6.10-src\Zend
    F:\php_pack\php-5.6.10-src\win32
    F:\php_pack\php-5.6.10-src\TSRM
    F:\php_pack\php-5.6.10-src\main
  4. 添加库路径:

    ?
    1
    F:\php_pack\php-5.6.10-Win32-VC11-x86\dev
  5. 添加依赖:

    ?
    1
    php5ts.lib
  6. 创建php_dbr.h

    ?
    1
    2
    3
    4
    #pragma once
      
    #include "zend_config.w32.h"    
    #include "php.h"
  7. 创建php_dbr.cpp

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #include "php_dbr.h"
      
    ZEND_FUNCTION(DecodeBarcodeFile);
      
    zend_function_entry CustomExtModule_functions[] = {
         ZEND_FE(DecodeBarcodeFile, NULL)
         {NULL, NULL, NULL}
    };
      
    zend_module_entry CustomExtModule_module_entry = {
         STANDARD_MODULE_HEADER,
         "Dynamsoft Barcode Reader" ,
         CustomExtModule_functions,
         NULL, NULL, NULL, NULL, NULL,
         NO_VERSION_YET, STANDARD_MODULE_PROPERTIES
    };
      
    ZEND_GET_MODULE(CustomExtModule)
      
    ZEND_FUNCTION(DecodeBarcodeFile){
      
         RETURN_STRING( "No Barcode detected" true );
    }
  8. 添加宏定义:

    ?
    1
    2
    3
    4
    ZEND_DEBUG=0
    ZTS=1
    ZEND_WIN32
    PHP_WIN32

    如果不添加,会出现很多错误。

  9. 现在build工程就可以生成php_dbr.dll了。

使用Dynamsoft Barcode SDK创建PHP Barcode Extension

来看一下如何通过PHP扩展调用第三方的DLL库:

  1. 添加Dynamsoft Barcode SDK的头文件和库文件路径到工程属性中

  2. 通过SDK的C/C++接口解码Barcode,并把结果转换成PHP可读数据:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include "php_dbr.h"
  
#include "If_DBR.h"
#include "BarcodeFormat.h"
#include "BarcodeStructs.h"
#include "ErrorCode.h"
  
#ifdef _WIN64
#pragma comment(lib, "DBRx64.lib")
#else
#pragma comment(lib, "DBRx86.lib")
#endif
  
void  SetOptions(pReaderOptions pOption,  int  option_iMaxBarcodesNumPerPage,  int  option_llBarcodeFormat){
  
     if  (option_llBarcodeFormat > 0)
         pOption->llBarcodeFormat = option_llBarcodeFormat;
     else
         pOption->llBarcodeFormat = OneD;
  
     if  (option_iMaxBarcodesNumPerPage > 0)
         pOption->iMaxBarcodesNumPerPage = option_iMaxBarcodesNumPerPage;
     else
         pOption->iMaxBarcodesNumPerPage = INT_MAX;
  
}
  
ZEND_FUNCTION(DecodeBarcodeFile);
  
zend_function_entry CustomExtModule_functions[] = {
     ZEND_FE(DecodeBarcodeFile, NULL)
     {NULL, NULL, NULL}
};
  
zend_module_entry CustomExtModule_module_entry = {
     STANDARD_MODULE_HEADER,
     "Dynamsoft Barcode Reader" ,
     CustomExtModule_functions,
     NULL, NULL, NULL, NULL, NULL,
     NO_VERSION_YET, STANDARD_MODULE_PROPERTIES
};
  
ZEND_GET_MODULE(CustomExtModule)
  
ZEND_FUNCTION(DecodeBarcodeFile){
     array_init(return_value);
  
     // Get Barcode image path
     char * pFileName = NULL;
     int  iLen = 0;
  
     if  (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,  "s" , &pFileName, &iLen) == FAILURE) {
         RETURN_STRING( "Invalid parameters" true );
     }
  
     // Dynamsoft Barcode Reader: init
     int  option_iMaxBarcodesNumPerPage = -1;
     int  option_llBarcodeFormat = -1;
     pBarcodeResultArray pResults = NULL;
     ReaderOptions option;
  
     SetOptions(&option, option_iMaxBarcodesNumPerPage, option_llBarcodeFormat);
  
     // decode barcode image file
     int  ret = DBR_DecodeFile(
         pFileName,
         &option,
         &pResults
         );
  
     if  (ret == DBR_OK)
     {
         int  count = pResults->iBarcodeCount;
         pBarcodeResult* ppBarcodes = pResults->ppBarcodes;
         pBarcodeResult tmp = NULL;
  
         // loop all results
         for  ( int  i = 0; i < count; i++)
         {
             tmp = ppBarcodes[i];
  
             // convert format type to string
             char  format[64]; 
             sprintf  (format,  "%d" , tmp->llFormat); 
  
             // (barcode type, result)
             add_assoc_string(return_value, format, tmp->pBarcodeData, 1);
         }
  
         // Dynamsoft Barcode Reader: release memory
         DBR_FreeBarcodeResults(&pResults);
     }
     else
     {
         RETURN_STRING( "No Barcode detected" true );
     }
  
}

现在我们需要写一个PHP的测试脚本,并把DLL部署到PHP中。

一个简单的PHP Barcode Reader:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
  
$filename  "F:\\git\\Dynamsoft-Barcode-Reader\\Images\\AllSupportedBarcodeTypes.tif" ;
  
if  ( file_exists ( $filename )) {
   echo  "Barcode file: $filename \n" ;
   $resultArray  = DecodeBarcodeFile( $filename );
  
   if  ( is_array ( $resultArray )) {
     foreach ( $resultArray  as  $key  =>  $value ) {
       print  "format:$key, result: $value \n" ;
       print  "*******************\n" ;
     }
   }
   else  {
     print  "$resultArray" ;
   }
  
else  {
     echo  "The file $filename does not exist" ;
}
  
?>

打开php.ini初始化文件,加入:

?
1
2
[Dynamsoft Barcode Reader]
extension=php_dbr.dll

现在要把生成的DLL拷贝到{PHP root directory}\ext。如果你同时把DynamsoftBarcodeReaderx86.dll也拷贝到这个目录下,PHP会找不到这个DLL,报出如下错误:

如何修复这个问题?你只要把第三方的DLL拷贝到PHP根目录下即可。现在再试一次:

源码

https://github.com/yushulx/Dynamsoft-Barcode-Reader/tree/master/samples/PHP

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值