Python Ctypes Exception: access violation reading
You're passing invalid pointer, provide a valid memory buffer instead:
data = create_string_buffer(nLength)
The argument should be just c_void_p
instead of POINTER(c_void_p)
if PVOID
means void *
. Don't set restype to None
(the function returns LONG
).
Also pass pointer(plcAddress)
(specify POINTER(AmsAddr)
in argtypes).
Use correct calling convention (choose between cdll, windll, oledll).
F. Justin
Updated on June 11, 2022Comments
-
F. Justin almost 2 years
I try to communicate with a PLC through a DLL (C API interface distributed by the manufacturer of the PLC). I'm using Python 3.1 who is embedded as a scripting environment in a other software (x64 - Windows 7).
I managed to get a few DLL functions working, but now a get an "Access violation reading" that I can't solve.
Information about the DLL function:
LONG AdsSyncReadReq( PAmsAddr pAddr, ULONG nIndexGroup, ULONG nIndexOffset, ULONG nLength, PVOID pData );
Parameters:
- pAddr: [in] Structure with NetId and port number of the ADS server.
- nIndexGroup: [in] Index Group.
- nIndexOffset: [in] Index Offset.
- nLength:[in] Length of the data in bytes.
- pData: [out] Pointer to a data buffer that will receive the data.
- Return value: Returns the function's error status.
Structure AmsAddr:
typedef struct { AmsNetId netId; USHORT port; } AmsAddr, *PAmsAddr;
Structure AmsNetId
typedef struct { UCHAR b[6]; } AmsNetId, *PAmsNetId;
Python Implementation:
# -*- 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
I hope anyone can't figure out what's wrong. I'm only a advanced novice in Python programming with no experience at all in C
Thanks in advance
-
F. Justin about 11 yearsI tried you solution but it didn't work. I still get the same error message. I guess the problem is in the first argument (plcAddress).
errCode = ADS_DLL.AdsSyncReadReq(plcAddress)
gives the same error -
F. Justin about 11 yearsThanks a lot. Error message is gone. I still don't have the response I want from the PLC but that something else.... :-)