我正在使用其他人编写的代码来读取和编码来自数字/模拟转换器的数据。我尝试通过使用python 3来改进此代码,因为它是在python 2中编码的。
我已经减少了很多代码以理解为什么它在Python 3上不起作用并且发现了“map”函数行为的问题,因为它说“在Python 3中出现了错误,但在python 2中没有。
我不知道我在哪里做错了,因为我自己没有制作这个代码,有些部分我无法理解。我应该改变什么才能使它与python 3一起使用?
from DTOL import DTOL
io = DTOL(name='DT9818(00)')
io.Initialize('DT9818(00)')
io.setupGetSingleValue()
DTOL
import ctypes
from time import sleep
from DTOL_defs import *
from DTOL_prototypes import *
class DTOL:
""" Data Translation DtOLWrapper Class """
def __init__(self, name='DT9818(00)'):
self.name = name
self.data = []
self.sshandle = []
self.hdev = []
self.range = (-10,10)
self.rmin = ctypes.c_double(-10)
self.rmax = ctypes.c_double(10)
self.gain = ctypes.c_double(1)
self.res = ctypes.c_uint(16)
self.enc = ctypes.c_uint(OL_ENC_BINARY)
self.val = 0
def Initialize(self, name):
print('Available Boards:')
olDaEnumBoards(listboardscallback, 1)
print('-----')
print('Initializing: ' + str(name))
name = name.encode('utf-8')
hdev = olDaInitialize(name)
self.hdev = hdev
return hdev
def GetSubsystem(self, subsystem_code, elemNum):
print(subsystem_code)
print(elemNum)
sshandle = olDaGetDASS(self.hdev, subsystem_code, elemNum)
self.sshandle = sshandle
return sshandle
def setupGetSingleValue(self):
self.Initialize(self.name)
self.GetSubsystem(OLSS_AD, ctypes.c_ulong(0))
if __name__ == "__main__":
print("Usage: io=DTOL('DT9818(00)')")
print("io.setupSingleValue()")
print("io.getSingleValue()")
io = DTOL()
io.setupGetSingleValue()
DTOL_prototypes
import ctypes
from ctypes.util import find_library
dll = ctypes.CDLL(find_library('oldaapi64'))
dll2 = ctypes.CDLL(find_library('OLMEM64'))
def errcheck_all(ret, func, args):
if ret:
print("Error occured in"+ str(func))
return
return args
def errcheck_none(ret, func, args):
if ret:
print("Error occured in"+ str(func))
print(ret)
return
# ----------- Initialize ---------------------------------
prototype = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_char_p, ctypes.POINTER(ctypes.c_ulong))
paramflags = (1, "name"), (2,"hDev")
olDaInitialize = prototype(('olDaInitialize', dll), paramflags)
olDaInitialize.errcheck = errcheck_all
# -----------END Initialize ---------------------------------
# ----------- olDaGetDASS ---------------------------------
prototype = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_ulong, ctypes.c_long, ctypes.c_uint, ctypes.POINTER(ctypes.c_ulong))
paramflags = (1, "hDev"), (1,"SubsystemType"), (1,"uiElementNr"), (2,"adhandle")
olDaGetDASS = prototype(('olDaGetDASS',dll), paramflags)
olDaGetDASS.errcheck = errcheck_all
# ----------- olDaGetDASS ---------------------------------
DTOL_defs
import ctypes
(OLSS_AD,
OLSS_DA,
OLSS_DIN,
OLSS_DOUT,
OLSS_SRL,
OLSS_CT) = list(map(ctypes.c_int, (range(6))))
OL_ENC_BINARY = 200
结果,我发现了python 3和2之间的区别:Python 3:
c_long(0)
<class 'ctypes.c_long'>
Available Boards:
Name = b'DT9818(00)'
Drivername = b'Dt9818'
1
-----
Initializing: DT9818(00)
Available Boards:
Name = b'DT9818(00)'
Drivername = b'Dt9818'
1
-----
Initializing: DT9818(00)
c_long(0)
c_ulong(0)
Error occured in<WinFunctionType object at 0x00000235269DC528>
Python 2:
c_long(0)
<class 'ctypes.c_long'>
Available Boards:
Name = DT9818(00)
Drivername = Dt9818
1
-----
Initializing: DT9818(00)
Available Boards:
Name = DT9818(00)
Drivername = Dt9818
1
-----
Initializing: DT9818(00)
c_long(0)
c_ulong(0L)
最后两个参数分别对应于“print(subsystem_code)”和“print(elemNum)”。
我不知道为什么你认为地图会成为问题。它的调用方式(从中构造一个列表)在两个Python版本上的工作方式相同。
张贴[Python 3]: ctypes - A foreign function library for Python。
没有函数文档,我不能100%确定,但从它们声明的方式来看:
prototype = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_char_p, ctypes.POINTER(ctypes.c_ulong))
paramflags = (1, "name"), (2, "hDev")
prototype = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_ulong, ctypes.c_long, ctypes.c_uint, ctypes.POINTER(ctypes.c_ulong))
paramflags = (1, "hDev"), (1, "SubsystemType"), (1, "uiElementNr"), (2, "adhandle")
我可以得出结论,返回值表示函数执行状态,通常:
但是,在Initialize中,你设置hDev(这是olDaInitialize的输出和olDaGetDASS的输入)(这里也存在类型不匹配,但它被自动转换隐藏):
hdev = olDaInitialize(name)
self.hdev = hdev
所以你给hdev分配olDaInitialize的状态是没有意义的。正确的方法是:
self.hdev = ctypes.c_ulong(0)
hdev = ctypes.c_ulong(0)
status = olDaInitialize(name, ctypes.byref(hdev))
if status == 0: # Or whichever value means SUCCESS
self.hdev = hdev
完全相同的事情也适用于adhandle(olDaGetDASS的最后一个参数),你在GetSubsystem中引用(作为sshandle)并且可能在代码中使用其他地方。
我们在改进部分:
self.name = name.encode("utf-8")
然后从Initialize中删除参数,并在其中使用self.name
@ EDIT0:
添加一些简化代码,以检查问题是否重现。
code.朋友:
#!/usr/bin/env python3
import sys
import ctypes
def main():
oldaapi64 = ctypes.CDLL(find_library("oldaapi64"))
olmem64 = ctypes.CDLL(find_library("olmem64"))
oldainitialize = oldaapi64.olDaInitialize
oldainitialize.argtypes = [
ctypes.c_char_p, ctypes.POINTER(ctypes.c_ulong),
]
oldainitialize.restype = ctypes.c_int
oldagetdass = olmem64.olDaGetDASS
oldagetdass.argtypes = [
ctypes.c_ulong, ctypes.c_long, ctypes.c_uint, ctypes.POINTER(ctypes.c_ulong),
]
oldagetdass.restype = ctypes.c_int
dev = ctypes.c_ulong(0)
res = oldainitialize(b"DT9818(00)", ctypes.byref(dev))
print("{:s} returned {:d}. Dev: {:d}".format(oldainitialize.name, res, dev.value))
OLSS_AD = 0
element_num = 0
handle = ctypes.c_ulong(0)
res = oldagetdass(dev, OLSS_AD, element_num, ctypes.byref(handle))
print("{:s} returned {:d}. Handle: {:d}".format(oldagetdass.name, res, handle.value))
if __name__ == "__main__":
print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
main()
print("Done.")
我也尝试使用类似的ADC与python 3.x一起工作。我和你一样,来自使用python 2.7运行的pyDTOL模块。不幸的是,我遇到了同样的问题。我试图理解pyDTOL中真正发生的事情,并最终得到了与CristiFati类似的方法。我添加了释放ADC的功能。这是我的代码(适用于python 2.7,但有3.x的问题):
import ctypes
from ctypes.util import find_library
def main():
ctypes.cdll.LoadLibrary(find_library('oldaapi64'))
oldaapi = ctypes.CDLL("oldaapi64")
name= b'DT9836S(00)'
olDaInitialize = oldaapi.olDaInitialize
olDaInitialize.argtypes = [ctypes.c_char_p, ctypes.POINTER(ctypes.c_ulong)]
olDaInitialize.retype = ctypes.c_ulong
hdev = ctypes.c_ulong()
ret_init = olDaInitialize(name, ctypes.byref(hdev))
print('hdev: ' + str(hdev))
print('return from olDaInitialize: ' + str(ret_init))
olDaGetDASS = oldaapi.olDaGetDASS
olDaGetDASS.argtypes = [ctypes.c_ulong, ctypes.c_long, ctypes.c_uint,
ctypes.POINTER(ctypes.c_ulong)]
olDaGetDASS.restype = ctypes.c_ulong
OLSS_AD = ctypes.c_long(0)
sshandle = ctypes.c_ulong()
ret_dass = olDaGetDASS(hdev.value, OLSS_AD, ctypes.c_uint(0),
ctypes.byref(sshandle))
print('sshandle: ' + str(sshandle))
print('return from olDaGetDASS: ' + str(ret_dass))
olDaReleaseDASS = oldaapi.olDaReleaseDASS
olDaReleaseDASS.argtype = ctypes.c_ulong
olDaReleaseDASS.restype = ctypes.c_ulong
ret_rdass = olDaReleaseDASS(sshandle.value)
olDaTerminate = oldaapi.olDaTerminate
olDaTerminate.argtype = ctypes.c_ulong
olDaTerminate.restype = ctypes.c_ulong
ret_term = olDaTerminate(hdev.value)
if __name__ == "__main__":
main()
Python 2.7中的输出:
hdev: c_ulong(11836704L)
return from olDaInitialize: 0
sshandle: c_ulong(11843088L)
return from olDaGetDASS: 0
Python 3.6中的输出:
hdev: c_ulong(3420637248)
return from olDaInitialize: 0
sshandle: c_ulong(0)
return from olDaGetDASS: 39
根据“oldaapi64 - manual”,返回值“0”表示“操作完成;没有错误。”olDaGetDass的后退值为39意味着:“指定了非法的设备句柄”。
在我看来,有两种可能性:hdev-pointer(来自“olDaInitialize”)在python 3中是不同的inperpreted,或者如果你将hdev传递给“olDaGetDASS”则会出现问题。
如果我们能找到解决方案,那就太好了!
编辑:来自CrisiFati的回复:DLL olmem64没有olDaGetDASS的功能
oldagetdass = olmem64.olDaGetDASS
你必须使用oldaapi64
oldagetdass = oldaapi64.olDaGetDASS
用户手册可在此处找到:
https://www.mccdaq.com/PDFs/Manuals/UMDataAcq.pdf附录A显示了一个例子。在调用约定中,声明返回值是unsigned long,并且使用Microsoft Pascal调用约定。
最好的问候