CGO是C语言和Go语言之间的桥梁,所以GO是没有办法直接使用CPP的类的。
我们可以通过增加一族C语言函数接口作为CPP类和CGO之前的桥梁的,这样
就可以实现C和Go之间的互联。
- my_buffer.h cpp代码内容,定义一个class。
// // Created by fly on 19-11-8. // #include <string> #ifndef TORCH_MY_BUFFER_H #define TORCH_MY_BUFFER_H class MyBuffer { std::string* s_; public: MyBuffer(int size) { this->s_ = new std::string(size, char(' ')); } ~MyBuffer() { delete this->s_; } public: int Size() const { return this->s_->size(); } public: char* Data() { return (char*)this->s_->data(); } }; #endif //TORCH_MY_BUFFER_H
- my_buffer_capi.h 声明c函数接口
// // Created by fly on 19-11-8. // #ifndef TORCH_MY_BUFFER_CAPI_H #define TORCH_MY_BUFFER_CAPI_H typedef void* handle; // 这里定义一下,然后才能在go里面使用这个数据类型 handle NewMyBuffer(int size); void DeleteMyBuffer(handle); char* MyBuffer_Data(handle); int MyBuffer_Size(handle); #endif //TORCH_MY_BUFFER_CAPI_H /* * class 的声明和定义 * * // student.h 进行类的声明 * * class Student { * Student(std::string name, int age); // 和类名相同的函数就是构造函数 ~Student(){} // 析构函数 * void display(); * private: * int num; * char name[20]; * char sex; * } * * * // student.cpp 进行类的定义 * * #include "student.h" * void Student::display(){ * count << "num:" << * } * * Student::Student(std::string name, int age) * : name_(name), * age_(age) {} * * // main.cpp 进行类的调用 * * #include * * int main() { * Student stud; * stud.display(); * return 0; * } * */
- my_buffer_capi.cc 实现c函数接口
// // Created by fly on 19-11-8. // #include "my_buffer.h" extern "C" { #include "my_buffer_capi.h" } handle NewMyBuffer(int size) { return new MyBuffer(size); } void DeleteMyBuffer(handle p) { delete static_cast<MyBuffer*>(p); } char* MyBuffer_Data(handle p) { return static_cast<MyBuffer*>(p)->Data(); } int MyBuffer_Size(handle p) { return static_cast<MyBuffer*>(p)->Size(); }
- my_buffer_capi.go 用go封装函数接口
package main /* #cgo CXXFLAGS: -std=c++11 #include "my_buffer_capi.h" */ import "C" import "unsafe" func cgo_NewMyBuffer(size int) (C.handle) { p := C.NewMyBuffer(C.int(size)) return p } func cgo_DeleteMyBuffer(p C.handle) { C.DeleteMyBuffer(p) } func cgo_MyBuffer_Data(p C.handle) *C.char { return C.MyBuffer_Data(p) } func cgo_MyBuffer_Size(p C.handle) C.int { return C.MyBuffer_Size(p) } type MyBuffer struct { cptr C.handle } func NewMyBuffer(size int) *MyBuffer { return &MyBuffer{ cptr: cgo_NewMyBuffer(size), } } func (p *MyBuffer) Delete(){ cgo_DeleteMyBuffer(p.cptr) } func (p *MyBuffer) Data() []byte { data := cgo_MyBuffer_Data(p.cptr) size := cgo_MyBuffer_Size(p.cptr) return ((*[1 << 31]byte)(unsafe.Pointer(data)))[0:int(size):int(size)] }
- main.go 定义主函数实现调用
package main //#include <stdio.h> import "C" import "unsafe" func main() { buf := NewMyBuffer(1024) defer buf.Delete() copy(buf.Data(), []byte("hellox00")) C.puts((*C.char)(unsafe.Pointer(&(buf.Data()[0])))) }
- demo源码
https://github.com/tangxiongfei/cgo
-
注意事项
需要关闭 unset GO111MODULE,不然依赖回去vendor里面找,导致项目go build 失败
-
打包命令 go build 会自动根据 #include "my_buffer_capi.h" 找到C库并进行打包
- 实例代码