如何在C的几个包中重用Go回调?

时间:2015-03-15 03:07:02

标签: go cgo

有没有办法构建一个Go + C应用程序:

  • 从主程序包X导入包Y和Z。
  • 包M导出一个go回调F。
  • 软件包X和Y都是使用随附的C文件构建的,两者都需要 从C源代码中调用F。

一般来说,我正在试图弄清楚如何从用于构建最终应用程序的其他模块中的伴随C文件中调用回调。我不知道如何实现这个或类似的东西。我也对复杂的解决方案感兴趣。

3 个答案:

答案 0 :(得分:3)

我没有看到跨包调用Go函数的方法,但是所有cgo包都链接到相同的二进制文件中并且可以相互调用。这意味着您可以将M.F导出到包M中的C函数,并从包Y和Z调用该C函数。

米/ m.go:

package m

// void F();
import "C"
import "fmt"

//export F
func F() {
    fmt.Println("m.f")
}

米/莫氏硬度:

void m_f();

米/ M.C:

#include <stdio.h>
#include "_cgo_export.h"
#include "m.h"

void m_f() {
    printf("m_f\n")
    F();
}

Y / y.go:

package y

// The LDFLAGS lines below are needed to prevent linker errors
// since not all packages are present while building intermediate
// packages. The darwin build tag is used as a proxy for clang
// versus gcc because there doesn't seem to be a better way
// to detect this.

// #cgo darwin LDFLAGS: -Wl,-undefined -Wl,dynamic_lookup
// #cgo !darwin LDFLAGS: -Wl,-unresolved-symbols=ignore-all
// #include "y.h"
import "C"

import (
    "fmt"
    _ "m"
)

func Y() {
    fmt.Println("y.Y")
    C.y()
}

Y / y.h:

void y();

Y / y.c:

#include <stdio.h>
#include "../m/m.h"

void y() {
    printf("y.C.y\n");
    m_f();
}

答案 1 :(得分:0)

这是一个例子,它将接受任何go回调(非线程安全)。

b.go:

package b

// typedef void (*cbFunc) ();
// void do_run(cbFunc);
// void goCallback();
import "C"

//export goCallback
func goCallback() {
    if goCallbackHolder != nil {
        goCallbackHolder()
    }
}

var goCallbackHolder func()

func Run(callback func()) {
    goCallbackHolder = callback
    C.do_run(C.cbFunc(C.goCallback))
}

b.c:

#include "_cgo_export.h"

void do_run(void (*callback)())
{
    callback();
}

答案 2 :(得分:0)

我无法让它以简单的方式工作IMO。

鉴于导入XY的主程序包Z,必须在程序包F中声明(来自C源代码)M,< / p>

我必须:

  1. W1中为F创建一个小包装器Y,然后将其导出以便从Y的C源调用。
  2. W2中为F创建一个小包装器Z,然后将其导出以便从Z的C源调用。
  3. Y CGO CPPFLAGS中定义-DCALLBACK=W1
  4. Z CGO CPPFLAGS中定义-DCALLBACK=W2
  5. 从C源代码,在任何地方,我现在能够将F称为CALLBACK(是的,内部它是所有不同的东西,我指的是在一端使用单个名称在另一端调用单个函数。)。
  6. 这很复杂,但它正在工作,虽然配置这样的宏并产生很少的包装器 不理想。如果有人能详细说明一个更简单的程序,我会很高兴。一切 我尝试了重复的符号或不可见的声明。