前言:Golang调用是通过cgo完成的,Golang调用C++,则需要将C++函数导出包装为C函数,然后再通过cgo完成调用,话不多说,直接给出调用示例。

开发工具:Clion,Goland

首先msys2,通过msys2安装mingw,cmake等开发C,C++的环境,golang开发环境自行搭建。

本次示例目录结构如下:

-->cgo 项目根目录

---->cshare C项目根目录

------>cplusplus C++项目根目录

-------->library.h C++库头文件

-------->library.cpp C++库源文件

-------->library_wrapper.h C++库包装头文件

-------->library_wrapper.cpp C++库包装源文件

------>library.h C库头文件

------>library.c C库源文件

------>library_wrapper.h C++库头文件

------>main.c C执行文件

------>CMakeList.txt CMake文件

---->add.go  golang调用C++示例

---->file_reader.go golang调用C示例

 

Golang调用C示例过程说明

1.在library.h中声明一个golang要调用的函数,如下所示

#ifndef CSHARE_LIBRARY_H
#define CSHARE_LIBRARY_H

void hello(); //简单测试示例
void readFile(const char* filename); //golang通过C读取任意位置文件,读取255个字符
int add(int x,int y);//golang通过C调用C++的加法

#endif //CSHARE_LIBRARY_H

2.在library.c中实现library.h中声明的函数,如下所示

#include "library_wrapper.h"
#include "library.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

void hello() {
    printf("hello,world!\n");
}

void readFile(const char *filename) {
    FILE *fp;
    char buff[255];
    fp = fopen(filename, "r");
    if (fp == NULL) {
        printf("Filename:%s,Open file failed:%s\n", filename, strerror(errno));
        return;
    }
    fgets(buff, 255, (FILE *) fp);
    printf("%s\n", buff);
    fclose(fp);
}

int add(int x, int y) {
    int sum = addWrapper(x, y);
    return sum;
}

3.在file_reader.go中实现对C方法readFile的调用

package main

//#include "cshare/library.c"
import "C"
import (
    "flag"
    "fmt"
    "os"
)

func main() {
    var help bool
    var file string
    var len int
    flag.IntVar(&len,"len",0,"golang c file reader will read this file with this len")
    flag.StringVar(&file, "file", "", `golang c file reader will read this file`)
    flag.BoolVar(&help, "help", false, "show golang c file reader usage")
    flag.Usage = func() {
        _, _ = fmt.Fprintln(os.Stdin, `golang c file reader 1.0`)
        _, _ = fmt.Fprintln(os.Stdin, `options:`)
        flag.PrintDefaults()
    }
    flag.Parse()
    if help {
        flag.Usage()
    }
    if file != "" {
        C.readFile(C.CString(file))
    }
}

至此Golang调用C的过程结束,在Golang中调用C库源文件,不需要调用C库的头文件,因为C库源文件中已经导入过C库头文件,所以不用再Golang文件导入了。