使用SWIG桥接Golang和Windows DLL

来源:互联网 发布:ksp 原版阻力算法 编辑:程序博客网 时间:2024/05/16 01:59

最近看了下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-projectset 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>

参考

  • 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


0 0
原创粉丝点击