python将整数传递给c ++ 64位库:大小不一

时间:2015-11-04 10:09:59

标签: python c++ int ctypes

我正在以python soft(也是64位)加载64位c ++库。我注意到的第一个麻烦是通过以下protocole传递给库的一些整数大小不正确:

Python方面:

c_int = c_int64
polynomialFittingDLL.loadComputationFromPython.restype = None
polynomialFittingDLL.loadComputationFromPython.argtypes = [c_void_p,POINTER(c_int),POINTER(c_int),c_int,c_int,c_int,c_bool,POINTER(c_double),POINTER(c_double),POINTER(c_double)] 


self.polynomialFittingDLL.loadComputationFromPython(self.dll,
                              self.btuplesDllFlat.ctypes.data_as(POINTER(c_int)),
                              self.bterm.ctypes.data_as(POINTER(c_int)),
                              len(self.bterm),
                              sum(self.bterm),
                              len(self.rangeX),
                              baseType,
                              self.coefficients.ctypes.data_as(POINTER(c_double)),
                              self.rangeX.ctypes.data_as(POINTER(c_double)),
                              self.minX.ctypes.data_as(POINTER(c_double)))

C ++方面:

#ifdef _MSC_VER
    typedef __int64 int64_t;
#else
    #include <stdint.h>
#endif

DLL_EXPORT void loadComputationFromPython(PolynomialCurve* curve,__int64 *_btuple,
                     int *_bterm, int _btermSize,
                     int _Nvalidbtuple,int _Nparams,bool _polynomial,
                     double *_coefficients,
                     double *_rangeX,double *_minX) 
{
curve->loadComputationFromPython(_btuple,_bterm,_btermSize,_Nvalidbtuple,_Nparams,_polynomial,_coefficients,_rangeX,_minX);
}

void PolynomialCurve::loadComputationFromPython(__int64 *_btuple,
                     int *_bterm, int _btermSize,
                     int _Nvalidbtuple,int _Nparams,bool _polynomial,
                     double *_coefficients,
                     double *_rangeX,double *_minX) 
{
btermSize = _btermSize;
Nparams = _Nparams;
btuple = new int*[btermSize];
for (int i=0;i<btermSize;++i) {
    btuple[i] = new int[Nparams];
    for (int j=0;j<Nparams;++j) {
        btuple[i][j] = _btuple[i*Nparams+j];
    }
}
bterm = _bterm;
NvalidBtuple = _Nvalidbtuple;
polynomial = _polynomial;
coefficients = _coefficients;
rangeX = _rangeX;
minX = _minX;
}

我必须使用__int64类型才能拥有_btuple的正确整数类型。但是其他的int指针似乎仍然无法处理整数大小...

我的问题是如何在c ++代码中保持连贯,使所有int属性始终具有相同的位大小?我希望与python中的c_int大小保持一致的大小。 __int64类型是否足以解决我的问题?我可以定义__int64的指针吗?我应该同样小心双打吗?

当我从32位编译更改为64位时出现了这些问题。 感谢

修改 进一步观察到的是:

从python到c ++:python整数是64字节整数,我必须在C ++中指定接收的整数是64Bytes(使用__int64类型)

从C ++到python:C ++中的int类型是一个32字节的整数,当我在python中收到整数时,我必须用c_int32类型指定它的大小:

addrBtuples = self.polynomialFittingDLL.getBtuples(self.dll)
self.btuplesDllFlat = np.ctypeslib.as_array((c_int32 * self.btuplesSize).from_address(addrBtuples))

所以,为了尽可能地移植:我应该将python int“转换”为32字节的吗?或者我应该强制c ++库使用__int64类型?

2 个答案:

答案 0 :(得分:1)

我不确定我是否理解你的问题,但你不应该&#34;影子&#34; c_int c_int64c_int类型仍然是64位上的4个字节

>>> import platform
>>> platform.architecture()
('64bit', 'WindowsPE')
>>> import ctypes
>>> ctypes.sizeof(ctypes.c_int)
4

第二个参数应为POINTER(ctypes.c_int64)

# c_int = c_int64
polynomialFittingDLL.loadComputationFromPython.restype = None
polynomialFittingDLL.loadComputationFromPython.argtypes = [c_void_p,POINTER(ctypes.c_int64),POINTER(c_int),c_int,c_int,c_int,c_bool,POINTER(c_double),POINTER(c_double),POINTER(c_double)] 

此外,指针保持相同的大小,无论它们指向何种类型。

答案 1 :(得分:0)

C侧的int和double的大小取决于实现(标准仅指定最小大小)。所以,它可能取决于编译器。尽管如此,在大多数情况下,ctypes python库与C ++编译器在同一平台中的作用之间存在一致性。

因此,要解决此问题,您需要以连贯的方式从python端更改大小以获得正确的转换。 在你的情况下给出C函数签名,我认为python方面的以下签名可以工作(只将第一个更改为c_longlong):

polynomialFittingDLL.loadComputationFromPython.argtypes = [c_void_p,
                POINTER(c_longlong),
                POINTER(c_int),
                c_int,c_int,c_int,c_bool,
                POINTER(c_double),
                POINTER(c_double),POINTER(c_double)]

但是如果您的C ++编译器正在增加整数的大小,那么您应该尝试:

polynomialFittingDLL.loadComputationFromPython.argtypes = [c_void_p,
                POINTER(c_longlong),
                POINTER(c_long),
                c_long,c_long,c_long,c_bool,
                POINTER(c_double),
                POINTER(c_double),POINTER(c_double)]

如果双打也增加了:

polynomialFittingDLL.loadComputationFromPython.argtypes = [c_void_p,
                POINTER(c_longlong),
                POINTER(c_long),
                c_long,c_long,c_long,c_bool,
                POINTER(c_longdouble),
                POINTER(c_longdouble),POINTER(c_longdouble)]

有关所有ctypes数据类型的详细信息,请参阅heidi

关键是你需要检查ctypes和编译模块之间的转换是哪一个。

我建议测试边框情况(长整数和最小尺寸以及溢出)以确保一切正常。