Python Ctypes Exception: access violation reading

13,346

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).

Share:
13,346
F. Justin
Author by

F. Justin

Updated on June 11, 2022

Comments

  • F. Justin
    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
    F. Justin about 11 years
    I 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
    F. Justin about 11 years
    Thanks a lot. Error message is gone. I still don't have the response I want from the PLC but that something else.... :-)