C语言如何调用LabVIEW实现功能交互?

99ANYc3cd6
预计阅读时长 21 分钟
位置: 首页 C语言 正文

核心思想

要理解C语言和LabVIEW的本质:

c语言 调用labview
(图片来源网络,侵删)
  • C语言:是编译型语言,编译后生成一个可执行文件(.exe)或动态链接库(.dll / .so),它运行在操作系统层面,直接与硬件交互。
  • LabVIEW:是图形化编程语言,其代码最终也会被编译成可执行文件(.exe)或共享库(.dll),它运行在操作系统之上,并拥有自己的图形用户界面。

C语言调用LabVIEW,本质上是一个进程(C程序)与另一个进程(LabVIEW程序或LabVIEW生成的DLL)进行通信


调用LabVIEW生成的共享库(.dll / .so)【推荐,性能最高】

这是最常用、性能最好的方法,它将LabVIEW的功能封装成一个标准的动态链接库,然后像调用普通Windows API或第三方库一样,在C程序中调用它。

工作原理

  1. 在LabVIEW中,将VI(虚拟仪器,即LabVIEW的程序)配置为“共享库”或“NI-compiled Library”。
  2. LabVIEW编译器会生成一个.dll文件(Windows)或.so文件(Linux),以及一个头文件(.h)和一个用于说明输入输出参数类型的文件(.lvlib.cat)。
  3. 在C语言项目中,包含生成的头文件,链接生成的.dll库文件,然后直接调用其中的函数。

详细步骤

在LabVIEW中创建并导出共享库

c语言 调用labview
(图片来源网络,侵删)

假设我们有一个简单的LabVIEW VI,它接收一个数字,进行平方运算后返回结果。

  • LabVIEW VI设计

    • 前面板:一个数值输入控件(命名为 inputNumber),一个数值显示控件(命名为 outputResult)。
    • 程序框图:将 inputNumber 连接到一个乘法函数的输入端,两个输入端都连接同一个,然后将结果连接到 outputResult
  • 配置为共享库

    1. 在LabVIEW中,打开你的VI。
    2. 点击 文件 -> 导出 -> 共享库
    3. 在弹出的对话框中:
      • 库名称:给你的库起一个名字,MyCalculator
      • 目标目录:选择一个保存位置。
      • VI 设置:确保你的VI被勾选,可以将其设置为“主VI”。
      • 函数面板:点击“添加”,选择你的VI,LabVIEW会自动将VI的输入控件和输出显示控件作为C函数的参数。
      • 数据类型映射:LabVIEW会自动将数据类型(如 I32)映射到C语言的数据类型(如 int32_t),通常保持默认即可。
    4. 点击 确定,LabVIEW会开始编译,完成后,你会在目标目录下看到:
      • MyCalculator.dll (Windows) 或 libMyCalculator.so (Linux)
      • MyCalculator.h (C语言头文件)
      • MyCalculator.lib (Windows库文件,用于链接)
      • MyCalculator.lvlib (LabVIEW库文件,用于高级应用)

在C语言中调用生成的DLL

c语言 调用labview
(图片来源网络,侵删)

我们写一个C程序来调用 MyCalculator.dll 中的 Square 函数。

  • C语言代码 (main.c)
#include <stdio.h>
#include <windows.h> // Windows下需要此头文件来加载DLL
// #include <dlfcn.h> // Linux下需要此头文件来加载.so文件
// 包含LabVIEW生成的头文件
#include "MyCalculator.h" // <-- 确保路径正确
// 定义函数指针类型,用于接收从DLL中加载的函数
// 函数签名必须与.h文件中声明的一致
typedef int32_t (*SquareFunc)(int32_t input);
int main() {
    // 1. 加载LabVIEW生成的DLL文件
    HINSTANCE hDLL = LoadLibrary(TEXT("MyCalculator.dll")); // Windows
    // void* hDLL = dlopen("./libMyCalculator.so", RTLD_LAZY); // Linux
    if (hDLL == NULL) { // if (!hDLL) for Linux
        printf("无法加载 DLL/so 文件,请确保文件在当前目录或系统PATH中,\n");
        return 1;
    }
    // 2. 从DLL中获取函数地址
    SquareFunc pSquare = (SquareFunc)GetProcAddress(hDLL, "Square"); // Windows
    // SquareFunc pSquare = (SquareFunc)dlsym(hDLL, "Square"); // Linux
    if (pSquare == NULL) { // if (dlerror() != NULL) for Linux
        printf("无法找到 'Square' 函数,\n");
        FreeLibrary(hDLL); // Windows
        // dlclose(hDLL); // Linux
        return 1;
    }
    // 3. 调用函数
    int32_t inputValue = 5;
    int32_t result = pSquare(inputValue);
    printf("C程序调用LabVIEW函数:\n");
    printf("输入: %d\n", inputValue);
    printf("LabVIEW计算结果: %d\n", result);
    // 4. 释放DLL
    FreeLibrary(hDLL); // Windows
    // dlclose(hDLL); // Linux
    return 0;
}
  • 编译和运行 (Windows)
    1. main.cMyCalculator.hMyCalculator.lib 放在同一目录下。
    2. 使用Visual Studio的开发人员命令提示符,运行以下命令:
      cl main.c MyCalculator.lib user32.lib
      • cl 是微软的C/C++编译器。
      • MyCalculator.lib 是我们需要链接的导入库。
      • user32.libLoadLibraryGetProcAddress 函数所在的库。
    3. 运行生成的 main.exe,你应该能看到正确的结果。

通过命令行调用【最简单,但性能较低】

这种方法不涉及复杂的DLL接口,而是将LabVIEW VI当作一个独立的可执行程序来运行,C程序通过启动这个进程,并向它传递命令行参数,然后从其标准输出中读取结果。

工作原理

  1. 在LabVIEW VI中,使用“命令行输入”函数获取参数,并将结果通过“命令行输出”函数打印到控制台。
  2. C程序使用 system() (Windows) 或 popen() (跨平台) 函数来执行LabVIEW生成的 .exe 文件,并传递参数。
  3. C程序捕获 .exe 程序的输出,解析后得到结果。

详细步骤

在LabVIEW中配置VI以接受命令行参数

  • LabVIEW VI设计

    1. 在程序框图中,找到 函数 -> 编程 -> 应用程序控制 -> 命令行输入 函数。
    2. 将它拖入框图,它会返回一个字符串数组,包含所有命令行参数。
    3. 取第一个参数(索引为0,通常是程序名),第二个参数(索引为1)才是我们传入的数值。
    4. 将字符串转换为数值(使用 字符串/数值转换 -> 十进制字符串转换为数值 函数)。
    5. 进行平方运算。
    6. 将结果转换为字符串(使用 数值/字符串转换 -> 数值转换为十进制字符串 函数)。
    7. 使用 函数 -> 编程 -> 字符串 -> 格式化写入 函数,将结果格式化为 "Result: [数值]"。
    8. 使用 函数 -> 编程 -> I/O -> 写入标准输出 函数将结果打印到控制台。
  • 生成独立可执行文件

    1. 在LabVIEW中,点击 文件 -> 构建 -> 应用程序
    2. 选择目标目录,配置应用程序信息,然后点击 构建
    3. LabVIEW会生成一个 .exe 文件,MyCalculator.exe

在C语言中调用生成的EXE

  • C语言代码 (main_cli.c)
#include <stdio.h>
#include <stdlib.h> // 用于 system() 和 popen()
// 使用 popen() 的方法(推荐,可以获取输出)
int main() {
    char command[100];
    char result_buffer[128];
    // 1. 构建要执行的命令
    // 注意:如果你的.exe有空格,需要用引号括起来,如 "\"C:\My Path\MyCalculator.exe\""
    int inputValue = 7;
    sprintf(command, "MyCalculator.exe %d", inputValue);
    printf("C程序准备执行命令: %s\n", command);
    // 2. 使用 popen() 执行命令并打开一个管道来读取输出
    FILE* pipe = _popen(command, "r"); // Windows用 _popen
    // FILE* pipe = popen(command, "r"); // Linux/macOS用 popen
    if (pipe == NULL) {
        printf("执行命令失败,\n");
        return 1;
    }
    // 3. 从管道中读取输出
    if (fgets(result_buffer, sizeof(result_buffer), pipe) != NULL) {
        printf("从LabVIEW.exe捕获到的输出: %s", result_buffer);
        // 在这里你可以解析 result_buffer 来提取数值
        // 如果输出是 "Result: 49",你可以用字符串处理函数提取 "49"
    }
    // 4. 关闭管道
    _pclose(pipe); // Windows用 _pclose
    // pclose(pipe); // Linux/macOS用 pclose
    return 0;
}
  • 编译和运行
    1. main_cli.cMyCalculator.exe 放在同一目录下。
    2. 编译 main_cli.c
    3. 运行 main_cli.exe,它会启动 MyCalculator.exe,并打印出结果。

方法对比与选择

特性 方法一 (调用DLL) 方法二 (命令行调用)
性能 非常高,函数直接在进程内调用,开销极小。 较低,需要创建新进程,进行进程间通信,开销大。
复杂度 较高,需要理解DLL、函数指针、数据类型映射。 非常低,只需了解如何执行命令和读取文本流。
数据交互 灵活,可以传递复杂数据结构(通过LabVIEW的簇、变体等映射)。 受限,通常只能通过字符串传递简单数据,解析复杂结构困难。
UI交互 ,被调用的LabVIEW VI通常是无界面(后台运行)的。 可以,LabVIEW EXE可以带自己的UI运行。
适用场景 需要高性能、频繁调用的集成,如硬件控制、实时数据处理。 快速原型验证、简单的脚本式任务调用、或LabVIEW程序必须保留其UI时。
  • 追求性能和深度集成:选择 方法一,这是专业工程应用的标准做法。
  • 追求简单和快速实现:选择 方法二,它非常直观,适合不太复杂的场景。

对于大多数需要将LabVIEW作为计算引擎嵌入到更大C/C++项目中的情况,方法一(调用DLL)是无可争议的最佳选择

-- 展开阅读全文 --
头像
dede上传图片不显示怎么办?
« 上一篇 今天
汇编、机器、C语言,谁才是底层代码的核心?
下一篇 » 今天

相关文章

取消
微信二维码
支付宝二维码

目录[+]