2012-07-09 100 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一個浮點/雙精度。