我正在学习SWIG,在Python中使用C。我已经编写了这个函数,但是我不明白,为什么wrappedmyfunc返回错误的float/double值:
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。
>>>导入mfuncs
>>>mfuncs.myfunc(三)
十一亿零七百五十五万八千四百
>>>
哪里出错了?

最佳答案

SWIG类型映射是不需要的-它是默认提供的,您只需要为“深奥”类型编写类型映射,这里提供的默认类型也可以。
这里真正的问题是,您没有在编译时启用或忽略警告!使用“-Walth-WEPUT”或编译程序所需的最大警告和注意,这是非常值得的。
SWIG接口只告诉SWIG关于函数double的信息,但该接口中没有任何东西可以让用于编译生成的myfuncs_wrap.c的编译器使用声明。这意味着,当您编译共享库时,您依赖于一个隐式声明float。我的挂墙机器上的GCC报告如下:
test_wrap.c:3139:3:警告:函数“myfunc”的隐式声明
隐式声明假定它返回myfunc。这只是C中的规则,如果没有声明,就好像你写了:

#include <stdlib.h>

int myfunc(int n);

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

这显然是错误的(确切地说是未定义的行为),因为myfunc的定义返回一个int。您的实现(合法地)选择为这种未定义的行为做最简单的事情,这大致是从myfuncfloat的一个有点明智的转换。(它同样可以做任何事情,甚至在每次运行中都可以做一些不同的事情——这就是未定义行为的美)。
您可以将SWIG接口更改为:
%module mfuncs
%{
extern float myfunc(int n);
%}

extern float myfunc(int n);

这是因为intfloat之间的代码直接传递给生成的包装器,这使得编译器在构建包装器时知道%{的真正声明。
不过,在我的视图中有一个更好的解决方案:只在头文件中提供一次声明,然后接口文件变成:
%module mfuncs
%{
#include "myfunc.h"
%}

%include "myfunc.h"

(在myfunc.c中明显%})。这样,您只需编写一次声明,如果有任何不太符合预期的内容,编译器将发出警告/错误,而不是只进行(通常是错误的)最佳猜测。

关于python - double到PyFloat的转换不正确,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11395600/

10-12 16:05