我正在以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类型?
答案 0 :(得分:1)
我不确定我是否理解你的问题,但你不应该&#34;影子&#34; c_int
c_int64
:c_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和编译模块之间的转换是哪一个。
我建议测试边框情况(长整数和最小尺寸以及溢出)以确保一切正常。