I found an NI example on how to use some of the DAQmx functions. It's a simple C-file that contains some of the following:
...
// This is a declaration/definition I think
int32 CVICALLBACK ChangeDetectionCallback(TaskHandle taskHandle, int32 signalID, void *callbackData);
...
// Later in the script there is actual function
int32 CVICALLBACK ChangeDetectionCallback(TaskHandle taskHandle, int32 signalID, void *callbackData)
{
    ...
return 0;
}
When I tend to use some of the variables or functions that are defined in .h file, the ChangeDetectionCallback function does not recognize them. I tried to define this callback function as a member function in .h file, hoping that now all functions will be accessible. Here's my .h content:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "NIDAQmx.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
int32 CVICALLBACK ChangeDetectionCallback(TaskHandle taskHandle, int32 signalID, void *callbackData);
private:
Ui::MainWindow *ui;
void mainLoop();
};
#endif // MAINWINDOW_H
and here's my .c content:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "NIDAQmx.h"
#include <stdio.h>
#include <string.h>
#include <time.h>
#define DAQmxErrChk(functionCall) if( DAQmxFailed(error=(functionCall)) ) goto Error; else
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
mainLoop();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::mainLoop()
{
...
DAQmxErrChk (DAQmxRegisterSignalEvent(taskHandle,DAQmx_Val_ChangeDetectionEvent,0,ChangeDetectionCallback,NULL));
...    
}
int32 MainWindow::ChangeDetectionCallback(TaskHandle taskHandle, int32 signalID, void *callbackData)
{
...
return 0;
}
So, again, I tried many wrong ways to define my callback function in the header file unsuccessfully. Please, help me to get this straight. And here's the error message that I do not clearly understand:
D:\Projects\sapm3\mainwindow.cpp:37: error: cannot convert 'MainWindow::ChangeDetectionCallback' from type 'int32 (MainWindow::)(TaskHandle, int32, void*) {aka long int (MainWindow::)(void*, long int, void*)}' to type 'DAQmxSignalEventCallbackPtr {aka long int (__attribute__((__cdecl__)) *)(void*, long int, void*)}'
     DAQmxErrChk (DAQmxRegisterSignalEvent(taskHandle,DAQmx_Val_ChangeDetectionEvent,0,ChangeDetectionCallback,NULL));
Here's the original code. It triggers callback function to get a measurement sample and outputs the data to console. I wish to write the sampled data to my member variable and emit a signal that is defined in the .h file of the object.
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <NIDAQmx.h>
#define DAQmxErrChk(functionCall) if( DAQmxFailed(error=(functionCall)) ) goto Error; else
static TaskHandle   taskHandle;
static uInt32       numLines;
static uInt8        cachedData[200];
int32 CVICALLBACK ChangeDetectionCallback(TaskHandle taskHandle, int32 signalID, void *callbackData);
void Cleanup (void);
int main(void)
{
int32       error=0;
char        errBuff[2048]={'\0'};
/*********************************************/
// DAQmx Configure Code
/*********************************************/
DAQmxErrChk (DAQmxCreateTask("",&taskHandle));
DAQmxErrChk (DAQmxCreateDIChan(taskHandle,"Dev1/port0/line0:7","",DAQmx_Val_ChanPerLine));
DAQmxErrChk (DAQmxCfgChangeDetectionTiming(taskHandle,"Dev1/port0/line0:7","Dev1/port0/line0:7",DAQmx_Val_ContSamps,1));
DAQmxErrChk (DAQmxRegisterSignalEvent(taskHandle,DAQmx_Val_ChangeDetectionEvent,0,ChangeDetectionCallback,NULL));
DAQmxErrChk (DAQmxGetTaskNumChans(taskHandle,&numLines));
/*********************************************/
// DAQmx Start Code
/*********************************************/
DAQmxErrChk (DAQmxStartTask(taskHandle));
puts("Continuously reading. Press Enter key to interrupt\n");
puts("Timestamp                 Data read   Changed Lines");
getchar();
Error:
if( DAQmxFailed(error) )
{
    DAQmxGetExtendedErrorInfo(errBuff,2048);
    Cleanup();
    printf("DAQmx Error: %s\n",errBuff);
}
printf("End of program, press Enter key to quit\n");
getchar();
return 0;
}
int32 CVICALLBACK ChangeDetectionCallback(TaskHandle taskHandle, int32 signalID, void *callbackData)
{
int32   error=0;
uInt8   data[200]={0};
int32   numRead;
uInt32  i=0;
char    buff[512], *buffPtr;
char    errBuff[2048]={'\0'};
char    *timeStr;
time_t  currTime;
if( taskHandle ) {
    time (&currTime);
    timeStr = ctime(&currTime);
    timeStr[strlen(timeStr)-1]='\0';  // Remove trailing newline.
    /*********************************************/
    // DAQmx Read Code
    /*********************************************/
    DAQmxErrChk (DAQmxReadDigitalLines(taskHandle,1,10.0,DAQmx_Val_GroupByScanNumber,data,8,&numRead,NULL,NULL));
    if( numRead ) {
        buffPtr = buff;
        strcpy(buff, timeStr);
        strcat(buff,"  ");
        buffPtr = buff + strlen(buff);
        for(;i<numLines;++i) {
            sprintf(buffPtr,"%d",data[i]);
            buffPtr++;
        }
        strcat(buff,"    ");
        buffPtr = buff + strlen(buff);
        for(i=0;i<numLines;++i) {
            sprintf(buffPtr,"%c",data[i]==cachedData[i]?'-':'X');
            buffPtr++;
            cachedData[i] = data[i];
        }
        puts(buff);
        fflush(stdout);
    }
}
return 0;
Error:
if( DAQmxFailed(error) )
{
    DAQmxGetExtendedErrorInfo(errBuff,2048);
    Cleanup();
    printf("DAQmx Error: %s\n",errBuff);
}
return 0;
}
void Cleanup (void)
{
if( taskHandle!=0 ) 
{
    /*********************************************/
    // DAQmx Stop Code
    /*********************************************/
    DAQmxStopTask(taskHandle);
    DAQmxClearTask(taskHandle);
    taskHandle = 0;
}
}
I found the way to go around my problem. I declare an array variable at the top of the file. This way my callback function recognizes it. Then, I copy data from this array to my member array. Similarly, I created a counter variable and increment it each time the callback runs. At the same time I loopcheck this variable in my member function until it reaches desirable value and then emit a signal. Such approach really sucks and I wish to find a more intelligent way to writ it.
                        
The problem is that you're trying to pass a member function pointer instead of a function pointer. You could use an indirection to get this working.
Outside of the class you'll define a function:
Then define the MainWindow method to be called like this:
int32 ChangeDetectionCallback(TaskHandle taskHandle, int32 signalID);And then register it like this:
Note that the
callbackDataparameter is used for passing the pointer to the object around. This data is passed when you register the event, instead of theNULL.This is a typical pattern for C libraries, and this is a typical way of how to connect this to C++.