通过swig实现go调用c++程序

基于Windows实现swigwin包装c++代码并提供接口给go

Posted by 矫红岩 on November 11, 2018

环境

  1. swigwin-3.0.12
  2. go version go1.11 windows/amd64
  3. visual studio 2015(可选)

关于go的环境参考博客《vscode配置go编译环境》
关于SWIGWIN
Simplified Wrapper and Interface Generator for windows
SWIG是一个通过包装和编译C/c++程序来达到与脚本语言通讯目的的工具。

  1. swig中文网站
  2. swig官网
  3. swigwin下载网址

下载安装swigwin后,将swig.exe文件所在路径(即swigwin-3.0.12的路径)添加到环境变量path中
测试swig是否安装成功:
在终端输入swig,若输出为: Must specify an input file. Use -help for available options.则swigwin安装成功
在swigwin-3.0.12目录下,有个Examples文件夹,里面提供了很多官方例子,如果能调试成功就不用往下看了,如果运行不成功,希望下面的内容可以帮到你。

一个简单的c++代码

《Go与C联编实例》博客中介绍了使用cgo实现c与go的联编
然而,当c的程序引用到c++的STL(Standard Template Library)标准模板库时,cgo不能识别set、vector、map等头文件,所以要借助swig工具进行包装
写一个简单的包含stl的c++程序

/*swig.h*/

#include <vector>
using namespace std;
class swig
{
public:
	vector<int> m_test;
public:
	swig();
	~swig();
public:
	void SetVector(int x);
	void PrintHello();
};


/*swig.cpp*/

#include "swig.h"
swig::swig()
{
	m_test.clear();
}
swig::~swig()
{
}
void swig::SetVector(int x) {
	m_test.push_back(x);
	printf("vector:%d\n", m_test[0]);
}
void swig::PrintHello() {
	printf("hello swig!\n");
}

这个程序很简单,一个PrintHello()函数。一个SetVector(int)函数,用于测试模板库中的vector是否能成功包装
这里我在vs2015的环境测试了一下 image

swig编译

编辑swig脚本,后缀为.i,这里我写的是swigtest.i

%module swigtest
%{
    #include "swig.h"

%}
%include "swig.h"

%module swigtest这行代码是将c++程序包装后的包命名为swigtest等待go调用
swig的编译只需要.h和.cpp文件,不需要vs的工程文件
将.h和.cpp以及.i文件放在同一目录下,然后在终端输入

swig -c++ -cgo -go -intgosize 64 swigtest.i

我的环境是64位的,这里可以将64改为32
运行成功后,会生成.go和_warp.cxx文件,可以看出来swig起到了一个过渡作用,一方面给go提供了接口:.go文件,一方面将c++的代码包装好_warp.cxx文件:

go程序

首先将准备好的.h和.cpp和.go和_warp.cxx四个文件放在%GOPATH/src/test目录下,test可以随意取个名字,放在src下是为了go文件可以读取到package
go程序

package main
import 	"test"
func main() {
	tmp := swigtest.NewSwig()
	swigtest.Swig.PrintHello(tmp)
	swigtest.Swig.SetVector(tmp, 10)
}

在终端输入go bulid执行go文件,会生成swigtest.exe可执行文件 image 我们来看一下go程序
首先import了test目录下的swigtest.go包
这里swigtest.NewSwig()实例化一个对象,相当于上面c++代码中的swig obswig; swigtest.Swig.PrintHello(tmp)以及swigtest.Swig.SetVector(tmp, 10)
相当于c++中的obswig.PrintHello();以及obswig.SetVector(10);