我使用SWIG将C++库包装为Python库。 C++库公开了抽象类,以便用户从中继承,因此我们使用SWIG中的处理来处理。它基本上可以工作(有一些调整)。在
一个问题是,C++类有以下两种方法:
class Base {
void* getObject();
void doSomething(void* o);
}
用户需要实现这些方法,然后用户在getObject()中返回的对象将传递给doSomething()方法。在
问题是,在使用SWIG时,Python中的doSomething()方法会收到一个包装类型为“void*”的SwigPyObject,因此我们不能像我们希望的那样使用原始的Python对象方法。 由于是Python(或者是Python),所以不能选择强制转换。在
有人有什么见解吗?在
我到处都发现了一些相关的问题,但似乎没有一个能完全解决我的问题,而且我已经尝试了很多方法来解决它,但是没有成功。在
如果你需要更多的细节请告诉我,我会提供的。在
非常感谢!在
首先,我们想让你的代码变得真实和可运行。我自己写的测试.hh基于您展示的小代码,我们可以稍微练习一下这个设计:
我们最初可以这样概括:
^{pr2}$并生成一个测试用例来展示我们希望它在Python中如何工作:
但这在现阶段还行不通,因为我们还没有告诉SWIG如何在Python中有意义地处理
void*
。在这里的基本思想是,我们希望让
void*
在接口内用作PyObject*
。我们可以用directorin和directorout类型映射配对来实现。大体上,我们需要解决两个问题:void*
不是一个PyObject*
,会发生什么?在如果我们一开始假设
getObject()
调用和doSomething()
调用之间存在1:1的映射,那么引用计数就相当简单,我们可以在接口中编写两个类型映射,保留对PyObject
的引用,然后在需要时将其从void*
转换回来(注意,我们在这里也完全避开了问题2添加1:1限制)。在因此,通过这两个类型映射,我们的界面变成:
当我们这样测试时:
但是,如果我们将这里的语义改为不完全是1:1,那么我们就有了一个问题,例如将
runMe
设为:因为第一次调用
doSomething
完成后,引用变小,所以现在该段发生错误。在在这个阶段,显然要做的事情是在directorin类型映射中添加对
Py_INCREF
的调用,但是这并不是全部内容—我们现在将永远不调用释放getObject()
的结果,它在runMe()
的末尾超出了范围。在我倾向于通过在
Base
接口中添加另一个调用来解决这个问题:有了它,我们就可以让你的SWIG接口完全在Python控制器内部实现(如果需要,还可以隐藏)。方法是使用一些
%rename
和%ignore
以及一些宏观的骗局:因此,通过对SWIG接口的以下修改,我们现在可以正确地处理
runMe
的第二个化身:从
runMe
引发对cleanupThing
的调用:当run now提供:
(如果语义比简单地来回传递给同一个实例的局部变量复杂,则存在其他可能的解决方案)。在
相关问题 更多 >
编程相关推荐