cgo/life
中的pkg/runtime
和任何内容均未显示此行为AFAICT。答案 0 :(得分:5)
你可以这样做,但解决方案相对较慢(我的机器每次通话约22μs)。 答案是C代码使用C线程原语与另一个实际运行回调的goroutine进行通信。
我创建了一个提供此功能的Go包:rog-go.googlecode.com/hg/exp/callback。 有一个示例包证明了它的使用here。该示例演示了从Go运行时外部创建的线程调用任意Go闭包。另一个例子是here。这演示了一个典型的C回调接口,并在其上层叠了一个Go回调。
试试第一个例子:
goinstall rog-go.googlecode.com/hg/exp/example/looper
cd $GOROOT/src/pkg/rog-go.googlecode.com/hg/exp/example/looper
gotest
尝试第二个例子:
goinstall rog-go.googlecode.com/hg/exp/example/event
cd $GOROOT/src/pkg/rog-go.googlecode.com/hg/exp/example/event
gotest
这两个例子都假设pthreads可用。当然,在cgo修复之前,这只是一个权宜之计,但是在C回调中调用任意Go闭包的技术即使在那时也适用。
以下是回调包的文档:
<强> PACKAGE 强>
package callback
import "rog-go.googlecode.com/hg/exp/callback"
<强>变量强>
var Func = callbackFunc
Func拥有一个指向C回调函数的指针。 调用时,它调用a中提供的函数f 带有给定参数的Go上下文。
首先将其转换为函数指针即可使用它 然后从C调用 以下是设置回调函数的示例:
//static void (*callback)(void (*f)(void*), void *arg);
//void setCallback(void *c){
// callback = c;
//}
import "C"
import "rog-go.googlecode.com/hg/exp/callback"
func init() {
C.setCallback(callback.Func)
}
答案 1 :(得分:4)
我假设您的意思是使用gcc编译的C代码?
IIRC,无论是使用6g + cgo还是朋友都无法做到或不能轻易完成。 Go使用不同的调用约定(以及分段堆栈等)。但是,你可以编写[685] c(甚至[685] a)的C代码,并使用package·function()轻松调用(你甚至可以调用方法IIRC)。有关示例,请参阅Source of the runtime
package。
更新后再回到这个问题,并给予更多考虑。这不能使用6c或cgo以标准方式完成。特别是因为线程不是由运行时启动的,所以当前的实现会失败。调度程序突然有一个它不知道的控制线程;此外,该线程将缺少一些线程局部变量,运行时用于管理堆栈和其他一些东西。此外,如果go函数返回一个值(或几个),则C代码无法在当前支持的平台上访问它,因为go返回堆栈上的值(您可以使用程序集访问它们)。考虑到这些因素,我相信你仍然可以使用渠道做到这一点。它需要你的C代码与go运行时的内部工作有点过于亲密,但它适用于给定的实现。虽然使用频道可能不是您正在寻找的解决方案,但它可能更适合Go的概念而不是回调。如果您的C代码至少重新实现了The channel implementation中的发送方法(该代码是针对6c编写的,那么它最有可能必须针对gcc进行调整,并调用go运行时,我们已经确定它可以'从非去线程完成,您应该能够锁定频道并将值推送到它。 go调度程序可以继续管理它自己的线程,但现在它可以从C中启动的其他线程接收数据。
不可否认,这是一个黑客攻击;我看起来不够近,但可能需要一些其他的黑客才能让它正常工作(我相信这些频道本身会保留一份等待它们的goroutine列表[编辑:已确认:runtime·ready(gp);
],所以你需要在你的代码中唤醒接收频道,或保证在你已经推送了一个值之前,通道代码不会在通道上收到。但是,我看不出这个无法工作的任何原因,而有明确的理由在C中创建的线程上运行由6g生成的代码不能。
我的原始答案仍然有效:除了语言或运行时的增加,这还不能完成你喜欢的方式(我喜欢在这里被证明是错的)
答案 2 :(得分:3)
您可以在PortAudio音频I / O库的这些绑定中找到rog的回调包的实际应用程序:http://code.google.com/p/portaudio-go/。可能会让它更容易理解..
(感谢您的实施,rog。这正是我需要的!)