How to Build PHP Barcode QR Code Reading Extension on Windows and Linux

Xiao Ling - Aug 3 '22 - - Dev Community

When using PHP, you may need to integrate a few C++ libraries sometimes. This article guides you through the process of building a PHP Barcode QR code reading extension with Dynamsoft C++ Barcode SDK on Windows and Linux.

Download

Visual C++ Compiler

According to the PHP online tutorial, the supported Visual C++ compilers are as follows:

Visual C++ 14.0 (Visual Studio 2015) for PHP 7.0 or PHP 7.1.
Visual C++ 15.0 (Visual Studio 2017) for PHP 7.2, PHP 7.3 or PHP 7.4.
Visual C++ 16.0 (Visual Studio 2019) for master.
Enter fullscreen mode Exit fullscreen mode

If you only have Visual Studio 2022 on Windows, you must install the corresponding Visual C++ build tools by Visual Studio Installer.

visual studio build tools

Afterwards, find and run the vcvars64.bat file to set the environment variables.

visual c++ environment varaibles

For example

Here we use PHP 7.4, so we should run Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat via cmd.exe.

Note: It is important to use the matching Visual C++ compiler version. Otherwise, the generated extension cannot be loaded by PHP.

Create PHP Barcode QR Code Extension Project

We scaffold a PHP extension project with the following commands:

cd php-7.4.30-src/ext
php ext_skel.php --ext dbr
cd dbr
Enter fullscreen mode Exit fullscreen mode

Then copy DynamsoftCommon.h, DynamsoftBarcodeReader.h and DBRx64.lib to the project directory.

In dbr.c, we implement the extension functions DBRInitLicense() and DecodeBarcodeFile().

#include "DynamsoftBarcodeReader.h"

static void *hBarcode = NULL;

#define CHECK_DBR()                                         \
if (!hBarcode)                                              \
{                                                           \
    hBarcode = DBR_CreateInstance();                        \
    const char* versionInfo = DBR_GetVersion();             \
    printf("Dynamsoft Barcode Reader %s\n", versionInfo);   \
}


PHP_FUNCTION(DBRInitLicense)
{
    CHECK_DBR();

    char *pszLicense;
    size_t iLen;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &pszLicense, &iLen) == FAILURE)
    {
        RETURN_STRING("Invalid parameters");
    }
    char errorMsgBuffer[512];
    // Click https://www.dynamsoft.com/customer/license/trialLicense/?product=dbr to get a trial license.
    DBR_InitLicense(pszLicense, errorMsgBuffer, 512);
    printf("DBR_InitLicense: %s\n", errorMsgBuffer);
}

PHP_FUNCTION(DecodeBarcodeFile)
{
    CHECK_DBR();

    array_init(return_value);

    // Get Barcode image path
    char *pFileName;
    long barcodeType = 0;
    size_t iLen;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &pFileName, &iLen, &barcodeType) == FAILURE)
    {
        RETURN_STRING("Invalid parameters");
    }

    if (hBarcode)
    {
        int iMaxCount = 0x7FFFFFFF;
        TextResultArray *pResults = NULL;

        // Update DBR params
        PublicRuntimeSettings pSettings = {0};
        DBR_GetRuntimeSettings(hBarcode, &pSettings);
        pSettings.barcodeFormatIds = barcodeType;
        char szErrorMsgBuffer[256];
        DBR_UpdateRuntimeSettings(hBarcode, &pSettings, szErrorMsgBuffer, 256);

        // Barcode detection
        int ret = DBR_DecodeFile(hBarcode, pFileName, "");
        DBR_GetAllTextResults(hBarcode, &pResults);
        if (pResults)
        {
            int count = pResults->resultsCount;
            int i = 0;
            char strLocalization[128];
            for (; i < count; i++)
            {
                zval tmp_array;
                array_init(&tmp_array);
                add_next_index_string(&tmp_array, pResults->results[i]->barcodeFormatString);
                add_next_index_string(&tmp_array, pResults->results[i]->barcodeText);
                add_next_index_stringl(&tmp_array, pResults->results[i]->barcodeBytes, pResults->results[i]->barcodeBytesLength);

                memset(strLocalization, 0, 128);
                sprintf(strLocalization, "[(%d,%d),(%d,%d),(%d,%d),(%d,%d)]", \
                pResults->results[i]->localizationResult->x1, pResults->results[i]->localizationResult->y1, \
                pResults->results[i]->localizationResult->x2, pResults->results[i]->localizationResult->y2, \
                pResults->results[i]->localizationResult->x3, pResults->results[i]->localizationResult->y3, \
                pResults->results[i]->localizationResult->x4, pResults->results[i]->localizationResult->y4); 
                add_next_index_string(&tmp_array, strLocalization);

                add_next_index_zval(return_value, &tmp_array);
            }
            DBR_FreeTextResults(&pResults);
        }
    }
}

static const zend_function_entry dbr_functions[] = {
    PHP_FE(DBRInitLicense, NULL)
    PHP_FE(DecodeBarcodeFile, NULL)
    PHP_FE_END
};
Enter fullscreen mode Exit fullscreen mode

config.w32 for Windows

To link DBRx64.lib, we specify LDFLAGS with linker options in config.w32 file.

ARG_ENABLE('dbr', 'dbr support', 'no');

if (PHP_DBR != 'no') {
    lib_path = "ext\\dbr";

    ADD_FLAG("LDFLAGS", '/libpath:"' + lib_path + '" /DYNAMICBASE "DBRx64.lib"');

    AC_DEFINE('HAVE_DBR', 1, 'dbr support enabled');

    EXTENSION('dbr', 'dbr.c', null, '/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1');
}
Enter fullscreen mode Exit fullscreen mode

config.m4 for Linux

To link shared libraries on Linux, we edit the config.m4 file.

PHP_ARG_ENABLE([dbr],
  [whether to enable dbr support],
  [AS_HELP_STRING([--enable-dbr],
    [Enable dbr support])],
  [no])

if test "$PHP_DBR" != "no"; then
  LIBNAME=DynamsoftBarcodeReader
  LIBSYMBOL=DBR_CreateInstance

  PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
  [
  PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, /usr/lib, DBR_SHARED_LIBADD)
  AC_DEFINE(HAVE_DBRLIB,1,[ ])
  ],[
  AC_MSG_ERROR([wrong dbr lib version or lib not found])
  ],[
  -L$DBR_DIR/$PHP_LIBDIR -lm
  ])

  PHP_SUBST(DBR_SHARED_LIBADD)

  AC_DEFINE(HAVE_DBR, 1, [ Have dbr support ])

  PHP_NEW_EXTENSION(dbr, dbr.c, $ext_shared)
fi
Enter fullscreen mode Exit fullscreen mode

Then copy libDynamicPdf.so, libDynamsoftBarcodeReader.so, libDynamsoftLicenseClient.so to the /usr/bin directory.

Steps to Build and Install the PHP Extension

There are two ways to build the extension. One is to use the source code, and the other is to use the pre-built binaries.

Build the PHP Extension from Source Code

Windows

cd php-7.4.30-src
buildconf
configure --disable-all --enable-cli --enable-dbr
nmake
Enter fullscreen mode Exit fullscreen mode

Linux

cd php-7.4.30-src
./buildconf
./configure --disable-all --enable-cli --enable-dbr
make
Enter fullscreen mode Exit fullscreen mode

By default, the extension is statically linked. To build shared libraries, we can modify the line:

- configure --disable-all --enable-cli --enable-dbr
+ configure --disable-all --enable-cli --enable-dbr=shared
Enter fullscreen mode Exit fullscreen mode

Build the PHP Extension with phpize

Windows

cd php-7.4.30-src/ext/dbr
phpize
configure --enable-dbr
nmake
Enter fullscreen mode Exit fullscreen mode

Linux

cd php-7.4.30-src/ext/dbr
phpize
./configure --enable-dbr
make
Enter fullscreen mode Exit fullscreen mode

Install the PHP Extension with *.dll and *.so Files

Windows

  1. Add extension=dbr to php.ini.
  2. Copy the generated php_dbr.dll to the php/ext/ folder, and copy DynamicPdfx64.dll, DynamsoftBarcodeReaderx64.dll, DynamsoftLicenseClientx64.dll and vcomp110.dll to the PHP root directory.

    install PHP barcode Qr code extension on Windows

Linux

  1. Add extension=dbr to /etc/php/7.4/cli/php.ini.
  2. Run make install.

Test the PHP Barcode QR Code Reader Extension

  1. Apply for a 30-day FREE trial license.
  2. Create a PHP script reader.php that reads the barcode and QR code from a local image.

    <?php
    
    $filename = "AllSupportedBarcodeTypes.tif";
    if (file_exists($filename)) {
        echo "Barcode file: $filename \n";
    
        // Get license key from https://www.dynamsoft.com/customer/license/trialLicense/?product=dbr
        DBRInitLicense("DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ==");
    
        //Best coverage settings
        DBRInitRuntimeSettingsWithString("{\"ImageParameter\":{\"Name\":\"BestCoverage\",\"DeblurLevel\":9,\"ExpectedBarcodesCount\":512,\"ScaleDownThreshold\":100000,\"LocalizationModes\":[{\"Mode\":\"LM_CONNECTED_BLOCKS\"},{\"Mode\":\"LM_SCAN_DIRECTLY\"},{\"Mode\":\"LM_STATISTICS\"},{\"Mode\":\"LM_LINES\"},{\"Mode\":\"LM_STATISTICS_MARKS\"}],\"GrayscaleTransformationModes\":[{\"Mode\":\"GTM_ORIGINAL\"},{\"Mode\":\"GTM_INVERTED\"}]}}");       
    
        $resultArray = DecodeBarcodeFile($filename, 0x3FF | 0x2000000 | 0x4000000 | 0x8000000 | 0x10000000); // 1D, PDF417, QRCODE, DataMatrix, Aztec Code
    
        if (is_array($resultArray)) {
            $resultCount = count($resultArray);
            echo "Total count: $resultCount\n";
            for ($i = 0; $i < $resultCount; $i++) {
                $result = $resultArray[$i];
                echo "Barcode format: $result[0], ";
                echo "value: $result[1], ";
                echo "raw: ", bin2hex($result[2]), "\n";
                echo "Localization : ", $result[3], "\n";
            }
        } else {
            echo "$resultArray[0]";
        }
    } else {
        echo "The file $filename does not exist";
    }
    ?>
    
    
  3. Run the PHP script in the terminal.

    php reader.php
    

    PHP barcode Qr code reader extension

Source Code

https://github.com/yushulx/php-laravel-barcode-qr-reader/tree/main/ext/dbr

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player