【发布时间】:2021-05-07 21:47:51
【问题描述】:
我正在尝试创建一个 LabVIEW DLL 并从 C++ 程序中调用它,但我遇到了数据传递问题。
我最近购买的一台科学相机带有 LabVIEW SDK,仅此而已。 SDK提供的示例程序主要是围绕ReadData和DecodeData两个函数的while循环。
- ReadData从USB采集数据(使用VISA读取),一次调用获取的数据包含几个完整的数据块和一个不完整的传入块。
- DecodeData 被多次调用以处理所有完整的块(它从缓冲区中删除处理过的数据)。处理完所有完整块后,剩余数据(传入块的开头)将传递给 ReadData,后者将在缓冲区末尾连接其新数据。
在用 LabVIEW 编写的示例程序中,一切正常。问题是当我在 DLL 中导出这些函数时。这两个函数的内存缓冲区、输入和输出都是字符数组。在 ReadData 之后,我的 C++ 程序正确地获得了一个包含数据的缓冲区,包括空字节。
问题是当我在 DecodeData 中注入这个缓冲区时,LabVIEW 似乎只考虑第一个空字节之前的字节......我猜 char[] 输入只是作为一个空终止字符串处理,并且剩下的数据就被丢弃了。
我尝试添加数据转换器(在输出端添加“字符串到字节数组”,在输入端添加“字节数组到字符串”),但转换函数也会丢弃第一个空字符后的数据。
我可以将 .vi 从 sdk 修改为只处理字节数组而不是字符串,但它使用了很多字符处理函数,我宁愿保持原样。
如何在不丢失部分数据的情况下将数据缓冲区从 C++ 传递到 LabVIEW DLL?
编辑:这里是 C++ 代码。
LabVIEW DLL 导出的头文件:
int32_t __cdecl CORE_S_Read_data_from_USB(char VISARefIn[],
Enum1 blockToProcessPrevCycle, uint32_t bytesToProcessPrevCycle,
uint8_t inBytesRead[], uint32_t *BytesReceived, LVBoolean *DataReception,
uint8_t outBytesRead[], Enum1 *blockToProcess, uint32_t *bytesToProcess,
int32_t longueur, int32_t longueur2);
void __cdecl CORE_S_Decode_data(uint8_t inBytesRead[],
LVBoolean LUXELL256TypeB, uint32_t bytesToProcess, Enum1 blockToProcess,
Cluster2 *PrevHeader, LVBoolean *FrameCompleto,
uint32_t *bytesToProcessNextCycle, Enum1 *blockToProcessNextCycle,
Cluster2 *HeaderOut, uint8_t outBytesRead[], Int16Array *InfraredImage,
Cluster2 *Header, int32_t longueur, int32_t longueur2, int32_t longueur3);
在我的 C++ 源代码中的用法:
while (...)
{
// Append new data in uiBytesRead
ret = CORE_S_Read_data_from_USB(VISARef, blockToProcess, bytesToProcess, uiBytesRead, &BytesReceived,
&DataReception, uiBytesRead, &blockToProcess, &bytesToProcess, BUFFER_SIZE, BUFFER_SIZE);
if (DataReception == 0)
continue;
bool FrameCompleto = true;
while (FrameCompleto)
{
// Removes one frame of uiBytesRead per call
CORE_S_Decode_data(uiBytesRead, LUXELL256TypeB, 0, blockToProcess, &Header, &FrameCompleto, &bytesToProcess, &blockToProcess, &Header,
uiBytesRead, &InfraredImage, &Header, BUFFER_SIZE, BUFFER_SIZE, BUFFER_SIZE);
}
}
【问题讨论】:
-
你能告诉我们你的代码吗?
-
@JanSchultke 我加了截图,够了吗?
-
很难说这么少的信息有什么问题。我会使用可靠的二进制序列化/反序列化库,如 ProtoBuffer 或 FlatBuffer(第一个更容易,第二个更快,旨在实时数据传输)。另外,不要相信 char*。 C/C++ 中的字符串意味着在第一个空字节处终止。使用 uint8* 所以,至少,如果你用它调用一个字符串函数,你会得到一些编译器错误/警告。 C++ 流也有同样的问题。永远不要相信二进制数据的字符串流,它们非常具有误导性。
-
感谢您的建议。我不以任何方式处理 C++ 中的缓冲区,我只是从 readData 中获取指针并将其传递给 decodeData。我将尝试在 LabVIEW 模块中添加 uint8 转换器。
-
另一种方法是使用 Kaitai 并尝试重写相同的语法。 Kaitai 是一个为二进制数据创建解析器的工具包,它使用 Yaml 来设计语法,它可以为许多不同的语言生成解析器。