用c扩展python时,如何处理任意大小的整数?

2024-10-03 09:15:25 发布

您现在位置:Python中文网/ 问答频道 /正文

Python/C API手册提到了从⁽¹⁾到⁽²⁾void指针的转换函数,这似乎是在C中使用任意长度Python整数的唯一方法。
(1) :PyLong_FromVoidPtr()并用Py_BuildValue()格式化0&
(2) :PyLong_AsVoidPtr()和格式00&0!PyArg_…Parse…()

但是,我在手册中没有找到任何关于如何使用这些空指针来处理C中的任意长整数的指示。
(3) :我尝试搜索«voidptr»、«void*»和«0&;»,但尚未完全阅读。你知道吗

我在哪里可以找到关于它们内部结构的信息,或者在它们上面计算的原语?你知道吗


Tags: 方法函数pyapiparse格式整数手册
2条回答

Include/longintrepr.h中有文档:

/* Parameters of the integer representation.  There are two different
   sets of parameters: one set for 30-bit digits, stored in an unsigned 32-bit
   integer type, and one set for 15-bit digits with each digit stored in an
   unsigned short.  The value of PYLONG_BITS_IN_DIGIT, defined either at
   configure time or in pyport.h, is used to decide which digit size to use.

   Type 'digit' should be able to hold 2*PyLong_BASE-1, and type 'twodigits'
   should be an unsigned integer type able to hold all integers up to
   PyLong_BASE*PyLong_BASE-1.  x_sub assumes that 'digit' is an unsigned type,
   and that overflow is handled by taking the result modulo 2**N for some N >
   PyLong_SHIFT.  The majority of the code doesn't care about the precise
   value of PyLong_SHIFT, but there are some notable exceptions:

   - long_pow() requires that PyLong_SHIFT be divisible by 5

   - PyLong_{As,From}ByteArray require that PyLong_SHIFT be at least 8

   - long_hash() requires that PyLong_SHIFT is *strictly* less than the number
     of bits in an unsigned long, as do the PyLong <-> long (or unsigned long)
     conversion functions

   - the Python int <-> size_t/Py_ssize_t conversion functions expect that
     PyLong_SHIFT is strictly less than the number of bits in a size_t

   - the marshal code currently expects that PyLong_SHIFT is a multiple of 15

   - NSMALLNEGINTS and NSMALLPOSINTS should be small enough to fit in a single
     digit; with the current values this forces PyLong_SHIFT >= 9

  The values 15 and 30 should fit all of the above requirements, on any
  platform.
*/

int的长度是可变长度部分的长度乘以15/16位-数字要么是30 bits in ^{}, ^{},要么是15 bits in ^{};长对象的结构是

struct _longobject {
    PyObject_VAR_HEAD
    digit ob_digit[1];
};

有一个成员ob_size将以字节表示大小-因此,如果PYLONG_BITS_IN_DIGIT是30,那么ob_digit是一个ob_size / sizeof(uint32_t)uint32_t的数组,30位在每个位中是有效的;否则ob_digit是一个ob_size / sizeof(uint16_t)uint16_t的数组,15位在每个位中存储。你知道吗

这都是Include/longintrepr.h的一部分,但它们只被#ifndef Py_LIMITED_API揭示!你知道吗

实际上,这些函数不是要有“指向任意大整数的指针”,而是字面上的整数值作为void *指针,例如,强制转换为void *类型。参见^{}^{}的实现。它只允许您在Python中保存任意指针,以确保正确完成转换。你知道吗

据我所知,从Python中获取任意长整数最实用的方法是使用^{}^{}。实际上有一个内部ishapi ^{}/^{},您可以使用它。参见相关问题Python extension - construct and inspect large integers efficiently。你知道吗

注意:有趣的是,似乎没有任何官方或其他的C API来告诉Python整数值的位或字节长度。在Python中有^{},但它似乎没有映射到任何公开可用的函数。你知道吗

相关问题 更多 >