06-19-2012 02:49 PM
I have successfully used and modified the ReadDigChan-ChangeDetectionEvent ASCII-C sample program. Only, things stopped working as soon as I transitioned from sample practice code to the c++ project where I wanted to put the demonstrated functions to use.
Below is the abbreviated code:
//-------------------My_NI_Functions.h--------------
class My_NI
{
public:
My_NI( void ); //constructor
//Assorted Variables
int32 CVICALLBACK ChangeDetectionCallback(TaskHandle taskListen, int32 signalID, void *callbackData);
//Other assorted functions
};
//-----------------My_NI_Functions.cpp-----------
#include "My_NI_Functions.h"
//other assorted includes
My_NI::My_NI( void ) {
//One-time initialization stuff
DAQmxErrChk (DAQmxCreateTask("",&taskListen));
DAQmxErrChk (DAQmxCreateDIChan(taskListen,"Dev1/port0/line4","",DAQmx_Val_ChanPerLine));
DAQmxErrChk (DAQmxCfgChangeDetectionTiming(taskListen,"Dev1/port0/line4",NULL,DAQmx_Val_ContSamps,1));
DAQmxErrChk (DAQmxRegisterSignalEvent(taskListen,DAQmx_Val_ChangeDetectionEvent,0,ChangeDetectionCallback,NULL));
DAQmxErrChk (DAQmxGetTaskNumChans(taskListen,&numLines));
}
int32 CVICALLBACK CNIComm:: ChangeDetectionCallback(TaskHandle taskHandle, int32 signalID, void *callbackData) {
//assorted logic
return 0;
}
//other functions
-------------------------------------------------
The compiler returns a single error message:
error C3867: 'My_NI::ChangeDetectionCallback': function call missing argument list; use '&CNIComm::ChangeDetectionCallback' to create a pointer to member
The line number for the error message corresponds to DAQ #4:
DAQmxErrChk (DAQmxRegisterSignalEvent(taskListen,DAQmx_Val_ChangeDetectionEvent,0,ChangeDetectionCallback,NULL));
Further examination revels the explanation:
"Error: argument of type "int32 (__Cdecl My_NI::*) (TaskHandle taskHandle, void *callbackData) is incompatible with parameter of type "DAQmxSignalEventCallbackPtr"
I know the rest of the code works. It compiles and runs when the 5 shown DAQ* lines are commented out.
and... that's as far as I've gotten debugging. Anyone know what I've done wrong? For that matter, has anyone successfully used DAQmxRegisterSignalEvent callback with classes in c++?
06-20-2012 08:06 PM
Hello,
Check this information, it might become handy. I think the issue is the way you're implementing the callback.
http://stackoverflow.com/questions/2298242/callback-functions-in-c
http://www.codeguru.com/cpp/cpp/cpp_mfc/callbacks/article.php/c10557/Callback-Functions-Tutorial.htm
http://www.codeguru.com/cpp/cpp/cpp_mfc/callbacks/article.php/c4129/C-Callback-Demo.htm
Have a good day!
06-28-2012 02:50 PM - edited 06-28-2012 02:55 PM
Just in case anyone else is facing the same issue I've since learned that using direct callbacks with dynamic class functions in c++ is impossible. (Static class functions might allow direct callbacks)
The problem is that every class function is class instance specific, and the callback contains no provision for the class information. However, there are work arrounds.
Proper work arounds that maintain the object oriented aroach seem to require compiler specific 'cheats', template inheritance tricks, or builing your own custom library of routines.
A simpler work arround is to use a combination of a global function and global class pointer variables to relay the callback signal from the callback to the proper function.
I ended up doing something similar to this:
/------------------------------My_NI_Functions.h---------------------------------------------
//Global Callback
My_NI* forwardingAddress;
int32 CALLBACK ForwardFunction(TaskHandle taskListen, int32 signalID, void *callbackData)
{
return forwardingAddress -> ChangeDetectionCallback(taskListen,signalID,callbackData);
}
//Class start
class My_NI
{
public:
int 32 ChangeDetectionCallback(TaskHandle taskListen, int32 signalID, void *callbackData)
{
//Assorted Logic
return 0;
}
My_NI( void) //Constructor
{
//callback request
DAQmxErrChk (DAQmxCreateTask("",&taskListen));
DAQmxErrChk (DAQmxCreateDIChan(taskListen,"Dev1/port0/line4","",DAQmx_Val_ChanPerLine));
DAQmxErrChk (DAQmxCfgChangeDetectionTiming(taskListen,"Dev1/port0/line4",NULL,DAQmx_Val_ContSamps,1));
forwardingAddress = this;
DAQmxErrChk (DAQmxRegisterSignalEvent(taskListen,DAQmx_Val_ChangeDetectionEvent,0,ForwardFunction,NULL));
DAQmxErrChk (DAQmxGetTaskNumChans(taskListen,&numLines));
}
}
//-------------------------------------------------------------------------------
If for some reason you have multiple class objects then I believe you can replace the 'NULL' in DAQmxRegisterSignalEvent with an index number or other distinguish variable that will reapear again at the *callbackData pointer of the callback function. That reference data combined with a pointer table or similar should alow the forwarding function to send the callback to the correct destination class. However since I haven't personaly tried this, no promices.