2014-04-29 15 views
0

這裏有一個奇怪的例子:我一直在關注this tutorial的框架,試圖編寫一個Python模塊,它將返回一個包含C函數結果的結構體。結構變量重疊(Python C API)

的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()

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

經過進一步研究,我發現當'my_struct_members'中的T_ULONG類型替換爲T_UINT時,不會發生此行爲。 T_ULONG的行爲仍然讓我感到困惑。 – Ian

回答

0

看起來像你的系統(可能是64機和操作系統),其中無符號長是64位類型的工作,所以確定這些字段之間的不匹配uint32_t並通過T_ULONG訪問它們。

更改爲T_UINT正是您需要做的;您現在可以使用適當的32位數據類型(無符號整數)而不是64位T_ULONG訪問32位類型。

+0

是的,你是對的!我沒有意識到Python以這種方式區分long和int。謝謝! – Ian