LabVIEW调用C生成的DLL无法正常获取struct类型返回值问题咨询
问题原因及解决方案
1. 先修复C代码的内存错误
你当前的getData函数存在野指针问题,DLL_RETURN_t* test没有分配内存就直接赋值,会触发内存访问错误,必须先分配内存,可选两种分配方式:
- 方式1:堆内存分配(后续需要在LabVIEW调用完再调用配套的释放函数避免内存泄漏)
#include <stdlib.h> #include <string.h> typedef struct { int success; /** 函数调用是否成功 **/ char returned[32]; /** 函数返回结果 **/ } DLL_RETURN_t; DLL_RETURN_t* getData() { // 给结构体分配堆内存 DLL_RETURN_t* test = (DLL_RETURN_t*)malloc(sizeof(DLL_RETURN_t)); if(test == NULL) return NULL; test->success = 1; strncpy(test->returned, "Simple Test", 31); // 避免字符串越界 test->returned[31] = '\0'; // 确保字符串结尾 return test; } // 配套内存释放函数,LabVIEW用完结构体后调用 void freeData(DLL_RETURN_t* p) { if(p != NULL) free(p); }
- 方式2:静态内存分配(缺点是多线程调用不安全,下一次调用会覆盖上一次的结果)
DLL_RETURN_t* getData() { static DLL_RETURN_t test; test.success = 1; strncpy(test.returned, "Simple Test", 31); test.returned[31] = '\0'; return &test; }
2. 修正LabVIEW端的参数配置
LabVIEW的导入共享库工具默认会把自定义结构体指针识别为指针地址整数,不会自动映射为簇,需要手动修改配置:
- 步骤1:在LabVIEW中创建和C结构体对应的簇:按顺序放入一个
I32数值控件(对应success)、一个字符串控件,右键字符串控件 -> 表示法 -> 选C字符串,再右键字符串 -> 字符串长度 -> 设置为32,调整簇内元素顺序和C结构体定义顺序完全一致。
注意:簇的字节对齐设置需要和C编译时的结构体对齐设置一致,右键簇 -> 高级 -> 自定义字节对齐,可修改对齐字节数,默认一般是4字节对齐,和大部分C编译器默认设置匹配。
- 步骤2:打开导入工具生成的VI,右键后面板的
调用库函数节点-> 选择配置:- 找到
返回类型,默认是数值->I32,修改为指针->匹配到类型,然后选择你刚才创建的自定义簇类型 - 确认调用规范和你编译DLL时的设置一致(一般是C调用规范
cdecl,如果是VS默认选了stdcall就对应选stdcall)
- 找到
- 步骤3:如果用的是堆内存分配的方式,调用完getData拿到结构体数据后,要再调用你写的
freeData函数把指针传进去释放内存,避免内存泄漏。
更安全的实现方案
你也可以不返回结构体指针,改成把结构体指针作为输出参数传入DLL,由LabVIEW端分配内存,这种方式不需要手动管理内存,稳定性更高:
// 修改后的C函数 void getData(DLL_RETURN_t* output) { if(output == NULL) return; output->success = 1; strncpy(output->returned, "Simple Test", 31); output->returned[31] = '\0'; }
这种情况下LabVIEW配置调用库函数节点时,把参数类型设置为指向对应簇的指针即可。
内容的提问来源于stack exchange,提问作者Arcaniaco
相关产品推荐
相关产品推荐

