Go語言與C/C++進行互動

2020-07-16 10:05:23
Go語言是類C的語言,與C語言有著千絲萬縷的聯絡,在Go語言的程式碼中可以直接呼叫C語言程式碼,但不支援直接呼叫 C++。

Go 呼叫 C/C++ 的方式:
  • C:直接呼叫 C API;
  • C++:通過實現一層封裝的 C 介面來呼叫 C++ 介面。

呼叫C語言

在Go語言的原始碼中直接宣告C語言程式碼是比較簡單的應用情況,可以直接使用這種方法將C語言程式碼直接寫在Go語言程式碼的註釋中,並在註釋之後緊跟import "C",通過C.xx 來參照C語言的結構和函數,如下所示:
package main

/*
#include <stdio.h>
#include <stdlib.h>

typedef struct {
    int id;
}ctx;

ctx *createCtx(int id) {
    ctx *obj = (ctx *)malloc(sizeof(ctx));
    obj->id = id;
    return obj;
}
*/
import "C"
import (
    "fmt"
)

func main() {
    var ctx *C.ctx = C.createCtx(100)
    fmt.Printf("id : %dn", ctx.id)
}
執行結果如下:

go run main.go
id : 100

通過封裝實現 C++ 介面的呼叫

首先我們新建一個 cpp 目錄,並將 C++ 的程式碼放置在 cpp 目錄下,C++ 程式碼需要提前編譯成動態庫(拷貝到系統庫目錄可以防止 go 找不到動態庫路徑),go 程式執行時會去連結。

├── cpp
│   ├── cwrap.cpp
│   ├── cwrap.h
│   ├── test.cpp
│   └── test.h
└── main.go

其中 test.cpp 和 test.h 是 C++ 介面的實現;cwrap.h 和 cwrap.cpp 是封裝的 C 介面的實現。

1) test.h

#ifndef __TEST_H__
#define __TEST_H__

#include <stdio.h>

class Test {
public:
    void call();
};

#endif

2) test.cpp

#include "test.h"

void Test::call() {
    printf("call from c++ languagen");
}

cwrap.cpp

#include "cwrap.h"
#include "test.h"

void call() {
    Test ctx;
    ctx.call();
}

3) cwrap.h

#ifndef __CWRAP_H__
#define __CWRAP_H__

#ifdef __cplusplus
extern "C" {
#endif
void call();

#ifdef __cplusplus
}
#endif

#endif

4) main.go

package main

/*
#cgo CFLAGS: -Icpp

#cgo LDFLAGS: -lgotest

#include "cwrap.h"
*/
import "C"

func main() {
    C.call()
}