从C++层调用未定义数量的回调函数

5us2dqdw  于 2023-05-02  发布在  其他
关注(0)|答案(1)|浏览(113)

最近,我开始使用SWIG开发一个解决方案,该解决方案(可能)传递了几个应该在C层中调用的回调函数。此外,我花了一些时间阅读介绍回调章节和导演功能。
我已经设法通过编写从文档示例中的C
层中的基类继承的不同类来实现我的目标,但我试图学习如何传递std::function示例而不是指向类的指针。
我相信下面的(不正确的)例子总结了我的目标:
文件示例。h:

#include <functional>
#include <map>
#include <vector>

class Controller {
 private:
  std::vector<std::function<void()>> functions;

 public:
  virtual void AddFunction(const std::function<void(void)>& func) {
    functions.push_back(func);
  }

  virtual void Execute() {
    for (int m = 0; m < functions.size(); ++m) functions[m]();
  }

  Controller() {}
  virtual ~Controller() {}
};

文件示例。i:

%module example
%{
#include "example.h"
%}

%include "example.h"

文件 www.example.com

import example

def foo():
    print("yey")

def bar():
    print("dog")

def cat():
   print("miaw")

e = example.Controller()
e.AddFunction(foo)
e.AddFunction(bar)
e.AddFunction(cat)

# Prints yey, dog and miaw sequentially
e.Execute()

所以我的问题是
1.我走的方向对吗?换句话说,SWIG真的可以做到吗?
1.我可以只通过导演功能实现我的目标吗?

5m1hhzi4

5m1hhzi41#

要使用控制器,需要一个具有要重写的虚函数的类。
假设您将Controller定义为test.h

#include <functional>
#include <map>
#include <vector>

class Controller {
 private:
  std::vector<std::function<void()>> functions;

 public:
  virtual void AddFunction(const std::function<void(void)>& func) {
    functions.push_back(func);
  }

  virtual void Execute() {
    for (int m = 0; m < functions.size(); ++m) functions[m]();
  }

  Controller() {}
  virtual ~Controller() {}
};

然后SWIG接口文件(test.i)可以声明一个支持目录的Callback类,并扩展Controller以将该类作为参数并调用重写的虚函数:

%module(directors="1") test

%feature("director") Callback;

%inline %{
class Callback {
public:
    virtual void function() = 0;
    virtual ~Callback() {}
};
%}

%{
#include "test.h"
%}
%include "test.h"

%extend Controller {
    void AddFunction(Callback* cb) {
        $self->AddFunction(std::bind(&Callback::function, cb));
    }
}

Python代码看起来像这样:

import test

class Foo(test.Callback):
    def function(self):
        print('yey')

class Bar(test.Callback):
    def function(self):
        print('dog')

class Cat(test.Callback):
    def function(self):
        print('miaw')

# Note that AddFunction needs to be provided an object instance that persists
# until after Execute is called, so "e.AddFunction(Foo())" wouldn't work
# because Foo() would be freed after the AddFunction call.
foo = Foo()
bar = Bar()
cat = Cat()

e = test.Controller()
e.AddFunction(foo)
e.AddFunction(bar)
e.AddFunction(cat)
e.Execute()

输出:

yey
dog
miaw

相关问题