Calling C++ mex in loop crashes Matlab
Show older comments
Goal: to interface with a device via a dll to collect and plot continuous data.
Problem: loadlibrary does not work since one of the exported functions take a function pointer as argument. So I wrote a mex file in c++ (compiled with VS2019). This works in the sense that all exported functions can be called from Matlab and return the expected data. However, when the read data function is called repeatedly in a loop, Matlab becomes unresponsive and then exits without any error message. Increasing the pause in each loop iteration or decreasing the sample rate of the device, makes this less likely to happen.
When initializing the device a pointer to a global function has to be provided, which will be called by the device repeatedly to write data. I copy the data to a global vector in this function and then copy this to plhs[0] in the read data function that is called from Matlab.
I suspected that the problem was caused by dataBuffer being read and written to simultaneously, so I added the isWriting/Reading flags (below). Still, the data in DataBuffer is not always evenly divisible by the nuber of channels, even though the device always writes an equal number of samples per channel for each channel, so it seems I still read the vector while being filled in in the global function.
I also tried debugging with Visual Studio, and it seems Matlab hits an Access violation when this happens, but I was not able to track down where this occurs.
The relevant code in the mex file (I trimmed out most of it):
#define N_CHANNELS 16
// Global functions:
void ReadDataFromDevice(int samples, channels, float *data);
// Global variables:
std::vector <float> dataBuffer; //dataBuffer.reserve(N_CHANNELS * samplerate) is called when recording starts
int isWriting = 0;
int isReading = 0;
class device_mex {
public:
protected:
};
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
char cmd[64];
device_mex* device_mex_instance;
mxGetString(prhs[0], cmd, sizeof(cmd));
// Read - read from and clear data buffer
if (!strcmp("read", cmd)){
if (!isWriting & !(dataBuffer.size() % N_CHANNELS)){
isReading = 1;
plhs[0] = mxCreateNumericMatrix(dataBuffer.size(),1,mxSINGLE_CLASS,mxREAL);
memcpy((float*) mxGetData(plhs[0]),dataBuffer.data(),dataBuffer.size()*sizeof(float));
dataBuffer.clear();
isReading = 0;
}else{
plhs[0] = mxCreateNumericMatrix(0,0,mxSINGLE_CLASS,mxREAL);
}
return;
}
}
void ProcessDataFromDevice(int samples, int channels, float *data){
if (!isReading){
isWriting = 1;
for(int i=0;i<(samples*channels);i++){
dataBuffer.push_back(data[i]);
}
isWriting = 0;
}
}
...which gets called through a Matlab classdef:
function [data] = readDevice(this)
data = [];
if ~this.isRecording
error('Could not read data buffer. Device is not recording.');
elseif strcmp(this.deviceStatus,'IS_OK')
data = device_mex('read');
if ~isempty(data)
data = reshape(data,this.nChannels,length(data)/this.nChannels)';
end
else
error('Device not ready: %s',this.deviceStatus);
end
end
...in a while loop:
while isvalid(figureHandle)
pause(.1);
d = readDevice(device);
if ~isempty(d)
buffer = [buffer;d(:,dig1Channel)];
end
pline.YData=buffer(end-buflen+1:end);
drawnow;
end
Accepted Answer
More Answers (0)
Categories
Find more on Write C Functions Callable from MATLAB (MEX Files) in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!