Go调用cpp类方式一

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('\0'));
    }
    ~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("hello\x00"))
	C.puts((*C.char)(unsafe.Pointer(&(buf.Data()[0]))))
}
  需要关闭 unset GO111MODULE,不然依赖回去vendor里面找,导致项目go build 失败
  • 打包命令  go build 会自动根据 #include "my_buffer_capi.h" 找到C库并进行打包
  • 实例代码
    
    
posted @ 2019-11-08 21:09  想飞的枫叶  阅读(1243)  评论(0编辑  收藏  举报