Python Ctypes异常:读取访问冲突

F. *_*tin 5 python dll ctypes

我尝试通过DLL(由PLC制造商分发的C API接口)与PLC通信。我正在使用Python 3.1,该Python 3.1作为脚本环境嵌入在其他软件(x64-Windows 7)中。

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

有关DLL函数的信息:

LONG AdsSyncReadReq(
  PAmsAddr  pAddr,
  ULONG     nIndexGroup,
  ULONG     nIndexOffset,
  ULONG     nLength,
  PVOID     pData
);
Run Code Online (Sandbox Code Playgroud)

参数:

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

结构AmsAddr:

typedef struct {
  AmsNetId        netId;
  USHORT          port;
} AmsAddr, *PAmsAddr;
Run Code Online (Sandbox Code Playgroud)

结构AmsNetId

typedef struct {
  UCHAR        b[6];
} AmsNetId, *PAmsNetId;
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

我希望任何人都无法弄清楚出了什么问题。我只是Python编程的高级新手,完全没有C方面的经验

提前致谢

jfs*_*jfs 2

您传递了无效的指针,请提供有效的内存缓冲区:

data = create_string_buffer(nLength)
Run Code Online (Sandbox Code Playgroud)

参数应该是 justc_void_p而不是POINTER(c_void_p)if PVOIDMeans void *。不要将 restype 设置为None(函数返回LONG)。

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

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