golang继承swig导出的c++基类

项目原来使用c++实现了底层逻辑,为了方便业务方使用,现在需要支持golang语言的sdk。经过调研了解到swig可以将C++导出接口类供其他脚本语言或者高级编程语言调用,本文基于swig实现C++类导出golang的接口类,然后在golang中利用struct实现继承。

为了更好地演示,本文利用简单的C++类进行描述。

首先定义C++的基类和一个辅助类,后面go会利用struct派生于基类BaseCase,辅助类用于调用派生类的函数。

// BaseCase.h
#include <string>
#include <iostream>

using namespace std;


class BaseCase
{
public:
    BaseCase() {}
    virtual ~BaseCase() {}
    BaseCase(const BaseCase& rhs) {
        m_caseName = rhs.m_caseName;
    }
    virtual void Run() {cout << "run the case in baseCase class." << endl;}

public:
    string m_caseName;
};

class CaseRunner
{
public:
    BaseCase* _baseCase_;

public:
    CaseRunner():_baseCase_(0) {}
    void RegisterCase(BaseCase *bc) {_baseCase_ = bc;}
    void run() {if (_baseCase_) _baseCase_->Run();}
};

编写swig.i文件

// swig.i
%module(directors="1") baseCase
%{
 #include "BaseCase.h"
%}
%include "std_string.i"
%include "std_map.i"
%feature("director") BaseCase;
%include "BaseCase.h"

然后利用swig命令行将导出BaseCase和CaseRunner的Golang接口类

// swig command line
swig -go -cgo -intgosize 64 -c++ swig.i

执行完上面个的命令之后,会生成对应的swig_wrap.cxx,swig_wrap.h,baseCase.go

然后编写test.go文件

package main

import (
    "fmt"
    . "baseCase"
)

type TestCase1Class interface {
    BaseCase
    deleteBaseCase()
    IsTestCase1Class()
}

type testCase1Class struct {
	BaseCase  // 这个是swig导出来的interface接口
}

func (caseClass_ *testCase1Class) IsTestCase1Class() {}

func (caseClass_ *testCase1Class) deleteBaseCase() {
    DeleteDirectorBaseCase(caseClass_.BaseCase)
}

type TestClass struct {
	p BaseCase
}

func NewGoTestCase1Class() TestCase1Class {
    om := &TestClass{}
    p := NewDirectorBaseCase(om)
    om.p = p
    return &testCase1Class{BaseCase: p}
}

func (caseClass_ *TestClass) Run() {
    fmt.Println("start to run caseClass ...")
    caseClass_.case1()
    caseClass_.case2()
}

// case1
func (caseClass_ *TestClass) case1() {
	fmt.Println("run caseClass 1")
}

// case2
func (caseClass_ *TestClass) case2() {
	fmt.Println("run caseClass 2")
}

func main() {
    goCase := NewGoTestCase1Class()
    caseRuner := NewCaseRunner()
    caseRuner.RegisterCase(goCase)
    caseRuner.Run()
    return
}

执行打包命令,即可以编译一个test的可执行文件

>> go build test.go
>> ./test
start to run caseClass ...
run caseClass 1
run caseClass 2