LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Interface dll function with struct in LabVIEW

Solved!
Go to solution

@myle00 wrote:

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?


Yes - it's different when part of a cluster than when just passing an array on its own.  In LabVIEW, an array inside a cluster is basically a pointer to the array stored somewhere else, because the array size can vary.  In C, an array in a struct is stored inline with the struct, because it has a fixed length.

0 Kudos
Message 31 of 41
(4,005 Views)

 


@myle00 wrote:

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


 

LabVIEW arrays and strings in the diagram are ALWAYS something different than what unsuspecting C programmers (and DLLs) would expect. However the Call Library Node allows to configure for a string and array parameter if it should be passed as native LabVIEW string or array handle or as C data pointer instead. LabVIEW does the underlaying translation to and from the C data pointer if you have configured the parameter to be such.

 

Theoretically the Call Library Node configuration could allow to configure the individual data type of structure elements too. However considering that the current configuration options are already more than most LabVIEW programmers can handle, this would be a real nightmare to maintain, support and explain.

 

So basically you can configure string and array parameters to be compatible to what a normal DLL expects, but you can not configure how LabVIEW passes elements inside a cluster to the underlaying shared library.

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

Thanks for the clearifications. I'm working on a few projects involving dlls so I have been reading up on dlls and specifically the issues of intefacing with LabVIEW, it seems most of the info is spread out over many threads; I'll probably post a new thread with some questions.

 

Before I open a new thread however I was wondering if you can point me to examples that use the LabVIEW memory manager functions in a CLN. It seems most info on these functions are old (i.e. Using External Code in LabVIEW pdf, 2003) and examples refer to CIN which is no more (I read Rolf's 3 part series on that) and I couldn't find examples that use them in CLN. In particular I think I'm having trouble getting the function prototypes right even though I looked through the h files in the cintools folder.

 

Thanks,

Matt

0 Kudos
Message 33 of 41
(3,978 Views)

There is no difference in using these functions in a CIN or a DLL. The only real difference is, in CINs they are mandatory since you will ALWAYS receive native LabVIEW data and have to provide same, while in DLLs they are mostly optional, since you can configure the CLN to pass parameters as C data pointers, eliminating the need to use those LabVIEW memory management functions, but requiring extra care in the LabVIEW diagram to always make sure you allocate any and all buffers with the required size explicitedly.

 

Basically if you pass LabVIEW native datatypes to external code, the external code writer will have to worry about correct allocation of memory buffers by using those functions, while when passing C data pointers, the VI diagram writer will have to worry about that, using CLN configuration options or explicit array allocations with Initialize Array or similar.

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

You're right, I wouldn't need these function typically, however, I was looking into allocating some memory in LV and pass it into my dll and use that memory to store an object that I can access in subsequent dll calls without having to create memory and return a pointer value in a first dll call and then pass around the pointer value to subsequent calls. I haven't however worked through the issues, like alignment that the first method would bring up (I'm trying to learn the inners of c++ while doing this).

 

When I tried testing the memory functions labview crashed so I figured I didn't get the prototypes correct (since labview doesn't autogenerate the prototype when I select a memory function in CLN). Like for example on my 32bit system I figured size_t is a u32 int but I wanted to see if there are any current vis that use these function so that I can see how they would be used.

 

Thanks,

Matt

0 Kudos
Message 35 of 41
(3,968 Views)

There are several here and on lavag.org but I'm sorry, I won't search and list them for you. Just no fun for me and way to much work Smiley Very Happy

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

Most likely your first error when calling these functions with a CLN is to use stdcall instead of cdecl. All LabVIEW manager functions use cdecl calling convention, because that is the only one that is supported on all LabVIEW platforms.

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

 


@rolfk wrote:

There are several here and on lavag.org but I'm sorry, I won't search and list them for you. Just no fun for me and way to much work Smiley Very Happy


 

Smiley Happy I found a couple examples, however, it seems that in some of those examples the prototype in the CLN doesn't match at all to the prototype in the extcode.h file. Although I'm pretty sure I'll generate the memory in my dll and pass the pointer back to my dll because it seems simpler in this instance, I'd still like to understand the use of these functions.

 

Here are some of the examples that didn't make sense (look at the MoveBlock function):

http://zone.ni.com/devzone/cda/epd/p/id/3672

http://forums.ni.com/t5/LabVIEW/DLL-Pointer-within-a-Cluster/m-p/1482162#M560431 (the prototype doesn't match at all!)

 

Doesn't the prototype in the CLN have to match the prototype in extcode.h or am I missing something?

 

It's not crashing anymore (I did have it set to the c calling convention) but I'm attaching an example vi. Why does the "check error 2" indicator not display an error code? The pointer is destroyed at that time so it should return with an error

 

Thanks for the help,

Matt

0 Kudos
Message 38 of 41
(3,942 Views)

The prototype does not have to be equal. First there are many ways to write a certain integer datatype depending which API header file you use. Second a void pointer (though LabVIEW uses UPtr for that which is for historical reasons a char pointer) can be anything really. So it is not important that the prototype matches exactly but that the memory buffers where the variables are in are the same. If the memory size matches but the underlaying type doesn't such as signed and unsigned for instance you get potentially a wrong result but nothing else.

 

The whole story is about understanding what a C compiler does for the different datavariables and types and that is indeed sometimes a bit more than a normal C programmer usually needs to know in order to make a C program.

 

DSCheckPtr() is a stupid function you should never really use. Either you know when you allocated a pointer and deallocated it and don't need to check at all, or you are in deep sh*t already. It only verifies that the pointer has been allocated with the according DSNewP..() functions, not that the pointer is still valid.

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

The most difficult part of you is probably when there is a pointer in the prototype while the Call Library Node is configured with a simple integer not even passed as pointer. This is done when we want to pass the pointer itself for some reasons.

 

For instance in the first example lvpointer.c the function returns an array of integers, aka a pointer. Yet LabVIEW does not support arrays as return type, since there is no way for LabVIEW to know how to return that array to the diagram as an array handle and for a LabVIEW programmer to tell LabVIEW how much memory to allocate beforehand.

 

So we do that all explicitedly by treating the pointer itself as integer (in LabVIEW 8.5 and higher it would be better to configure this as pointer sized integer, in order to be forwards compatible when we ever move this code to 64Bit) and then we use MoveBlock() to copy the contents of that pointer into a properly sized array. It's really a bad example to solve things since it couples two things very tightly that have little connection. If a programmer updates the DLL and returns a larger or smaller array instead, the calling code needs to be adapted too, or it will produce failures.

 

Same as far as MoveBlock() goes applies to the second sample. However glancing at it for 5 seconds showed me several other errors in that diagram. The string buffers to some of the API calls are never initialized so that WILL always corrupt memory.And an I16 array has not 4 times the number of elements in bytes so the MoveBlock() function will overrun the output array.

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