使用 SWIG 将 C++ 文件包装为 Python 文件

Posted

技术标签:

【中文标题】使用 SWIG 将 C++ 文件包装为 Python 文件【英文标题】:Wrapping a C++ file as a Python file using SWIG 【发布时间】:2018-03-26 20:01:34 【问题描述】:

我是使用 SWIG 的新手,并且有点超出我作为程序员的深度。我希望能够通过将包装类作为模块“import C++_file”导入来调用python 2中的C++类的函数,然后在我的python类中使用类似“C++_file.function”的东西调用它(输入)'。

在http://intermediate-and-advanced-software-carpentry.readthedocs.io/en/latest/c++-wrapping.html之后,我将头文件multiplyChannel.h包装起来:

#include <vector>
#include <complex>

using namespace std;

class MultiplyChannel 
    public:
        MultiplyChannel(double in_alpha);
        void applyToVector(vector<complex<double> > *in_signal);
    private:
        double alpha;
;

对应于我的示例 C++ 文件 multiplyChannel.cpp:

#include "multiplyChannel.h"
#include <vector>
#include <complex>

using namespace std;

MultiplyChannel::MultiplyChannel(double in_alpha)
    this->alpha = in_alpha;


void MultiplyChannel::applyToVector(vector<complex<double> > *in_signal)
    unsigned int size = in_signal->size();
    for (int i = 0; i < size; i++) 
        in_signal->at(i).real() = in_signal->at(i).real() * this->alpha;
        in_signal->at(i).imag() = in_signal->at(i).imag() * this->alpha;
    

使用makefile:

all:
    swig -python -c++ -o mult.cpp swigdemo.i
    python setup.py build_ext --inplace

包装文件 swigdemo.i:

%module swigdemo

%
#include <stdlib.h>
#include "multiplyChannel.h"
%

%include "multiplyChannel.h"

和 setup.py 构建文件:

from distutils.core import setup, Extension

extension_mod = Extension("_swigdemo", ["mult.cpp"])

setup(name = "swigdemo", ext_modules=[extension_mod])

通过在我的 Ubuntu 命令窗口中输入:

$ make
swig -python -c++ -o multiplyChannel.cpp swigdemo.i
python setup.py build_ext --inplace
running build_ext
$ python setup.py build
running build
running build_ext

使用 C++_tester.py 测试导入,我尝试使用 MultiplyChannel 对象 'demo' 将向量 [1, 2, 3] 乘以 [5, 10, 15],实例变量 'in_alpha' 为 5x ,将所有输入乘以 5:

#!/usr/bin/python

import swigdemo

if __name__ == '__main__':
    demo = swigdemo.MultiplyChannel(in_alpha=5)
    out = demo.applyToVector(in_signal=[1, 2, 3])
    print(out)

我什至没有通过导入行,收到以下错误:

$ python C++_tester.py
ImportError: ./_swigdemo.so: undefined symbol: _ZN15MultiplyChannelC1Ed

我不确定该怎么做,因为我什至无法 gedit 或 vim 进入 .so 文件。我猜我的错误在于我的包装器、构建文件或 makefile 中的包装不正确,因为 C++_tester.py 文件中的几乎所有内容都在我的 Pycharm IDE 中自动完成。

非常感谢!

【问题讨论】:

【参考方案1】:

问题确实与扩展构建有关:

swigdemo.i - 生成 swig 包装器 (mult.cpp) MultiplyChannel 类实现在 multiplyChannel.cpp 在构建扩展时,由于它是一个共享对象 (.so),链接器(默认情况下)不会抱怨未定义的符号(如 2 @ 987654325@ 方法(因为它对它们一无所知) - 以及其他),但考虑到符号可以在运行时可用(当 .so 将被加载时)创建它李>

简而言之,修改setup.py,将multiplyChannel.cpp添加到扩展源苍蝇列表中:

extension_mod = Extension("_swigdemo", ["mult.cpp", "multiplyChannel.cpp"])

检查[SO]: SWIG: How to pass list of complex from c++ to python 了解您将遇到的下一个问题。

【讨论】:

谢谢。我有一条新消息:“错误:命令'c++'失败,退出状态为1”,“makefile:2:目标'all'的配方失败”,它描述了一行错误:“swig -python -c++ -o multiplyChannel.cpp swigdemo.i”,在我的 makefile 中。我关注了askubuntu.com/questions/685380/… 和***.com/questions/36127987/…,但错误消息仍然存在,并且在您发布的链接中没有看到任何相关问题(尽管以后肯定会需要) 失败的步骤在原始问题之前。这意味着您修改了一些文件(很可能是 swigdemo.i)。但是这个错误没有任何意义,而且这2个链接在这里似乎没有任何关系。你确定“-c++”参数不包含空格(“-”之后)吗? 我引用的所有内容都是复制粘贴的,连字符后没有空格。当我删除你在 setup.py 中指出的修复时,这个错误不存在,并且像在我的 OP 中一样发生,所以看起来这个错误与修复有关,虽然我不明白 如果我从 setup.py 中删除 mult.cpp,错误就会消失,但我又回到未定义符号错误 您是说将我提出的修复方案应用于问题(发布的代码现在是这样(第二次编辑))会产生这种行为吗?这没有任何意义。我的修复针对的是编译阶段(python setup.py),而您的错误发生在之前(swig)。它是其他产生这种行为的东西(你更新了系统上的库,或者修改了文件?)。顺便说一句,您在测试之前接受了答案吗?对我来说,它构建了 .so ,但是在调用 func 时,因为您没有正确定义转换协议(我包含的 URL)。在问题中包含输出。

以上是关于使用 SWIG 将 C++ 文件包装为 Python 文件的主要内容,如果未能解决你的问题,请参考以下文章

SWIG:使用带有 shared_ptr 的 std::map 访问器?

SWIG:Lua - 将 c++ 实例作为 lua 函数参数传递

如何在 swig 接口文件中集成可以抛出 MyException 的 C++ 函数

将 python 函数传递给 SWIG 包装的 C++ 代码

使用 SWIG 跨 C++ 和 Ruby 的多态性

SWIG:你能否使用 SWIG 专门使用 C++ 头文件使 C++ 在 Python 中可用?