- 代码复用:利用现有的、经过长期验证的 C/C++ 库(如数学库、通信协议库、硬件驱动库)。
- 性能优化:对于计算密集型任务(如复杂算法、数字信号处理),用 C/C++ 编写可以达到比纯 LabVIEW 更高的运行效率。
- 硬件访问:直接操作内存或硬件寄存器,实现 LabVIEW 无法直接完成的底层控制。
- 封装算法:将复杂的算法封装成一个 DLL(动态链接库),供 LabVIEW 项目或其他项目调用,隐藏实现细节。
LabVIEW 提供了多种方式与 C 语言代码交互,主要分为两大类:

(图片来源网络,侵删)
- 调用外部共享库:这是最常用、最标准的方法,你需要将 C 代码编译成一个 DLL(Windows)或 SO(Linux)文件,然后在 LabVIEW 中使用“调用库函数”节点来调用其中的函数。
- 使用 Code Interface Node (CIN):这是一种比较老的方法,直接在 LabVIEW 的 Block Diagram 中嵌入 C 代码,现在官方已不推荐,因为它调试困难、不兼容 64 位系统,且与 LabVIEW 项目系统集成度低。本文将重点介绍第一种方法,并简要提及 CIN。
调用外部共享库 - 详细步骤
这是现代 LabVIEW 开发的首选方法,整个过程分为三个主要阶段:C 语言端、LabVIEW 端 和 调试与部署。
C 语言端 - 创建 DLL
你需要一个 C 语言开发环境,如 Visual Studio (Windows) 或 GCC (Linux)。
示例:创建一个简单的 DLL,包含一个加法函数和一个字符串处理函数。
编写 C 代码 (my_functions.c)

(图片来源网络,侵删)
// my_functions.c
// 定义导出宏,以便在 DLL 外部可见
#ifdef _WIN32
#define API __declspec(dllexport)
#else
#define API
#endif
// 一个简单的整数加法函数
API int add(int a, int b) {
return a + b;
}
// 一个字符串拼接函数
API void concatenate_strings(const char* str1, const char* str2, char* result, int result_size) {
// 简单的拼接,不考虑安全性,仅作演示
snprintf(result, result_size, "%s%s", str1, str2);
}
关键点:
__declspec(dllexport):这是 Windows 平台下告诉编译器将此函数导出到 DLL 的关键字,Linux/macOS 下不需要,但需要确保编译时生成共享库。- 数据类型:C 中的基本数据类型(
int,double,float)可以直接对应,但字符串和数组需要特殊处理(见下文)。
创建项目并编译为 DLL
以 Visual Studio 为例:
- 创建一个新的 "Dynamic-Link Library (DLL)" 项目。
- 将上面的
my_functions.c代码添加到项目中。 - 编译项目。
- 编译成功后,你会在项目的
x64/Debug(或其他配置) 目录下找到my_functions.dll文件。你还需要my_functions.lib(导入库) 和my_functions.h(头文件),它们对于链接和 LabVIEW 的配置非常重要。
LabVIEW 端 - 配置和调用
创建 VI

(图片来源网络,侵删)
打开 LabVIEW,新建一个 VI。
放置“调用库函数”节点
在函数选板中找到 互连接口 -> 库与可执行程序 -> 调用库函数,并将其拖到 Block Diagram 上。
配置节点参数
这是最关键的一步,双击“调用库函数”节点,会弹出“配置”对话框。
配置 add 函数:
- 路径:点击“浏览...”,找到并选择你刚刚生成的
my_functions.dll文件。 - 函数名:在下拉菜单中选择
add。 - 线程:选择在
运行中执行。 - 调用规范:通常选择
C,C 代码使用stdcall(Windows API 常用),则选择StdCall。必须与 DLL 中定义的保持一致! - 参数:
- 点击
添加一个参数按钮。 - 名称:
a(可选,用于文档) - 类型:选择
Numeric->Signed 32-bit Integer(对应 C 的int)。 - 重复此步骤,添加第二个参数
b,类型相同。 - 点击
返回类型,选择Numeric->Signed 32-bit Integer。
- 点击
配置完成后,你的节点看起来会像这样:
配置 concatenate_strings 函数:
这个函数展示了如何处理字符串和指针,这在 DLL 调用中非常常见。
- 右键点击“调用库函数”节点 ->
添加函数,选择concatenate_strings。 - 路径:确保仍然是同一个
my_functions.dll。 - 函数名:
concatenate_strings - 参数:
- 参数 1:
- 名称:
str1 - 类型: 选择
String,LabVIEW 会自动将其处理为 C 中的const char*。
- 名称:
- 参数 2:
- 名称:
str2 - 类型: 选择
String。
- 名称:
- 参数 3:
- 名称:
result - 类型: 选择
Array->U8 Unsigned 8-bit Integer,这对应 C 中的char*,LabVIEW 会传递一个指向字节数组的指针。
- 名称:
- 参数 4:
- 名称:
result_size - 类型: 选择
Numeric->Signed 32-bit Integer(对应 C 的int),表示缓冲区大小。
- 名称:
- 返回类型: 选择
Numeric->Void,因为 C 函数返回类型是void。
- 参数 1:
配置完成后,节点看起来会像这样:
连接控件和指示器
- 为
add函数的两个输入创建数值控件,为输出创建数值指示器。 - 为
concatenate_strings函数创建两个字符串输入控件。 - 对于
result参数:你不能直接连接一个字符串,你需要创建一个预分配的字节数组作为缓冲区。- 在前面板上创建一个字符串指示器。
- 在 Block Diagram 上,右键点击该字符串指示器 ->
创建->常量,这会创建一个字符串常量。 - 右键点击这个新的字符串常量 ->
表示法->字节数组,现在它变成了一个字节数组常量。 - 调整这个字节数组常量的大小,输入 "Hello World" 并将其转换为字节数组,可以看到它需要 12 个字节(11个字符+1个结束符),你可以手动设置数组大小为 32 或 64,为结果预留足够空间。
- 将这个字节数组常量连接到
concatenate_strings节点的result输入端。 - 为了在调用后能看到结果,你需要将这个字节数组转换回字符串,使用
函数选板 -> 编程 -> 字符串 -> 字符串/字节数组转换下的字节数组至字符串函数,将输出连接到你最初的字符串指示器上。
完整的 LabVIEW Block Diagram 示例:
调试与部署
调试
- 找不到 DLL:确保 DLL 文件与你的 VI 在同一目录,或者 DLL 文件位于系统的
PATH环境变量路径下(如C:\Windows\System32),最佳实践是使用相对路径。 - 运行时错误 (Error 1096, 1097):这通常是参数类型或调用规范不匹配导致的,仔细检查 C 代码中的数据类型和
__stdcall/__cdecl声明,并与 LabVIEW 配置一一对应。 - 内存访问错误:对于指针和缓冲区(如字符串函数),最常见的错误是:
- 缓冲区溢出:C 代码写入的数据超过了 LabVIEW 预分配的字节数组大小。
- 未初始化指针:传递了无效的指针。
- 忘记转换:没有将字节数组正确地连接到
char*参数,或没有将结果字节数组转换回字符串。
部署
当你将应用程序打包为可执行文件 (.exe) 或安装程序时,必须包含你调用的 DLL 文件,否则,程序在其他没有安装 LabVIEW 或该 DLL 的电脑上运行时会失败,最简单的方法是将 DLL 文件放在生成的 .exe 文件所在的同一目录下。
使用 Code Interface Node (CIN) - (不推荐)
简介:CIN 允许你直接在 Block Diagram 中放置一个节点,然后双击它打开一个 C 代码编辑窗口,直接编写 C 代码。
步骤概览:
- 在 Block Diagram 上放置一个 CIN 节点 (
互连接口 -> 代码接口节点)。 - 连接输入/输出控件,这些会自动生成 C 代码中的变量。
- 双击 CIN 节点,打开 CIN Development 环境(一个简化的编辑器)。
- 在
main.c文件中编写你的 C 代码,实现输入到输出的逻辑。 - 点击 "Build" 按钮,LabVIEW 会自动调用 C 编译器(如 VC++)将代码编译成一个与该 VI 绑定的代码资源文件。
- 运行 VI,LabVIEW 会自动加载并执行这个 C 代码资源。
为什么被弃用?
- 64位不兼容:CIN 仅支持 32 位。
- 调试困难:没有方便的调试工具,错误定位很麻烦。
- 版本管理:CIN 代码是作为资源嵌入到 VI 中的,与项目文件分离,不易进行版本控制和团队协作。
- 集成度低:不适用于现代 LabVIEW 项目结构。
总结与最佳实践
| 特性 | 调用外部共享库 | Code Interface Node (CIN) |
|---|---|---|
| 推荐度 | 强烈推荐 | 不推荐 |
| 兼容性 | 支持 32 位和 64 位 | 仅支持 32 位 |
| 调试 | 方便,可使用标准 C 调试器 | 困难,功能有限 |
| 部署 | 需要单独打包 DLL | 无需额外文件,代码嵌入 VI |
| 代码管理 | 标准 C 项目,易于版本控制 | 代码嵌入 VI,管理困难 |
| 适用场景 | 所有新项目,特别是需要跨平台或64位的场景 | 维护非常古老的遗留代码 |
最佳实践:
- 始终首选“调用外部共享库”方法。
- 为你的 DLL 创建一个清晰的头文件 (
.h),并注释好每个函数的参数、返回值和调用规范。 - 使用数据类型常量:在 LabVIEW 配置“调用库函数”节点时,尽量使用 LabVIEW 内置的数据类型(如
I32而不是int),这能增强代码的可读性和可移植性。 - 小心处理内存:对于涉及指针和缓冲区的函数,一定要在 C 端和 LabVIEW 端都做好边界检查,防止缓冲区溢出。
- 错误处理:在 C 代码中,可以通过返回一个错误码来传递状态信息,在 LabVIEW 端,可以检查“调用库函数”节点的
错误输出来捕获运行时异常。 - 使用 LabVIEW 的“导入共享库”向导:
工具 -> 导入 -> 共享库...,这个向导可以自动读取 DLL 的头文件,并为你生成一组封装了“调用库函数”节点的 VI,大大简化了配置过程,是管理复杂 DLL 的利器。
