结构变量重叠(Python C API)

时间:2014-04-29 23:51:22

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

这对你来说很奇怪:我一直在关注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'

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

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;
};

我一直无法找到类似的问题,请帮忙!

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

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 */
};

1 个答案:

答案 0 :(得分:0)

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

更改为T_UINT正是您需要做的事情;您现在使用适当的32位数据类型(unsigned int)而不是64位T_ULONG访问32位类型。