2019独角兽企业重金招聘Python工程师标准>>>
最近看了下Go语言,利用Dynamsoft Barcode SDK做了一个简单的Golang条形码扫描。这里分享下如何使用SWIG来快速封装底层C/C++接口。
参考原文:How to Use SWIG to Link Windows DLL with Golang
作者:Xiao Ling
翻译:yushulx
下载安装
mingw-w64
SWIG
Go
Dynamsoft Barcode Reader
如何使用SWIG实现Cgo封装
运行cmd.exe,设置GOPATH:
set GOPATH=f:\go-project
set DBR=
创建一个package:
mkdir %GOPATH%\src\github.com\dynamsoftsamples\go-barcode-reader\dbr
从SDK目录中把DynamsoftBarcodeReaderx64.dll拷贝到%GOPATH%\src\github.com\dynamsoftsamples\go-barcode-reader\dbr\bin。
接下来把头文件都拷贝到%GOPATH%\src\github.com\dynamsoftsamples\go-barcode-reader\dbr\include。
创建dbr.c:
#include
#include
#include
#include "include/If_DBR.h"
__int64 GetFormat(int iIndex)
{
__int64 llFormat = 0;
switch(iIndex)
{
case 1:
llFormat = OneD | QR_CODE | PDF417 |DATAMATRIX;
break;
case 2:
llFormat = OneD;
break;
case 3:
llFormat = QR_CODE;
break;
case 4:
llFormat = CODE_39;
break;
case 5:
llFormat = CODE_128;
break;
case 6:
llFormat = CODE_93;
break;
case 7:
llFormat = CODABAR;
break;
case 8:
llFormat = ITF;
break;
case 9:
llFormat = INDUSTRIAL_25;
break;
case 10:
llFormat = EAN_13;
break;
case 11:
llFormat = EAN_8;
break;
case 12:
llFormat = UPC_A;
break;
case 13:
llFormat = UPC_E;
break;
case 14:
llFormat = PDF417;
break;
case 15:
llFormat = DATAMATRIX;
break;
default:
break;
}
return llFormat;
}
const char * GetFormatStr(__int64 format)
{
if (format == CODE_39)
return "CODE_39";
if (format == CODE_128)
return "CODE_128";
if (format == CODE_93)
return "CODE_93";
if (format == CODABAR)
return "CODABAR";
if (format == ITF)
return "ITF";
if (format == UPC_A)
return "UPC_A";
if (format == UPC_E)
return "UPC_E";
if (format == EAN_13)
return "EAN_13";
if (format == EAN_8)
return "EAN_8";
if (format == INDUSTRIAL_25)
return "INDUSTRIAL_25";
if (format == QR_CODE)
return "QR_CODE";
if (format == PDF417)
return "PDF417";
if (format == DATAMATRIX)
return "DATAMATRIX";
return "UNKNOWN";
}
int decode_file(const char *pszImageFile)
{
if (!pszImageFile)
{
return -1;
}
// const char *pszImageFile = "f:\\AllSupportedBarcodeTypes.tif";
__int64 llFormat = (OneD | QR_CODE | PDF417 | DATAMATRIX);
char pszBuffer[512] = {0};
int iMaxCount = 0x7FFFFFFF;
int iIndex = 0;
ReaderOptions ro = {0};
pBarcodeResultArray paryResult = NULL;
int iRet = -1;
char * pszTemp = NULL;
char * pszTemp1 = NULL;
unsigned __int64 ullTimeBegin = 0;
unsigned __int64 ullTimeEnd = 0;
size_t iLen;
FILE* fp = NULL;
int iExitFlag = 0;
DBR_InitLicense("38B9B94D8B0E2B41DB1CC80A58946567");
// Read barcode
ullTimeBegin = GetTickCount();
ro.llBarcodeFormat = llFormat;
ro.iMaxBarcodesNumPerPage = iMaxCount;
iRet = DBR_DecodeFile(pszImageFile, &ro, &paryResult);
ullTimeEnd = GetTickCount();
// Output barcode result
pszTemp = (char*)malloc(4096);
if (iRet != DBR_OK)
{
sprintf(pszTemp, "Failed to read barcode: %s\r\n", DBR_GetErrorString(iRet));
printf(pszTemp);
free(pszTemp);
return 0;
}
if (paryResult->iBarcodeCount == 0)
{
sprintf(pszTemp, "No barcode found. Total time spent: %.3f seconds.\r\n", ((float)(ullTimeEnd - ullTimeBegin)/1000));
printf(pszTemp);
free(pszTemp);
DBR_FreeBarcodeResults(&paryResult);
return 0;
}
sprintf(pszTemp, "Total barcode(s) found: %d. Total time spent: %.3f seconds\r\n\r\n", paryResult->iBarcodeCount, ((float)(ullTimeEnd - ullTimeBegin)/1000));
printf(pszTemp);
for (iIndex = 0; iIndex < paryResult->iBarcodeCount; iIndex++)
{
sprintf(pszTemp, "Barcode %d:\r\n", iIndex + 1);
printf(pszTemp);
sprintf(pszTemp, " Page: %d\r\n", paryResult->ppBarcodes[iIndex]->iPageNum);
printf(pszTemp);
sprintf(pszTemp, " Type: %s\r\n", GetFormatStr(paryResult->ppBarcodes[iIndex]->llFormat));
printf(pszTemp);
pszTemp1 = (char*)malloc(paryResult->ppBarcodes[iIndex]->iBarcodeDataLength + 1);
memset(pszTemp1, 0, paryResult->ppBarcodes[iIndex]->iBarcodeDataLength + 1);
memcpy(pszTemp1, paryResult->ppBarcodes[iIndex]->pBarcodeData, paryResult->ppBarcodes[iIndex]->iBarcodeDataLength);
sprintf(pszTemp, " Value: %s\r\n", pszTemp1);
printf(pszTemp);
free(pszTemp1);
sprintf(pszTemp, " Region: {Left: %d, Top: %d, Width: %d, Height: %d}\r\n\r\n",
paryResult->ppBarcodes[iIndex]->iLeft, paryResult->ppBarcodes[iIndex]->iTop,
paryResult->ppBarcodes[iIndex]->iWidth, paryResult->ppBarcodes[iIndex]->iHeight);
printf(pszTemp);
}
free(pszTemp);
DBR_FreeBarcodeResults(&paryResult);
return 0;
}
创建对应的dbr.i:
/* dbr.i */
%module dbr
%{
/* Put header files here or function declarations like below */
extern int decode_file(const char *pszImageFile);
%}
extern int decode_file(const char *pszImageFile);
生成dbr.go和dbr_wrapper.c:
swig -go -cgo -intgosize 32 dbr.i
这个时候看到的目录结构:
打开dbr.go,添加头文件和库文件路径:
#cgo CFLAGS: -I .
#cgo LDFLAGS: -L ./bin -lDynamsoftBarcodeReaderx64
切换路径到根目录%GOPATH%,编译安装:
go install github.com\dynamsoftsamples\go-barcode-reader\dbr
如果在package目录中,可以直接使用:
go install
这个时候会在%GOPATH%\pkg\windows_amd64\github.com\dynamsoftsamples\go-barcode-reader中生成一个包dbr.a。
Windows上实现Golang条码扫描应用
创建%GOPATH%\github.com\dynamsoftsamples\go-barcode-reader\BarcodeReader\BarcodeReader.go:
package main
import (
"github.com/dynamsoftsamples/go-barcode-reader/dbr"
"os"
)
func main() {
if len(os.Args) == 1 { // read the default image
dbr.Decode_file("AllSupportedBarcodeTypes.tif")
} else {
dbr.Decode_file(os.Args[1])
}
}
拷贝DynamsoftBarcodeReaderx64.dll到%GOPATH%\bin。
在根目录使用下面的命令行生成可执行文件:
go install github.com\dynamsoftsamples\go-barcode-reader\BarcodeReader
测试程序:
%GOPATH%bin\BarcodeReader.exe
参考
Cgo: https://github.com/golang/go/wiki/cgo
SWIG and Go: http://www.swig.org/Doc3.0/Go.html
源码
https://github.com/dynamsoftsamples/go-barcode-reader