创建 VI 将结构从 DLL 导入 LabVIEW 时出现问题

Problem creating a VI importing a struct from DLL to LabVIEW

我想将 DLL 导入 LabVIEW 并从我的函数创建 VI,但对于具有常见数据类型的简单函数,导入效果很好。我的问题是当函数具有结构数据类型时。

我按照this tutorial导入。

我的 DLL 文件:

test.h:

#ifndef TEST_H_
#define TEST_H_

typedef struct
{
    int r_sum;
    int r_minus;
    int r_multiply;
    float r_divide;
}CALC_t;

int sum(int a, int b);
int minus(int a, int b);
int multiply(int a, int b);
float divide(int a, int b);
CALC_t calc_all(int a, int b);

#endif /* TEST_H_ */

test.c:

#include "test.h"

int sum(int a, int b)
{
    return a+b;
}

int minus(int a, int b)
{
    return a-b;
}

int multiply(int a, int b)
{
    return a*b;
}

float divide(int a, int b)
{
    return (float)a/b;
}

CALC_t calc_all(int a, int b)
{
    CALC_t result;
    result.r_sum = sum(a, b);
    result.r_minus = minus(a, b);
    result.r_multiply = multiply(a, b);
    result.r_divide = divide(a, b);
    return result;
}

导入DLL时,函数summinusmultiplydivide的VI成功创建,运行良好。但函数 calc_all 未创建,LabVIEW 显示警告消息:

Cannot create VI

The following VI cannot be created. This might indicate that the associated function contains
parameters of a data type that cannot be converted directly. To work around this issue, you can 
create a custom control or typedef control to represent a complex structure or multidimensional 
array, then re-run the Import Shared Library wizard and select Update VIs from a shared library.
Using the same shared library, step through the wizard again. On the Configure VIs and Controls 
page, assign the custom control or typedef to the associated parameter(s). Complex structures 
include nested structures, structures containing arrays, arrays of strings, and multidimensional 
arrays.

    dll_calc_all.vi

我尝试在“配置 VI 和控件”页面上进行更改,分配自定义控件、簇和其他数据类型,但没有成功。

我用 cygwin32 用 Eclipse IDE 编译库,我的 LabVIEW 是 LabVIEW 2021 32 bits

LabVIEW 的导入功能难以处理重要的类型,并且鉴于它无法推断内存分配之类的事情,除了最简单的调用外,最好避免使用它。

这通常意味着希望将 C/C++ 库集成到 LabVIEW 中的用户必须创建自己的 VI 来执行库调用,有时 create a wrapper in C/C++ 将库的类型转换为 LabVIEW 友好的类型.

在这种情况下,我建议修改 calc_all 函数以采用 CALC_t 类型指针作为结果。在 LabVIEW 端,我们可以创建一个具有与 CALC_t 类型完全相同的数据结构的集群,并将指向它的指针传递给库调用。

此外,对于 32 位系统,it is advisable to enforce the packing alignment 使用 #pragma pack 编译器指令。

综合起来:

test.h

#ifndef TEST_H_
#define TEST_H_

// enforce packing alignment for LabVIEW <-> C/C++ types when compiling for Windows 32-bit
// see https://knowledge.ni.com/KnowledgeArticleDetails?id=kA00Z0000019YsYSAU
#pragma pack(push) 
#pragma pack(1)

typedef struct
{
    int r_sum;
    int r_minus;
    int r_multiply;
    float r_divide;
}CALC_t;

#pragma pack(pop)

int sum(int a, int b);
int minus(int a, int b);
int multiply(int a, int b);
float divide(int a, int b);
void calc_all(int a, int b, CALC_t* );

#endif /* TEST_H_ */

test.c

#include "test.h"

.
.
.

void calc_all(int a, int b, CALC_t* result_ptr)
{
    result_ptr->r_sum = sum(a, b);
    result_ptr->r_minus = minus(a, b);
    result_ptr->r_multiply = multiply(a, b);
    result_ptr->r_divide = divide(a, b);
}

LabVIEW Snippet(拖放到空白 VI 程序框图上并将调用库节点指向您的 .dll