一尘不染

C回调和非Go线程

go

  1. 如何用非Go创建的线程在C中调用Go代码?
  2. 我应为C函数指针分配什么,以便非Go创建的线程可以调用该指针并输入Go代码?

更新0

  • 我不想使用SWIG。
  • 回调将来自Go从未见过的线程。AFAICT 均未显示cgo/life任何pkg/runtime行为。

阅读 171

收藏
2020-07-02

共1个答案

一尘不染

我假设您的意思是使用gcc编译的C代码?

IIRC,使用6g + cgo和朋友无法完成或无法轻松完成。Go使用不同的调用约定(以及分段堆栈等)。

但是,您 可以 为[685] c(甚至[685]
a)编写C代码,并使用package·function()轻松调用go(甚至可以调用IIRC方法)。有关示例,请参见软件包来源runtime

更新:

更新后再回到这个问题,并再考虑一下。使用6c或cgo无法以标准方式完成此操作。特别是因为线程不是由go运行时启动的,所以当前的实现会失败。调度程序突然将一个它不知道的线程置于其控制之下。另外,该线程将缺少go运行时用于管理堆栈的其他线程局部变量和其他一些东西。另外,如果go函数返回一个(或多个)值,那么C代码将无法在当前支持的平台上访问它,因为go返回了堆栈中的值(不过您可以使用汇编程序来访问它们)。考虑到这些事情,我相信您仍然可以使用渠道进行此操作。这将需要您的C代码与go运行时的内部工作过于亲密,但对于给定的实现它会起作用。虽然使用通道可能不是您要寻找的解决方案,但它可能比回调更适合Go的概念。如果您的C代码至少重新实现了发送方法,通道实现(该代码是为6c编写的,因此很可能必须针对gcc进行修改,并且它调用go运行时,我们已经确定无法通过非执行线程完成该运行时),您应该能够锁定通道并向其推送值。go调度程序可以继续管理自己的线程,但是现在它可以从C中启动的其他线程接收数据。

诚然,这是黑客。我的距离还不够近,但是可能还需要一些其他技巧才能使其正常工作(我相信渠道本身会维护正在等待它们的goroutine的列表[EDIT:Confirmed:runtime·ready(gp);],因此您需要您的Go代码中的某些内容会唤醒接收通道或保证Go代码不会在您已推入值之前在该通道上接收)。不过,我看不出任何原因,这
不能 工作,而有一些产生以6克代码运行在C不能创建一个线程明确的原因。

我的原始答案仍然成立: 除非在语言或运行时中添加任何内容,否则尚无法 按照您希望的方式进行(我很乐意在此证明是错误的)。

2020-07-02