文章系列
【GO】Golang/C++混合编程 - SWIG
【GO】Golang/C++混合编程 - 初识
【GO】Golang/C++混合编程 - 入门
【GO】Golang/C++混合编程 - 基础
【GO】Golang/C++混合编程 - 进阶一
【GO】Golang/C++混合编程 - 进阶二
【GO】Golang/C++混合编程 - 实战
SWIG使用手册
安装
Download:
swig: https://www.swig.org/
- download: https://www.swig.org/survey.html
- download-are: https://www.swig.org/download.html
- download-last-release: swig-xxx.tar.gz
- swig-xxx.tar.gz -> swig-xxx
pcre2: https://www.pcre.org/
- download: https://github.com/PCRE2Project/pcre2/releases
- pcre2-10.44.tar.bz2: https://github.com/PCRE2Project/pcre2/releases/tag/pcre2-10.44
Install:
cp pcre2-10.44.tar.bz2 swig-xxx
cd swig-xxx
./Tools/pcre-build.sh
./configure & make & sudo make install
check:
swig -version
-------------------------------------------------------------------------
SWIG Version 4.2.1
Compiled with g++ [x86_64-apple-darwin23.3.0]
Configured options: +pcre
Please see https://www.swig.org for reporting bugs and further information
-------------------------------------------------------------------------
示例
swig文件命名: xxx.i
接口文件包含 C 函数原型和变量声明
%module 指令定义了 SWIG 将创建的模块的名称。
{%
提供了一个位置,用于将其他代码(如 C 头文件或附加 C 声明)插入到生成的 C 包装器代码中
%}
示例:
./example/example.i
%module example
%{
/* Put headers and other declarations here */
extern double My_variable;
extern int fact(int);
extern int my_mod(int n, int m);
%}
extern double My_variable;
extern int fact(int);
extern int my_mod(int n, int m);
使用
1. swig -go ./example/example.i
2. swig -go -cgo -intgosize 64 -c++ ./example/example.i
具体参数信息: swig -go -help
实战
- C++ 到 Go 的回调实现
# callback.h
#include <cstdio>
#include <iostream>
#include <unistd.h>
// 生成一个代理者
// 虚函数
class Callback {
public:
virtual ~Callback() { std::cout << "Callback::~Callback()" << std::endl; }
virtual void run(iRF_Classification *msg) { std::cout << "C++ Callback, msg: " << msg << " data: " << msg->candidate_num << std::endl; }
};
// 调用者, 没有虚函数的类
class Caller {
private:
Callback *_callback;
public:
Caller(): _callback(0) {}
~Caller() { delCallback(); }
void delCallback() { delete _callback; _callback = 0; }
void setCallback(Callback *cb) { delCallback(); _callback = cb; }
void call() { dowork(); }
void dowork() { for(int i = 0; i < 5; i++) { sleep(1); iRF_Classification *msg = (struct iRF_Classification *)malloc(sizeof(struct iRF_Classification)); msg->candidate_num=1; printf("%p\n", msg); if (_callback) _callback->run(msg); } }
};
callback.i
%module(directors="1") callback
%{
/* Put headers and other declarations here */
#include "callback.h"
%}
%feature("director") Callback;
%include "callback.h"
// callback.go
package callback
import "fmt"
type GoCallback interface {
Callback
deleteCallback()
}
type goCallback struct {
Callback
}
func (cb *goCallback) deleteCallback() {
DeleteDirectorCallback(cb.Callback)
}
type overwrittenMethodsOnCallback struct {
p Callback
}
func NewGoCallback() GoCallback {
om := &overwrittenMethodsOnCallback{}
om.p = NewDirectorCallback(om)
return &goCallback{Callback: om.p}
}
func DeleteGoCallback(cb GoCallback) {
cb.deleteCallback()
}
func (om *overwrittenMethodsOnCallback) Run(msg IRF_Classification) {
fmt.Printf("[Run] Go Callback, msg:%+v, data:%+v\n", &msg, (msg).GetCandidate_num())
}
不足
- swig 脚本语言自动生成 cgo 代码,使用起来比较方便,但是很难维护
- swig-go 语言社区并不活跃,很多 C++ 新特性无法支持