• 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(''));
        }
        ~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]))))
    }
    
      需要关闭 unset GO111MODULE,不然依赖回去vendor里面找,导致项目go build 失败
    • 打包命令  go build 会自动根据 #include "my_buffer_capi.h" 找到C库并进行打包
    • 实例代码
      
      
    不断学习,做更好的自己!
  • 相关阅读:
    🍖名称空间与作用域
    🍖文件打开模式 "t"
    🍖函数参数
    【转】LINQ中的Aggregate语法
    【转】c#中string.trimstart() 和string.trimend() 的用法
    1094 和为k的连续区间(暴力)
    1095 Anigram单词
    1031 骨牌覆盖 (斐波拉契数列)
    最长公共子序列(模板 LCSL)
    1092 回文字符串(LCSL_DP)
  • 原文地址:https://www.cnblogs.com/moontower/p/11823297.html
Copyright © 2020-2023  润新知