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

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

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

  1. #include <functional>
  2. #include <map>
  3. #include <vector>
  4. class Controller {
  5. private:
  6. std::vector<std::function<void()>> functions;
  7. public:
  8. virtual void AddFunction(const std::function<void(void)>& func) {
  9. functions.push_back(func);
  10. }
  11. virtual void Execute() {
  12. for (int m = 0; m < functions.size(); ++m) functions[m]();
  13. }
  14. Controller() {}
  15. virtual ~Controller() {}
  16. };

文件示例。i:

  1. %module example
  2. %{
  3. #include "example.h"
  4. %}
  5. %include "example.h"

文件 www.example.com

  1. import example
  2. def foo():
  3. print("yey")
  4. def bar():
  5. print("dog")
  6. def cat():
  7. print("miaw")
  8. e = example.Controller()
  9. e.AddFunction(foo)
  10. e.AddFunction(bar)
  11. e.AddFunction(cat)
  12. # Prints yey, dog and miaw sequentially
  13. e.Execute()

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

5m1hhzi4

5m1hhzi41#

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

  1. #include <functional>
  2. #include <map>
  3. #include <vector>
  4. class Controller {
  5. private:
  6. std::vector<std::function<void()>> functions;
  7. public:
  8. virtual void AddFunction(const std::function<void(void)>& func) {
  9. functions.push_back(func);
  10. }
  11. virtual void Execute() {
  12. for (int m = 0; m < functions.size(); ++m) functions[m]();
  13. }
  14. Controller() {}
  15. virtual ~Controller() {}
  16. };

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

  1. %module(directors="1") test
  2. %feature("director") Callback;
  3. %inline %{
  4. class Callback {
  5. public:
  6. virtual void function() = 0;
  7. virtual ~Callback() {}
  8. };
  9. %}
  10. %{
  11. #include "test.h"
  12. %}
  13. %include "test.h"
  14. %extend Controller {
  15. void AddFunction(Callback* cb) {
  16. $self->AddFunction(std::bind(&Callback::function, cb));
  17. }
  18. }

Python代码看起来像这样:

  1. import test
  2. class Foo(test.Callback):
  3. def function(self):
  4. print('yey')
  5. class Bar(test.Callback):
  6. def function(self):
  7. print('dog')
  8. class Cat(test.Callback):
  9. def function(self):
  10. print('miaw')
  11. # Note that AddFunction needs to be provided an object instance that persists
  12. # until after Execute is called, so "e.AddFunction(Foo())" wouldn't work
  13. # because Foo() would be freed after the AddFunction call.
  14. foo = Foo()
  15. bar = Bar()
  16. cat = Cat()
  17. e = test.Controller()
  18. e.AddFunction(foo)
  19. e.AddFunction(bar)
  20. e.AddFunction(cat)
  21. e.Execute()

输出:

  1. yey
  2. dog
  3. miaw
展开查看全部

相关问题