LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

LabView user-event from external dll source

Hi Rolf,

The C++ dll library holds the notifications in a list, if the notification (LVUserEventRef pointer) isn't identical to the registered ones, otherwise the library prints an erro.

 

Put each user event (dynamic register, event loop & dynamic unregister) in different subvi which is called in Top level twice with different notification names; The LV program runs/acts is it should be. Subvi's are reentrant because they are started parallel.

 

In dll debug mode I see different LVuserEventRef pointers for each registered event.

 

By putting a for loop around the dynamic register function and the call library node for registration, the different user event refnums passed to the call library node, gives twice the same pointer to the Notification DLL API.

 

 

 

 

 

0 Kudos
Message 51 of 56
(527 Views)

Instead of letting us guess what you did and having to rebuild your test setup it would be easier to simply attach your test case in source code to your post. No 1000 lines of prosa text can be as efficient in describing a programming sequence properly, than the source code itself.

Rolf Kalbermatter
Averna BV
LabVIEW ArchitectLabVIEW ChampionLabVIEW Instructor
0 Kudos
Message 52 of 56
(529 Views)

Hi Rolf,

Hereby a screenshot of the labview code, i placed probes to show the 2 user event refs are different.

Also put the DLL debug output when the LVUserEventRef pointers are passed through the call library node.

The concerning Vi and DLL API header file are attached in the zip file.

 

ScreenshotLabviewCode.jpg

DebugInfoDLL.jpg

0 Kudos
Message 53 of 56
(509 Views)

They better be different on the LabVIEW diagram! One is a notification refnum and the other is a user event refnum. Two totally different things! The user event refnum wraps the notification refnum which is in itself a somewhat roundabout way to do this as you could just as easily only use the user event in the first place.

 

There are some problems with your approach:

 

PostLVUserEvent() expects as its second parameter a pointer to the datatype that your user event wraps. Usually that is a numeric, an array or string handle or a cluster of those things. But LabVIEW allows you to wrap other data in an user event. However there is no documented way to create a notification refnum or any other of those refnums in the C code. So in order to pass the right data to PostLVUserEvent() you would also have to pass the notification refnum itself to the Call Library Node, store it somewhere and then pass that to the PostLVUserEvent(). There is a very strict match required between what the user event refnum wraps through its Create User Event node and what you pass as pointer to PostLVUserEvent(). You got lucky here, since refnums have a build in verification mechanisme that simply generates a Not A Refnum result, if the refnum is not a valid refnum in the currently registered refnums for that type. With other data you can easily get a hard crash if those two don't match since LabVIEW has no possibility to verify that the pointer you pass to PostLVUserEvent() is indeed the data that it implicitedly expects due to the datatype that the user event refnum wraps.

 

However wrapping a notification with a user event refnum is most likely anyhow the wrong approach. Better would be to wrap the actual data that you can directly use in the event structure such as the index into the boolean control refnum array that you want to set to true. Pass that index to the Call Library Node function and then let PostLVUserEvent() send it to the event structure. That allows you to create one user event for an integer and also saves you from having to register a new user event for every transaction as well as doing a roundabout way of identifying in the user event structure which event was triggered. Don't use the user event refnum itself as identification but the data that the user event carries along!

 

Personally I could think of even better ways than directly access the boolean control through a refnum from inside this driver VI, but that would go to far to try to teach you here proper application design too.

Rolf Kalbermatter
Averna BV
LabVIEW ArchitectLabVIEW ChampionLabVIEW Instructor
0 Kudos
Message 54 of 56
(498 Views)

Hi Rolf,

Passing the index or a cluster of four integers to the user event registration, in the right sequence as coded in the dll data structure, still gives meaningless index or integer values from the event data nodes. I've double checked the data which is passed to the PostLVUserEvent through its address. I assume Labview interprets the data wrong or data gets overwritten or lost. 

Hereby the code that passes the 4 integers to PostLVUserEvent function. This code comes along with the specific hardware.

Wild guess, can the pc architecture 64bit, Labview and DLL compilation for 32bit cause memory allocation missmatch?

 

0 Kudos
Message 55 of 56
(461 Views)

Well, LabVIEW data is not always a handle! For strings and arrays of anything, LabVIEW uses a handle to store the data in. For clusters and scalars it only stores the data in a data pointer.

 

So instead of creating a DSHandle to store your data in and then pass to PostLVUserEvent() you simply declare the data struct that is compatible with the LabVIEW cluster your user event does contain, on the stack and then pass a pointer to that struct to PostLVUserEvent(). The data that is passed into the PostLVUserEvent() function is always copied, so if you allocated something beforehand for this data you have to somehow deallocate it afterwards. This could be done after each call but if you think that you will call that function frequently that might add up and eat performance. In that case you could allocate a handle the first time and store it somewhere globally (don't forget to protect it with a semaphore or something to avoud race conditions) and whenever you need it check if it is long enough for what is needed and eventually resize it if it is not. Then at the end of your application you call a cleanup function that checks this global variable and deallocates it if it is not invalid.

 

A simple method to find out what LabVIEW expects in the pointer to the PostLVUserEvent() is to create a Call Library Node with an Adapt to Type parameter and then wire the datatype that the user event contains, to this parameter. Then right-click on the Call Library Node and select Create C source.

 

You get a C file that contains the declaration of the C data type that matches the LabVIEW datatype and an empty function body using that datatype as parameter. Simply make sure to pass this exact same datatype to the PostLVUserEvent() function.

Rolf Kalbermatter
Averna BV
LabVIEW ArchitectLabVIEW ChampionLabVIEW Instructor
0 Kudos
Message 56 of 56
(452 Views)