从C语言(或其他语言)调用Golang的方法

从C语言(或其他语言)调用Golang的方法 我找到了一些从C语言调用Go的示例,但没能找到专门讲解运行时如何启动的资源,或许还需要一个关于调用过程(例如线程切换、栈切换等)的简要说明。

是否有全面的资源来解释那里发生了什么?

谢谢。

2 回复

嗨,@gnaaman-dn,据我理解,要从 C 调用 Go,你需要已经处于从 Go 进入 C 的环境中(即 Go → C → 再次 Go)。我不了解任何可以从 C 开始,然后引导运行时并调用 Go 的方法。

更多关于从C语言(或其他语言)调用Golang的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


从C语言调用Go函数涉及Go运行时的初始化和跨语言调用机制。以下是关键步骤和示例代码:

1. 运行时初始化

当C代码调用Go函数时,需要先初始化Go运行时环境。这通常在Go的main包中通过//export指令和import "C"实现。运行时初始化包括:

  • 内存分配器设置
  • 垃圾回收器初始化
  • Goroutine调度器启动

2. 线程和栈管理

  • 线程切换:Go运行时使用M:N调度模型,C线程调用Go函数时,可能会被Go运行时复用为工作线程(M)。
  • 栈切换:Go函数使用分段栈,调用时切换到Go栈空间,确保安全执行。

3. 调用过程示例

Go端代码 (lib.go):

package main

import "C"
import "fmt"

//export HelloFromGo
func HelloFromGo(name *C.char) {
    fmt.Printf("Hello from Go: %s\n", C.GoString(name))
}

func main() {} // 必需,但可为空

编译为C共享库:

go build -buildmode=c-shared -o libgo.so lib.go

C端代码 (main.c):

#include <stdio.h>
#include <dlfcn.h>

typedef void (*HelloFunc)(const char*);

int main() {
    void* lib = dlopen("./libgo.so", RTLD_LAZY);
    HelloFunc hello = (HelloFunc)dlsym(lib, "HelloFromGo");
    
    hello("C caller"); // 调用Go函数
    
    dlclose(lib);
    return 0;
}

编译并运行:

gcc -o main main.c -ldl
./main

4. 内部机制说明

  • cgo调用:通过cgo生成桥接代码,处理C与Go类型转换。
  • 栈增长:Go函数执行期间,分段栈可能自动增长。
  • 调度器介入:长时间运行的Go函数可能触发调度器切换Goroutine。

5. 资源推荐

  • Go官方文档:runtime包和cgo命令说明。
  • 源码参考:$GOROOT/src/runtime中的proc.gocgo相关实现。

此过程确保了跨语言调用的稳定性和性能,但需注意避免在Go回调中长时间阻塞C线程。

回到顶部