Invalid Mex file: Undefined symbol: mxrErrMsgTxt

Hi everyone,
I've been trying to run a piece of code I downloaded from here (code below): CCG_mine
It's supposed to call a C code designed to quickly compute multiple cross-correlograms. In git, you will also find the corresponding mex-files.
I use Matlab 2020a on Ubuntu 18.04, and when calling the function I get the following error message:
"Invalid MEX-file '{path-to}/CCGHeart.mexa64': Undefined symbol: mxErrMsgTxt"
It is my understanding that mxErrMsgTxt is legacy code and shouldn't be used. However, in the code I downloaded, it's already commented out and replaced by mexErrMsgIdAndTxt. Am I missing something in the code?
Best,
Michael
/* CCGEngine.c /*
/* This is a bare-bones C program whos purpose is to compute
Multi-unit cross correlograms quickly. Not intended for
use on its own. It is designed to be wrapped by a MATLAB
function.
Usage - [CCG, PAIRS] = CCGEngine(TIMES, MARKS, BINSIZE, HALFBINS)
TIMES ( is the name of a binary file containing N doubles giving the spike times
MARKS is the name of a binary file containing N unsigned ints giving the spike markers. Don't use zero!
BINSIZE is a number giving the size of the ccg bins in TIMES units
HALFBINS is the number of bins to compute - so there are a total of nBins = 1+2*HALFBINS bins
These should be: double, uint32,double,uint32
NB The spikes MUST be sorted.
CCG contains unsigned ints containing the counts in each bin
It is like a 3d array, indexed by [nBins*nMarks*Mark1 + nBins*Mark2 + Bin]
PAIRS contains the spike numbers of every pair of spikes included in the ccg.
If you think this program is anal, you're right. Use the MATLAB wrapper instead.
*/
#include "mex.h"
#include "matrix.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#define CHECK
#define STRLEN 10000
#define PAIRBLOCKSIZE 100000000
unsigned int *Pairs;
unsigned int PairCnt, PairSz;
void AddPair(unsigned int n1, unsigned int n2) {
unsigned int *pui;
if (PairSz==0) {
/* mexPrintf("Allocating pair memory\n"); */
Pairs = mxMalloc(PAIRBLOCKSIZE*sizeof(unsigned int));
PairSz = PAIRBLOCKSIZE;
if (!Pairs) {
/*mxErrMsgTxt("Could not allocate memory for pairs");*/
mexErrMsgIdAndTxt("someerror", "Could not allocate memory for pairs");
}
}
/* check if array is full, if so add more memory*/
if(PairCnt>=PairSz) {
/* mexPrintf("Reallocating pair memory ... ");
PairSz += PAIRBLOCKSIZE;
pui = mxRealloc(Pairs, PairSz);
mexPrintf("got %x\n", pui);
if (!pui) {
mxFree(Pairs);
mxErrMsgTxt("Could not reallocate memory for pairs");
}
Pairs = pui;
*/
/*mxErrMsgTxt("Too many pairs");*/
mexErrMsgIdAndTxt("someerror", "Too many pairs");
}
Pairs[PairCnt++] = n1;
Pairs[PairCnt++] = n2;
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) {
unsigned int nSpikes, nMarks, HalfBins, nBins, i, CountArraySize, CountIndex;
double *Times;
double BinSize, FurthestEdge;
unsigned int *Marks, Mark, *Count;
unsigned int CenterSpike, Mark1, Mark2, Bin;
int SecondSpike; /* we want to let it go negative so we can stop it there... */
double Time1, Time2;
char errstr[STRLEN];
/* global variables are not initialized on each call to mex fn!! */
PairCnt = 0; PairSz = 0;
if (nrhs!=4) {
/*mxErrMsgTxt("Must have 4 arguments\nBut listen: You don't want to use this program.\nUse the MATLAB wrapper function CCG instead.\n");*/
mexErrMsgIdAndTxt("someerror", "Must have 4 arguments\nBut listen: You don't want to use this program.\nUse the MATLAB wrapper function CCG instead.\n");
}
if (mxGetClassID(prhs[0])!=mxDOUBLE_CLASS || mxGetClassID(prhs[1])!=mxUINT32_CLASS
|| mxGetClassID(prhs[2])!=mxDOUBLE_CLASS || mxGetClassID(prhs[3])!=mxUINT32_CLASS ) {
/*mxErrMsgTxt("Arguments are wrong type\n");*/
mexErrMsgIdAndTxt("someerror", "Arguments are wrong type\n");
}
/* get arguments */
Times = mxGetPr(prhs[0]);
Marks = (unsigned int *) mxGetPr(prhs[1]);
nSpikes = mxGetNumberOfElements(prhs[0]);
if (mxGetNumberOfElements(prhs[1])!=nSpikes) {
/*mxErrMsgTxt("Number of marks ~= number of spikes");*/
mexErrMsgIdAndTxt("someerror", "Number of marks ~= number of spikes");
}
BinSize = mxGetScalar(prhs[2]);
HalfBins = (unsigned int) mxGetScalar(prhs[3]);
/* derive other constants */
nBins = 1+2*HalfBins;
FurthestEdge = BinSize * (HalfBins + 0.5);
/* count nMarks */
nMarks = 0;
for(i=0; i<nSpikes; i++) {
Mark = Marks[i];
if (Mark>nMarks) nMarks = Mark;
if (Mark==0) {
/*mxErrMsgTxt("CCGEngine: No zeros allowed in Marks");*/
mexErrMsgIdAndTxt("someerror", "CCGEngine: No zeros allowed in Marks");
abort();
}
}
/* allocate output array */
CountArraySize = nMarks * nMarks * nBins;
plhs[0] = mxCreateNumericMatrix(CountArraySize, 1, mxUINT32_CLASS, mxREAL);
Count = (unsigned int *) mxGetPr(plhs[0]);
if (!Times || !Marks || !Count) {
/*mxErrMsgTxt("CCGEngine could not allocate memory!\n");*/
mexErrMsgIdAndTxt("someerror", "CCGEngine could not allocate memory!\n");
}
/* Now the main program .... */
for(CenterSpike=0; CenterSpike<nSpikes; CenterSpike++) {
Mark1 = Marks[CenterSpike];
Time1 = Times[CenterSpike];
/* Go back from CenterSpike */
for(SecondSpike=CenterSpike-1; SecondSpike>=0; SecondSpike--) {
Time2 = Times[SecondSpike];
/* check if we have left the interesting region */
if(fabs(Time1 - Time2) > FurthestEdge) break;
/* calculate bin */
Bin = HalfBins + (int)(floor(0.5+(Time2-Time1)/BinSize));
Mark2 = Marks[SecondSpike];
CountIndex = nBins*nMarks*(Mark1-1) + nBins*(Mark2-1) + Bin;
#ifdef CHECK
if (CountIndex<0 || CountIndex >= CountArraySize) {
sprintf(errstr, "err a: t1 %f t2 %f m1 %d m2 %d Bin %d, index %d out of bounds",
Time1, Time2, Mark1, Mark2, Bin, CountIndex);
/*mxErrMsgTxt(errstr);*/
mexErrMsgIdAndTxt("someerror", errstr);
}
#endif
/* increment count */
Count[CountIndex]++;
if (nlhs>=2) AddPair(CenterSpike, SecondSpike);
}
/* Now do the same thing going forward... */
for(SecondSpike=CenterSpike+1; SecondSpike<nSpikes; SecondSpike++) {
Time2 = Times[SecondSpike];
/* check if we have left the interesting region */
if(fabs(Time1 - Time2) >= FurthestEdge) break;
/* calculate bin */
Bin = HalfBins + (unsigned int)(floor(0.5+(Time2-Time1)/BinSize));
Mark2 = Marks[SecondSpike];
CountIndex = nBins*nMarks*(Mark1-1) + nBins*(Mark2-1) + Bin;
#ifdef CHECK
if (CountIndex<0 || CountIndex >= CountArraySize) {
sprintf(errstr, "err b: t1 %f t2 %f m1 %d m2 %d Bin %d, index %d out of bounds",
Time1, Time2, Mark1, Mark2, Bin, CountIndex);
/*mxErrMsgTxt(errstr);*/
mexErrMsgIdAndTxt("someerror", errstr);
}
#endif
/* increment count */
Count[CountIndex]++;
if (nlhs>=2) AddPair(CenterSpike, SecondSpike);
}
}
if (nlhs>=2) {
plhs[1] = mxCreateNumericMatrix(PairCnt, 1, mxUINT32_CLASS, mxREAL);
memcpy(mxGetPr(plhs[1]), (void *)Pairs, PairCnt*sizeof(unsigned int));
mxFree(Pairs);
}
/* sayonara */
}

 Respuesta aceptada

James Tursa
James Tursa el 22 de Mayo de 2020
Editada: James Tursa el 22 de Mayo de 2020
All of the mxGetErrMsg references have been commented out in your posted code, so that is not the problem. I would guess that you are inadvertently running a mex routine that you downloaded ... i.e. compiled with the mxGetErrMsg references in it. Try this and see what function you are actually running:
which CCGEngine
You should get rid of the compiled mex routines you downloaded, or at least move them somewhere out of your path and out of your working directory.

6 comentarios

Michael Hadler
Michael Hadler el 25 de Mayo de 2020
Dear James,
thanks a lot for your reply! Ufortunately, the command "which CCGEngine" returns " 'CCGEngine' not found".
The same goes for CCGHeartEngine (the name of the C code) and CCG_mineEngine (the name of the file calling CCGHeart) - I already tried cd'ing into the exact path where the files are with the same result.
I deleted all mex-files other than the mexa64-file relating the CCGHeart, with the same result.
Best
Michael
Sorry, I misread the error message. This is the culprit:
which CCGHeart
Where did this mex routine come from? Surely not from the compiled code above, which has no mxErrMsgTxt.
The mex routines are all from the same git-repository here.
The routine called on Ubuntu (which produces the error here) is the .mexa64 file.
So I double-checked on windows, the code works fine there with the mex file being CCGHeart.mexw64.
I re-compiled the file with
mex '/path/to/CCGHeart.c'
Although it completed successfully, got an error concerning my compiler:
"Building with 'gcc'.
Warning: You are using gcc version '7.5.0'. The version of gcc is not supported. The version currently supported with MEX is '6.3.x'. For
a list of currently supported compilers see: https://www.mathworks.com/support/compilers/current_release.
/path/to/CCGHeart.c: In function ‘mexFunction’:
/path/to/CCGHeart.c:200:3: warning: implicit declaration of function ‘memcpy’ [-Wimplicit-function-declaration]
memcpy(mxGetPr(plhs[1]), (void *)Pairs, PairCnt*sizeof(unsigned int));
^~~~~~
/path/to/CCGHeart.c:200:3: warning: incompatible implicit declaration of built-in function ‘memcpy’
/path/to/CCGHeart.c:200:3: note: include ‘<string.h>’ or provide a declaration of ‘memcpy’
MEX completed successfully."
I presume the lower comments concern the undefined variable "memcpy", which I don't need, but I'm worried that I'm using the wrong compiler. The code thankfully runs now, but is it fail-safe when compiled this way?
Best
Michael
James Tursa
James Tursa el 27 de Mayo de 2020
Editada: James Tursa el 27 de Mayo de 2020
I don't know what you mean by "fail-safe". But you should definitely heed the warning and include string.h so that memset and memcpy have prototypes.
As for the gcc compiler version warning, I think it basically means that the version of MATLAB you are using has not been tested by TMW to work with that specific compiler version. Doesn't necessarily mean it will not work, but there is no formal testing by TMW to support it.
Michael Hadler
Michael Hadler el 28 de Mayo de 2020
Thank you so much! I'll include it just to be sure :)
(just to be sure, I'm not fit in C: where do I include string.h?)
In every source code file that uses a function or type defined in string.h, you need to include it before the compiler sees those functions or types. In your case, every source file that uses memset( ) or memcpy( ) needs this line, usually at the top of the file:
#include <string.h>

Iniciar sesión para comentar.

Más respuestas (0)

Categorías

Más información sobre Write C Functions Callable from MATLAB (MEX Files) en Centro de ayuda y File Exchange.

Productos

Versión

R2020a

Preguntada:

el 20 de Mayo de 2020

Comentada:

el 28 de Mayo de 2020

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by