【问题标题】:double to PyFloat conversion is incorrectdouble 到 PyFloat 的转换不正确
【发布时间】:2012-07-09 13:03:23
【问题描述】:

我正在学习 SWIG,用于在 Python 中使用 C。我已经写了这个函数,但我不明白,为什么包装的myfunc 返回错误的浮点/双精度值:

mfuncs.c

#include <stdlib.h>

float myfunc(int n) {
    float result;
    result = 100 / n;
    return result;
}

mfuncs.i

%module mfuncs
%typemap(out) double, float "$result = PyFloat_FromDouble($1);"

extern float myfunc(int n);

最后我得到 1107558400.0 而不是 33.33333。

>>> 导入 mfunc >>> mfuncs.myfunc(3) 1107558400.0 >>>

错在哪里?

【问题讨论】:

  • 对我来说,这看起来不像通常的 swig typemap 语法。你为什么要使用 typemaps 来转换 swig 无论如何都是正确的?
  • @Voo - 类型映射是合法的语法 - 它是 2 element typelist(不要与多参数类型映射混淆),但你说得对,它是不必要的。
  • @Flexo 我对他将其定义为字符串这一事实感到困惑,以前从未见过。对我来说似乎没有必要(我喜欢我的自动完成),但允许。顺便说一句,很好。

标签: python c swig


【解决方案1】:

不需要 SWIG 类型映射 - 它是默认提供的,您只需要为“深奥”类型编写类型映射,这里提供的默认 double/float 就可以了。

这里真正的问题是您没有在编译时启用或忽略警告! 确实值得养成使用“-Wall -Wextra”或编译器所需的任何东西来启用最大警告并注意它们的习惯。

您的 SWIG 接口只告诉 SWIG 关于函数 myfunc 的信息,但该接口中没有任何内容可以使您用于编译生成的 myfuncs_wrap.c 的编译器可以使用该声明。这意味着当您编译共享库时,您依赖于myfunc 的隐式声明。我的机器上的 GCC 使用 -Wall 报告这个:

test_wrap.c:3139:3:警告:函数“myfunc”的隐式声明

隐式声明假定它返回int。如果没有声明,这只是 C 中的规则,就好像你写的一样:

#include <stdlib.h>

int myfunc(int n);

int main() {
  printf("%d\n", myfunc(3));   
  return 0;
}

鉴于myfunc 的定义返回float,这显然是错误的(确切地说是未定义的行为)。您的实现(合法地)选择为这种未定义的行为做最简单的事情,这大致是从intfloat 的按位转换。 (它同样可以做任何事情,甚至在每次运行时都做一些不同的事情——这就是未定义行为的美妙之处。

您可以将 SWIG 界面更改为:

%module mfuncs
%{
extern float myfunc(int n);
%}

extern float myfunc(int n);

这是因为%{%} 之间的代码直接传递给生成的包装器,这使得编译器在构建包装器时知道myfunc 的真实声明。

在我看来有一个更好的解决方案:只提供一次声明,在头文件中,然后你的接口文件变为:

%module mfuncs
%{
#include "myfunc.h"
%}

%include "myfunc.h"

(显然是 #include "myfunc.h" 在 myfunc.c 中)。这样,您只需编写一次声明,如果有任何不完全预期的内容,编译器将发出警告/错误,而不是仅仅采取(通常是错误的)最佳猜测。

【讨论】:

  • @Alexander,您应该通过他帖子左侧的复选标记将 Flexo 的答案标记为正确答案。
【解决方案2】:

此代码中有两个错误阻止myfunc(3) 返回您期望的 33.3333。 Flexo 精彩地解释了包装问题。另一个问题是这一行

    result = 100 / n;

100 是一个 int,n 是一个 int,除法的结果将是一个 int,然后转换为 float。所以myfunc(3) == 33。 Python 2 的行为方式相同,在 Python 3 中进行了更改,使得两个整数的除法产生一个浮点数。

只需将该行更改为

    result = 100.0 / n;

或将n 设为浮点数/双精度数。

【讨论】:

    猜你喜欢
    • 2015-03-17
    • 1970-01-01
    • 2021-01-04
    • 2022-10-20
    • 1970-01-01
    • 2023-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多