Python int使用ctypes被截断后传入C ++函数

时间:2012-11-16 01:16:01

标签: c++ python macos ffi

我正在Mac上使用MacOSX 10.8.2开发最新的xcode和股票python解释器。

以下是我在fails.cpp

中添加的一些代码
#include <iostream>

using namespace std;

extern "C" {

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

}

这里有一些代码可以从python中调用它来放入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 个答案:

答案 0 :(得分: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位的。您可以通过略微修改上述示例来找到答案。