最近看了下Go语言,利用Dynamsoft Barcode SDK做了一个简单的Golang条形码扫描。这里分享下如何使用SWIG来快速封装底层C/C++接口。
参考原文:How to Use SWIG to Link Windows DLL with Golang
作者:Xiao Ling
翻译:yushulx
下载安装
如何使用SWIG实现Cgo封装
运行cmd.exe,设置GOPATH:
set GOPATH=f:\go-project set DBR=<Dynamsoft Barcode Reader Directory>
创建一个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 <windows.h> #include <stdio.h> #include <conio.h> #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 <barcode image>
参考
-
SWIG and Go: http://www.swig.org/Doc3.0/Go.html
源码
https://github.com/dynamsoftsamples/go-barcode-reader
有疑问加站长微信联系(非本文作者)