【问题标题】:Struct variables overlap (Python C API)结构变量重叠(Python C API)
【发布时间】:2014-04-29 23:51:22
【问题描述】:

这对你来说很奇怪:我一直在遵循this tutorial 的框架,试图编写一个 Python 模块,该模块将返回一个包含 C 函数结果的结构。

C 结构体是这样定义的:

typedef struct my_struct
{
    // Initialize refcount and pointer to type objects (no ';' )
    PyObject_HEAD

    // Components of the structure go here.
    uint32_t width; // unsigned long
    uint32_t height; // unsigned long
    uint8_t numcomps; // unsigned char
    uint8_t bitspercomp; // unsigned char
    uint8_t bytespercomp; // unsighed char
    uint32_t total_data_len; // unsigned long
    int data;

} my_struct;

问题是在 Python 级别访问时,结构的成员似乎在内存中重叠!表格输入:

my_struct.My_Struct(unsigned_long 1, unsigned_long 2, unsigned_char 3, unsigned_char 4, unsigned_char 5, unsigned_long 6, int 7)

存储在返回位置的值明显重叠。当它们表示为十六进制值时,最容易看出这一点:

In [1]: import my_struct as ms

In [2]: op = ms.My_Struct(1,2,3,4,5,6,7)

In [3]: myfi.width
Out[3]: 8589934593L  ***should be "1"***

In [4]: "%x"%op.width
Out[4]: '200000001'

In [5]: "%x"%op.height
Out[5]: '5040300000002'

In [6]: "%x"%op.numcomps
Out[6]: '3'

In [7]: "%x"%op.bitspercomp
Out[7]: '4'

In [8]: "%x"%op.bytespercomp
Out[8]: '5'

In [9]: "%x"%op.total_data_len
Out[9]: '700000006'

In [10]: "%x"%op.data
Out[10]: '7'

输入参数的分配发生在一个调用方法Py_Arg_ParseTupleAndKeywords()的init函数中:

static int
my_struct_init(my_struct *self, PyObject *args, PyObject *kwds)
{
    static char *kwlist[] = 
    {"width","height","numcomps","bitspercomp","bytespercomp","total_data_len","data", NULL};

    // Increase reference count before parsing
    Py_INCREF(self);

    if (! PyArg_ParseTupleAndKeywords(args, kwds, "kkbbbki"
                                      , kwlist, &self->width, &self->height,
                                      &self->numcomps, &self->bitspercomp, 
                                      &self->bytespercomp,
                                      &self->total_data_len, &self->data))
        return -1;

    return 0;
};

一直找不到类似的问题,请帮忙!

脚本的其余部分遵循示例的格式。有一个“新”函数将每个结构成员值设置为零,还有一个析构函数。可能相关的是模块成员定义:

static PyMemberDef my_struct_members[] = {
    /*member name, type, offset, access flags, documentation string*/
    {"width", T_ULONG, offsetof(my_struct, width), 0,
     "words and such."},
    {"height", T_ULONG, offsetof(my_struct, height), 0,
     "words and such."},
    {"numcomps", T_UBYTE, offsetof(my_struct, numcomps), 0,
     "words and such."},
    {"bitspercomp", T_UBYTE, offsetof(my_struct, bitspercomp), 0,
     "words and such."},
    {"bytespercomp", T_UBYTE, offsetof(my_struct, bytespercomp), 0,
     "words and such."},
    {"total_data_len", T_ULONG, offsetof(my_struct, total_data_len), 0,
     "words and such."},
    {"data", T_UINT, offsetof(my_struct, data), 0,
     "words and such."},

    {NULL}  /* Sentinel */
};

【问题讨论】:

  • 经过进一步研究,发现my_struct_members中将T_ULONG类型替换为T_UINT时不会出现这种行为。 T_ULONG 行为仍然让我感到困惑。

标签: memory-management struct python-module python-c-api


【解决方案1】:

看起来您正在使用 unsigned long 是 64 位类型的系统(可能是 64 位机器和操作系统),因此将这些字段定义为 uint32_t 和通过 T_ULONG 访问它们之间存在不匹配。

更改为 T_UINT 正是您需要做的;您现在可以使用适当的 32 位数据类型(无符号整数)而不是 64 位 T_ULONG 访问 32 位类型。

【讨论】:

  • 是的,你是对的!我没有意识到 Python 以这种方式区分 long 和 int 。谢谢!
猜你喜欢
  • 2023-03-05
  • 1970-01-01
  • 2015-05-21
  • 1970-01-01
  • 1970-01-01
  • 2017-10-28
  • 1970-01-01
  • 2013-03-30
  • 2016-05-09
相关资源
最近更新 更多