2013-03-18 74 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