LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

I'm new to DLL's. I want to create a DLL using Labview which outputs an array. I built a VI that outputs an array...how do I turn it into a DLL

I built a labview VI  that takes two controls and adds then and puts the result in a indicator..the dll works fine....when I try to build a dll with an array as the output I cant seem to get it to function.....

Maybe I'm missing some steps for the array case.....

0 Kudos
Message 1 of 17
(312 Views)

The problem is usually not to create a DLL in LabVIEW that creates an array but the caller needs to be correctly setup. Standard C memory handling rules apply!

 

Much easier is to allocate the buffer for the array in the caller and let the DLL function write the array elements in there.

 

From the very helpful code you forget to attach, that’s as much as we can basically tell you.

Rolf Kalbermatter
My Blog
0 Kudos
Message 2 of 17
(291 Views)

VERY SORRY !  Here is the process I went through but when I try and read the array in a C/Python environment I can't read the array so my set up must be wrong as you have indicated.....

 

OK...I have attached the VI  I then put it into a project folder  I then proceeded with the building of the DLL and this is where I get lost....

The tool generates len and len 2 which I suspect is related to the array lengths ?  However in the return value option it shows no output...aka void in the H file which I have also attached...what am I missing.....

 

Willie7_0-1712432900763.png

 

 

 

 

0 Kudos
Message 3 of 17
(241 Views)

let me try this again with the attachments....

 

 

0 Kudos
Message 4 of 17
(240 Views)

I have attached to VI...hopefully this time it will stay attached.....

0 Kudos
Message 5 of 17
(236 Views)

Here is the H file Labview generated.....

 

 

#include "extcode.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef uint32_t  Enum;
#define Enum_Lowpass 0
#define Enum_Highpass 1
#define Enum_Bandpass 2
#define Enum_Bandstop 3
#define Enum_WidebandLowpass 4
#define Enum_WidebandHighpass 5
typedef struct {
int32_t dimSize;
double passband[1];
} DoubleArrayBase;
typedef DoubleArrayBase **DoubleArray;
typedef struct {
Enum filterType;
int32_t interpolation;
DoubleArray ModelFilter;
DoubleArray ImageSuppressor;
} Cluster;
 
/*!
 * Test_1
 */
void __cdecl Test_1(double TIMES_05_OUT_OF_SINE_WAVE[], 
double IFIRINPUTARRAY[], double IFIROUTPUTARRAY[], 
int32_t *IFIRCOEFFICIENTGENERATEDERRORZeroNoError, Cluster *IFIRCoefficients, 
int32_t len, int32_t len2, int32_t len3);
 
MgErr __cdecl LVDLLStatus(char *errStr, int errStrLen, void *module);
 
/*
* Memory Allocation/Resize/Deallocation APIs for type 'DoubleArray'
*/
DoubleArray __cdecl AllocateDoubleArray (int32 elmtCount);
MgErr __cdecl ResizeDoubleArray (DoubleArray *hdlPtr, int32 elmtCount);
MgErr __cdecl DeAllocateDoubleArray (DoubleArray *hdlPtr);
 
void __cdecl SetExecuteVIsInPrivateExecutionSystem(Bool32 value);
 
#ifdef __cplusplus
} // extern "C"
#endif
 

 

0 Kudos
Message 6 of 17
(233 Views)

You're certainly trying to make this quite complicated. First mix and match C array pointers and LabVIEW array handles. While that is not invalid, it is for sure making things not easier, especially if you don't have a lot of C programming experience.

 

There is nothing wrong with that DLL but there is a lot that could be wrong in how you call this function in C or Python. Nothing LabVIEW could help you with.

 

While calling this from C is not really very complicated, at least if you know about C programming and the fact that LabVIEW array handles are not simply C pointers but specific LabVIEW objects that need to be allocated, resized and de-allocated with the according LabVIEW memory manager functions. Luckily, LabVIEW also adds exports to your DLL that are specifically meant to do these things for the array types used in your DLL interface.

 

 

DoubleArray __cdecl AllocateDoubleArray (int32 elmtCount);
MgErr __cdecl ResizeDoubleArray (DoubleArray *hdlPtr, int32 elmtCount);
MgErr __cdecl DeAllocateDoubleArray (DoubleArray *hdlPtr);

 

 

You have to use these functions to deal with every single DoubleArray data element in your API. A little convinience trick is that you can pass in the according cluster containing these array handles with a NULL pointer value for each, and the LabVIEW DLL will then allocate a valid handle if necessary.

 

When you want to interface to this DLL from Python things get immediately a lot more nasty.You have to setup the interface using ctypes and that needs to be done in a way that is perfect. If not done perfect you get at best nothing, but much more likely crashes. And in order to do that perfect you need to know in fact even more about C programming than what you would need when calling this from C. Because you need to configure the Cluster struct for instance perfectly and while the C compiler does the exact memory layout automatically right based on the declaration in the header file, there is no such thing in Python ctypes. You have to build/define it yourself.

 

Also accessing a handle in C is fairly straightforward as you can simply double reference the handle to get at the actual data in the handle. But in Python things get also more complicated. Your DoubleArray handle in Python is really something like

 

class DoubleArrayRec(Structure)
    _pack_ = 1
    _fields_ = [("dimSize", c_int),
                ("elm", c_double * 1000)]

DoubleArrayPtr = POINTER(DoubleArrayRec)
DoubleArrayHdl = POINTER(DoubleArrayPtr)

 

But of course things are actually more complicated than this.

 

First, LabVIEW 32-bit uses byte packing so you need to add a pack attribute to the Structure class definition when you use 32-bit DLL and Python. But in 64-bit this is not only unnecessary but wrong.

 

Python ctypes does not have OOR (original object return) datatypes, this means you can not simply declare a Python type and hope to use it to lay over an external value like that. So basically trying to access LabVIEW handles from Python is going to be a very tricky thing. I can't recommend to try it. It would be better to define these as extra function parameters and as array pointers too, and preallocate them in Python to the right number of elements before calling the function. That way you avoid most of the memory management hassles that you always get when calling managed environments such as LabVIEW from another differently managed environment such as Python.

Rolf Kalbermatter
My Blog
0 Kudos
Message 7 of 17
(218 Views)

The question relates to how to evaluate the output arrays and properly assign the start address and length of the arrays from the DLL so that C can properly allocate the proper memory.

 

In my application you can see from the VI that I am generating arrays using Labview and the Filter Routines for interpolated FIR filters (linear phase).  

 

THe issue that I'm having is that I don't if I'm setting up the DLL correctly and how best to ensure the subsequent C code that will be calling this dll, external from labview, can process the arrays properly.

 

Any assistance you can provide would be appreciated as I am new to DLLs and the requirements C has to properly allocate the start address, memory space, and ensure the space is not over written.

 

THANK YOU!

0 Kudos
Message 8 of 17
(210 Views)

OK, lets make this easier for me.  Lets talk about what is needed to take the dll H file generated by labview, output only 1D double precision numeri's (NO CLUSTERS) and get the C code to be able to read the arrays generated by the Labview DLL.  

 

IT sounds like Labview is generating the proper DLL so the underlying question I have is how do I take this labview generated DLL and have C properly read the arrays an properly allocate  the required memory size and address for the data.  

 

THANK YOU !

 

 

0 Kudos
Message 9 of 17
(206 Views)

For  clarification: I'll ensure the DLL is only dealing with 1D 64bit double precision numbers. No Clusters. No Python.  

 

After I generate the DLL, what is the proper code needed to get C to properly allocate memory, proper size, and start address to allow me to read the 1D array.  The input size of the array is always smaller than the output size of the array due to the IFIR delay caused by the number of samples it takes to fill the Z-1 terms and provide valid output data.  As you can see from the VI the length of the array on the output of the IFIR filter is longer than the array entering the IFIR Filter.  

 

If I am annoying you due to my limited knowledge in this space forgive me.

 

 

0 Kudos
Message 10 of 17
(202 Views)