2013-03-18 127 views
2

我尝试通过DLL(由PLC制造商分发的C API接口)与PLC通信。我使用Python 3.1作为脚本环境嵌入到其他软件(x64 - Windows 7)中。Python Ctypes异常:访问违规读取

我设法得到一些DLL函数的工作,但现在得到一个“访问冲突阅读”,我无法解决。

对DLL功能的信息:

LONG AdsSyncReadReq(
    PAmsAddr pAddr, 
    ULONG  nIndexGroup, 
    ULONG  nIndexOffset, 
    ULONG  nLength, 
    PVOID  pData 
); 

参数:

  • PADDR:[中]与NETID和ADS服务器的端口号结构。
  • nIndexGroup:[in]索引组。
  • nIndexOffset:[in]索引偏移量。
  • nLength:[in]以字节为单位的数据长度。
  • pData:[out]指向将接收数据的数据缓冲区的指针。
  • 返回值:返回函数的错误状态。

结构AmsAddr:

typedef struct { 
    AmsNetId  netId; 
    USHORT   port; 
} AmsAddr, *PAmsAddr; 

结构AmsNetId

typedef struct { 
    UCHAR  b[6]; 
} AmsNetId, *PAmsNetId; 

Python实现:

# -*- coding: utf-8 -*- 
from ctypes import * 

#I've tried OleDll and windll as wel.. 
ADS_DLL = CDLL("C:/Program Files/TwinCAT/Ads Api/TcAdsDll/x64/TcAdsDll.dll") 

class AmsNetId(Structure): 
    _fields_ = [('NetId', c_ubyte*6)] 

class AmsAddr(Structure): 
    _fields_=[('AmsNetId',AmsNetId),('port',c_ushort)] 

# DLL function working fine 
version = ADS_DLL.AdsGetDllVersion() 
print(version) 

#DLL function working fine 
errCode = ADS_DLL.AdsPortOpen() 
print(errCode) 

#DLL function using the AmsAddr() class, working fine 
amsAddress = AmsAddr() 
pointer_amsAddress = pointer(amsAddress) 
errCode = ADS_DLL.AdsGetLocalAddress(pointer_amsAddress) 
print(errCode) 
contents_amsAddres = pointer_amsAddress.contents 

#Function that doens't work: 
errCode = ADS_DLL.AdsSyncReadReq() 
print(errCode) # --> errCode = timeout error, normal because I didn't pass any arguments 

# Now with arguments: 
plcNetId = AmsNetId((c_ubyte*6)(5,18,18,27,1,1)) #correct adress to the PLC 
plcAddress = AmsAddr(plcNetId,801) #correct port to the PLC 
nIndexGroup = c_ulong(0xF020) 
nIndexOffset = c_ulong(0x0) 
nLength = c_ulong(0x4) 
data = c_void_p() 
pointer_data = pointer(data) 

#I tried with an without the following 2 lines, doesn't matters 
ADS_DLL.AdsSyncReadReq.argtypes=[AmsAddr,c_ulong,c_ulong,c_ulong,POINTER(c_void_p)] 
ADS_DLL.AdsSyncReadReq.restype=None 

#This line crashes 
errCode = ADS_DLL.AdsSyncReadReq(plcAddress,nIndexGroup,nIndexOffset,nLength,pointer_data) 
print(errCode) 


>>>> Error in line 57: exception: access violation reading 0xFFFFFFFFFFFFFFFF 

我希望任何人都无法弄清楚什么是错的。我只是在Python编程没有任何经验,在C中的全部先进新手提前

感谢

回答

2

你传递无效指针,提供一个有效的内存缓冲区,而不是:

data = create_string_buffer(nLength) 

的参数应该只是c_void_p而不是POINTER(c_void_p)如果PVOID表示void *。不要将restype设置为None(函数返回LONG)。

同样通过pointer(plcAddress)(在argtypes中指定POINTER(AmsAddr))。

使用正确的调用约定(在cdll,windll,oledll之间进行选择)。

+0

我试过你的解决方案,但它没有奏效。我仍然收到相同的错误信息。我想这个问题在第一个参数(plcAddress)中。 'errCode = ADS_DLL.AdsSyncReadReq(plcAddress)' 给出了相同的错误 – 2013-03-18 09:30:00

+0

我已经更新了答案:使用'pointer(plcAddress)'。 – jfs 2013-03-18 09:33:50

+0

非常感谢。错误信息消失了。我仍然没有从PLC那里得到我想要的回应,但那是另一回事.... :-) – 2013-03-18 09:41:33