双PyFloat转换不正确
我学习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 >>>
错误在哪里?
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
(未定义行为是精确的)。你的实现(合法)选择为这个未定义的行为做最简单的事情,这大致是从int
到float
。 (它也可以做任何事情,甚至在每次运行中都会有所不同 - 这是未定义行为的美妙之处)。
您可以将其更改为解决您的痛饮接口:
%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"
)。这样你只需要写一次声明,编译器会发出警告/错误,如果有什么不是预期的事情,而不是仅仅采取(通常是错误的)最佳猜测。
谢谢,这是解决方案 – Alexander 2012-07-10 07:25:40
@Alexander,您应通过其帖子左侧的复选标记将Flexo的答案标记为正确的答案。 – 2012-07-11 01:24:05
您在此代码中有两个错误,它们会阻止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
一个浮点/双精度。
这看起来不像我通常的swig typemap语法。为什么你使用typemaps进行转换swig无论如何都能正确使用? – Voo 2012-07-09 14:04:32
@Voo - typemap是合法的语法 - 它是[2元素类型列表](http://www.swig.org/Doc1.3/Typemaps.html#Typemaps_nn10)(不要与多参数类型映射混淆) ,你说的没错,但没有必要。 – Flexo 2012-07-09 16:05:24
@Flexo我对这个事实感到困惑,他把它定义为一个字符串,从来没有见过。对我来说似乎没有必要(我喜欢我的自动完成),但允许。很好抓住顺便说一句。 – Voo 2012-07-09 18:10:06