文档章节

使用SWIG桥接Golang和Windows DLL

yushulx
 yushulx
发布于 2015/11/24 09:47
字数 862
阅读 281
收藏 1
点赞 0
评论 0

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

参考

源码

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


© 著作权归作者所有

共有 人打赏支持
yushulx
粉丝 25
博文 86
码字总数 48403
作品 0
杭州
Windows平台下Python使用swig调用C++

步骤0:swig简介 swig是一种可以将C++代码转换为多种脚本语言封装的工具,可以在swig官网www.swig.org下载,解压后将swig.exe的路径添加到环境变量path中即可使用swig 步骤1:准备C++代码 编...

月见樽
01/14
0
0
运行tensorflow报错

D:UsersAdministratorAppDataLocalProgramsPythonPython35python.exe D:/360c/shaozhechen-learntensorflow-master/learntensorflow/RNN_classification.py I c:tfjenkinshomeworkspacerelea......

sca7
2017/03/20
1K
0
C/C++ 和 Python混合编程

链接:https://www.zhihu.com/question/23003213/answer/56121859 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 #include int main(int argc, char *...

sirius_0
04/21
0
0
使用swig工具为go语言生成调用C、C++代码例子

swig开源项目(http://www.swig.org)为多种编程语言提供了相互访问的接口生成工具,这里面也包含了为go语言生成调用C、C++代码的功能。Go语言自带的cgo工具已经支持对C代码的调用,但对C++...

qinhui99
2012/06/29
0
5
简单的Windows Webcam应用:Barcode Reader

在Windows上用WinForm创建一个Webcam应用需要用到DirectShow。DirectShow没有提供C#的接口。如果要用C#开发,需要创建一个桥接DLL。Touchless SDK是一个免费开源的.NET库,对DirectShow进行了...

yushulx
2016/09/20
31
0
Windows上如何使用SWIG (c++ android 示例)

SWIG介绍 SWIG (Simplified Wrapper and Interface Generator) ,即简化包以及接口生成器,为脚本语言(tcl,perl,python等)提供了C和C++的接口。SWIG在1995年在Los Alamos National Laborat...

u014644594
05/28
0
0
编译ngrok的Windows、Mac的客户端

ngrok是一个ddns服务,为内网机器绑定一个公网域名,方便开发调试远程接口(如微信开发)。 之前博文里面写过如何安装ngrok,但是由于公司里面的研发工程师的笔记本有windows本和mac本,所以本...

小南学技术
2016/03/08
0
0
C#脚本实践(三): 集成到游戏

编译 冒似不编译没有.lib可以用 从官方上下载稳定版本的代码, 不要去GitHub直接拉 默认的工程有几个路径和宏之类的不对, 小改一下就可以 如果缺文件, 可以到GitHub的历史版本里去找 编译好了...

长平狐
2012/11/12
397
0
NDK学习笔记(三)SWIG:自动生成JNI代码

编写JNI封装器的代码,还有处理数据类型的转换耗时且费力,所以要用到 SWIG。 SWIG 的全称是 Simplified Wrapper and Interface Generator,它是一个开发工具,在Android Native开发中可被用...

LeoXu
2016/01/02
277
0
Windows 下 gcc + golang 编译 git2go

最近研究用go语言操作git,除了直接走命令行用包,还可以使用的go绑定操作。但是是c语言库,go使用连接c程序,需要的支持。总之过程复杂,摔了一路。 安装 gcc 和 pkg-config 首先是安装和(...

傅小黑
2014/02/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

CVE-2013-0077 堆溢出分析

找了很久才发现这个环境比较容易搭建分析... 环境: 系统---Win XP SP3 漏洞程序:QQPlayer 3.7.892.400 出错DLL:quartz.dll 6.5.2600.5512 调试工具:x32db+gflag.exe 过程: 首先gflag设置...

Explorer0
7分钟前
0
0
python上传文件

//注意 <form action="/login/" method="post" enctype="multipart/form-data"> f=request.FILES.get('fafa') ff=open(f.name,mode='wb') for i in f.chunks(): ff.write(i) ff.close()......

南桥北木
20分钟前
0
0
CISCO VPN Client Reason 442 WIN8/10错误解决方案

http://jdkleo.iteye.com/blog/2163493 引用 http://my.oschina.net/cloudcoder/blog/220391?p={{currentPage 1}} 在使用cisco VPN 客户端登录时,产生Reason 442:Failedto enable Virtual......

chenfj_fer
23分钟前
0
0
信号量有没有容量限制?

之前一直误以为信号量初始化的时候那个初始化的值是信号量的“容量”,昨天同事指出了我的错误,最初我是不相信的,经过以下代码实践,证明了我的错误: Java版: import java.util.concurr...

锟斤拷烫烫烫
27分钟前
0
0
【RocketMQ】Message存储笔记

概述 消息中间件存储分为三种,一是保存在内存中,速度快但会因为系统宕机等因素造成消息丢失;二是保存在内存中,同时定时将消息写入DB中,好处是持久化消息,如何读写DB是MQ的瓶颈;三是内...

SaintTinyBoy
38分钟前
0
0
Android应用Context详解及源码解析

Android应用Context详解及源码解析 本文定位:优质文章收集 本文转载 1 背景 今天突然想起之前在上家公司(做TV与BOX盒子)时有好几个人问过我关于Android的Context到底是啥的问题,所以就马...

lichuangnk
今天
0
0
PostgreSQL的昨天今天和明天

PostgreSQL 是一种非常复杂的对象-关系型数据库管理系统(ORDBMS), 也是目前功能最强大,特性最丰富和最复杂的自由软件数据库系统。有些特性甚至连商业数据库都不具备。 这个起源于伯克利(...

闻术苑
今天
1
0
Mysql对自增主键ID进行重新排序

1,删除原有主键: ALTER TABLE `table_name` DROP `id`; 2,添加新主键字段: ALTER TABLE `table_name` ADD `id` MEDIUMINT( 8 ) NOT NULL FIRST; 3,设置新主键: ALTER TABLE `table_nam......

niithub
今天
0
0
福利篇:免费csdn vip账号分享

分享一个发布免费csdn vip账号的网站:啰嗦vip www.lostvip.com , 各种软件开发类的视频教程:慕课网、动脑学院、黑马各大培训机构VIP视频教程,非常不错!

在水一方发盐人
今天
1
0
Nginx+Tomcat搭建高性能负载均衡集群

一、 工具   nginx-1.8.0   apache-tomcat-6.0.33 二、 目标   实现高性能负载均衡的Tomcat集群:    三、 步骤   1、首先下载Nginx,要下载稳定版:      2、然后解压两个Tom...

码代码的小司机
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部