在Python中使用NI-VISA:viFindRsrc错误码-1073807343

0 投票
1 回答
1908 浏览
提问于 2025-04-17 21:38

我正在使用Python,并且安装了最新版本的NI-VISA。我使用ctypes这个包来加载和NI-VISA一起安装的visa32.dll文件。

我参考了NI-VISA的文档,还有这个页面来写我的代码。

我知道有个叫pyVisa的工具,它的find_resources函数可以找到连接的仪器。不过,我不想用这个工具,而是想直接使用VISA的DLL文件。

我也在查看pyVisa的代码,想看看他们是怎么做的,试着从中学习,但似乎还是没搞明白。

这是我目前还没完成的代码:

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)

我一直在网上查找错误代码-1073807343(十六进制是4000FFEF)的意思,虽然在国家仪器的论坛上找到了一些讨论,但我还是不太明白它具体是什么意思。

我希望能得到任何建议、指导或者相关信息的链接。

1 个回答

1

字面意思上的 "?*INSTR" 创建了一个 str 对象,在 Python 3 中这是 Unicode 字符串。ctypes 会把这个 Unicode 字符串转换成 wchar_t * 类型。在 Windows 系统中,wchar_t 占用 2 个字节,所以 ctypes 会传递一个指向 UTF-16 编码的缓冲区 "?\x00*\x00I\x00N\x00S\x00T\x00R\x00" 的指针。需要注意的是,这个函数期望接收到一个以空字符结尾的字符串。

如果你想传递一个字节字符串,可以在字面量前加上 b,这样就会创建一个 bytes 对象,比如使用 b"?*INSTR"

为了避免像这样的错误被忽视,可以定义函数指针的 argtypes。如果传递了一个 Unicode str 类型的参数,而这个参数应该是 c_char_p 类型,ctypes 会抛出一个 ArgumentError 错误。

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)

NI-VISA 程序员参考手册 在第 5-30 页提到,instrDesc 应该至少为 256 字节。

撰写回答