Я занимаюсь разработкой на 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-битную длину не усекается.
Я подозреваю, что это потому, что библиотека Python ctypes решила, что размер c_long составляет 32 бита. Есть некоторые подсказки в документы:
Представляет тип данных со знаком C. Конструктор принимает необязательный целочисленный инициализатор; проверка переполнения не производится. На платформах, где sizeof (int) == sizeof (long) это псевдоним c_long.
Этот код скажет вам, насколько велик c_long:
import ctypes
print ctypes.sizeof(ctypes.c_long())
Значение, на которое ссылается указатель, не будет усечено, поскольку ctypes должен только маршалировать сам указатель. Возможно, указатель усекается, но это не имеет значения, поскольку старшие биты все равно равны нулю. Также возможно, что ctypes решил, что ctypes.POINTER является 64-битным. Вы можете узнать, немного изменив приведенный выше пример.
Других решений пока нет …