Miykoll Posted October 5, 2022 Report Share Posted October 5, 2022 Hi there, I've issues by reading a pointer in a pointer in Labview DLL. I tried several suggestions found in other topics on this forum, but didn't succeed, so here we go. # Problem The DLL FTMProLib has a function called GetSpectrumData. This function requires an int of spectrumtype and a pointer to pSpectrum). (see attachment Page_FTMProLib_GetSpectrumData.jpg) This pSpectrum is of the type Spectrum, which is a struct. (see attachment Page_FTMProLib_Spectrum.jpg) In the Spectrum struct there is a double called pdSpectrum which contains my spectrum data. However, different from the other elements, this is a pointer. I know how to call a pointer to an double array through the DLL in LabVIEW. However, this pointer is nested inside the pointer to the Spectrum struct. When generating the DLL, LabVIEW created the control shown as "pSpectrum oud" in 2022-10-05_Labview_library_control.png. As one can see, the pdSpectrum is not an array, but a single number field. I tried to change this to an array, as shown in "sRawData". However, when I use this new control format, LabVIEW crashes (see 2022-10-05_Labview_library_error.png). The Labview program is working when using the pSpectrum oud control, which to me suggests that I need to add a pointer to the double array in this single number field. But I've no idea how to do this, since labview is not working with pointers. So far I've no luck into getting this working and I'm out of ideas how to approach / fix it. Any help appreciated. Quote Link to comment
dadreamer Posted October 5, 2022 Report Share Posted October 5, 2022 (edited) 4 hours ago, Miykoll said: But I've no idea how to do this, since labview is not working with pointers. You can deal with pointers in LabVIEW with the help of Memory Manager and its functions. Just create an allocated pointer of 8 bytes (size of DBL) with DSNewPtr / DSNewPClr, build your cluster using that and pass it to the DLL. Don't forget to free the pointer in the end with DSDisposePtr. DSNewPtr-DSDisposePtr.vi upd: Seems like I've read it diagonally. Now I see you need a pointer to an array of doubles. So you'd allocate a space in memory large enough to hold all the doubles (not 8 bytes, but 8 x Array Size, i.e. 8 x lNumberDiodes). After the function call you'll need to read the data out of the pointer with MoveBlock function. Edited October 5, 2022 by dadreamer 2 Quote Link to comment
mcduff Posted October 5, 2022 Report Share Posted October 5, 2022 @dadreamer Can you please save the VI for an earlier version, say 2020? What you did may help me with a different DLL but a similar problem. Thanks. Quote Link to comment
dadreamer Posted October 5, 2022 Report Share Posted October 5, 2022 @mcduffDone. It's very limited example though as I don't have the OP's SDK and no VIs were posted to tinker with. 1 Quote Link to comment
mcduff Posted October 5, 2022 Report Share Posted October 5, 2022 @OP Sorry, don't mean to hijack this thread but... @dadreamer A few more quick questions. I am trying to interface with a TEK RSA using their RSA API. There is a function that allows one to stream the data from the instrument to the client, called IQSTREAM_GetIQData. The function prototype looks like this ReturnStatus IQSTREAM_GetIQData(void* iqdata, int* iqlen, IQSTRMIQINFO* iqinfo) Iqdata is an array of data and I think I can use the Array Data Pointer function in the library function, iqlen is just the length of the array. I believe the problem I am having is the IQSTRMIQINFO structure. The structure looks like this IQSTRMIQINFO(Structure): [('timestamp', c_uint64), ('triggerCount', c_int), ('triggerIndices', POINTER(c_int)), ('scaleFactor', c_double), ('acqStatus', c_uint32)] There is a pointer to an array of 100 elements in the structure. If I am understanding you correctly, I should use the pointer from DSNewPtr in the cluster, instead of an array. (See example below.) In the Call Library function what should the data format be: Handles by Value, Pointers to Handles, Array Data Pointer, or Interface to data? Thanks again for all of your help. Quote Link to comment
Miykoll Posted October 6, 2022 Author Report Share Posted October 6, 2022 @dadreamer Thank you for the detailed instructions. I'm going to try it today @mcduff No worries about the hijacking. your questioning and your image give me better understanding as well. 💪 1 Quote Link to comment
dadreamer Posted October 6, 2022 Report Share Posted October 6, 2022 (edited) 11 hours ago, mcduff said: In the Call Library function what should the data format be: Handles by Value, Pointers to Handles, Array Data Pointer, or Interface to data? Each time a library function wants a struct pointer as an input parameter, you should pass it as Adapt to Type -> Handles by Value. In this case LabVIEW provides a pointer to the structure (cluster). If the struct is very complex (not in your case) it's possible to pass a (prearranged) pointer as an Unsigned Pointer-Sized Integer and take it apart after the call with MoveBlock function. I see some inconsistencies in your struct declaration and the cluster on the diagram. The second field should be triggerCount, but the cluster has it named as triggerindices. The same for the third field: triggerIndices -> ListTI. Might be a naming issue only. Then which representation does that array have? If there are common double values, it's enough to allocate 8*100 bytes of memory. Of course, you may make some memory margin and it's not doing any bad, except taking an extra space in RAM. After the IQSTREAM_GetIQData call you likely want to extract the array data into a LabVIEW array, so before doing DSDisposePtr you would call MoveBlock to transfer the data. Also an important note: Unsigned Pointer-sized Integers are always represented as U64 numbers on the diagram. So if you are working in 32-bit LabVIEW, you should cast it to U32 explicitly before building a cluster. It's even better to make a Conditional Disable Structure with two cases for 32-bits and 64-bits, where a pointer field would be an U32 or U64 number respectively. Edited October 6, 2022 by dadreamer 1 Quote Link to comment
mcduff Posted October 6, 2022 Report Share Posted October 6, 2022 Sorry for haste when making the diagram, I made some typos. So please excuse my stupidity and ignorance, but here it goes. The IQSTRMIQINFO Structure contains the following content IQSTRMIQINFO(Structure): [('timestamp', c_uint64), ('triggerCount', c_int), ('triggerIndices', POINTER(c_int)), ('scaleFactor', c_double), ('acqStatus', c_uint32)] So I should set up my cluster as shown below and use DSNewPtr and MoveBlock if I want to read the data. If I have the function in a tight loop, can I make the pointer outside the loop and use it over and over again until I exit the loop and dispose of it? Thanks Quote Link to comment
dadreamer Posted October 6, 2022 Report Share Posted October 6, 2022 21 minutes ago, mcduff said: If I have the function in a tight loop, can I make the pointer outside the loop and use it over and over again until I exit the loop and dispose of it? Of course, you can. 🙂 1 Quote Link to comment
mcduff Posted October 6, 2022 Report Share Posted October 6, 2022 @dadreamer Thanks for all of your help, will have to try it out later today when I have the instrument. Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.