使用和不使用`-builtin`交互SWIG模块

时间:2014-01-13 23:11:55

标签: python c++ swig

如何在没有 -builtin的情况下告诉编译的模块,使用 %import编译了-builtin ed模块?当非内置模块假定来自第一个模块的对象具有包装器时,天真地这样做会给我带来段错误。

(如果所有内容都是在-builtin已关闭关闭的情况下进行编译,或者单独使用第二个模块且-builtin已启用时,我绝不会遇到段错误;只是在将它们一起使用时使用不同的编译选项。)

详细

我有几个单独的模块,我使用SWIG。假设其中一个名为A,并包含基本对象(四元数)。因为它包含许多计算中涉及的基本对象,所以我更喜欢使用SWIG的-builtin选项。我测试了它,这确实在时间上产生了非常显着的差异。

现在,我还有另一个名为B的模块需要使用A中的对象。但是B包含很多胖的复合对象,我很多次都不会这样做,所以我不认为在这里使用-builtin有很多好处。此外,我真的想扩展B中的类,并执行-builtin无法实现的各种事情。

问题是我必须在%import A.iB.i。但是,为B生成的代码假定A对象具有额外的包装器,而不是使用-builtin。因此,当我使用B时,我会遇到段错误。

(至少,我假设segfaults结果是因为B假设额外的包装器。我查看了我的B_wrap.cpp文件足以看到它假设存在这些包装器,尽管我可以'我真的说我做了任何测试,以确保问题来自哪里。但是,段错误只与A B的使用相吻合。A从来没有给我带来任何麻烦。另外,如果我在没有A的情况下编译B-builtin,我就永远不会遇到段错误。)

原则上,我可以使用MONK's approach并将我需要添加方法的任何类子类化,同时使用-builtin编译所有内容。但这会破坏我的C ++代码中的名称和我的python代码中的名称之间的良好对应关系,以及要求一组或另一组用户更改他们使用的名称,以及在对接中一般的痛苦。

我为没有MWE而道歉,但我认为这将是一个不合理的大型MWE。

1 个答案:

答案 0 :(得分:1)

我不知道用单独的标志编译是可能的,但我对MONK的解决方案感到满意。结合SWIG的%rename功能,MONK的方法不需要重命名用户可见的任何内容。此外,它易于实现,每个类我只想修改五行。因此,所有内容都将使用-builtin进行编译,并且不会出现段错误。虽然这在技术上没有回答我在顶部提出的问题,但它适合我。

所以,我们假设B中的关键对象是一个名为Classy的类。我只是告诉SWIG将其重命名为_Classy(下划线,这样我每次在ipython中使用tab完成时都不必查看它)。然后,我将创建一个子类,这些子类是那些对象的子类。最后,我将创建一个名为Classy的新对象,它只包含元类。所以我的python用户和我的C ++用户会将它看作同一个对象,但python用户将能够将其子类化。

这是这部分的MWE。一个简单的标题:

// Classy.hpp
class Classy {
public:
  Classy() { }
};

和SWIG文件

// test.i
%module "test"

%{
  #include "Classy.hpp"
%}

%rename(_Classy) Classy;

%include "Classy.hpp"

%insert("python") %{
class _MetaClassy(type(_Classy)):
    pass
class Classy(_Classy):
    __metaclass__ = _MetaClassy
Classy.myattr = 'anything'
%}

(看看我们最后在那里添加了一个属性。)最后,设置文件:

# setup.py
from distutils.core import setup, Extension
example_module = Extension('_test',
                           sources=['test_wrap.cxx'])
setup (name = 'test',
       ext_modules = [example_module],
       py_modules = ["test"])

现在,只需使用

进行编译和测试
swig -python -builtin -c++ test.i
python setup.py build_ext --inplace
python -c 'import test; x=test.Classy(); print x.myattr'

在最后一行中,类型为x的python对象Classy确实具有一个属性 - 即使C ++类根本没有任何内容。所以我们成功了。

据推测,这个子类化会使-builtin对象的Classy的速度优势失效,但我已经决定我不关心那一个类。另一方面,我可以保留任何我没有显式子类化的对象的速度优势,因此仍然有理由使用builtin