LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Interface dll function with struct in LabVIEW

Solved!
Go to solution

 


@K1200LT rider wrote:

I'd still be interested in seeing how to pass a cluster by value.  Smiley Tongue


 

As I wrote it is highly unusual to do that, and hence most engineers never even would think of creating such an example. The only ones who would ever consider to pass structs by value are those who have absolutely no idea about C programming, but what the heck are they doing writing DLLs anyhow? Smiley Very Happy They should stay in VB or LabVIEW and not bother with DLLs at all! Or stop doing programming altogether.Smiley Tongue

 

As you write, passing parameters by value or reference is something so basic in terms of traditional programming that it is hardly worth a mentioning. If someone doesn't know that difference, adding those cases to the example VI won't help and if he does know he can make the small adaption jump easily. Fact is if you don't have any C or equivalent programming experience, interfacing a DLL will be always a nightmare, there is no amount of manual or examples that could make that significantly less.

 

As to an example of doing this, if you read this thread carefully you should have no problems to do that now if that need ever arises.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 21 of 41
(3,817 Views)

Since this thread isn't too old i'll just pick up on it:

 

Right now I am developing a Programm that (hopefully) makes the tiny_CAN Interface usable on LabVIEW. Now I am facing a similar Problem to the one described  above. One function in the DLL requieres a "struct TCanMsg" Datatype that is defined like this:

 

 

struct TCanFlagsBits
{
unsigned Len:4; // Dlc
unsigned TxD:1; // TxD -> 1 = Tx CAN Message, 0 = Rx CAN Message
unsigned Res:1; // Reserviert
unsigned RTR:1; // remote transmition request bit
unsigned EFF:1; // extended frame bit
unsigned Res2:8;
};

union TCanFlags
{
struct TCanFlagsBits Flag;
uint32_t Long;
};

union TCanData
{
char Chars[8];
unsigned char Bytes[8];
uint16_t Words[4];
uint32_t Longs[2];
};

struct TTime
{
uint32_t Sec;
uint32_t USec;
};

struct TCanMsg
{
uint32_t Id;
union TCanFlags Flags;
union TCanData Data;
struct TTime Time;
};

As you can possibly imagine I can't start to see the end of it. Does anyone have any suggestion on how to tackle this problem?

 



Remember Cunningham's Law
0 Kudos
Message 22 of 41
(3,788 Views)

It's fairly easy to convert that structure into an equivalent LabVIEW data type if you're familiar with C data structures.  The key thing here is that a union has the same space requirements as the largest element it contains.  You could use a cluster containing the following elements:

 

U32 Id

U32 TCanFlags

cluster of 8 U8 (this needs to be a cluster, not an array) Data

cluster of U32 Sec, U32 USec

 

You'll then need to write LabVIEW code to set or parse the bits of Flags.  What is the prototype of the function call that needs this structure?

0 Kudos
Message 23 of 41
(3,785 Views)

The prototype is as follows:

int32_t CanTransmit(uint32_t index, struct TCanMsg *msg, int32_t count)

 

You even answered a question I didn't even ask yet: how do I realize the TCanFlagsBits Structure? So what you're saying is, that I can basically pass an array of 16 boolean numbers, isn't it?

 

Can I use Clusters for both struct and union?



Remember Cunningham's Law
0 Kudos
Message 24 of 41
(3,778 Views)

 


@jak888 wrote:

The prototype is as follows:

int32_t CanTransmit(uint32_t index, struct TCanMsg *msg, int32_t count)

 

You even answered a question I didn't even ask yet: how do I realize the TCanFlagsBits Structure? So what you're saying is, that I can basically pass an array of 16 boolean numbers, isn't it?

 

Can I use Clusters for both struct and union?


 

No to both your questions.

 

Bitflags are just bits in a single integer. The number after the colon indicates how many bits of the integer the actual element will have. If you add up the bit numbers you will see that you end up with 16 bits which is a 16 bit integer. However this is again an element in an union and an union simply means it's either of the elements in that union, so it is either the 16 bit integer containing the bitflags or the 32 bit integer that the other datatype means.

 

So your unions in this case are simply the biggest element in that union, meaning for the flags a single unsigned 32 bit integer, and for the data 8 bytes in a cluster. Arrays in LabVIEW are always something different than what standard C code would expect, so don't use them as embedded elements in a cluster ever, when passing them to a call library node.

 

Instead you will use Boolean (N)AND and (N)OR and bit rotate functions to isolate the according bit from the integer or add it to the integer.

 

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 25 of 41
(3,770 Views)

 


jak888 wrote: 

You even answered a question I didn't even ask yet: how do I realize the TCanFlagsBits Structure? So what you're saying is, that I can basically pass an array of 16 boolean numbers, isn't it?

 

Can I use Clusters for both struct and union?


Let me answer your questions in reverse order: you can only replace a struct with a cluster.  A Union is a C construct in which the same value can be addressed as any one of several elements, but it only contains one value.  For example, the TCanData union can be an array of 8 bytes (signed or unsigned), 4 16-bit values, or 2 32-bit values.  In the computer's memory that's a single block of 8 bytes; the union lets the C programmer access it in whatever format he finds convenient.  There's no LabVIEW equivalent, but you can replace it with any data type (for example, a cluster of 8 U8 values) that has the same length.

 

 

You can't duplicate the TCanFlagsBits structure in LabVIEW because LabVIEW doesn't support bitfields, but fortunately you don't need to duplicate it.  Instead you can use a 32-bit value, as indicated by the 32-bit element of the TCanFlags union.  As I mentioned before, you'll then need to do some bit manipulation to convert that into individual values LabVIEW can use.

0 Kudos
Message 26 of 41
(3,764 Views)

Thank you guys, you've been one hell of a help already. The deeper I dive into this topic the more questions appear, so here's another Couple:

 

I don't quite get the "union TCanFlags"... Why is this defined as uint16 or as uint32? Doesn't make sense to me right now, as there's no way of telling what to expect...

 

Anyway: Can I treat a union like it wasn't there at all? E.g.: Do I have to define a "union TCanData" or could I just pass on the one type I prefer, which is uint8 Array[8]?

 

Since you can't really define unions per se in LabVIEW I currently am writing some subVIs that takes in Data and puts out one of the espected Data Types. Can I do it like this?

 

The DLL expects a structure, but would it be possible, to just pass the number of bits, it expects? in this Case 5 uint32...

 



Remember Cunningham's Law
0 Kudos
Message 27 of 41
(3,752 Views)

@jak888 wrote:

I don't quite get the "union TCanFlags"... Why is this defined as uint16 or as uint32? Doesn't make sense to me right now, as there's no way of telling what to expect...


It's not an issue of which one to expect; the union is purely a convenience to the C programmer, who can use whichever one is more convenient.  The union has a size equal to the largest of its elements, so TCanFlags will always be 32 bits.


@jak888 wrote:

 

Anyway: Can I treat a union like it wasn't there at all? E.g.: Do I have to define a "union TCanData" or could I just pass on the one type I prefer, which is uint8 Array[8]?


Yup, that's right.  You only need to use one of the union data types and it must be as long as the largest element of the union.  Since LabVIEW does not have fixed-size arrays, you need to define it as a cluster of 8 U8, not an array of U8.


@jak888 wrote:

Since you can't really define unions per se in LabVIEW I currently am writing some subVIs that takes in Data and puts out one of the espected Data Types. Can I do it like this?

 

The DLL expects a structure, but would it be possible, to just pass the number of bits, it expects? in this Case 5 uint32...


Sounds like you're making this more complicated than necessary.  Here's a cluster you could use, which you can pass directly to the function (in the Call Library Node setup, set the parameter to "Adapt to Type" and connect the cluster to it).  You could pass in an array of bytes (or U32) intead, but why make things difficult?  (Looks like some of the sub-cluster contents got lost in the snippet image, but they're fine when you drag it onto a block diagram - it's identical to the way I described it in my earlier post.)

TCanMsg cluster.png

0 Kudos
Message 28 of 41
(3,743 Views)

 


@nathand wrote:
 
Sounds like you're making this more complicated than necessary.

No I'm not...Smiley Happy
I just asked, for better understanding

 



Remember Cunningham's Law
0 Kudos
Message 29 of 41
(3,740 Views)

To jump in, can you please elaborate on this: "Arrays in LabVIEW are always something different than what standard C code would expect." In the LabVIEW dll examples (floorarray1d) of sending an array they simply pass an array to/from the CLFN. Did you just mean that it's different when the array is in a cluster because then the array might not actually be a continuous part of the structure but pointing somewhere else where the array is, or is this wrong?

 

Thanks,

Matt

0 Kudos
Message 30 of 41
(3,714 Views)