2

我正在尝试将 python 回调添加到 C++ 库,如图所示:

template<typename T> void doCallback(shared_ptr<T> data) {
   PyObject* pyfunc; //I have this already
   PyObject* args = Py_BuildValue("(O)", data);
   PyEval_CallObject(pyfunc,args);
}

这失败了,因为数据没有经过 swig,并且不是 PyObject。

我尝试使用:

swigData = SWIG_NewPointerObj((void*)data, NULL, 0);

但是因为它是一个模板,我真的不知道第二个参数该使用什么。即使我对“正确”的 SWIGTYPE 进行硬编码,它通常也会在 PyEval_CallObject 上出现段错误。

所以我的问题是:

  1. 调用 swig 类型包装的最佳方法是什么?

  2. 我在这里是否朝着正确的方向前进?导演看起来很有希望实现回调,但我找不到使用 python 的导演示例。

更新:正在生成正确的包装。我还有其他返回 shared_ptrs 并且可以正确调用它们的函数。

4

2 回答 2

0

shared_ptr<T>for unknownT不是类型,所以 SWIG 不能希望包装它。您需要做的是为shared_ptr您打算使用的每个实例提供一个 SWIG 包装。因此,例如,如果您希望能够doCallback()同时使用shared_ptr<Foo>shared_ptr<Bar>,您将需要:

  • 一个包装器Foo
  • 一个包装器Bar
  • shared_ptr<Foo>和的包装器shared_ptr<Bar>

你让那些像这样:

namespace boost {
    template<class T> class shared_ptr
      {
      public:
          T * operator-> () const;
      };
  }

%template(FooSharedPtr) boost::shared_ptr<Foo>;
%template(BarSharedPtr) boost::shared_ptr<Bar>;
于 2009-10-16T23:31:33.837 回答
0

我的第一个答案完全误解了这个问题,所以让我们再试一次。

T您的中心问题是定义中的自由类型参数doCallback。正如您在问题中指出的那样,没有办法从 a 中制作 SWIG 对象,shared_ptr<T>T:shared_ptr<T>不是真正的类型。

因此,我认为您必须专门化:对于doCallback主机系统使用的每个具体实例化,为目标类型提供模板专门化。完成后,您可以生成 Python 友好的包装data,并将其传递给您的 Python 函数。最简单的技术可能是:

swigData = SWIG_NewPointerObj((void*)(data.get()), SWIGType_Whatever, 0);

...尽管这仅在您的 Python 函数没有将其参数保存在任何地方时才有效,因为它shared_ptr本身没有被复制。

如果确实需要保留对 的引用data,则需要使用 SWIG 通常用于包装的任何机制shared_ptr。如果没有特殊情况的智能指针魔法,它可能是这样的:

pythonData = new shared_ptr<Whatever>(data);
swigData = SWIG_NewPointerObj(pythonData, SWIGType_shared_ptr_to_Whatever, 1);

无论如何,您将拥有一个适用于Py_BuildValue().

希望这可以帮助。

于 2009-10-20T23:11:22.530 回答