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

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

Prerequisites

Visual C++ Compiler for Building PHP Extension

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.

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

visual studio build tools

Afterward, locate and execute 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 will be incompatible.

Creating PHP Barcode QR Code Extension Project

We scaffold a PHP extension project using the following commands:

cd php-7.4.30-src/ext
php ext_skel.php --ext dbr
cd dbr

Then, copy DynamsoftCommon.h, DynamsoftBarcodeReader.h and DBRx64.lib to the project root 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=dcv&package=cross-platform
	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
};

config.w32 for Windows

To link DBRx64.lib, we specify LDFLAGS with linker options in the 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');
}

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

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

Steps to Build and Install the PHP Extension

You can build the extension in two ways: from the source code or by using 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

Linux

cd php-7.4.30-src
./buildconf
./configure --disable-all --enable-cli --enable-dbr
make

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

Build the PHP Extension with phpize

Windows

cd php-7.4.30-src/ext/dbr
phpize
configure --enable-dbr
nmake

Linux

cd php-7.4.30-src/ext/dbr
phpize
./configure --enable-dbr
make

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

Windows

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

    install PHP barcode Qr code extension on Windows

    Alternatively, you can add the folder containing the DLLs to the system path for easier management.

Linux

  1. Add extension=dbr to /etc/php/7.4/cli/php.ini.
  2. Execute sudo make install to install the extension system-wide.

Test the PHP Barcode QR Code Reader Extension

  1. Create a PHP script named reader.php that reads barcodes and QR codes from a local image. Replace LICENSE-KEY with your own license key.

     <?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=dcv&package=cross-platform
         DBRInitLicense("LICENSE-KEY");
    
         //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";
     }
     ?>
    
    
  2. Execute 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