How to Build Golang Barcode QR Code Reader with Dynamsoft C++ Barcode SDK

Prerequisites

Creating a Go Module for Reading Barcode and QR Code

Dynamsoft C++ Barcode Reader SDK supports Windows(x86, x64), Linux(x64, ARM32, ARM64), and macOS(x64, ARM64). Here we only focus on Windows and Linux.

Initialize a Go Module Project

According to the Go documentation, we create a Go module named goBarcodeQrSDK in the terminal:

mkdir goBarcodeQrSDK
cd goBarcodeQrSDK
go mod init github.com/yushulx/goBarcodeQrSDK
module github.com/yushulx/goBarcodeQrSDK

go 1.19

Link Dynamsoft C++ Barcode Reader Libraries to Go

  1. Create a lib folder.
  2. Copy shared libraries and header files of Dynamsoft C++ Barcode Reader SDK to the lib folder. Change DynamsoftBarcodeReaderx64.dll to DynamsoftBarcodeReader.dll to make the linking work on both Windows and Linux.
  3. In your text editor, create a reader.go file.
  4. Add cgo LDFLAGS and include C++ header files in the reader.go file.
package goBarcodeQrSDK

import (
"unsafe"

// #include <stdlib.h>
// #include <lib/DynamsoftBarcodeReader.h>
// #include <lib/DynamsoftCommon.h>
// #include <lib/bridge.c>
// #cgo LDFLAGS: -L ./lib -lDynamsoftBarcodeReader -Wl,-rpath=./lib
"C"
)

Calling Dynamsoft C++ Barcode Reader Functions in Go

To implement a barcode QR code reader with Dynamsoft Barcode SDK, we need to call the following functions:

  • DBR_InitLicense: Set a valid license key to activate the SDK.
func InitLicense(license string) (int, string) {
c_license := C.CString(license)
defer C.free(unsafe.Pointer(c_license))

errorBuffer := make([]byte, 256)
ret := C.DBR_InitLicense(c_license, (*C.char)(unsafe.Pointer(&errorBuffer[0])), C.int(len(errorBuffer)))

return int(ret), string(errorBuffer)
}
  • DBR_CreateInstance: Create an instance of the barcode reader.
type BarcodeReader struct {
handler unsafe.Pointer
}

func CreateBarcodeReader() *BarcodeReader {
handler := C.DBR_CreateInstance()
if handler == nil {
return nil
}
return &BarcodeReader{handler: handler}
}
  • DBR_InitRuntimeSettingsWithFile: Load a parameter template file for customizing the barcode scanning algorithm.
func (reader *BarcodeReader) LoadTemplateFile(params string) (int, string) {
errorBuffer := make([]byte, 256)
ret := C.DBR_InitRuntimeSettingsWithFile(reader.handler, C.CString(params), C.CM_OVERWRITE, (*C.char)(unsafe.Pointer(&errorBuffer[0])), C.int(len(errorBuffer)))
return int(ret), string(errorBuffer)
}
  • DBR_DecodeFile: Read barcode QR code from an image file and return the results.
func (reader *BarcodeReader) DecodeFile(filePath string) (int, []Barcode) {
c_filePath := C.CString(filePath)
defer C.free(unsafe.Pointer(c_filePath))
template := C.CString("")
defer C.free(unsafe.Pointer(template))

var barcodes = []Barcode{}
ret := C.DBR_DecodeFile(reader.handler, c_filePath, template)

if ret != 0 {
return int(ret), barcodes
}

var resultArray *C.TextResultArray
C.DBR_GetAllTextResults(reader.handler, &resultArray)

if resultArray.resultsCount > 0 {
for i := 0; i < int(resultArray.resultsCount); i++ {
barcode := Barcode{}
result := C.getTextResultPointer(resultArray, C.int(i))

format := C.getFormatString(result)
barcode.Format = C.GoString(format)

text := C.getText(result)
barcode.Text = C.GoString(text)

localization := C.getLocalizationPointer(result)
barcode.X1 = int(localization.x1)
barcode.Y1 = int(localization.y1)
barcode.X2 = int(localization.x2)
barcode.Y2 = int(localization.y2)
barcode.X3 = int(localization.x3)
barcode.Y3 = int(localization.y3)
barcode.X4 = int(localization.x4)
barcode.Y4 = int(localization.y4)

barcodes = append(barcodes, barcode)
}
}

C.DBR_FreeTextResults(&resultArray)
return int(ret), barcodes
}
type Barcode struct {
Text string
Format string
X1 int
Y1 int
X2 int
Y2 int
X3 int
Y3 int
X4 int
Y4 int
}
#include <stdio.h>
#include <stdlib.h>
#include "DynamsoftBarcodeReader.h"

TextResult *getTextResultPointer(TextResultArray *resultArray, int offset) {
return resultArray->results[offset];
}

LocalizationResult *getLocalizationPointer(TextResult *result) {
return result->localizationResult;
}

const char *getText(TextResult *result) {
return result->barcodeText;
}

Test the Go Module

We create a goBarcodeQrSDK_test.go file to test the Go module.

package goBarcodeQrSDK

import (
"fmt"
"testing"
"time"
)

func TestInitLicense(t *testing.T) {
ret, _ := InitLicense("DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ==")
if ret != 0 {
t.Fatalf(`initLicense("") = %d`, ret)
}
}

func TestCreateBarcodeReader(t *testing.T) {
obj := CreateBarcodeReader()
if obj == nil {
t.Fatalf(`Failed to create instance`)
}
}

func TestLoadTemplateFile(t *testing.T) {
obj := CreateBarcodeReader()
ret, _ := obj.LoadTemplateFile("template.json")
if ret != 0 {
t.Fatalf(`LoadTemplateFile() = %d`, ret)
}
}

func TestDecodeFile(t *testing.T) {
obj := CreateBarcodeReader()
obj.SetParameters("{\"ImageParameter\":{\"BarcodeFormatIds\":[\"BF_ONED\",\"BF_PDF417\",\"BF_QR_CODE\",\"BF_DATAMATRIX\"],\"BarcodeFormatIds_2\":null,\"Name\":\"sts\",\"RegionDefinitionNameArray\":[\"region0\"]},\"RegionDefinition\":{\"Bottom\":100,\"Left\":0,\"MeasuredByPercentage\":1,\"Name\":\"region0\",\"Right\":100,\"Top\":0}}")
ret, _ := obj.DecodeFile("test.png")
if ret != 0 {
t.Fatalf(`DecodeFile() = %d`, ret)
}
}

Implementing Golang Barcode QR Code Reader

Create a new module in another directory and add the goBarcodeQrSDK module as a dependency locally.

mkdir example
go mod init example.com/test
go mod edit -replace github.com/yushulx/goBarcodeQrSDK=../
go mod tidy
module example.com/test

go 1.19

replace github.com/yushulx/goBarcodeQrSDK => ../

require github.com/yushulx/goBarcodeQrSDK v0.0.0-00010101000000-000000000000
- replace github.com/yushulx/goBarcodeQrSDK => ../
+ require github.com/yushulx/goBarcodeQrSDK v1.0.3
package main

import (
"fmt"
"os"
"time"

"github.com/yushulx/goBarcodeQrSDK"
)

func main() {
filename := "test.png"
license := "DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ=="
template := "template.json"

ret, errMsg := goBarcodeQrSDK.InitLicense(license)
if ret != 0 {
fmt.Println(`initLicense(): `, ret)
fmt.Println(errMsg)
return
}
obj := goBarcodeQrSDK.CreateBarcodeReader()
ret, errMsg = obj.LoadTemplateFile(template)
if ret != 0 {
fmt.Println(`LoadTemplateFile(): `, ret)
fmt.Println(errMsg)
}
startTime := time.Now()
ret, barcodes := obj.DecodeFile(filename)
elapsed := time.Since(startTime)
fmt.Println("DecodeFile() time cost: ", elapsed)

if ret != 0 {
fmt.Printf(`DecodeFile() = %d`, ret)
}

for i := 0; i < len(barcodes); i++ {
barcode := barcodes[i]
fmt.Println(barcode.Text)
fmt.Println(barcode.Format)
fmt.Println(barcode.X1)
fmt.Println(barcode.Y1)
fmt.Println(barcode.X2)
fmt.Println(barcode.Y2)
fmt.Println(barcode.X3)
fmt.Println(barcode.Y3)
fmt.Println(barcode.X4)
fmt.Println(barcode.Y4)
fmt.Println("--------------")
}
}
go run .
go build -o ../reader
cd ..
./reader test.png

Deploying Golang Barcode QR Reader to Docker

  1. Create a Dockerfile file in the root directory of the project:
FROM golang:1.19
COPY . /usr/src/myapp
WORKDIR /usr/src/myapp/example
COPY ../lib/ /usr/lib/x86_64-linux-gnu/
RUN cp test.png /usr/local/bin/
RUN cp template.json /usr/local/bin/
RUN go mod download
RUN go build -v -o /usr/local/bin/reader
CMD [ "reader"]
docker build -t golang-barcode-qr-reader .
docker run -it --rm -v <image-folder>:/app golang-barcode-qr-reader reader /app/<image-file> <license-key> <template-file>

Published Docker Image

docker run -it --rm -v <image-folder>:/app yushulx/golang-barcode-qr-reader:latest reader /app/<image-file> <license-key> <template-file>

Source Code

https://github.com/yushulx/goBarcodeQrSDK

--

--

Manager of Dynamsoft Open Source Projects | Tech Lover

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store