Dear all, I need your help using a .dll in labview using arrays at the input and output.
I've created a .dll from MATLAB (implementing a voigt function) to be used in Labview 2017 (32bit). The function requires at the input an array of number (frequencies) and two scalars (gaussian and lorentzian width). The output is an array with the same dimensions as the frequency array.
Using a MATLAB-coder I build the .dll but I think that I do some mistake when handling the array, in particular the memory allocation/initialization even if I set a buffer array for the output and use "Array Handle" in the .dll setup. When running the VI I get the error 1097 "corrupted Labview memory" and sometimes Labview itself forces to close.
The VI and .dll (plus folders generated by the MATLAB coder) are attached in the .zip file.
During the compilation of the .dll from the MATLAB-coder the array size of the input array is set to be "unbounded" because in the code there are other local variables calling it with variable sizes and the .dll cannot be compiled if I fix the input array size.
Can you provide some suggestions to make the VI with the .dll work? I read a lot of posts with similar problems in handling arrays with .dll, also I tried to follow the configurations steps in the Labview-HELP VIs.
Do you think that there is an error in the .dll compilation or in the C++ code?
Thank you very much for your help!
I have never built a DLL using Matlab but I have created plenty of DLL using C++.
In general, passing a 1D array is straightforward, especially if you do not do memory allocation within the DLL.
When using a DLL that I created myself, to pass and receive a 1D array to and from a DLL in LabVIEW, I found it easier to simply use "Data Array Pointer" rather than "Array Handle". You then pass the array to the LaVIEW Call Library Node and in the C code, it is simply a pointer to the array (double *x).
If you need to receive an array, just pass to the Call Library Node an array having the size that you need.
All you need to do is make sure the output array has its size already initialized before you pass it into the dll. Use something like the code below:
What this does is take in an array (the size of which is already known). It grabs the size and initializes a new array with the data type that will be output. Then you just wire up those arrays on the left side of the dll to their respective area. That way LabVIEW has reserved the memory.
With this, you want to make sure everything on the left side of the dll is wired to something, that way the memory is already allocated.
Then once you do that, use Array Data Pointer instead of array Handle. It's common in dll's to also pass in the array size to the dll as a parameter, that way the dll knows what size is being passed in.
Dear MarcDub and ShockHouse,
Thank you for your answer.
I tried to do as you suggested sending a buffer array and also the size needed as input parameters when calling the VI, I also chose "Array data pointer" for the two arrays: input (x=frequency axis) and output. Yet I got the error 1097 again with output values "0".
I tried also to change the calling convention but the problem persist...
Regarding the question of altenbach I already implemented the Voigt function using the convolution of a gaussian and a lorentzian directly in Labview but this way is much more time consuming (expecially if you need to use to fit some data of similar functional shape in a for loop) than the MATLAB code which uses the "complex error function" (Fadeeva function) to extract the values of the profile. Unfortunately the complex error function is not implemented in Labview (I found the erf and other ones). Maybe the latter can be implemented in Labview but I didn't try, if you have any suggestion I thank you.
I also tried to generate a .dll only for the "complex error function" which requires the same input parameters if the voigt function, the issue is that the output array is made of complex numbers but I wasn't able to set such number-type in the output of the .dll apart from sending a complex-array as a buffer and choose "adapt to type"... yet I had the same problem with error 1097 if i select "Array data pointer" or a Labview forced closing if I set "Array Handle".
Any other suggestions?
Thank you again,
Array handles are wrong, unless you explicitly created the dll to accept pointers to pointers.
Have you tried switching the calling convention from stdapi to c (on the first tab)?
If the 2nd array returns complex numbers, make it twice as long. You can let the dll do that, by selecting a minimal length. No need to wire the input array, as long as there is an output array and the minimum size is selected.
My suggestion is to simply create a test dll that would simply take an array in, do a very simple operation (like adding a constant to all elements) and output the new array.
If that does not work, it would be easy to fix. If it works, it means that your problem is somewhere else in your C++ code.
I still don't understand why you would need to create that dll at all. Basically, you are insisting on using an ocean liner to cross a small creek. (Note that there might be icebergs. Remember the Titanic!)
A Voight lineshape with the given parameters could probably be written in plain LabVIEW using the area of a few postage stamps. Creating a Gaussian is trivial, creating a Lorenzian is trivial, and doing a convolution is trivial. You should really try it! One slight problem is the fact that your x-values are not spaced equally. I would use an equally spaced x-ramp of sufficient resolution, create the lineshape, then map it back to the slightly uneven x-values using interpolation.
Could you take a step back and explain where the x-is coming from and what you are trying to do with the result? What's the purpose of all this?
Dear wiebe@CARYA and MarcDub thank you for your suggestions. I'll implement a simple .dll with MATLAB and tell you if there is still a problem, which means that the code generated through that coder has some issues when dealing with arrays. Indeed a simple .dll doing the sum of just two scalar works with no problems.
Dear altenbach thank you again for your answer, I already implemented the lineshape from the convolution of a gaussian and lorentzian and reconstructed the profile form the x-axis with the interpolation and you are right this is trivial but for the application I need it is not a way to generate the lineshape faster, I'll try to explain my application: I have several dataset of points with different frequency axis (the x-axis not spaced equally in the VI) but following the same lineshape and I want to fit them all with a voigt function, to do this I want to use the non-linear-curve fitting VI in a for loop for all the datasets using as the model the voigt function. I have a written a code in MATLAB doing the non-linear-curve-fitting directly just sending the parameters of the datasets and I can call it through the MATLAB script node in the for loop. When I compare the overall time required for the fitting of all the dataset using the voigt function implemented in Labview (convolution of gaussian and lorentizian followed by interpolation) and the non-linear-curve-fitting.VI the time required is much more longer than calling the voigt+fitting script in the MATLAB script.
Since I tried to fit the dataset with a gaussian function I found no relevant differences if using completely Labview or MATLAB (both for the gaussian generation and non-linear curve fitting), the same happens for a lorentzian function while the voigt is completely different... The main difference is that in Labview I implement the function with the convolution, while MATLAB uses the complex-error-function as a sort of lookup table, and with this approach the generation is much faster. Indeed the implementation of the voigt lineshape with the complex-error-function has been treated with the purpose to fasten fitting algorithm of datasets similiar to the ones i'm collecting.
That is why I want to compile the .dll from MATLAB, because in that way I can generate the voigt function "skipping" the convolution and then use the non-linear-curve-fitting.VI directly in Labview without using the MATLAB.script node (which increases the time consumption).
I hope to have clarified better why it can be useful a voigt.dll that works.