【问题标题】:Python & Ctypes: Wrong data when reading structure passed as parameterPython & Ctypes:读取作为参数传递的结构时数据错误
【发布时间】:2015-02-02 17:14:14
【问题描述】:

我正在尝试将 ctypes 结构传递给 DLL。问题是DLL从结构中读取的数据是垃圾。这不是我在 ctypes 中实现的第一个结构,但它比我做过的其他结构更复杂。

结构定义如下:

typedef struct {
    double L, x, y;
} CieLxy;


typedef struct {
    int ledCur[3];
    CieLxy targetCie, modelCie, measuredCie;
} I1VpCal;


typedef struct {
    I1VpCal i1CalArray[8][7];
} I1CalArray;

具有以下测试功能:

int foo(I1CalArray* p_i1CalArray)
{
    int i, j;

    for (i=0; i<8; i++)
    {
        for (j=0; j<7; j++)
        {
            printf("in dll, i1CalArray[%d][%d].ledCur[0] = %d\n", 
                   i, j, p_i1CalArray->i1CalArray[i][j].ledCur[0]);
            printf("in dll, i1CalArray[%d][%d].measuredCie.L = %f\n", 
                   i, j, p_i1CalArray->i1CalArray[i][j].measuredCie.L);
        }    
    }
    return 0;
}

在 Python 中,我有以下 ctypes 定义:

class CieLxy(ctypes.Structure):
    _fields_ = [("L", ctypes.c_double),
                ("x", ctypes.c_double),
                ("y", ctypes.c_double)]


class I1VpCal(ctypes.Structure):
    _fields_ = [("ledCur", ctypes.c_int * 3),
                ("targetCie", CieLxy),
                ("modelCie", CieLxy),
                ("measuredCie", CieLxy)]


class I1CalArray(ctypes.Structure):
    _fields_ = [("i1CalArray", 8*(7*I1VpCal))]


Foo = Dll['foo']
# Foo.argtypes = [ctypes.POINTER(I1CalArray)]
Foo.argtypes = [ctypes.c_void_p]
Foo.restype = ctypes.c_int

def foo( i1CalArray):
#     p_i1CalArray = ctypes.POINTER(I1CalArray)
#     Foo(p_I1CalArray.from_address(ctypes.addressof(i1CalArray)))
#     Foo(i1CalArray)
    Foo(ctypes.byref(i1CalArray))

当我运行以下代码时:

i1CalArray_struct = I1CalArray()    
i1CalArray = i1CalArray_struct.i1CalArray

for i in range(8):
    for j in range(7):
        temp = i1CalArray[i][j].ledCur[0] = i+j
        temp = i1CalArray[i][j].measuredCie.L = float(i+j)

foo(i1CalArray_struct)

它打印的数据是垃圾。它看起来更像地址。

in dll, i1CalArray[0][0].ledCur[0] = 2620124
in dll, i1CalArray[0][0].measuredCie.L = -166230287672847070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000
in dll, i1CalArray[0][1].ledCur[0] = 31662056
in dll, i1CalArray[0][1].measuredCie.L = 0.000000
in dll, i1CalArray[0][2].ledCur[0] = 36890704
in dll, i1CalArray[0][2].measuredCie.L = 0.000000
in dll, i1CalArray[0][3].ledCur[0] = 488321588
in dll, i1CalArray[0][3].measuredCie.L = 0.000000
in dll, i1CalArray[0][4].ledCur[0] = 0

对此的任何帮助将不胜感激。看了很多帖子,尝试了不同的解决方案,但结果总是一样。

使用适用于 Windows、Mac 和 Linux 的 Python 2.7。 谢谢

【问题讨论】:

  • 我的错误,我删除了一些东西以避免混淆。我错过了那个。
  • 谢谢,您的回答让我看到了我的错误!我在 byref() 上使用了错误的对象。您想提供答案以便我为您投票吗?
  • Foo.argtypes = [ctypes.POINTER(I1CalArray)] 是正确的,对于文字实现。然后调用foo(i1CalArray_struct),它调用Foo(ctypes.byref(i1CalArray))。那应该行得通。当我测试使用 VS 2010 创建的 32 位和 64 位版本时,它对我有用。
  • 它确实有效。谢谢。
  • 您可以稍后添加答案。

标签: python c ctypes


【解决方案1】:

感谢评论,我能够看到错误。我没有正确使用 byref 变量。见 cmets。正确使用 byref 变量时,代码会按预期工作。


编辑

按照评论中的要求,这是我最后使用的。

class I1CalArray(ctypes.Structure):
    _fields_ = [("i1CalArray", 8*(7*I1VpCal))]


Foo = Dll['foo']
Foo.argtypes = [ctypes.POINTER(I1CalArray)] 
def foo( i1CalArray):
    Foo(ctypes.byref(i1CalArray))   
    return i1CalArray

【讨论】:

  • 您能否在答案中添加示例代码,突出显示问题所在以及如何解决?
  • 我已经有一段时间没有使用它了。我根据我记得的内容和剩下的 cmets 编辑了我的答案。我现在无法测试它。我会尽快尝试测试它。
猜你喜欢
  • 2011-05-20
  • 1970-01-01
  • 2020-04-01
  • 2021-05-22
  • 1970-01-01
  • 2011-07-13
  • 1970-01-01
  • 1970-01-01
  • 2016-02-22
相关资源
最近更新 更多