You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于SWIG实现C++调用多回调:std::function方案可行性及director适用性问询

问题描述

近期我开始使用SWIG开发解决方案,需向C层传递若干回调函数并在该层调用。我已通过继承C层基类的方式实现需求,但希望改用std::function实例替代类指针传递回调。以下是我设想的示例代码(目前无法正常运行):

File example.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() {}
};

File example.i

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

%include "example.h"

File example.py

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)

# 预期依次打印yey、dog和miaw
e.Execute()

我有两个问题:

  1. 该实现方向是否正确?即SWIG是否支持这种方式?
  2. 是否仅通过director特性即可达成我的目标?

解答

问题1:实现方向是否正确,SWIG是否支持?

方向可行,但SWIG默认不会自动处理std::function与Python函数的绑定。默认情况下,SWIG无法识别如何将Python函数对象转换为C++的std::function<void()>实例,因此现有代码直接编译会报错,需要额外添加类型映射(type mapping)来完成两者的转换适配。

问题2:仅用director特性能否达成目标?

不行。director特性核心是实现C基类的Python派生类,让C代码可以调用Python子类的虚函数,属于基于类继承的回调模式。而你需要的是直接传递独立的Python函数作为std::function参数,这和director的应用场景完全不同,必须通过编写SWIG类型映射来实现。

可行修改方案

修改example.i文件,添加针对std::function<void()>的类型映射,完成Python函数到C++函数对象的转换:

%module example
%{
#include "example.h"
#include <functional>
%}

// 类型映射:将Python可调用对象转换为std::function<void()>
%typemap(in) const std::function<void()>& {
  if (!PyCallable_Check($input)) {
    PyErr_SetString(PyExc_TypeError, "Expected a callable object");
    return NULL;
  }
  PyObject* func = Py_XINCREF($input);
  $1 = new std::function<void()>([func]() {
    PyObject* result = PyObject_CallObject(func, NULL);
    if (result == NULL) {
      PyErr_Print();
    } else {
      Py_DECREF(result);
    }
  });
}

// 清理std::function占用的内存
%typemap(freearg) const std::function<void()>& {
  delete $1;
}

%include "example.h"

修改后编译运行,Python中的函数即可被正确传递到C++层,Execute()调用时会依次打印预期内容。

内容的提问来源于stack exchange,提问作者José Joaquim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 04:50:17