双到PyFloat转换是不正确 [英] double to PyFloat conversion is incorrect

查看:133
本文介绍了双到PyFloat转换是不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我学习痛饮,在Python中使用C。我已经写了这个功能,但我不明白,为什么包裹 MYFUNC 返回错误的浮点/双精度值:

I'm learning SWIG, for using C in Python. I've written this function, but I can't understand, why the wrapped myfunc returns wrong float/double values:

mfuncs.c

#include <stdlib.h>

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

mfuncs.i

mfuncs.i

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

extern float myfunc(int n);

最后我得到1107558400.0,而不是33.33333。

Finally I get 1107558400.0 instead of 33.33333.


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

在哪儿错了吗?

推荐答案

该SWIG类型映射是不必要的 - 它是默认提供的,你只需要编写typemaps为深奥的类型,默认双<提供/ code> / 浮动的是在这里很好。

The SWIG typemap is unneeded - it's provided by default, you only need to write typemaps for "esoteric" types and the default double/float ones provided are fine here.

这里真正的问题是,你不打开了警告编译或忽视他们! 这是什么值得与-Wall -Wextra或任何你的编译器编译的习惯要求,实现了最大的警告,并听取他们。

The real problem here is that you're not compiling with warnings enabled or ignoring them! It's really worth getting in the habit of compiling with "-Wall -Wextra" or whatever your compiler requires to enable maximum warnings and heeding them.

您痛饮接口只告诉的痛饮的有关函数 MYFUNC 但没有什么在接口作出声明提供给您使用的编译器编译生成的myfuncs_wrap.c。这意味着,当你来到编译你依靠 MYFUNC 的隐式声明的共享库。 GCC我的机器上-Wall此报告:

Your SWIG interface only tells SWIG about the function myfunc but there's nothing in that interface to make the declaration available to the compiler you use to compile the generated myfuncs_wrap.c. This means that when you come to compile the shared library you're relying on an implicit declaration of myfunc. GCC on my machine with -Wall reports this:

test_wrap.c:3139:3:警告:函数隐式声明MYFUNC

test_wrap.c:3139:3: warning: implicit declaration of function 'myfunc'

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

The implicit declaration assumes it returns int. That's just the rule in C if there is no declaration, it's as though you wrote:

#include <stdlib.h>

int myfunc(int n);

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

这显然是错误的(不确定的行为是精确的)给出 MYFUNC 定义返回浮动。你的实现(法律)选择做最简单的事情对于这个不确定的行为,这大概是从 INT 逐位投地浮动。 (它同样可以做的任何的,甚至一些在每次运行不同 - 这是未定义行为的美女)。

which is clearly wrong (undefined behaviour to be exact) given the definition of myfunc returns a float. Your implementation (legally) chooses to do the simplest thing for this undefined behaviour, which is roughly a bit-wise cast from int to float. (It could equally well do anything, even something different on every run - that's the beauty of undefined behaviour).

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

You can fix your SWIG interface by changing it to:

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

extern float myfunc(int n);

这工作,因为之间code %{%} 直接传递到生成的包装,这让编译器知道真正的声明 MYFUNC 建筑包装时。

this works because the code between %{ and %} is directly passed to the generated wrapper, which makes the compiler aware of the real declaration of myfunc when building the wrapper.

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

There's a nicer solution in my view though: provide the declaration only once, in a header file and then your interface file becomes:

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

%include "myfunc.h"

(显然的#includemyfunc.h在myfunc.c)。这样,你就只写声明一次,编译器会发出警告/错误,如果有什么事,这不是相当有料,而不是只取一个(通常是错误的)最好的猜测。

(and obviously #include "myfunc.h" in myfunc.c). In that way you only write the declaration once and the compiler will warn/error if there's anything that's not quite expected rather than just take a (usually wrong) best guess.

这篇关于双到PyFloat转换是不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆