2012-11-16 9 views
1

我正在Mac上使用MacOSX 10.8.2與最新的xcode和stock python解釋器一起開發。Python整數傳遞到C++函數中,因爲使用ctypes得到的截詞被截短

下面是一些代碼,我投入fails.cpp

#include <iostream> 

using namespace std; 

extern "C" { 

void mysort(long *data, long data2) { 
    cout << hex << *data << ' ' << data2 << endl; 
} 

} 

這裏的一些代碼來調用它從蟒蛇,我把在fails.py

import ctypes 

sort_dll = ctypes.CDLL("fails.dylib") 
mysort = ctypes.CFUNCTYPE(None, ctypes.POINTER(ctypes.c_long), ctypes.c_long)(sort_dll.mysort) 

a = ctypes.c_long(0x987654321) 
mysort(ctypes.byref(a), 0x123456789) 

我編譯和

c++ -arch x86_64 -o fails.o -c fails.cpp && g++ -o fails.dylib -dynamiclib fails.o && python fails.py 
運行

結果是:

987654321 23456789 

爲什麼按值傳遞的64位整數被截斷爲32位?令人驚訝的是,指向64位長的指針不會被截斷。

回答

1

我懷疑這是因爲Python的ctypes庫已經決定c_long的大小是32位。 docs中有一些提示:

表示C signed int數據類型。構造函數接受一個可選的整數初始值設定項;沒有溢出檢查完成。 在sizeof(int)== sizeof(long)的平臺上,它是c_long的別名。

此代碼會告訴你大c_long實際上是如何爲:

import ctypes 
print ctypes.sizeof(ctypes.c_long()) 

值的指針引用不會因爲ctypes的被截斷,只需要馬歇爾指針本身。指針可能被截斷,但無論如何高位都爲零並不重要。 ctypes也可能決定ctypes.POINTER是64位的。你可以通過稍微修改上面的例子來找到答案。

+0

好主意。但'ctypes.sizeof(ctypes.c_long())'給出8,所以它不會被截斷,因爲它具有'c_long'的錯誤大小。儘管如此,我傾向於認爲這是一個錯誤,儘管如此明顯的錯誤會被基本測試所捕獲。 – sigfpe

+0

這可能是bug從Python int到c_long的隱式轉換。作爲一種解決方法,可能值得嘗試使用顯式ctypes.c_long(0x123456789)作爲解決方法,甚至是int64。 –

+0

我已經嘗試了很多代碼顯式轉換爲64位整數的組合,並且它們都似乎失敗了。我的解決方法是通過引用傳遞。它工作正常,但我不知道我能信任什麼...... – sigfpe