LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Code for the LV dotNet "NET Event Callback for DataWatcher.vi" example

Hello All,
 
I need to do some communication between C# and LabVIEW.
The "NET Event Callback for DataWatcher.vi" example is a great starting point.
It shows how you can register a LabVIEW vi for a custom written C# dotnet object (DataWatcher).
 
The compiled version of this DataWatcher object is delivered together with LabVIEW 8.
It is contained inside the EventExample.dll that is installed together with LV 8.
What I'm missing is the C# source code for this object. I cannot find it anywhere.
 
It looks like the source code of this dotNet object is not supplied together with LV 8.
 
Since this is also a crucial part of the example I would like to have it.
(as I'm not that experienced in C# I would like to have a look at it)
 
Is anyone willing to share the source code for a similar object (including event generation) written in C#.
 
Thanks for all the help!
 
Cheers,
 
noxus
 
0 Kudos
Message 1 of 13
(5,872 Views)
The code is very simple. It is simply a matter of defining an event along with a property set operation that triggers it. Let me know if you have any questions on it.
 
using System;
 
namespace EventExample
{
 public delegate void EventHappenedDelegate(Double dValue);
 
 public class DataWatcher
 {
  public event EventHappenedDelegate EventHappened;
 
  public DataWatcher()
  {
  }
 
  private Double m_dvalue = 3.14;
  public Double DoubleValue
  {
   get { return m_dvalue; }
   set
   {
    m_dvalue = value;
    if (EventHappened != null)
     EventHappened(m_dvalue);
   }
  }
 }
}
Message 2 of 13
(5,859 Views)
Hopefully, this thread is still monitored. I have a follow-up to the original question. How can I set the cluster values (Error, Warning, Code) fields from .NET? That is, in the event structure, the DataWatcher property node has and error out cluser of (Error, Warning, Code). Say I want to send an error from my .NET component to the VI. I would assumed that an Application exception would be the tool. However, how do you associate the cluster with the exception to pass values to the cluster?
 
Thanks,

Dave
0 Kudos
Message 3 of 13
(5,656 Views)
Hi Dave,

I talked about this issue in another post and provided some example code. Take a look at my post here.

Let me know if that answers your question.

Hope this helps!

Best Regards,
Jonathan N.
National Instruments
0 Kudos
Message 4 of 13
(5,655 Views)

Hi Jonathan,

That was exactly what I was looking for. After reading your post, it occured to me that, perhaps, when an error 1172 is caught by LabVIEW, the VI could then call a property on the .NEt instance (e.g. "public System.Exception ErrorReason{get;}" ) that would contain the exception specifics. Anyway, thaks so much for your rapid reply.

Dave

0 Kudos
Message 5 of 13
(5,652 Views)
Jonathan,
 
I hope you are still monitoring this thread. My apologies, in advance, if I am diverging from the main topic (callbacks). I have a follow-up question to your other post (referenced in a prior reply) in relation to the project I am working on. I think others may benefit as well from your wonderfull experience and help in this area.
 
My question relates to passing objects into LabVIEW from C#. Not in the context (no pun intended) of an exception but as an object returned from a property. First, I assume the proper way to reference object passed into LabVIEW is by adding a property node and connecting the refnum of the read property to the returned object property node? Here's a rather crude LabVIEW block diagram to illustrate my question (may not quit appear right due to formatting in HTML).
 
        | Constructor Node | ---(refnum) --- | Property Node |
                                                                 | Property Read |  ---- (refnum of property read) --- | Property node for returned object |
                                                                                                                                                  | Properties of returned object        |
 
Second, I tend to program using interfaces (to separate the implementation from the interface). If my property returns a reference to an interface (implemented by the specific object passed back), how do I then get to the specific properties of the returned object? My initial guess is to use the "to more general" or "to more specific" pallette items? That, of course, presumes I know in advance what the more specific or general class is. Does that question make sense? (Note: For some reason, I am having trouble getting LabVIEW reflect the methods as well as properties in property nodes - I thought this was the norm).
 
Here's an example (It's a rather useless example, but is correct in structure. Furthermore,  I understand that many will wonder why programming to an interface is so important - that is a rather in-depth topic an is the topic of programming with patterns):
 
// Class that in reference in a LabView Constructor node
public class MyTestClass
{
      private MyInterface m_A;
 
      // Property that is returned in a LabVIEW property node
      // connected to the constructor node's refnum for this class
      public MyInterface A
      {
              get { return m_A; };  // Note, the object returned "shows up as a type of the MyInterface
      }
 
      MyTestClass()
      {
              m_A = new MyGenericClass();
      }
}
 
public class MyGenericClass : MyInterface
{
      private int m_AnIntegerValue;
 
      public int AnIntegerValue
      {
           get { return m_AnIntegerValue; }  // Read only foir simplicity
      }
 
      public SetTheIntegerValue(int value)
      {
            m_AnIntegerValue = value;
      }
}
 
Thanks for your help in advance,
 
Dave
 
public interface MyInterface
{
        void SetTheIntegerValue();
}
0 Kudos
Message 6 of 13
(5,616 Views)

Hi Dave,

I'm actually kinda confused as to what behavior you are expecting verse what you are seeing.  So let me make some general statements and we can go from there.

The first piece of information I wanted to mention is that LabVIEW automatically provides conversion between .NET types and native LabVIEW types. For example, suppose you had a .NET method that accepted a .NET string as an input parameter. Well, you can simply drop down a .NET Invoke Node, select the method, and then wire a LabVIEW string up to it. The same conversion works for the opposite direction as well. If a Property Node returned a .NET string, you would notice that a LabVIEW string comes out.

Now there are cases where we don’t know what conversion to do and so LabVIEW displays data types it can't convert as .NET refnums.  You can then wire that object into an Invoke Node or Property Node to call methods or get/set properties.  You can see the data types that we can convert in the Data Type Mapping sub-category in the Using .NET with LabVIEW section found in the LabVIEW Help. 

I am not sure I understand your .NET interface question. Interfaces simple contain the declarations of methods, properties, and events.  Implementation is done in the class that inherits the interface. You don't apply a method or property to an interface. Thus I am a little confused as to what you need to do.

The "To More Specific Class" node is used when you need to downcast a .NET refnum to its derived class. The "To More Generic Class" node is used to upcast a .NET refnum to its base class.

Maybe you can clarify what you actual problem is?

Best Regards,

Message Edited by Jonathan N on 10-16-2007 01:38 PM

Jonathan N.
National Instruments
0 Kudos
Message 7 of 13
(5,609 Views)

Jonathan,

First, as always, thanks for your quick and informative reply.

>The first piece of information I wanted to mention is that LabVIEW automatically provides conversion between .NET types and native >LabVIEW types.

Right. No problem with that so far. The "type" returned from the object property is an instance of a class that implements a specific interface. That's where my learning curve starts.

>Now there are cases where we don't know what conversion to do and so LabVIEW displays data types it can't convert as .NET refnums.  >You can then wire that object into an Invoke Node or Property Node to call methods or get/set properties.  You can see the data types that >we can convert in the Data Type Mapping sub-category in the Using .NET with LabVIEW section found in the LabVIEW Help. 

Ah. Never thought about using the Invoke Node. For some reason, I was thinking that was for asynchronous calls. I will investigate.

>I am not sure I understand your .NET interface question. Interfaces simple contain the declarations of methods, properties, and events.  >Implementation is done in the class that inherits the interface. You don't apply a method or property to an interface. Thus I am a little >confused as to what you need to do.

K. Here's the deal. I am using the "command design pattern". In a nutshell, this .NET interface is a distributed system that sends commands and receives responses from client(s). So, instead of building a base class (CommandBase) and deriving commands from that class (CommandA : CommandBase, CommandB : CommandBase, ...) I am using an interface to delcare the type and then dynamically binding the commands as they come across the wire. There are many reasons to do this; the key is that I want the interface to drive implementation. If I derive from a base class and I need to change _anything_ in the base, it means that I have to consider all of the commands developed on both the client and the server. So, for example, say CommandA, CommandB, CommandC, ... all implement ICommand, then,

ICommand cmd;         // Declared an instance of a type
                                    // implementing the ICommand interface.
                                    // ("Code to an interface, not an implementation")

cmd = CommandA;   // Dynamically bind a command.
cmd.Execute();          // Execute CommandA.
                                   // In this application, the command is passed to LabVIEW
                                   // and the vi executes the command based on the command's
                                   // properties. So, the method Execute really is not really executed in .NET.

// later...

cmd = CommanB;     // CommandB received, dynamically bind.
cmd.Execute();          // Execute CommandB. Ditto.

So, taking this one step further, I pass cmd to LabVIEW via a property into a property or invoke node. What I am seeing now is that LabVIEW “sees” all of the Interface properties and methods, but no any of the other public properties and methods specific to, say CommandA, verse CommandB.

Now, that said, I think my mistake may be not using interfaces properly, which is probably the case. To use this scenario I am using a "To more specific class item casting the ICommand. I think what I need to do is 1) Explore your suggestion of the Invoke Node further, and 2) Consider my interface implementation in more depth. Then, based on my discovery, follow-up with an example project that you can download and load to see what it is I'm trying to accomplish (that is a basic simple project that highlights the key points). Does that sound like a plan?

Thank You,

Dave

 

0 Kudos
Message 8 of 13
(5,599 Views)
Hi Dave,

If you are still working on the design phase, you probably should make sure that it works in .NET before trying to use the assembly in LabVIEW. By that I mean develop your .NET assembly first, write a small .NET application that uses that assembly to validate that everything you expect works. At this point, I would work on calling the code from LabVIEW.

That's just my suggestion.

If you start running into issues, you can always call our technical support department for immediate responses. You can also post your problems on the forums as well. When you run into a specific problem, its best to create a new discussion forum post.

Best Regards,
Jonathan N.
National Instruments
0 Kudos
Message 9 of 13
(5,595 Views)
> If you are still working on the design phase, you probably should make sure that it works in .NET before trying to use the assembly in
> LabVIEW. By that I mean develop your .NET assembly first, write a small .NET application that uses that assembly to validate that
> everything you expect works. At this point, I would work on calling the code from LabVIEW.
 
Yeah, I understand and appreciate your concern. I'm actually a seasoned (.NET) developer and completed the .NET design portion about 2 weeks ago. The problem is that being of the, as NI pharases it, code-based group, I am new to LabVIEW. The issues is really understanding how to interface with LabVIEW (from .NET in this case). I've been through the basis course, and have a decent understanding of LabVIEW in general. So, it's more of a how do I play this new piano with the keys slightly re-arranged.
 
Anyway, my design philiosoply is 1) Code based, 2) Object-oriented, but more important, 3) Focused on reusability and pattern driven. This design is targeted towards a tool that is various configurations.
 
Dave
0 Kudos
Message 10 of 13
(5,584 Views)