Reputation: 444
I'm working in Python and have installed the lastest version of NI-VISA. I'm using the ctypes package in order to load the visa32.dll installed with NI-VISA.
I used both the NI-VISA documentation, as well as the following page as a base for my code.
I already know of the pyVisa wrapper and using their find_resources function does return the instruments connected. However, I do not wish to use this wrapper and would rather use the VISA DLL file directly.
I've also been browsing the pyVisa code to see how they do it, and tried to learn from it, but it seems I still don't get it.
Here is my current unfinished code:
import sys
from ctypes import *
visa = windll.LoadLibrary("visa32.dll")
resourceManagerHandle = c_int(0)
visa.viOpenDefaultRM(byref(resourceManagerHandle))
instr_list = c_ulong(0)
nb = c_ulong(0)
desc = create_string_buffer(128)
print(visa.viFindRsrc(resourceManagerHandle,
"?*INSTR",
byref(instr_list),
byref(nb),
byref(desc)))
# The previous line prints: -1073807343
print(instr_list)
# The previous line prints: c_ulong(0)
I've been trying to find the meaning of the error code -1073807343 (4000FFEF in hex) on the Internet and though I have found some forum threads about it on the National Instruments forums, I still don't quite understand what it means.
I would welcome any advice, guidance or link towards relevant information.
Upvotes: 0
Views: 2139
Reputation: 34260
The literal "?*INSTR"
creates an str
object, which is Unicode in Python 3. ctypes converts a unicode string to a wchar_t *
. On Windows, wchar_t
is 2 bytes, so ctypes passes a pointer to the UTF-16 encoded buffer "?\x00*\x00I\x00N\x00S\x00T\x00R\x00"
. Bear in mind that the function expects a null-terminated string.
To pass a byte string instead, prefix the literal with b
to create a bytes
object, i.e. use b"?*INSTR"
.
To prevent a mistake like this from passing unnoticed, define the function pointer's argtypes
. ctypes will raise an ArgumentError
if a unicode str
argument is passed for a parameter that's defined to be c_char_p
.
from ctypes import *
visa = WinDLL("visa32.dll") # or windll.visa32
def vi_status_check(vi_status, func, args):
if vi_status < 0:
raise RuntimeError(hex(vi_status + 2**32))
return args
visa.viOpenDefaultRM.errcheck = vi_status_check
visa.viOpenDefaultRM.argtypes = [POINTER(c_uint32)]
visa.viFindRsrc.errcheck = vi_status_check
visa.viFindRsrc.argtypes = [c_uint32, # sesn
c_char_p, # expr
POINTER(c_uint32), # findList
POINTER(c_uint32), # retcnt
c_char_p] # desc
rm_session = c_uint32()
visa.viOpenDefaultRM(byref(rm_session))
expr = b"?*INSTR"
instr_list = c_uint32()
nb = c_uint32()
desc = create_string_buffer(256)
visa.viFindRsrc(rm_session,
expr,
byref(instr_list),
byref(nb),
desc)
The NI-VISA Programmer Reference Manual says on page 5-30 that instrDesc
should be at least 256 bytes.
Upvotes: 1