使用C/C++編寫PHP Extension

和Python,JavaScript等高級語言同樣,PHP也能夠經過C/C++編寫擴展功能。這裏分享下如何構建一個簡單的PHP擴展,以及如何調用第三方DLL庫。php

參考原文:Making PHP Barcode Extension with Dynamsoft Barcode SDKhtml

使用Visual Studio 2012構建PHP擴展

Windows PHP的安裝包自己不包涵頭文件,因此要構建PHP擴展,必須下載PHP的源碼。在Windows上,要編譯PHP,以及構建PHP擴展都必須使用對應的Visual Studio,否則會出現大量的錯誤。在這裏咱們使用Visual Studio 2012去構建PHP 5.6的擴展。步驟以下:
git

  1. 下載PHP 5.6的源碼以及VC11 build版本。github

  2. 建立一個空的Win32工程,應用類型選擇DLL。windows

  3. 添加頭文件路徑:oop

    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. 添加庫路徑:測試

    F:\php_pack\php-5.6.10-Win32-VC11-x86\dev
  5. 添加依賴:ui

    php5ts.lib
  6. 建立php_dbr.hspa

    #pragma once
     
    #include "zend_config.w32.h"    
    #include "php.h"
  7. 建立php_dbr.cpp.net

    #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. 添加宏定義:

    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可讀數據:

#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:

<?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初始化文件,加入:

[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

相關文章
相關標籤/搜索