10-19-2009 04:11 PM
Hi All,
I have a C++ DLL that should run continuously collecting new data from some hardware.
I can call the DLL with no problems from Labview, but I would like to access some numeric array data in the DLL back in Labview (either the caller, or another VI) while it is running.
Working towards this, I have already got the event posting working, i.e. triggering messages from the running DLL in the caller VI using PostLVUserEvent(). This would solve my problem (perhaps inappropriately) if I only needed a scalar or string from each event (which works fine).
I then tried passing some small integer arrays via the event (correctly changing the input type to Create User Event in LV), but this didn't work out (either empty arrays, or crashes...oops!). Perhaps events are not the way to send large arrays (say 10^4-10^5 integers) anyhow...
Can anyone suggest a way to achieve this? Are there any functions for manipulating the values in a LV control/indicator from the running DLL?
Many thanks for any assistance, MT
Solved! Go to Solution.
10-19-2009 09:24 PM
I thought PostLVUserEvent was a function for CINs. But you said you have a DLL.
??
10-20-2009 01:54 AM
smercurio_fc wrote:I thought PostLVUserEvent was a function for CINs. But you said you have a DLL.
??
CIN or DLL makes no difference. CINs are in fact specialized DLLs. However CIN's are legacy and should be avoided by all means for new development.
To the OP, PostLVUserEvent() expects to be passed a LabVIEW datatype. So you can't just simply pass a pointer to your data back. You do need to allocate a LabVIEW array handle with the correct size and fill in the data. And I believe once PostLVUserEvent() has been called it takes ownership of the handle. That means you can't just allocate a handle somewhere and keep it around and pass it over and over to PostLVUserEvent(). PostLVUserEvent() being an asynchronous function, where the parameters that you pass to it can and usually will be only evaluated after the function returns to you, can not work with referenced data, but needs to own the data it is passed, so it can deallocate it when it needs to, not when you as caller think it is right to do so.
10-20-2009 06:09 AM
Hi there,
Thanks for the info, Andy. Yes - I got the feeling trying to send data via the event was a bit shady.
Do you think it could work in principle if I am careful to allocate memory and use the right kind of variable?
In any case, I am still on the hunt then for an alternative way to send back info to Labview.
Some possibilities that I have seen briefly elsewhere:
- TCP/IP or VISA
- Windows "memory mapped file" in DLL, to share data between DLL calls
Does anyone know if one of these options might work?
Regards, MT
10-20-2009 09:32 AM
rolfk wrote:
smercurio_fc wrote:I thought PostLVUserEvent was a function for CINs. But you said you have a DLL.
??
CIN or DLL makes no difference. CINs are in fact specialized DLLs. However CIN's are legacy and should be avoided by all means for new development.
OK. Wasn't aware the function could be used in a DLL as well. Haven't written a CIN in about 15 years.
10-20-2009 10:19 AM - edited 10-20-2009 10:21 AM
nz_mark wrote:Hi there,
Thanks for the info, Andy. Yes - I got the feeling trying to send data via the event was a bit shady.
Do you think it could work in principle if I am careful to allocate memory and use the right kind of variable?
In any case, I am still on the hunt then for an alternative way to send back info to Labview.
Some possibilities that I have seen briefly elsewhere:
- TCP/IP or VISA
- Windows "memory mapped file" in DLL, to share data between DLL calls
Does anyone know if one of these options might work?
Regards, MT
Not sure what is shady about passing data with an event. You just need to understand the LabVIEW datatypes and their handling. It's in fact even all documented in the manuals although not in a way that takes you by your hand and tells you step for step how to do it. On the other hand if they wanted to make it this way, especially will all the features that can be accessed through the C interface, then the LabVIEW manuals would get a few GB larger, and even more people would not even bother to look for any informationin there.
All the options you name are a possibility with their advantages and disadvantages. In all cases you will not be able to avoid data copies. Full by reference data in a dataflow language is virtually impossible, unless you want to be bothered with every nitty gritty detail about memory management in LabVIEW personally.
10-20-2009 04:07 PM
Dear Rolf,
Thanks for the advice - inspired me to continue. After mulling around the LV external code manuals for a while and looking at the string stuff in extcode.h, I tried the following DLL code, which seems to work fine:
//------------------------------------------
// Test sending arrays back to Labview caller via events
#include <windows.h>
#include <extcode.h>
#include "LVevent1.h"
typedef struct {
int32 length; // Length of array
int32 data[1]; // Array
} arr1D, *arr1DP, **arr1DH;
// Sends a 1D array of 32-bit integers, length N, Nevents times with msWait in between
DEXP int sendLVevents(LVUserEventRef *msg, int N, DWORD msWait, int Nevents)
{
int ii, jj;
arr1DH arrayH;
for (jj=0;jj<Nevents;jj++){
Sleep(msWait);
arrayH=(arr1DH)DSNewHandle(sizeof(int32)+N*sizeof(int32));
(*arrayH)->length = N;
for (ii=0;ii<N;ii++) (*arrayH)->data[ii]=(int32)(ii+jj);
PostLVUserEvent(*msg,(void *)&arrayH);
}
return 0;
}
//------------------------------------------
I can post a screen shot of the LV diagram (with an event structure, similar to those in the posts I quoted above), if anyone wants...
This seems to work error-free so far, i.e. tests with a 10000-element vector sent with 50 ms waits, 100 times, did not cause a crash or anything weird.
Just one question: Do I need to add some additional code to be more conscientious with the creation/deletion of these handles? Am I building up a ton of trash in the memory, or are the handles destroyed after LV gets the event? (The DLL should run for minutes to hours, sending 10-100 kB/second...).
Regards, MT
10-25-2009 07:58 AM
Hello Mark,
thank you for helping with my dll problem another day.
I came to an understanding, that the only good solution for me is to pass also array to labview.
Could you post the example, where dll passes array to labview.
I have to pass a small 1D array with about 20 values.
Thanks,
Mario.
10-25-2009 09:38 AM
A DLL does normally not pass an array to LabVIEW. Instead you allocate an array in LabVIEW using the Intialize Array node and pass that array to the DLL to let it fill in whatever it needs to fill in. And you do need to know in LabVIEW beforehand how big that array needs to be, because if you make it smaller than what the DLL wants to write in you WILL get crashes sooner or later and the mean thing about these crashes is, that they often do not happen when the DLL function is called but only later on when LabVIEW tries to access data structures your DLL has overwritten.
If you talk about returning array data asynchronously to LabVIEW then what Mark has posted above should be enough to figure out how to do it.
10-26-2009 04:45 AM