LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

dll with a complex type in a structure

one of the solution for the x64 was to create for each element in the array single variable in the struct  but it didn't work on the LabVIEW x32.

for example for an array with a length of 32 you need to create 32 variable inside the cluster with the same type.

0 Kudos
Message 11 of 16
(850 Views)

@LLindenbauer wrote:

I also remember that. I recently had an array of char of size 32 inside a struct/cluster I dealt with in this way. It seems incredibly hacky and needlessly difficult to maintain. I guess writing wrapper functions that return LabVIEW-native types would be a cleaner solution. I'd enjoy hearing other solutions though.


One of the issues is that an Array is sent as a pointer and that works bad between systems. But a cluster has allocated space (or something like that).

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
0 Kudos
Message 12 of 16
(843 Views)

@Yamaeda wrote:

Isn't a char[256] made as a 256 element u8 cluster? I have some memory of that being a solution in some old thread.


It is.

 

That's what I meant in the first reply: Re: dll with a complex type in a structure - NI Community:

 


wiebe@CARYA wrote:
So you can probably replace it with the right amount of integer data (e.g. a U8 for each element in the array). A LabVIEW array will always be a pointer.
Message 13 of 16
(834 Views)

@Yamaeda wrote:

@LLindenbauer wrote:

I also remember that. I recently had an array of char of size 32 inside a struct/cluster I dealt with in this way. It seems incredibly hacky and needlessly difficult to maintain. I guess writing wrapper functions that return LabVIEW-native types would be a cleaner solution. I'd enjoy hearing other solutions though.


One of the issues is that an Array is sent as a pointer and that works bad between systems. But a cluster has allocated space (or something like that).


Of course you can also allocate data (in e.g. an array of U8s) and pass that.

 

In a way, that is the reverse solution.

 

Simply pass enough bytes in an array, matching the number of bytes in the cluster. The function doesn't know this memory is an array or a cluster... It will simply use the memory.

 

This array can than be unflattened to the cluster. You probably have to swap bytes, words and sometimes longs (for 64 bit integers).

Message 14 of 16
(831 Views)

wiebe@CARYA wrote:

@Yamaeda wrote:

@LLindenbauer wrote:

I also remember that. I recently had an array of char of size 32 inside a struct/cluster I dealt with in this way. It seems incredibly hacky and needlessly difficult to maintain. I guess writing wrapper functions that return LabVIEW-native types would be a cleaner solution. I'd enjoy hearing other solutions though.


One of the issues is that an Array is sent as a pointer and that works bad between systems. But a cluster has allocated space (or something like that).


Of course you can also allocate data (in e.g. an array of U8s) and pass that.

 

In a way, that is the reverse solution.

 

Simply pass enough bytes in an array, matching the number of bytes in the cluster. The function doesn't know this memory is an array or a cluster... It will simply use the memory.

 

This array can than be unflattened to the cluster. You probably have to swap bytes, words and sometimes longs (for 64 bit integers).


Like this:

 

wiebeCARYA_1-1652192691184.png

 

Option 1 and 3 work as char[10], the middle one needs work on the receiving part.

Message 15 of 16
(819 Views)

@gmassaad1 wrote:

one of the solution for the x64 was to create for each element in the array single variable in the struct  but it didn't work on the LabVIEW x32.

for example for an array with a length of 32 you need to create 32 variable inside the cluster with the same type.


If you interface to different architectures you have to be careful about alignment. A C compiler will usually not pack variables in a structure directly side by side, but will align each element on a natural border that is a multiple of the the smaller of its natural size and the currently used alignment. This alignment can be set globally through a command line option, or explicitly in the code though #pragma pack statements. If not specified in any of these locations the compiler uses a default alignment limit which is currently usually 8 for most compiler out there, but nowhere standardized so if a compiler chooses a different default, it is not breaking the standard. 😀

LabVIEW is a little special in that, since for the 32-bit Windows version it uses byte packing when allocating clusters and it passes that memory space also to Call Library Nodes. In all other still sold platforms including Windows 64-bit it uses 8 byte alignment. This byte packing anachronism is a remainder of the LabVIEW Windows 3.1 days. On computers where you only had 4 MB of RAM, it really could matter if you were continuously wasting memory by not packing clusters and the x86 architecture has a minimal performance penalty for unaligned memory access. Other architectures like the Sparc processor back in those days were going into overdrive when they had to access unaligned operands in memory and LabVIEW used already natural alignment on those platforms back in those days.

 

As far as the original problem goes, these are exactly equivalent in C in terms of memory used:

 

typedef struct
{
   char buffer[256];
} Parameter;

void Function1(Parameter *param);
void Function2(char param[256]);

 

So in this specific case it would be simply enough to configure the according parameter in the Call Library Node as String, Pass as C pointer, and minimum size 256. The additional benefit of this would be that LabVIEW on return from the function will scan the string buffer for a NULL character and then resize its own string handle to that size, which usually is something you would really like to happen unless the string can contain embedded NULL characters. If that is the case you have to pass it as Array of U8, pass as Array C pointer, minimum size of 256 to prevent the Call Library Node from trying to scan for a NULL character.

 

If you pass it as a LabVIEW cluster of 256 U8 elements, there won't be any scanning for a NULL character either and you have to do yourself the conversion back into a string and find its length.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
Message 16 of 16
(800 Views)