LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Return array data from running DLL to Labview

Solved!
Go to solution

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

0 Kudos
Message 1 of 26
(5,522 Views)

I thought PostLVUserEvent was a function for CINs. But you said you have a DLL.

 

??

0 Kudos
Message 2 of 26
(5,505 Views)

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.

Rolf Kalbermatter
Averna BV
0 Kudos
Message 3 of 26
(5,492 Views)

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

0 Kudos
Message 4 of 26
(5,481 Views)

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.

0 Kudos
Message 5 of 26
(5,474 Views)

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.

Message Edited by rolfk on 10-20-2009 05:21 PM
Rolf Kalbermatter
Averna BV
0 Kudos
Message 6 of 26
(5,470 Views)

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

 

 

0 Kudos
Message 7 of 26
(5,449 Views)

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. 

0 Kudos
Message 8 of 26
(5,389 Views)

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.

Rolf Kalbermatter
Averna BV
0 Kudos
Message 9 of 26
(5,381 Views)
Unfortunately it seems that it is not enough for me, because i couldn't get to work it:(...Right now I have solved this problem with sending string from dll and converting it into array in LV, but that doesn't seem to be correct solution.
0 Kudos
Message 10 of 26
(5,366 Views)