使用 SWIG 围绕 C++ 的 Python 包装器。参数类型无法识别

Posted

技术标签:

【中文标题】使用 SWIG 围绕 C++ 的 Python 包装器。参数类型无法识别【英文标题】:Python wrapper around C++ using SWIG. Argument type not recognised 【发布时间】:2020-01-08 00:05:21 【问题描述】:

我正在尝试在 Linux 上使用 SWIG 围绕 C++ 代码构建 Python 包装器,但我不确定是否正确创建了包装器。例如,这是一个小问题(在我的较大项目中)。

假设我有一个名为 message.cpp 的文件

message.cpp

#include <iostream>

#include "message.hpp"

void warning (std::string message) 
  using std::cout;
    cout << "\n!! WARNING!  " << message << " !!\n";

对应的头文件为:

message.hpp

#include <string> 
#include <fstream>   // file I/O
#include <sstream>
#include <iostream>

void warning (const std::string message);

为了通过 SWIG 传递它,我有以下 SWIG 输入文件:

message.i

%module message

%
#include "message.hpp"
%

%include "message.hpp"

从 Linux 终端,我使用以下命令创建包装器:

$ swig -c++ -python message.i

$ g++ -fpic -c message.hpp message_wrap.cxx message.cpp -I/usr/include/python2.7/ -I/usr/include

$ gcc -shared message_wrap.o message.o -o _message.so -lstdc++

命令提示符下的所有 3 个步骤在终端上都通过,没有任何错误,并且生成了以下文件,没有任何抱怨:

message_wrap.cxx
message_wrap.o
message.o
message.py
message.hpp.gch
_message.so

然后我尝试通过在 Linux 终端上输入以下命令(位于同一目录中)来测试 Python 包装器:

$ python
Python 2.7.17
[GCC 7.4.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import _message
>>> _message.warning("SampleMessage")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: in method 'warning', argument 1 of type 'std::string const'

我原以为它只是在终端上显示WARNING! SampleMessage 行,但它却崩溃了。所以似乎出了点问题。有人可以指导我问题出在哪里吗?

【问题讨论】:

【参考方案1】:

您的声明和实现不匹配(缺少const),您应该导入message 而不是_message。说了这么多,你缺少的是:

%include "std_string.i"

message.hpp 包含之前的 .i 中。这将提供将 Python str 转换为 C++ std::string 所需的类型映射。

【讨论】:

太棒了!那行得通,谢谢。再深入一点,似乎所有可能的 SWIG 库都存储在我的 PC 上的/usr/local/share/swig/4.0.1/ 及其子目录中。由于我的项目有许多以复杂方式链接的大型 C++ 文件,因此在包装特定 C++ 文件时告诉我应该包含哪些特定 SWIG 库将非常耗时。愚蠢的问题:如果我包含所有安装在我的 PC 上的 SWIG 库,它会不会无害?还是有更聪明的方法,以便自动获取所需的库? 是的,基本上是无害的。也就是说,类型映射是代码 sn-ps,只有在使用时才会被放置在行内。如果帮助例程被放置在包装文件中,那么这些例程将被声明为静态并在模块之间复制(但仅在使用时再次重复)。您最大的成本是 swig 运行速度较慢,但​​我怀疑这是相对于总编译时间的问题。大规模 swig 的实际问题具有不同的性质:您需要为每个 python 版本重新编译和重新链接包装器,并注意不要重复类。绑定大型 C++ 项目不是我的事(但我有偏见)。

以上是关于使用 SWIG 围绕 C++ 的 Python 包装器。参数类型无法识别的主要内容,如果未能解决你的问题,请参考以下文章

SWIG C++ Python 多态性和多线程

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

使用 SWIG 的 C++ 的 Python 包装器

SWIG:将其参数从 c++ 修改为 python 的函数

无法使用 SWIG 在 Python 中实例化 C++ 类(获取属性错误)

使用 SWIG 将 C++ 对象指针传递给 Python,而不是再次返回 C++