GO调用C函数

voidFan · · 1187 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

GO调用C函数

在很多场景下,在Go的程序中需要调用c函数或者是用c编写的库(底层驱动,算法等,不想用Go语言再去造一遍轮子,复用现有的c库)。我们在使用Golang开发项目或系统的时候难免会遇到Go和C语言混合编程,这时很多人都会选择使用cgo

直接引用C函数

Go代码直接调用c函数

package main
import "fmt"

/*
#include <stdio.h>

void funcC(int a) {
    printf("recv num is %d \n", a);
}
*/
import "C"

func main() {
    var a C.int
    a = 100
    C.funcC(a)
    fmt.Println("Test OK")
}

传递数组的场景

package main

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

void fill_array(char *s) {
    strcpy(s, "cobbliu");
}

void fill_2d_array(char **arr, int colSize) {
    strcpy((char*)(arr + 0 * sizeof(char) * colSize), "hello");
    strcpy((char*)(arr + 1 * sizeof(char) * colSize/sizeof(char*)), "cgo");
}
*/
import "C"    // 注意这个地方与上面注释的地方不能有空行,并且不能使用括号如import ("C" "fmt")
import "fmt"
import "unsafe"
 
func main() {
        var dir [10]byte
        C.fill_array((*C.char)(unsafe.Pointer(&dir[0])))
        fmt.Println(string(dir[:]))
        //var dirs [4][16]byte                                                                                                                                                                                   
        dirs := make([][]byte, 4)
        for i := 0; i < 4; i++ {
                dirs[i] = make([]byte, 16)
        }
 
        C.fill_2d_array((**C.char)(unsafe.Pointer(&dirs[0][0])), C.int(16))
        fmt.Println(dirs)                  
}

调用so中的c函数

  • 编译一个so
//源文件test.c
#include <stdio.h>
void funcC() {
    printf("recv num is %d \n", a);
}

//头文件test.h
void funcC(int a)

//编译成动态库.so
gcc -c -fPIC -o test.o test.c
gcc -shared -o libtest.so test.o
//也可以直接生成so
gcc -fPIC -shared -o libtest.so test.c
  • go文件
package main
import "fmt"

/*
#cgo CFLAGS: -I./
#cgo LDFLAGS: -L./ -lhi
#include "hi.h" //非标准c头文件,所以用引号
*/
import "C"

func main() {
    C.hi()
    fmt.Println("Test ok")
}
  • CFLAGS中的-I(大写的i) 参数表示.h头文件所在的路径
  • LDFLAGS中的-L(大写) 表示.so文件所在的路径 -l(小写的L) 表示指定该路径下的库名称
  • 直接运行go run main.go
  • 如果引用不*.so, 将存入so的路径添加到环境变量当中: export LD_LIBRARY_PATH=/xxx/lib
  • 也可以在 go build 的时候指定so的路径: go build -ldflags="-r ./" test.go。编译时指定连接目录

使用pkg-config进行so的管理

GO调C基本原理

cgo


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:voidFan

查看原文:GO调用C函数

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1187 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传