【问题标题】:Using SWIG to Wrap C++ Function With Default Values使用 SWIG 用默认值包装 C++ 函数
【发布时间】:2021-11-15 18:03:25
【问题描述】:

我在say.hpp 中有以下 C++ 函数:

#include <iostream>


void say(const char* text, const uint32_t x = 16, const uint32_t y = 24, const int32_t z = -1) {
    std::cout << text << std::endl;
}

这是我的say.i

%module say
%{
#include "say.hpp"
%}

%include "say.hpp"

然后,我构建了共享库:

$ swig -python -c++ -I/usr/include say.i
$ g++ -fPIC -c say_wrap.cxx -I/opt/rh/rh-python38/root/usr/include/python3.8 
$ g++ -shared say_wrap.o -o _say.so

然后,我尝试调用它:

>>> import say
>>> say.say("hello")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/hc/test/cpp/say.py", line 66, in say
    return _say.say(text, x, y, z)
TypeError: Wrong number or type of arguments for overloaded function 'say'.
  Possible C/C++ prototypes are:
    say(char const *,uint32_t const,uint32_t const,int32_t const)
    say(char const *,uint32_t const,uint32_t const)
    say(char const *,uint32_t const)
    say(char const *)

>>> 

函数参数的默认值似乎有问题,因为一旦我删除它们,它就会起作用。

有什么想法吗?

【问题讨论】:

  • 你展示的C++代码,是say.hpp文件的内容吗?
  • 是的,我只是尽量保持简单,将所有内容都放在标题中。
  • 您能否验证重载方法是否正确生成(- 如here 所述)
  • 您是否尝试过使用“compactdefaultargs”功能标志?
  • @ttuna 我该如何验证?我查看了生成的python文件say.py,我只看到一个定义——def say(text, x=16, y=24, z=-1):

标签: c++ python-3.x linux g++ swig


【解决方案1】:

使用以下say.i 文件。 SWIG 已经为标准整数类型预先编写了代码,需要包含它来理解它们。没有它们,包装器将默认值作为不透明的 Python 对象接收,并且不知道如何将它们转换为正确的 C++ 整数类型。

%module say
%{
#include "say.hpp"
%}
%include <stdint.i>
%include "say.hpp"

结果:

>>> import say
>>> say.say('hello')
hello
>>> say.say('hello',1,2,3)
hello

请注意,您也可以直接提供 typedef,但最好使用 stdint.i

%module say
%{
#include "say.hpp"
%}
typedef unsigned int uint32_t;
typedef int int32_t;
%include "say.hpp"

【讨论】:

  • 谢谢。有用。我很困惑什么需要'%include',什么不需要。介意详细说明吗?
  • @HCSF SWIG 是一个 C/C++ 解析器。它为它解析的任何内容创建包装器,但是 %{/%} 之间的代码被插入到包装器中而不生成包装器。所以#include "say.hpp" 让包装器知道你的函数,但不生成接口。 %include "say.hpp" 直接将文件中的代码处理成封装的接口(不是递归的,就像忽略 iostream 一样)。 SWIG 只理解基本类型,但很宽容,因此在您的情况下,stdint 类型被包装为 C++ 代码不理解的不透明指针。
  • @HCSF SWIG 了解 typedef 和基本类型,并且 stdint.i 具有许多用于 stdint 类型的 typedef,因此必须包含它以使 SWIG 知道它们等效于预定义类型。然后手动添加也可以。
  • %include "say.hpp" processes the code directly in the file into wrapped interfaces (not recursively, like iostream is ignored)。所以听起来say.hpp 中的所有#include 指令都应该通过%include 包含在say.i 中?似乎没有。那么它的规则/指南是什么?谢谢!
  • @HCSF 仅当您希望包装所有 iostream 时(通常不会,并且无论如何都不会工作,更复杂的接口),但是如果您需要在子包含中包含其他一些定义,好的。准确包含您需要包装的内容。如果您只需要一个函数,请将其原型复制到 .i 中,而不是根据需要包含整个文件
猜你喜欢
  • 2017-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-17
  • 2023-03-10
相关资源
最近更新 更多