views:

31

answers:

2

I have a function, singleFrameEventHandler, that I wish to be called when a certain event, OnNewFrame, occurs. After doing some research, it seemed to me that functions which handle events have a void return type and take a parameter of the type that contains the event. From what I could find online, that is done like this:

Function declaration:

void singleFrameEventHandler(IAFrame ^ frame);

When the function is assigned to handle the event:

iaframe->OnNewFrame += &singleFrameEventHandler;

When I try to compile the code containing the above segments, I get the following error:

error C2664: 'Spiricon::BeamGage::Automation::Interfaces::IAFrame::OnNewFrame::add' : cannot convert parameter 1 from 'void (__clrcall *)(Spiricon::BeamGage::Automation::Interfaces::IAFrame ^)' to 'Spiricon::BeamGage::Automation::Interfaces::newFrame ^'
No user-defined-conversion operator available, or
There is no context in which this conversion is possible

The OnNewFrame is of type Spiricon::BeamGage::Automation::Interfaces::newFrame, which unfortunately has no documentation beyond being described as "The event that is called when a new frame is available."

In the object browser, I can find some information about it:

public delegate newFrame:
    public System.IAsyncResult BeginInvoke(System.AsyncCallback callback, System.Object object)
    public System.Void EndInvoke(System.IAsyncResult result)
    public System.Void Invoke()
    public newFrame(System.Object object, System.IntPtr method)

The newFrame constructor (?) seems to be the best bet, as it appears to take a method pointer, but when I try to use it like this:

iaframe->OnNewFrame += gcnew newFrame(iaframe, &singleFrameEventHandler);

I get the following error:

error C3352: 'singleFrameEventHandler' : the specified function does not match the delegate type 'void (void)'

Does this mean that my function has to take no parameters? If so, how would I get information about the event?

+2  A: 

The first syntax cannot work, that's C# syntax sugar that C++/CLI doesn't have.

The problem with the 2nd snippet is that the delegate type doesn't match the signature of your event handler. The delegate was declared like this:

 delegate void newFrame();

You'll have to change your method signature to:

 void singleFrameEventHandler() 
 {
    // etc..
 }

How you're supposed to get a reference to the frame is not clear from your snippets. I'd guess at a property on the class.

Hans Passant
Okay, thank you. I also found out that when I get an IAFrame (which also includes data for an individual frame in addition to the event) from the factory, I get the latest frame, so I don't need the event handler to have an IAFrame object handle passed to it.
Eric Finn
+3  A: 

Event handlers in .NET are typically defined with two parameters (see MSDN)

delegate void EventHandler(object sender, EventArgs e)

However, the error messages you've posted do strongly imply that OnNewFrame does not follow this pattern and that singleFrameEventHandler should take no parameters.

My guess is that the developers of this API thought that the event itself was enough information, and that the event handler would store a reference to the IAFrame raising the event if it needed to query it. Code similar to the following should work (note that when creating the event handler delegate, you need to reference the class owning the event handler method, not the source object):

class FrameEventHandlers
{
public:
    FrameEventHandlers(IAFrame ^ frame)
      : m_frame(frame)
    {
        m_frame->OnNewFrame += gcnew newFrame(this, &FrameEventHandlers::singleFrameEventHandler);
    }

private:
    void singleFrameEventHandler()
    {
        // query m_frame for new data
    }
};
Bradley Grainger