使用和不使用内置的SWIG模块交互`

2024-05-04 21:48:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我如何告诉一个不带-builtin编译的模块是用-builtin编译的?当非内置模块假定第一个模块中的对象具有包装器时,这样做会给我带来一些错误。在

(如果所有的代码都是在-builtin关闭的情况下编译的,或者在启用-builtin的情况下单独使用第二个模块时,我永远不会得到segfaults;这只是当它们与不同的编译选项一起使用时。)

细节

我有几个单独的模块。假设其中一个命名为A,包含基本对象(四元数)。因为它包含许多计算中涉及的基本对象,所以我更喜欢使用SWIG的-builtin选项。我已经测试过了,这在时间上确实有很大的不同。在

现在,我还有另一个名为B的模块,它需要使用A中的对象。但是B包含了我不经常操作的大型复合对象,所以我不认为在这里使用-builtin有什么好处。而且,我真的很喜欢扩展B中的类,并且做很多用-builtin不可能的事情。在

问题是我必须在B.i内部%import A.i。但是,为B生成的代码假定A对象具有额外的包装器,而不是使用-builtin。所以当我使用B时,我得到了segfaults。在

(至少,我假设segfaults的结果是因为B假设了额外的包装器。我仔细查看了我的B_wrap.cpp文件,发现它假设存在这些包装器,尽管我不能说我做了任何测试来确保问题的根源。但是这些分段断层只与A来自B的用法一致。单靠它,A从来没有给我带来任何麻烦。另外,如果我编译AB而没有-builtin,我永远不会得到segfaults。)

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

我很抱歉没有一个MWE,但我认为这将是一个不合理的大MWE。在


Tags: 模块对象代码名称选项错误时间情况
1条回答
网友
1楼 · 发布于 2024-05-04 21:48:41

我不知道是否可以用单独的标志进行编译,但我对MONK的解决方案很满意。结合SWIG的%rename功能,MONK的方法不需要重命名用户可见的任何内容。另外,它很容易实现,只需要为每个我想要修改的类增加五行代码。因此,所有的东西都要用-builtin编译,而没有segfaults。虽然从技术上讲,这并不能回答我在上面提出的问题,但它适合我。在

所以,让我们假设B中的关键对象是一个名为Classy的类。我只告诉SWIG将其重命名为_Classy(下划线,这样我就不必每次在ipython中使用tab completion时都查看它)。然后,我将生成一个空的元类来子类化这些对象。最后,我将创建一个名为Classy的新对象,它只有元类。因此,我的Python用户和我的C++用户将把它看作是同一个对象,但是Python用户将能够对它进行子类。在

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

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

还有SWIG文件

^{pr2}$

(请参阅我们如何在结尾处添加属性。)最后,设置文件:

^{3}$

现在,只需使用

swig -python -builtin -c++ test.i
python setup.py build_ext  inplace
python -c 'import test; x=test.Classy(); print x.myattr'

在最后一行中,Python对象^ {< CD7>},类型^ {< CD4>}确实具有属性,即使C++类根本没有任何属性。所以我们成功了。在

大概,这个子类化会破坏-builtin对于Classy对象的速度优势,但我已经决定不关心这一个类。另一方面,对于没有显式子类化的任何对象,我都可以保留速度优势,因此仍然有理由使用builtin。在

相关问题 更多 >