为了账号安全,请及时绑定邮箱和手机立即绑定

通过SWIG从C ++调用Go回调函数

通过SWIG从C ++调用Go回调函数

Go
慕勒3428872 2021-05-18 06:06:40
我正在尝试调用C ++函数:void TestFunc(void(*f)(void)) { f(); }从Go Code。我真的希望它只是将Go函数传递给该函数。我知道我可以将其包装到一个类中,并使用%feature(“ director”)解决它,但这并不是我的最佳解决方案。从我在本页中看到的内容来看,Go中的函数指针应与C ++中的相同,因此我尝试了以下.swig文件:%{#include "test.h"%}%typemap(gotype) FUNC* "func()"%typemap(in) FUNC* {  $1 = (void(*)(void))$input;}%apply FUNC* { void(*)(void) };%include "test.h"我很惊讶它最初会起作用,但是后来发现它并不总是起作用:(。例如,在此Go代码中,它可以按预期工作:import "fmt"import "test_wrap"func main() {  b := false  test_wrap.TestFunc(func() { b = true })  fmt.Println(b)  // This actually DOES print "true"!}但是在其他情况下,它不起作用。例如,在这里:import "fmt"import "test_wrap"func main() {  test_wrap.TestFunc(func() { fmt.Println("SUCCESS") })  fmt.Println("Done")}我实际上得到:SUCCESSSIGILL: illegal instructionPC=0x4c20005d000goroutine 1 [syscall]:test_wrap._swig_wrap_TestFunc(0x400cb0, 0x400c2a)        base_go_test__wrap_gc.c:33 +0x32test_wrap.TestFunc(0x400cb0, 0x2)        base_go_test__wrap.go:37 +0x25main.main()        test.go:8 +0x2agoroutine 2 [syscall]:created by runtime.main        go/gc/src/pkg/runtime/proc.c:225rax     0x0rbx     0x0rcx     0x0rdx     0x8rdi     0x4c200073050rsi     0x4c20004c0f0rbp     0x0rsp     0x4c20004c100r8      0x2r9      0x4b0ae0r10     0x4f5620r11     0x4dbb88r12     0x4f5530r13     0x7fad5977f9c0r14     0x0r15     0x3rip     0x4c20005d000rflags  0x10202cs      0x33fs      0x0gs      0x0请注意,它确实打印了“ SUCCESS”,这意味着函数DID运行了,即使我将更复杂(又长)的代码放入该函数中,它也能完美执行,但并没有返回:(。请让我知道您的想法,以及如何解决此问题。我不介意在C ++部分上添加一些代码,但我确实希望Go部分看起来“干净”。
查看完整描述

1 回答

?
翻翻过去那场雪

TA贡献2065条经验 获得超14个赞

成功!我有一个可行的解决方案:


我所做的想法是用“ director”包装回调,然后将Go函数指针返回“ Go”,以便可以在该上下文中运行它。


下面的解决方案并不完美,但已经足够满足我的需求,从现在开始很容易使其完美。


C ++文件:


class Callback {

 public:

  virtual void Run(void(*f)(void)) = 0;

  virtual ~Callback() {}

};


Callback* GlobalCallback;


void TestFunc(void(*f)(void)) {

  GlobalCallback->Run(f);

}

我添加了一个Callback类,它将在Go中“扩展”(使用Swig导演),并且我将拥有该扩展类的全局实例。因此,调用该实例的Run()将调用Go函数,该函数将接收一个函数指针。


请注意,我的TestFunc现在不只是运行f(),而是通过GlobalCallback运行它。添加另一个函数将返回一个指向运行GlobalCallback-> Run(f)的函数的指针,然后将此指针传递给该函数而不是* f,这很容易解决。


我的Swig文件:


%{

#include "test.h"

%}


%module(directors="1") Callback

%feature("director");


%typemap(gotype) FUNC* "func()"

%typemap(in) FUNC* {

  $1 = (void(*)(void))$input;

}

%apply FUNC* { void(*)(void) };


%include "test.h"


%insert(go_wrapper) %{

type go_callback struct { }


func (c* go_callback) Run(f func()) {

  f()

}


func init() {

  SetGlobalCallback(NewDirectorCallback(&go_callback{}))                                                                                                     

}

%}

请注意,我已经添加了一个init()函数,该函数通过运行指针的Go函数来设置GlobalCallback。


就是这样,Go代码保持原样,并且可以正常工作:)


查看完整回答
反对 回复 2021-05-24
  • 1 回答
  • 0 关注
  • 269 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信