跳到主要内容

LabVIEW 面临的挑战与未来

这一节,主要是笔者对于 LabVIEW 的一些反思。

LabVIEW 的 unicode 问题

笔者最近试图去查看自己很久之前写的一些 VI,但是却发现那些 VI 要么无法打开,要么打开后,里面的中文字符全部成了乱码。造成这个问题的根本原因是因为 LabVIEW 不支持 unicode 编码。

先简略的介绍一下 unicode 的背景:

计算机是在美国被发明的,所以当时很自然的就只考虑了处理英文。最早出现的一个,也是最著名的一个关于在计算机中表达字符的标准,是 ASCII 标准(American Standard Code for Information Interchange,美国信息互换标准代码)。它定义了128个字符,包括英文字母大小写,数字,常用的标点和一些特殊符号。当时世界上所有的计算机都在使用 ASCII 方案来保存英文文字。这个方案最大的问题是它只包含了英文字母,于是其它国家,组织和公司纷纷开始扩展这个标准,用以支持其它字符,比如制表符、数学运算符号、中文字符、日文字符等等。在中国,最常用的标准,包括 GB2312,GBK,GB18030 等都是对 ASCII 的中文扩展。这些扩展出的标准有一个很麻烦的问题:同一个数值在不同的标准中被定义了不同的含义。比如,某一数值在中文的标准下可能是一个中文字符,在韩文的标准下,可能就是一个完全不相关的制表符。这就造成了,在中文环境下开发的软件,运行到韩文系统下,显示的就完全是乱码。如果有人需要在一个系统下同时运行一个中文软件和一个韩文软件,就只能 有一个软件可以正确显示文字。

为了解决这个问题,1990年开始,计算机业界开始研发一种新的编码标准,它可以覆盖全世界所有的字符,也就是说,任何一个字符都有自己独占的编码,在任何系统下都会保持这个编码,这样就不会出现换个系统就乱码的问题了。这就是 unicode 编码,也叫万国码、单一码。unicode 规定了字符集,但是这套字符集也还存在多种不同的编码格式。Windows 采用了 UTF-16LE 格式的 unicode 编码(UTF全称为 Unicode Transformation Format),使用 16 位的(双字节)数据表示一个字符。但是当前最流行的 unicode 编码格式却是 UTF-8,这是一种变长的编码方式,根据字符的常用程度,使用不同长度的编码来表示这个字符,编码长度有可能是 1 到 6 个字节。目前大多数的 unicode 文档采用的都是 UTF-8 编码。

经过几十年的推广和发展,现在已经很少有不支持 unicode 的主流软件了。但是,非常遗憾的是 LabVIEW 始终没有支持 unicode。在整个2010年代,NI 公司的重点放在了开发支持 unicode 的 LabVIEW NXG。计划用它彻底取代 LabVIEW,所以没有投入足够的资源去改进 LabVIEW。但后来,NI 公司又放弃了 LabVIEW NXG。目前,不支持 unicode 的 LabVIEW 仍然是使用者的唯一选择。

虽然 Windows 很早就开始支持 unicode 了,但是为了兼容那些还没有支持 unicode 的软件,Windows 系统保留了一个默认字符集的设置。对于非 unicode 的软件,Windows 会使用默认的字符集来解释那些字符编码。国内使用的 Windows 操作系统,无论是中文版还是英文版,几乎都把默认的字符集设置为了中文字符集。所以,一个软件是否支持 unicode,对于绝大多数用户来说,都是没有差别的。笔者之前也从来没意识到 LabVIEW 不支持 unicode 会有什么问题。

直到最近,笔者才开始注意到这个问题的严重性。笔者家里有两台电脑,一台操作系统安装了 Windows;另一台操作系统是中文 Deepin Linux。两台电脑上都安装了社区版的 LabVIEW 2021。笔者发现,在 Windows 系统下编写的 VI,如果包含中文常量或注释,拿到 Linux 系统下打开,看到的就全部是乱码;反之亦然。更严重的是,如果项目、库、类等,如果包含了有中文名的 VI,那么,把项目拿到另一个系统下就根本无法打开了。

造成这些问题的根源在就在于 LabVIEW 没有直接支持 unicode,它总是采用操作系统的默认字符编码对字符进行编解码:在中文 Windows 系统下使用 GB18030 中文编码;在 Linux 系统下使用 UTF-8 编码。

因为 Linux 系统普遍采用了 unicode,也没有别的默认编码,所以 VI 在不同版本的 Linux 系统上的行为和显示内容都是一致的。但 Windows 系统本身采用的是 unicode 编码,为应用程序提供的却又是可以由用户设置的默认编码。假设,在一个项目中有两个 VI,分别是“界面.vi”和“任务1.vi”,其中“任务1.vi”是“界面.vi”的子 VI。在操作系统层面,有两个文件:“界面.vi”和“任务1.vi”,它们的名字都是使用 unicode 编码保存的。但是在“界面.vi”内部,它记录了自己要调用“任务1.vi”,用的却是非 unicode 编码(比如在中文 Windows 系统下使用 GB18030 中文编码)保存的子 VI 的名字。所以 LabVIEW 中用于记录这个子 VI 的名字的一段二进制数据与操作系统中记录这个子 VI 文件名使用的二进制数据是不同的。每次 LabVIEW 需要操作系统装载一个子 VI 文件时,还需要做一次编码转换,把文字转为系统使用的 unicode 编码。如果保存 VI,和读取 VI 都是在中文 Windows 中,编码始终一致,不会有任何问题,VI 名字总能被正确转换。

当我们把之前在中文 Windows 系统下保存的项目拿到非中文 Windows(默认语言编码不再是 GB18030)下打开,或是拿到 Linux 系统上打开,会发现,我们会发现 VI 文件的名字都还是对的,因为操作系统采用的编码都是 unicode。但是,在 LabVIEW 中打开 VI 就会出错了。在 LabVIEW 内部,解析子 VI 的时候,它会试图用新的系统默认编码来解释原本使用 GB18030 格式保存的子 VI 名,结果自然得不到正确的 VI 文件名,也就无法找到正确的子 VI。同理,中文 Windows 下保存的 VI,如果有中文名,拿到 Linux 系统下打开也会出错;反过来也是一样会出错。

总之,由于 LabVIEW 在 Windows 下没有使用 unicode,造成了中文(或其它非英语文字)在不同系统下显示行为的不一致,切换系统就会出现乱码,甚至 VI 无法被加载。目前,笔者也没有找到好的办法解决这个问题。笔者只能尽量在 LabVIEW 中只使用英文,不使用中文以及特殊字符。

如果有一天 LabVIEW 开始支持 unicode 了,那么这很可能意味着用户使用之前版本的 LabVIEW 编写的项目,如果有其它语言文字的话,会无法在 unicode 版本 LabVIEW 下打开,或是打开后出现乱码。这将会是一个非常严重的兼容问题。这可能也是 NI 公司迟迟无法下决心支持 unicode 的原因之一。

LabVIEW 的源代码管理

LabVIEW 源代码管理一直是个非常麻烦的问题。

文本编程语言有个大优势,文本有统一标准的文件存储格式。不论哪种文本编程语言,都可以使用通用的工具进行编辑,排版,存取,跟踪修改历史等等。市面上有着大量成熟的工具可以完成这些工作。而 LabVIEW 是一种非文本的编程语言,它也没有使用任何一种通用的开放的文件格式来保存代码,所以,除了 LabVIEW 自己,没有任何其它工具能解析编辑 LabVIEW 代码。所以,也只有 NI 公司自己才有可能去开发适合 LabVIEW 的源代码管理工具了。只是不知道 NI 公司有多少资源可以分配给这个问题。可以预期,就算将来 LabVIEW 在这方面有所改进,也不太可能像管理文本代码一样方便的管理 LabVIEW 代码。

除了源代码管理,LabVIEW 在交流和学习方面也非常不方便。比如在论坛里张贴一段示例代码,文本编程语言直接复制粘贴文本就可以,LabVIEW 代码只能截图,如果遇到层次较多的条件结构,或者事件结构,一张截图恐怕还不够。直接张贴 VI 文件,读者也是无法看到 VI 内容的,需要在 LabVIEW 中打开 VI 文件。我在与读者的交流中还遇到了这样的问题,我为这本书编写了大量的示例程序。如果读者的 LabVIEW 版本低于我的 LabVIEW 版本,那么他们是无法打开示例程序查看的。因为我只能用尽量低的 LabVIEW 版本保存示例程序,以便更多读者可以查看到程序内容。但是,如果读者的 LabVIEW 版本太新,比如,比我的 LabVIEW 新 5 年以上,可能还是无法打开我的示例程序。因为有些版本的 LabVIEW 只支持 5 个版本内的 VI。这为我和读者之间的交流造成了巨大不便。

我觉得最理想的情况是,LabVIEW 可以把程序的逻辑、前面板的界面、节点和连线的排布、编译好的代码等几个部分完全隔离开,分别保存。程序员只需要关注程序的逻辑部分。前面板,程序框图的布局可以根据不同用户各自的规范完全自动排布。而程序的逻辑部分也可以使用文本格式进行保存,这样就可以完美的集成任何一个文本源代码管理工具了。

LabVIEW 程序框图的缩放

我最早使用 LabVIEW 的时候,电脑显示器的主流分辨率还是 640*480,那时候一满屏也显示不下多少代码。如果某个 VI 程序框图比较大,就必须挪来挪去一块一块查看。这也是 LabVIEW 代码难以阅读的一个重要原因。虽说有缩略图,但是缩略图里只能看到个大概轮廓,根本看不出程序逻辑,帮助十分有限。那时候就想,如果可以把程序代码的视图稍稍缩小一点,让我能一次多看到一些代码就好了。

我现在使用的显示器分辨率都在 3840*2160 以上,LabVIEW 一个子 VI 的图标一般也就 32*32 个像素,连屏幕宽度的百分之一都不到,有些函数和节点的图标就更小了。再加上现在眼神也不好使,很多代码的逻辑都看不清楚了,比如是加法,减法还是乘除法?LabVIEW 同样不支持把代码视图放大。好在现在的操作系统都视图缩放了,使用系统提供的功能把 LabVIEW 画面放大个两三倍是我感觉最舒适的大小。可是这时候就会发现,其它程序放大两三倍,图像依然清晰光滑,而 LabVIEW 却显得粗糙模糊了。究其原因,LabVIEW 的显示用的全是像素图,而非矢量图。LabVIEW 中,如果换一个图标需要用 1K 个点表示,边长放大 3 倍,它还是只有 1K 个点;而其它软件通常就会用 9K 个点来表示放大后的图标。同样面积下,显示点数只有别人的 1/9,当然模糊了。

显示逻辑也是 LabVIEW 最底层的最基础的部分之一,改动它也是个棘手的问题,不知 LabVIEW 何时才能有所优化了。

逐渐失去的优势

LabVIEW 在某些方面依然优势明显:比如画图就是比写文字看着更有趣;它还可以简便地连接和读取 NI 的硬件采集的数据。但不得不说,在过去的十来年里(2012~2022),LabVIEW 并没有太多改善,而同时期,其它主流的编程语言,却都有明显进步,以至于我觉得当年 LabVIEW 一些独特的优势,现在都不再那么突出了。我感受比较深的是两点:

调试便利性

LabVIEW 的一大优势是可以单独运行一个 VI,这会让程序调试非常便利。以前调试 C 语言程序的时候,即便只改一行代码,也要重新编译整个程序才能观察修改后的结果。如果是个大项目,重新编译、重现出问题时候程序的状态都是非常麻烦的。但如果可以只运行一个函数,或者 VI,那就可以省去之前提到的麻烦,快速验证修改的结果了。

然而,在过去的十来年里,很多主流的编程语言都开始改进了类似的用法。最典型的是 Python。Python 是一种解释型语言,本来就不必编译整个程序,可以单独运行一行程序。只不过,在传统的编辑环境中单独运行某几行代码还是不太方便。但是后来出现的,以 Jupyter Notebook 为代表的基于网页的编程环境大大改进了这一用法。在 Jupyter Notebook 中,程序代码被分成了小块,点个按钮就可以运行某个小块内的代码。每个小块内可以包含任意多的函数、变量,这甚至比 LabVIEW 运行单个 VI 还方便。

此外,Jupyter 编辑环境完全基于网页,没有一个独立的程序界面。运行 Jupyter,它会开启一个网络服务,然后就可以使用网络浏览器来查看、编辑、调试程序了。这极大便利了远端编写程序。以前要想验证一段程序对不对,必须现在自己电脑上安装那个编程语言的编译器,然后才能编译测试。如今,网上可以找到很多在线的编程环境,支持所有主流的编程语言。只要打开那些网站的网页,选择相应的语言,然后直接在网页中输入程序代码,就可以运行调试。

LabVIEW 也曾经搞过类似的网页版本的 LabVIEW UI Builder,可是它跟 LabVIEW 程序并不兼容,属于是另一种语言了。要想运行调试 LabVIEW 还是不得不在自己的电脑上安装一个巨大的安装包。

并发

能够方便地编写多线程程序也是 LabVIEW 的优点,而且 LabVIEW 有自己的执行系统,即便是在单线程下,也可以并行运行程序框图上两个没有依赖关系的模块。这对于读写仪器数据这类大量 I/O 操作的程序是个极大的优势,可以在不需要程序员进行额外编程的情况下,就大大提升程序效率。主流的文本编程语言也都支持编写多线程程序,但是,在十几年前,它们对于多线程的支持都是比较繁琐的,要编写一个多线程程序就不得不考虑数据同步、安全等棘手的问题。不过最近这些年,各种高层的工具包被开发出来,编写多线程程序变得容易多了。尤其是,编程语言对于异步 I/O 的支持,让并发操作变得更容易了。

比如,Python,JavaScript,PHP 等都支持异步 I/O 了。异步 I/O 依赖编程语言自己管理和调度,有点类似于 LabVIEW 的执行系统,可以在单线程下并发运行不同的代码块。异步 I/O 可以使用少量代码,就解决那些慢速操作(比如外设读写、网络连接等)阻塞整个程序的问题,同时也不需要开发者去关注数据同步之类的安全问题。

以 Python 为例:

async def foo(some_arguments):
# read a file
return "something from foo"

async def bar(some_arguments):
# write to a database
return "something from bar"

async def main():
results = await asyncio.gather(
foo("file_name"),
bar("database"),
)

这段程序只用了一条语句就可以让函数 foo 和 bar 并发运行,一点也不比 LabVIEW 中实现并行运行更困难。

AI 编程时代的冲击

自 20 世纪 50 年代第一批编程语言诞生以来,人们便不断尝试用人工智能(AI)来改进编程过程。然而,真正的革命始于 2020 年之后。大型语言模型(LLM)的崛起,使 AI 编程从研究概念一跃成为产业现实。尤其自 2022 年 GPT-3.5 问世以来,AI 辅助编程以惊人的速度普及。AI 在大大提升专职程序员开发效率的同时,也使得非软件专业人员能够在 AI 的帮助下,开发出以往无法企及的复杂程序。如今(2025 年),几乎所有大型科技公司都已将 AI 辅助编程纳入开发流程,在部分项目中,AI 自动生成的代码比例甚至可以超过一半。

然而,当这股浪潮汹涌席卷整个软件开发行业时,若将目光转向 LabVIEW,我们会发现它面临的局面并不乐观。AI 编程的崛起,不仅不是 LabVIEW 的新机遇,反而正在以一种根本性的方式,动摇其赖以存在的根基。在其它编程语言因 AI 发展而受益时,LabVIEW 正处在逆水行舟的境地。

图形化编程与大语言模型的结构性矛盾

会不会也有厂商为 LabVIEW 开发一套 AI 编程系统,让大部分 LabVIEW 编程工作都由 AI 完成呢?也许会有,但其难度比为其它语言开发编程 AI 要大得多。

LabVIEW 采用了独特的图形化编程范式(G代码),它以数据流为驱动,工程师通过连接节点与数据线构建逻辑结构,既直观又高效。然而,这种优势在 AI 时代却成了最致命的桎梏。

主流大型语言模型天生擅长处理线性、序列化的文本数据。它们通过分析海量文本源代码(如 Python、C++)的语法、上下文与模式来学习其中的逻辑规律。可 LabVIEW 的代码是二维图形化的,空间结构与连线逻辑难以被线性地处理,也无法直接输入模型进行深度学习。让 AI 理解一个 VI 的功能、甚至生成一个符合逻辑的框图,其难度远高于生成同等复杂度的 Python 代码。

另一方面,AI 的“智能”取决于训练数据的丰富与质量。GitHub 与 Stack Overflow 为文本编程语言提供了几乎无限的学习素材,而 LabVIEW 的开源生态却小得多。可公开获取的高质量 LabVIEW 项目寥寥无几,模型因缺乏足够的“养料”而无法真正掌握其编程思维。这意味着,AI 对 LabVIEW 的支持先天不足。

AI 的“釜底抽薪”

更具威胁的是,AI 的强项恰恰覆盖了 LabVIEW 曾经的核心优势。

LabVIEW 一直以其可视化界面设计著称。通过拖拽控件即可快速生成交互式程序界面。然而,如今的 AI 工具往往只需一句自然语言指令,比如:“生成一个包含三张图表和若干控制按钮的监控界面”,就可在几秒钟内产出高质量的程序界面代码。前端界面布局与交互逻辑本就容易用自然语言描述,因此 AI 在这一领域的效率甚至超越人类工程师。例证之一是在 Web 开发领域,AI 对前端工程师的冲击速度远超后端工程师。同样,LabVIEW 在快速原型设计和 UI 开发上的传统优势,正被 AI 以更通用、更灵活的方式取代。

LabVIEW 在仪器控制与数据采集领域的便捷性,曾是其坚固的护城河。然而,这也是 AI 能够轻易突破的领域。如今,工程师仅需一句自然语言指令,就能让 AI 生成一段基于 Python 及开源库的完整脚本,实现硬件控制与数据分析,这种方式相比于编写 LabVIEW 代码,更加便捷、自由。

未来展望

从趋势上看,AI 编程正在重塑软件开发的生态。当主流文本语言在 AI 的加持下,能够以同等甚至更高的效率完成任务时,选择 LabVIEW 的理由势必减少。

未来,LabVIEW 的应用空间或将被压缩到那些它最具不可替代性的领域,例如实时控制与工业自动化等。在这些对确定性和可靠性要求极高的场景中,LabVIEW 与其专用硬件平台(如 CompactRIO、PXI)在实时操作系统(RTOS)上的表现,仍具有无可比拟的优势。

当然,LabVIEW 并非没有机会。它或许可以尝试融合生成式图形模型(Generative Graph Models)等新方向,让 AI 直接生成可执行的图形化代码。如果能够实现这种跨越,LabVIEW 或许能在 AI 时代重新定义自身的价值。

但无论如何,这将是一个充满挑战与变革的时代。AI 的浪潮不会等待任何人,LabVIEW 唯有不断进化,方能避免被时代的洪流所淹没。