Python ctypes - 内存读取在DLL中调用函数时出错

时间:2012-03-23 05:42:51

标签: python ctypes

我是python和ctypes的初学者,我正在编写一个脚本来控制PCMCIA设备,供应商提供的驱动程序是一个dll文件。我只是想调用它中的函数,但我只是不知道为什么我一直得到[在“0x7c9108d3”处的指令引用了“0xfffffff8”的内存。内存无法“读取”]。这是文件说:

//declaration
XLstatus xlGetDriverConfig(XLdriverConfig *pDriverConfig) 

typedef struct s_xl_driver_config  { 
    unsigned int      dllVersion; 
    unsigned int      channelCount;  
    unsigned int      reserved[10]; 
    XLchannelConfig   channel[XL_CONFIG_MAX_CHANNELS]; 
} XLdriverConfig; 

//types
typedef struct s_xl_channel_config { 

    char            name [XL_MAX_LENGTH + 1]; 
    unsigned char   hwType; 
    unsigned char   hwIndex;  
    unsigned char   hwChannel; 
    unsigned short  transceiverType;  
    unsigned int    transceiverState; 
    unsigned char   channelIndex;    

    XLuint64      channelMask;      //here  
    unsigned int  channelCapabilities; 
    unsigned int  channelBusCapabilities; 
    unsigned char isOnBus; 
    unsigned int  connectedBusType; 
    XLbusParams   busParams; 
    unsigned int  driverVersion; 
    unsigned int  interfaceVersion; 
    unsigned int  raw_data[10]; 
    unsigned int  serialNumber; 
    unsigned int  articleNumber; 
    char          transceiverName [XL_MAX_LENGTH + 1]; 
    unsigned int  specialCabFlags; 
    unsigned int  dominantTimeout; 
    unsigned int  reserved[8]; 
} XLchannelConfig; 

typedef unsigned __int64 XLuint64;

typedef struct {                                                                         
  unsigned int busType;
  union {
    struct {
      unsigned int bitRate;
      unsigned char sjw;
      unsigned char tseg1;
      unsigned char tseg2;
      unsigned char sam;  // 1 or 3
      unsigned char outputMode;
    } can;
    struct {
      unsigned int  activeSpeedGrade;
      unsigned int  compatibleSpeedGrade;
    } most;
    unsigned char raw[32];
  }data;
} XLbusParams; 

下面有我的python脚本:

from ctypes import *
vxlapi = WinDLL("vxlapi.dll")
PyxlGetDriverConfig = vxlapi.xlGetDriverConfig

class PyXLchannelConfig(Structure):
    _fields_ = [("Pyname",c_char*32),
                ("PyhwType",c_ubyte),
                ("PyhwIndex",c_ubyte),
                ("PyhwChannel",c_ubyte),
                ("PytransceiverType",c_ushort),
                ("PytransceiverState",c_ushort),
                ("PyconfigError",c_ushort),
                ("PychannelIndex",c_ubyte),
                ("PychannelMask",c_longlong),
                ("PychannelCapabilities",c_uint),
                ("PychannelBusCapabilities",c_uint),

                ("PyisOnBus",c_ubyte),
                ("PyconnectedBusType",c_uint),
                ("PybusParams",c_uint),

                ("PydriverVersion",c_uint),
                ("PyinterfaceVersion",c_uint),
                ("Pyraw_data",c_uint*10),

                ("PyserialNumber",c_uint),
                ("PyarticleNumber",c_uint),

                ("PytransceiverName",c_char*32),

                ("PyspecialCabFlags",c_uint),
                ("PydominantTimeout",c_uint),
                ("PydominantRecessiveDelay",c_ubyte),
                ("PyrecessiveDominantDelay",c_ubyte),
                ("PyconnectionInfo",c_ubyte),
                ("PycurrentlyAvailableTimestamps",c_ubyte),
                ("PyminimalSupplyVoltage",c_ubyte),
                ("PymaximalSupplyVoltage",c_ubyte),
                ("PymaximalBaudrate",c_uint),
                ("PyfpgaCoreCapabilities",c_ubyte),
                ("PyspecialDeviceStatus",c_ubyte),
                ("PychannelBusActiveCapabilities",c_ushort),
                ("PybreakOffset",c_ushort),
                ("PydelimiterOffset",c_ushort),
                ("Pyreserved",c_uint*3)
                ]

class PyXLdriverConfig(Structure):
    _fields_ = [("PydllVersion",c_uint),
                ("PychannelCount",c_uint),
                ("Pyreserved",c_uint*10),
                ("Pychannel",PyXLchannelConfig*64)
                ]

if __name__ == "__main__":
    drivercfg = PyXLdriverConfig()
    PyxlGetDriverConfig(byref(drivercfg))

你能帮我解决这个问题吗,非常感谢你!

3 个答案:

答案 0 :(得分:0)

我发现至少有两个不同之处:

unsigned int    transceiverState; 
("PytransceiverState",c_ushort),

XLbusParams   busParams; 
("PybusParams",c_uint),

答案 1 :(得分:0)

您的代码中存在一些错误,但大多数错误都在那里。

我假设以下定义出现在原始C中。

#define XL_CONFIG_MAX_CHANNELS (64)
#define XL_MAX_LENGTH (31)

虽然我觉得XL_MAX_LENGTH可能定义为32。

我认为问题源于你的ctypes结构,你的C结构大小不同,所以你的库正在读/写内存,不允许访问。

以下是相关问题:

  • ctypes结构中有一些错误的类型; PytransceiverState应该是c_uint,而不是c_ushort; PyconfigError应该是c_ulonglong,而不是c_longlong);等
  • 有很多错误的领域;什么是PyconfigError的C等价物; PydominantTimeout之后的所有ctypes字段来自哪里?
  • 您没有定义等同于XLBusParams的ctypes结构,而是使用c_uint。由于XLBusParams的大小至少为45个字节,而您提供4个字节,因此会发生不好的事情。

答案 2 :(得分:0)

你有没有看过这个用于python的vxlapi的包装器: http://code.google.com/p/pycanlibxl/

请注意,它不会实现所有vxlapi.dll函数和头文件常量和枚举。 此外,一些函数定义具有默认值,可能不适合您(例如接口类型)。