Measurement Studio for VC++

cancel
Showing results for 
Search instead for 
Did you mean: 

accessing imaq objects using pointers

I defined a CWIMAQ control object in my application's view class using the visual C++ Resource View dialog builder utility. I also defined a generic class to acquire and process the images from the 1428 frame grabber card. When I create the generic class object in the application's view, I pass a pointer to the view to the generic class's constructor.

When the generic class tries to acquire an image using the CWIMAQ object defined in the view using the View pointer I get a windows error.

//MFC view class
CMyView::OnInitDialog(....)
{
m_processImage=new CProcessImage(this);
}

//generic class
CProcessImage::CProcessImage(CMyView* view)
{
m_viewPtr=view;
}

CProessImage::CProcessImage()
{
m_viewPtr ->
m_cImaqObject.AcquireImage(); //this fails
}

If I put the AcquireImage function call inside the view it doesn't fail. But then when I try to get my images from the buffer from my genric processing class I get the same error. So I really need to figure out how to access the CCWIMAQ object from other classes. How can I call the AcquireImage function from my worker class?

Thanks for your help
0 Kudos
Message 1 of 17
(4,684 Views)
What is the error that you get? Could you post a screen shot of it?
0 Kudos
Message 2 of 17
(4,683 Views)
Sure, but I don't know how much help it will be. Have you tried something similar to this before? Thanks for your help.
0 Kudos
Message 3 of 17
(4,683 Views)
The error message you are getting is the result of a breakpoint being hit. If you run in the debugger, you will see where the breakpoint is in your code. I suspect that you are hitting a breakpoint as the result of hitting an assert in the MFC source code.

Without running this myself, I can only speculate as to the cause. From what you describe, one thing I would look to is whether the view HWND is being created before you attempt to access the control in the failure case. You are hosting the ActiveX control on the view window (even though it doesn't draw). Consequently, the control still needs an HWND (I believe). If the view window has not been constructed, the control cannot be properly hosted. MFC might detect this and assert, causing th
e breakpoint that you are seeing. One way to try this out would be to delay calling into the ActiveX control until you are certain that the view window has been constructed.

Also, I'm having some trouble figuring out what you're showing with the example code you posted. Your code shows 2 constructors, one of which takes the view pointer and one of which doesn't and instead calls m_viewPtr->m_cImaqObject.AcquireImage(); If this latter constructor is the one that fails, how are you initiailizing the m_viewPtr? Another point of confusion for me is that your code shows CMyView::OnInitDialog, but CFormView doesn't have an OnInitDialog - do you mean OnInitialUpdate or something else?

If none of this helps, could you post a .zip file with a stripped-down version of your project that demonstrates the problem?
0 Kudos
Message 4 of 17
(4,683 Views)
You are right, the code I posted is confusing, it should be more along these lines.

//MFC view class
void CMyView::OnInitialUpdate()
{
m_processImage=new CProcessImage(this);
}

//generic class
CProcessImage::CProcessImage(CMyView* view)
{
m_viewPtr=view;
}

void CProessImage::AcquireLiveImage()
{
m_viewPtr -> m_cImaqObject.AcquireImage(); //this fails
}

I checked m_viewPtr->m_hWnd in the debugger and it shows that the m_hWnd is not NULL.

One thing that may be a problem is the fact that I have a trigger class that accesses the CWIMAQ control to check the status of the 1428 trigger line. Would that cause a problem? I can read the trigger line from the CCWIMAQ object but I can't Acquire an Image from it.


Thanks for your help, if you want me to I'll post the scaled down project.
0 Kudos
Message 5 of 17
(4,683 Views)
I'm not sure if reading the trigger line would put the CCWIMAQ object in a state where you can't acquire an image. I can look into that, but at this point I'm still hoping this is a general MFC/COM-related issue. Do you read the trigger line in the case that succeeds (where you call AcquireImage in the View class)?

Please do post the project; I think it'll be helpful.
0 Kudos
Message 6 of 17
(4,683 Views)
Another shot in the dark - in the failure case, what causes CProcessImage::AcquireLiveImage to be called? Is this method being called in a thread other than the main user interface thread?
0 Kudos
Message 7 of 17
(4,683 Views)
My trigger class is instantiated from a worker thread, I used AfxBeginThread(TriggerThread,this)to start the thread. The thread essentially runs an infinite while loop, checking the status of the trigger line in each iteration. When the trigger line is set, the thread posts a message to the application's messaging queue to Acquire and Process an image.

So to answer your question, the AcquireImage function is called from the UI thread but checking the Trigger Status is called from a worker thread. Both use the same CCWIMAQ object. I pass a view pointer to both classes.

Let me Work on Scaling down my code so that I can post it.
0 Kudos
Message 8 of 17
(4,681 Views)
Can I email you the scaled down version instead of posting it.
0 Kudos
Message 9 of 17
(4,681 Views)
Instead of emailing it, could you upload it to ftp://ftp.ni.com/incoming/ and post here to let me know the name?

I think we're onto something with the threading. The CCWIMAQ object is an apartment threaded in-process COM server. This basically means that it expects to be called only by the thread that created it (really it expects to be called from the apartment that created it, but for our purposes this is equivalent to the thread that created it).

In order to call it from another thread, you need to marshal the COM pointer to the control from the thread that created it to the other thread. There are two ways to do this. You can use CoMarshalInterThreadInterfaceInStream or you can use
the Global Interface Table. Check out this MSDN topic for information about this.

One thing I'm not sure of is exactly why the call from the worker thread succeeds and then the call from the creating thread fails. I'll need to check out your program to try to figure that out. Does the worker thread call CoInitialize or CoInitializeEx?

In the end, I suspect that you will not want to marshal the pointer to the other thread and instead will prefer to just post a message from the worker thread to the UI thread to make the call that checks the status of the trigger and then use an event or some other synchronization mechanism to cooridinate the communication of the status back to the worker thread. You could try always accessing the CCWIMAQ object from the main thread and see if you no longer get the exception.
0 Kudos
Message 10 of 17
(4,681 Views)