2012-07-09 71 views
2

我学习SWIG,在Python中使用C语言。我已经写了这个功能,但我不明白,为什么包裹myfunc返回错误的浮点/双精度值:双PyFloat转换不正确

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。

 
>>> import mfuncs 
>>> mfuncs.myfunc(3) 
1107558400.0 
>>> 

错误在哪里?

+0

这看起来不像我通常的swig typemap语法。为什么你使用typemaps进行转换swig无论如何都能正确使用? – Voo 2012-07-09 14:04:32

+0

@Voo - typemap是合法的语法 - 它是[2元素类型列表](http://www.swig.org/Doc1.3/Typemaps.html#Typemaps_nn10)(不要与多参数类型映射混淆) ,你说的没错,但没有必要。 – Flexo 2012-07-09 16:05:24

+0

@Flexo我对这个事实感到困惑,他把它定义为一个字符串,从来没有见过。对我来说似乎没有必要(我喜欢我的自动完成),但允许。很好抓住顺便说一句。 – Voo 2012-07-09 18:10:06

回答

4

SWIG类型图不需要 - 它是默认提供的,你只需要为“深奥”类型编写类型映射,并且在这里提供的默认值是很好的。

这里真正的问题是,您不是编译时启用了警告或忽略它们! 确实值得养成用“-Wall -Wextra”编译的习惯,或者你的编译器需要启用最大警告并注意它们。

你痛饮接口只告诉痛饮有关函数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。 (它也可以做任何事情,甚至在每次运行中都会有所不同 - 这是未定义行为的美妙之处)。

您可以将其更改为解决您的痛饮接口:

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

extern float myfunc(int n); 

这个工作,因为%{%}之间的代码被直接传递到生成的包装,这使得编译器知道myfunc真正的声明当建造包装。

有一个在我看来,一个更好的解决办法,但:提供报关只有一次,在一个头文件,然后你的接口文件就变成了:

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

%include "myfunc.h" 

(和myfunc.c明显#include "myfunc.h")。这样你只需要写一次声明,编译器会发出警告/错误,如果有什么不是预期的事情,而不是仅仅采取(通常是错误的)最佳猜测。

+0

谢谢,这是解决方案 – Alexander 2012-07-10 07:25:40

+1

@Alexander,您应通过其帖子左侧的复选标记将Flexo的答案标记为正确的答案。 – 2012-07-11 01:24:05

1

您在此代码中有两个错误,它们会阻止myfunc(3)返回您期望的33.3333。 Flexo奇妙地解释了包装问题。另一个问题是这样的线

result = 100/n; 

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

只是把上面一行

result = 100.0/n; 

或使n一个浮点/双精度。