LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Use a UI message from a Visual Studio C++ DLL

Steve and Joe,

First of all, UIMessages is probably the best way to do this.  It's not too complicated to create the handler in LabVIEW and to post the UIMessage in C++.  Note that for a brief introduction to UIMessages, please refer the my post in this thread: http://forums.ni.com/ni/board/message?board.id=330&message.id=16023 in which I give a description and links to very helpful resources for UIMessages.

Secondly, I have attached an example of posting the UIMessage from C++.  Note that I simply used the AccessPropertiesUsingAPI example located in <TestStand>\Examples\AccessingPropertiesUsingAPI\UsingMFC.  I added a function:
void __declspec(dllexport) __stdcall Post(SequenceContext *seqContext)
{
    seqContext->Thread->PostUIMessageEx((TS::UIMessageCodes)10000,0,"",NULL,false);
}

I then simply recompiled the DLL and called the method from TestStand.  Note that my environment was VS 2005, but the code will be the same.

Finally, I also attached an example of the modifications to the User(Operator) Interface.  There are two files that need to be modified to create the handler: In Configure Event Callbacks, you need to extend the Register Event Callbacks, and then create the callback VI to handle the UIMessage event.  Note that I modified the Full-Featured UI so the references might not be valid for the simple UI, but at least you can see what's happening.

Thanks,

Andy McRorie
NI R&D
Message 11 of 21
(1,802 Views)

Andy,

Thanks very much for helping - I've got it working now. As usual, I was trying to make it too difficult. For others who may be C++ challenged like me, here's what I did:

This is contained in a C++ MFC DLL (VS2003) that I call from TestStand

Added includes to my header file:

#include

"stdlib.h"

#include

"tsapivc.h"

using

namespace TS;

Added the argument SequenceContext *seqContext to my function definition

Inserted the following in my function:

CString tmpStr = "My UI update info";  //This is the string I wanted to pass to the LabView user interface

bstr = tmpStr.AllocSysString();

seqContext->Thread->PostUIMessageEx((TS::UIMessageCodes)10005,0,bstr,NULL,true);

In my case the event code is the base number + 5. I had to convert the Cstring to BSTR to be compatible with PostUIMessageEx. Another thing I did was to add NI Application Class Libraries/TestStand Support using the Add Class Libraries Wizard from the Measurement Studio menu in VS 2003. It seems to be necessary if one is going to pass string pointers from the DLL to TestStand. Not sure if its needed for passing UI messages

Steve S

Message Edited by Steve Smith on 10-12-2007 01:01 PM

0 Kudos
Message 12 of 21
(1,769 Views)


wiebe@CARYA wrote:
I'd avoid sending a string if possible. If you want to send a status, send
an numeric. At least test with numerics, in general they are a lot easier.

The problem with strings is that you are passing a pointer. This pointer
lives in the memory of the sender, but the receivers wants to read it. The
sender should release the memory, but has no idea about when the reader is
done with it. So strings are very likelly to cause problems here. On the
other hand, there are some windows messages that pass strings, so it might
be handled internally.


If you use PostLVUserEvent there is no Windows message queue involved. That function takes a pointer to the LabVIEW data of the type as specified when creating the user event. For a string this would be a LabVIEW string handle.

Rolf Kalbermatter
Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 13 of 21
(1,663 Views)

Hi Rolf,

I've been running this code using strings for about 7 months on two test systems with no apparent problems. These UI messages are used to notify the operator of test status, time remaining, etc. and are executed as many as several hundred times in some tests such as in a percent complete indication for software download for 16 boards in a batch test.

Thanks,

Steve S.

0 Kudos
Message 14 of 21
(1,640 Views)


@Steve Smith wrote:

Hi Rolf,

I've been running this code using strings for about 7 months on two test systems with no apparent problems. These UI messages are used to notify the operator of test status, time remaining, etc. and are executed as many as several hundred times in some tests such as in a percent complete indication for software download for 16 boards in a batch test.


We are in fact talking about two different functions. You are using the PostUIMessage(Ex) function which is a TestStand API and follows standard C notations. I was talking about PostLVUserEvent which is a LabVIEW API and uses specific LabVIEW datatypes.

LabVIEW uses handles for variable sized data and those can be moved around and ownership often carries over from sender to receiver. For TestStand APIs you most likely allocate the string in your application, then send it with PostUIMessage off and the PostUIMessage then creates a copy to move it to the final owner so that the string can be changed/deallocated after PostUIMessage returns. So ownership of the string pointer parameter to PostUIMessage always remains at the caller.

Rolf Kalbermatter
Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 15 of 21
(1,634 Views)
Rolf,
 
Are you saying that instead of posting UI messages in TS in which the UI message fires LV Events we can actually fire LV User events with TS.
If we do it this way can we still get the sequence context of the sequence. If we could this might make things easier.
 
thanks



Joe.
"NOTHING IS EVER EASY"
0 Kudos
Message 16 of 21
(1,615 Views)


@Jhoskins wrote:
Rolf,
 
Are you saying that instead of posting UI messages in TS in which the UI message fires LV Events we can actually fire LV User events with TS.
If we do it this way can we still get the sequence context of the sequence. If we could this might make things easier.
 
thanks



Unfortunately I'm not familiar enough with TestStand to be able to tell you one way or the other. I'm not exactly sure about how TestStand invokes LabVIEW to run LabVIEW teststeps. The function PostLVUserEvent is only available in the LabVIEW kernel, either if you run from within the LabVIEW development system or inside the LabVIEW runtime system. Now the actual LabVIEW VI teststeps obviously need to run inside either of these two but I would expect the C++ DLL testssteps to run in the context of the TestStand process. So they may not have direct access to the LabVIEW environment and its kernel but instead rely on interprocess message passing to communicate with teststeps in the other environment. It's what I would expect to happen really since instantiation of the LabVIEW kernel inside another process would seem to me a rather complicated if not almost impossible task.

Basically all LabVIEW APIs are only available inside the process that consists of the LabVIEW kernel, which is either the process started up by LabVIEW.exe or a process that instantiated lvrt.dll. If TestStand would instantiate lvrt.dll in order to run LabVIEW tests then it should work. If it however starts up a separate process for running of LabVIEW tests and runs those tests through VI server, then your TestStand DLLs have no way to actually import PostLVUserEvent at all. And personally I would say that implementing the second is a lot easier to do although it has also certain limitations since you end up with interapplication communication.

Rolf Kalbermatter


Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 17 of 21
(1,601 Views)

Hey Joe,

Regardless of whether LabVIEW affords you the option to post a user event from your C++ DLL (which I don't believe to be possible), the absolute best option in terms of reliability/ease/maintainability is to use UIMessages (which are intended for the kind of task you are performing).  I would strongly encourage you to maintain this platform for communication with your OI unless you have problems with it (in which case, let us know).

As a sidenote, if you have a LabVIEW event structure that you want to respond to UIMessages instead of your callback VI, the way that I would recommend implementing this would be to create a user event in LV, pass the reference to your callback, and then fire the event from your UIMessage handler. The idea would be that you would still use UIMessages as your TestStand to LabVIEW communication as it was intended; you would just internally use a user event to signal the reception of the message to some other part of your LabVIEW program.



Message Edited by AndrewMc on 05-08-2008 02:01 PM
Thanks,

Andy McRorie
NI R&D
0 Kudos
Message 18 of 21
(1,593 Views)

Andy,

That is exactly what i am doing right now and it has worked great for months now. Rolf just replied to an older post of Steve's and I just hought that maybe he had a fresh idea.

thanks all,




Joe.
"NOTHING IS EVER EASY"
0 Kudos
Message 19 of 21
(1,582 Views)
> Regardless of&nbsp;whether LabVIEW affords you the option to post a user
event from your C++ DLL (which I don't believe to be possible),

This is possible, but you need a reference to the user event. I have done
this in a C dll called from within LabVIEW. I'm not sure if it will work
from another application calling the dll, perhaps it will if you use
LoadLibrary to open a reference to a running LabVIEW executable. You might
as well call the PostUserEvent from a LabVIEW VI.

Regards,

Wiebe.


0 Kudos
Message 20 of 21
(1,555 Views)