CGO 不能直接支持 C++,只能靠 C 来嫁接,所以也不能支持 C++特有的类型,比如引用参数、对象类。如果把上一章节的 Say 函数使用 C++ 实现,其实和 C、C++ 配合没什么区别,主要使用 extern “C” 让 cpp 生成的函数符合 C 的调用规范,代码如下:
// say.h
void Say(const char* s);
// say.cpp
#include <iostream>
extern "C" {
#include "say.h"
}
void Say(const char* s) {
std::cout << s;
}
// main.go
package main
//#include "say.h"
import "C"
func main() {
C.Say(C.CString("hi, cgo"))
}
但是使用 C++类就不同了,先说结论,使用 C++ 类的步骤:
1. 用纯 C 来包装 C++ 的类对象行为
2. 将包装的 C 函数映射到 Go 的函数
3. 调用 Go 的包装函数
下面举例,首先写一个 Person 的 C++ 类(使用 struct),有 2 个属性(name、age)和一个 方法(Say):
//person.h
#define _GLIBCXX_USE_CXX11_ABI 0 // 禁用 C++ 11 的新类
#include <iostream>
#include <string>
using namespace std;
struct Person
{
private:
string name;
int age;
public:
Person(string name, int age);
void Say();
};
Person::Person(string name, int age)
{
this->name = name;
this->age = age;
}
void Person::Say()
{
cout << "name: " << this->name << ", age: " << this->age;
}
第二步,编写包装的 C 函数,定义了 C 的类型 Person_T,把创建对象、调用 Say、释放对象都定义了 C 风格的函数:
// person_cgo.h
typedef struct Person_T Person_T;
Person_T* NewPerson(const char* name, int age);
void PersonSay(Person_T *person);
void DeletePerson(Person_T* person);
第三步,在 cpp 文件里使实现 C 的函数,注意新的类型 Person_T 继承 C++ 类型 Person:
// person_cgo.cpp
#include "person.h"
extern "C"
{
#include "person_cgo.h"
}
struct Person_T : Person
{
Person_T(const char *name, int age) : Person(name, age) {}
~Person_T() {}
};
Person_T *NewPerson(const char *name, int age)
{
return new Person_T(name, age);
}
void PersonSay(Person_T *person)
{
person->Say();
}
void DeletePerson(Person_T *person)
{
delete person;
}
第三步,就是使用 import “C” 来调用了,定义了 CGO_NewPerson、CGO_PersonSay、CGO_DeletePerson 来映射:
// main.go
package main
//#include "person_cgo.h"
import "C"
type CGO_Person_T = C.Person_T
func CGO_NewPerson(name string, age int) *CGO_Person_T {
return C.NewPerson(C.CString(name), C.int(age))
}
func CGO_PersonSay(person *CGO_Person_T) {
C.PersonSay(person)
}
func CGO_DeletePerson(person *CGO_Person_T) {
C.DeletePerson(person)
}
func main() {
person := CGO_NewPerson("zhangsan", 20)
CGO_PersonSay(person)
CGO_DeletePerson(person)
}
执行 go run . 显示:
callcppclass[master*] go run .
name: zhangsan, age: 20
本章节的代码