使用SWIG橋接Golang和Windows DLL

最近看了下Go語言,利用Dynamsoft Barcode SDK作了一個簡單的Golang條形碼掃描。這裏分享下如何使用SWIG來快速封裝底層C/C++接口。
html

參考原文:How to Use SWIG to Link Windows DLL with Golanggit

做者:Xiao Linggithub

翻譯:yushulxgolang

下載安裝

如何使用SWIG實現Cgo封裝

運行cmd.exe,設置GOPATH:
.net

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>

參考

源碼

https://github.com/dynamsoftsamples/go-barcode-reader

相關文章
相關標籤/搜索