Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Ctypes Exception: access violation reading

Tags:

python

dll

ctypes

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

like image 907
F. Justin Avatar asked Nov 03 '22 02:11

F. Justin


1 Answers

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

like image 177
jfs Avatar answered Nov 09 '22 14:11

jfs