mvIMPACT Acquire SDK C++
Callback.cpp

The Callback example is meant to show how to register a custom callback function to a property or feature in mvIMPACT Acquire.

Program location
The source file Callback.cpp can be found under:
%INSTALLDIR%\apps\Callback\
Note
If you have installed the package without example applications, this file will not be available. On Windows the sample application can be installed or removed from the target system at any time by simply restarting the installation package.
Callback example:
  1. Opens a MATRIX VISION device.
  2. Shows custom callbacks.
Console Output
[0]: GX001559 (mvBlueCOUGAR-X122G, Family: mvBlueCOUGAR, interface layout: DeviceSpecific)
[1]: BF000306 (mvBlueFOX-120C, Family: mvBlueFOX, interface layout: DeviceSpecific)

Please enter the number in front of the listed device followed by [ENTER] to open it: 1
Using device number 1.
Initialising the device. This might take some time...
=== List of records BEFORE callbacks ===
This record is called 'The number of the Beast' and since creation it has been played 0 times.
This record is called 'Holy Diver' and since creation it has been played 0 times.
This record is called 'Master of Reality' and since creation it has been played 0 times.
Component 'ImageRequestTimeout_ms' did just cause a callback. It's the 1 time this function got called.
This callback carries 3 good old vinyl records with it.
  There is a record called 'The number of the Beast'
  There is a record called 'Holy Diver', which I will play now
  There is a record called 'Master of Reality'
Component 'ImageRequestTimeout_ms' did just cause a callback. It's the 2 time this function got called.
This callback carries 3 good old vinyl records with it.
  There is a record called 'The number of the Beast'
  There is a record called 'Holy Diver'
  There is a record called 'Master of Reality', which I will play now
Component 'RequestCount' did just cause a callback. It's the 3 time this function got called.
This callback carries 3 good old vinyl records with it.
  There is a record called 'The number of the Beast', which I will play now
  There is a record called 'Holy Diver'
  There is a record called 'Master of Reality'
...
How it works

After getting the device from user input the sample tries to

  1. open the device by calling
    pDev->open();
  2. Attach a custom callback to some driver properties that get called whenever a property is modified.
  3. Modify these properties in order to cause the callbacks to be called.

But now step by step through the source:

Any application that wants to get notified when a certain feature in the mvIMPACT Acquire property tree did change needs to derive a class from mvIMPACT::acquire::ComponentCallback and override the mvIMPACT::acquire::ComponentCallback::execute() method:

//-----------------------------------------------------------------------------
class MyCallback : public ComponentCallback
//-----------------------------------------------------------------------------
{
unsigned int hitCount_;
public:
explicit MyCallback( void* pUserData = 0 ) : ComponentCallback( pUserData ),
hitCount_( 0 ) {}
// Please note that this function might be executed from ANY thread context, which is
// most likely not the same as used by the application thus appropriate mechanisms to ensure
// correct execution must be implemented by an application(e.g. GUI applications might send an
// event to the main thread instead of directly accessing GUI elements).
virtual void execute( Component& c, void* pUserData )
{
// get access to the user data previously associated with the component that just executes the callback
RecordStack* pRecordStack = reinterpret_cast<RecordStack*>( pUserData );
// do some work with the user data object
const RecordStack::size_type recordCount = pRecordStack->size();
cout << "Component '" << c.name() << "' did just cause a callback. It's the " << ++hitCount_ << " time this function got called." << endl
<< "This callback carries " << recordCount << " good old vinyl records with it." << endl;
RecordStack::const_iterator it = pRecordStack->begin();
const RecordStack::const_iterator itEND = pRecordStack->end();
unsigned int i = 0;
while( it != itEND )
{
cout << " There is a record called '" << ( *it )->getAlbum() << "'";
if( hitCount_ % recordCount == i )
{
cout << ", which I will play now";
( *it )->play();
}
cout << endl;
++it;
++i;
}
}
};

In order to be able to do something useful each callback can carry a pointer to arbitrary user data that can be used to get access to any part of the application code within the callback context. This example attaches an instance of the class VinylRecord when creating the callback handler later.

Now within the actual application first of all a device handle must be obtained. In this sample the user is prompted to select the device he wants to use:

DeviceManager devMgr;
Device* pDev = getDeviceFromUserInput( devMgr );

The function getDeviceFromUserInput() is included via

#include <apps/Common/exampleHelper.h>

Afterwards some interface classes are created in order to get access to some driver properties that shall get a callback attached to.

CameraSettingsBase cs( pDev );
SystemSettings ss( pDev );

Now some objects that will serve as dummy user data for the callback will be created:

vector<VinylRecord*> vinylRecords;
vinylRecords.push_back( new VinylRecord( "The number of the Beast" ) );
vinylRecords.push_back( new VinylRecord( "Holy Diver" ) );
vinylRecords.push_back( new VinylRecord( "Master of Reality" ) );

Now the actual callback handler will be created and 2 properties will be registered to it:

MyCallback myCallback( &vinylRecords );
// attach the callback to some features
myCallback.registerComponent( cs.imageRequestTimeout_ms );
myCallback.registerComponent( ss.requestCount );

When now modifying one of these properties the callback handler will be invoked

for( int i = 1; i < 30; i++ )
{
cs.imageRequestTimeout_ms.write( i );
ss.requestCount.write( i );
}

This can be shown by sending the user data objects to the standard output now. In this example this will increase to 'play' counter of a record:

// now verify that the callbacks have actually been executed by displaying the times all records have
// been played within the callback handlers
cout << "=== List of records AFTER callbacks ===" << endl;
for_each( vinylRecords.begin(), vinylRecords.end(), mem_fun( &VinylRecord::display ) );
Source code
#ifdef _MSC_VER // is Microsoft compiler?
# if _MSC_VER < 1300 // is 'old' VC 6 compiler?
# pragma warning( disable : 4786 ) // 'identifier was truncated to '255' characters in the debug information'
# endif // #if _MSC_VER < 1300
#endif // #ifdef _MSC_VER
#include <algorithm>
#include <apps/Common/exampleHelper.h>
#include <functional>
using namespace std;
using namespace mvIMPACT::acquire;
//-----------------------------------------------------------------------------
class VinylRecord
//-----------------------------------------------------------------------------
{
private:
std::string album_;
unsigned int timesPlayed_;
public:
explicit VinylRecord( const std::string& album ) : album_( album ), timesPlayed_( 0 ) {}
bool display( void )
{
cout << "This record is called '" << getAlbum() << "' and since creation it has been played " << getTimesPlayed() << " times." << endl; // if this function is declared 'const' or does not return a value the 'for_each' calls does not compile with VS 6...
return true;
}
const std::string& getAlbum( void ) const
{
return album_;
}
unsigned int getTimesPlayed( void ) const
{
return timesPlayed_;
}
void play( void )
{
++timesPlayed_;
}
};
typedef vector<VinylRecord*> RecordStack;
//-----------------------------------------------------------------------------
class MyCallback : public ComponentCallback
//-----------------------------------------------------------------------------
{
unsigned int hitCount_;
public:
explicit MyCallback( void* pUserData = 0 ) : ComponentCallback( pUserData ),
hitCount_( 0 ) {}
// Please note that this function might be executed from ANY thread context, which is
// most likely not the same as used by the application thus appropriate mechanisms to ensure
// correct execution must be implemented by an application(e.g. GUI applications might send an
// event to the main thread instead of directly accessing GUI elements).
virtual void execute( Component& c, void* pUserData )
{
// get access to the user data previously associated with the component that just executes the callback
RecordStack* pRecordStack = reinterpret_cast<RecordStack*>( pUserData );
// do some work with the user data object
const RecordStack::size_type recordCount = pRecordStack->size();
cout << "Component '" << c.name() << "' did just cause a callback. It's the " << ++hitCount_ << " time this function got called." << endl
<< "This callback carries " << recordCount << " good old vinyl records with it." << endl;
RecordStack::const_iterator it = pRecordStack->begin();
const RecordStack::const_iterator itEND = pRecordStack->end();
unsigned int i = 0;
while( it != itEND )
{
cout << " There is a record called '" << ( *it )->getAlbum() << "'";
if( ( hitCount_ % recordCount ) == i )
{
cout << ", which I will play now";
( *it )->play();
}
cout << endl;
++it;
++i;
}
}
};
//-----------------------------------------------------------------------------
int main( void )
//-----------------------------------------------------------------------------
{
DeviceManager devMgr;
Device* pDev = getDeviceFromUserInput( devMgr );
if( !pDev )
{
cout << "Unable to continue! Press [ENTER] to end the application" << endl;
cin.get();
return 1;
}
cout << "Initialising the device. This might take some time..." << endl;
try
{
pDev->open();
}
catch( const ImpactAcquireException& e )
{
// this e.g. might happen if the same device is already opened in another process...
cout << "An error occurred while opening the device(error code: " << e.getErrorCode() << ")." << endl
<< "Press [ENTER] to end the application" << endl;
cin.get();
return 1;
}
BasicDeviceSettings bds( pDev );
SystemSettings ss( pDev );
// create some user data to attach to the callback
vector<VinylRecord*> vinylRecords;
vinylRecords.push_back( new VinylRecord( "The number of the Beast" ) );
vinylRecords.push_back( new VinylRecord( "Holy Diver" ) );
vinylRecords.push_back( new VinylRecord( "Master of Reality" ) );
// create the callback with user data
MyCallback myCallback( &vinylRecords );
// attach the callback to some features
myCallback.registerComponent( bds.imageRequestTimeout_ms );
myCallback.registerComponent( ss.requestCount );
const vector<VinylRecord*>::size_type vinylRecordCnt = vinylRecords.size();
cout << "=== List of records BEFORE callbacks ===" << endl;
for_each( vinylRecords.begin(), vinylRecords.end(), mem_fun( &VinylRecord::display ) );
// provoke some callbacks by modifying the properties we just registered callbacks for.
// Whenever one of this features is changed in any way the previously attached callback
// handler will be called.
for( int i = 1; i < 30; i++ )
{
bds.imageRequestTimeout_ms.write( i );
ss.requestCount.write( i );
}
// now verify that the callbacks have actually been executed by displaying the times all records have
// been played within the callback handlers
cout << "=== List of records AFTER callbacks ===" << endl;
for_each( vinylRecords.begin(), vinylRecords.end(), mem_fun( &VinylRecord::display ) );
// clean up
myCallback.unregisterComponent( ss.requestCount );
myCallback.unregisterComponent( bds.imageRequestTimeout_ms );
for( vector<VinylRecord*>::size_type j = 0; j < vinylRecordCnt; j++ )
{
delete vinylRecords[j];
}
vinylRecords.clear();
cout << "Press [ENTER] to end the application" << endl;
cin.get();
return 0;
}
mvIMPACT::acquire::SystemSettings
A base class for accessing settings that control the overall behaviour of a device driver.
Definition: mvIMPACT_acquire.h:14221
mvIMPACT::acquire::ImpactAcquireException
A base class for exceptions generated by mvIMPACT Acquire.
Definition: mvIMPACT_acquire.h:245
mvIMPACT::acquire::Component
A base class to implement access to internal driver components.
Definition: mvIMPACT_acquire.h:1318
mvIMPACT_acquire.h
mvIMPACT::acquire::ComponentCallback
A simple helper class to wrap the creation of a callback object.
Definition: mvIMPACT_acquire.h:1954
mvIMPACT::acquire::Device::open
void open(void)
Opens a device.
Definition: mvIMPACT_acquire.h:6159
mvIMPACT::acquire::ComponentAccess::name
std::string name(void) const
Returns the name of the component referenced by this object.
Definition: mvIMPACT_acquire.h:1088
mvIMPACT::acquire::Device
This class and its functions represent an actual device detected by this interface in the current sys...
Definition: mvIMPACT_acquire.h:5887
mvIMPACT::acquire::ImpactAcquireException::getErrorCode
int getErrorCode(void) const
Returns a unique numerical representation for this error.
Definition: mvIMPACT_acquire.h:266
mvIMPACT::acquire::BasicDeviceSettings
A base class for essential device related settings.
Definition: mvIMPACT_acquire.h:11778
mvIMPACT::acquire::DeviceManager
Grants access to devices that can be operated by this software interface.
Definition: mvIMPACT_acquire.h:6856
mvIMPACT::acquire