在日常开发中,我们有时会遇到这样的场景:需要用C语言调用Go语言编写的函数。这时,//export 指令就派上了用场。

什么是//export?

//export 是Go语言中的一个特殊注释指令,用于将Go函数导出为C语言函数,使C代码能够直接调用Go函数。

当我们在Go函数前添加 //export 注释时,Go编译器会生成相应的C语言头文件,其中包含该函数的C接口声明。这样,C程序就可以像调用普通C函数一样调用Go函数了。

基本语法规则

使用 //export 有两个基本要求:

  1. 必须在函数声明前添加 //export 函数名 注释
  2. 必须导入C包(import "C"

需要注意的是,//export 和函数名之间不能有空格,且 // 后直接跟 export

简单示例:一个可运行的加法函数

下面是一个完整且可运行的示例,展示了如何将Go函数导出给C调用:

// add.go
package main

import "C"

//export Add
func Add(a, b C.int) C.int {
    return a + b
}

func main() {
    // 此处留空,但必须有main函数
}

将上述代码保存为 add.go,然后使用以下命令编译:

go build -buildmode=c-shared -o add.so add.go

此命令会生成 add.so(动态库)和 add.h(头文件)两个文件。

C代码调用示例

以下是C语言调用上述Go函数的示例代码:

// main.c
#include <stdio.h>
#include "add.h"  // 包含自动生成的头文件

int main() {
    int result = Add(5, 3);
    printf("5 + 3 = %d\n", result);
    return 0;
}

编译并运行C程序:

gcc -o main main.c add.so
./main

运行结果将会显示:5 + 3 = 8

注意事项

  1. 内存管理:Go和C的内存管理方式不同。如果函数涉及字符串等复杂数据类型,需要手动管理内存,防止泄漏。

  2. 类型转换:Go的int类型与C的int类型兼容,但其他类型(如字符串)需要转换。

  3. 平台兼容性:编译生成的动态库是平台相关的,不同操作系统需要重新编译。

实际应用场景

//export 在实际开发中有多种应用:

  • 性能优化:将计算密集型任务用Go实现,供C/C++程序调用
  • 代码复用:利用Go丰富的标准库,避免C重复造轮子
  • 跨语言开发:作为桥梁,连接Go与其他语言

写在最后

//export 指令是Go语言与C交互的重要工具,它简化了跨语言调用的复杂度。通过本文的示例,你可以快速上手这一功能,为项目增加跨语言能力。