Building Swift Barcode Reader with DBR 5.2 for Linux

A few weeks ago, Apple released Swift 4.0 which is available for macOS and Ubuntu 14/16. In this post, I will share how to implement a simple Swift barcode reader (command line tool) with Dynamsoft Barcode Reader SDK for Linux.

Environment

Operating system and SDK

How to enable a shared folder in VMware

When using a virtual machine, a shared folder is handy if you want to use a Windows tool to write code for Linux.

It is easy to add a shared folder via virtual machine settings:

vmware share folder

However, there may be no shared folder listed under /mnt/ in guest OS, such as Ubuntu 14.04. Run the following command to check Ubuntu version:

lsb_release -a

To solve the issue, download and install a patch:

git clone https://github.com/rasa/vmware-tools-patches.git
cd vmware-tools-patches
sudo ./patched-open-vm-tools.sh
sudo vmware-config-tools.pl
sudo reboot

Now you can see the shared folder and files. This way is fine for running swift code as follows:

swift xxx.swift

vmware swift demo

Nevertheless, it will cause errors if you compiling the code with swiftc:

swiftc test.swift
/usr/bin/ld.gold: fatal error: test: Input/output error
clang: error: linker command failed with exit code 1 (use -v to see invocation)
<unknown>:0: error: link command failed with exit code 1 (use -v to see invocation)

How to solve swiftc issue: “<unknown>:0: error: link command failed with exit code 127 (use -v to see invocation)”

To use Swift, you have to install following dependencies beforehand:

sudo apt-get install clang libicu-dev

If you fail to run swiftc, please refer to Vincent Saluzzo’s solution:

sudo apt-get install -y libicu-dev
sudo apt-get install -y clang-3.6
sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-3.6 100
sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-3.6 100

Creating Swift Barcode Reader with C library

Inspired by StackOverflow question – Compile C Code and Expose it to Swift under Linux, I have successfully created a command line barcode reader by linking libDynamsoftBarcodeReader.so.

Create dbr.h with some exposed methods:

#include "DynamsoftBarcodeReader.h"

int initLicense(const char* pszLicense);
char* decodeFile(const char* pFileName, int iFormat);
int createDBR();
void destroyDBR();

Create dbr.c to invoke Dynamsoft Barcode Reader SDK:

#include <stdio.h>
#include "dbr.h"

#define DBR_NO_MEMORY 0
#define DBR_SUCCESS   1

// Barcode reader handler
void* hBarcode = NULL; 

/**
 * Create DBR instance
 */
int createDBR() 
{
    if (!hBarcode) {
        hBarcode = DBR_CreateInstance();
        if (!hBarcode)
        {
            printf("Cannot allocate memory!\n");
            return DBR_NO_MEMORY;
        }
    }

    return DBR_SUCCESS;
}

/**
 * Destroy DBR instance
 */
void destroyDBR()
{
    if (hBarcode) {
        DBR_DestroyInstance(hBarcode);
    }
}

/**
 * Set Dynamsoft Barcode Reader license.  
 * To get valid license, please contact support@dynamsoft.com
 * Invalid license is acceptable. With an invalid license, SDK will return an imcomplete result.
 */
int initLicense(const char* pszLicense)
{
    if (!createDBR()) 
    {
        return -1;
    }

	return DBR_InitLicenseEx(hBarcode, pszLicense);
}

char* createPyResults(SBarcodeResultArray *pResults)
{
    // Get barcode results
    int count = pResults->iBarcodeCount;
	SBarcodeResult** ppBarcodes = pResults->ppBarcodes;
    SBarcodeResult* tmp = NULL;
    int i = 0;
    for (; i < count; i++)
    {
        tmp = ppBarcodes[i];
        printf("Result: %s, Format: %s\n", tmp->pBarcodeData, tmp->pBarcodeFormatString);
    }

    // Release memory
    DBR_FreeBarcodeResults(&pResults);

    return NULL;
}

/**
 * Decode barcode from a file 
 */
char* decodeFile(const char* pFileName, int iFormat)
{
    if (!createDBR()) 
    {
        return NULL;
    }

    // Initialize Dynamsoft Barcode Reader
	int iMaxCount = 0x7FFFFFFF;
	SBarcodeResultArray *pResults = NULL;
	DBR_SetBarcodeFormats(hBarcode, iFormat);
	DBR_SetMaxBarcodesNumPerPage(hBarcode, iMaxCount);

    // Barcode detection
    int ret = DBR_DecodeFileEx(hBarcode, pFileName, &pResults);

    // Wrap results
    return createPyResults(pResults);
}

Create barcode.swift to call C APIs:

let count = CommandLine.arguments.count
if count < 2 {
    print("Please add a file name. E.g. ./barcode test.tif")
}
else {
    let fileName = CommandLine.arguments[1]

    createDBR()
    let ret = initLicense("t0068MgAAAGvV3VqfqOzkuVGi7x/PFfZUQoUyJOakuduaSEoI2Pc8+kMwjrojxQgE5aJphmhagRmq/S9lppTkM4w3qCQezxk=")
    if ret == 0 {
        // Read barcode
        let barcodeTypes : Int32 = 0x3FF | 0x2000000 | 0x8000000 |
                    0x4000000;  // 1D, QRCODE, PDF417, DataMatrix
        decodeFile(fileName, barcodeTypes);
    }
    destroyDBR()
}

Compile dbr.c with gcc:

gcc -c dbr.c

Compile barcode.swift with swiftc:

swiftc -import-objc-header dbr.h barcode.swift dbr.o -o barcode -lDynamsoftBarcodeReader

Run the swift barcode reader:

 ./barcode test.tif

Linux Swift Barcode Reader

Source Code

https://github.com/dynamsoft-dbr/linux-swift-4.0-barcode-reader