views:

472

answers:

3

I have a bit of code I'm running to test multithreading in MATLAB mex functions (I know MATLAB isn't thread safe... I'm just playing around to see what happens). The entry point to MATLAB C code functions has the signature of the mexFunction function in the code snipped at the bottom of the post. Since I want to essentially pass the arguments from this function into another thread created using pthreads, I need to bundle everything up into a structure. The signature of the mexFunction (which I cannot change) includes an array of pointers to mxArray, however I can't directly include an array of pointers to mxArray in the structure definition since then I couldn't assign to that field of the structure (can't assign to an array). For example, this doesn't work:

typedef struct MexFunArgs {
  int nrhs;
  const mxArray *prhs[];
} MexFunArgs;

/* ... now within the mexFunction ... */

MexFunArgs mfa;

mfa.prhs = prhs;

A first thought to fix this is to change the structure definition to this:

typedef struct MexFunArgs {
  int nrhs;
  const mxArray **prhs;
} MexFunArgs;

However, then when I use this structure in the other thread, I would need to cast back to an array of pointers in order to pass it to the mexCallMATLAB function, which as far as I know can't be done (please correct me if I'm wrong here!).

So, I thought instead I would change the structure definition to this:

typedef struct MexFunArgs {
  int nrhs;
  const mxArray *(*prhs)[];
} MexFunArgs;

I.e., a pointer to an array of pointers to mxArray. This solves the assignment issue (though the compiler still complains about incompatible pointer types for reasons I don't understand). However, it turns out the mexCallMATLAB function doesn't take an array of pointers to const mxArrays, but instead an array of pointers to non-const mxArrays. So now I'd like to know if there's a way of casting away the const aspect of my pointer to an array of pointers to const mxArrays. I have no idea how to do that... the following isn't legal:

(mxArray *(*)[])

Can it be done? If not, is what I'm trying to do (pass these arguments to the other thread unscathed in such a way that they can be used without the compiler whining) possible in some other way in C?

The following is the complete code I'm using at the moment, which runs as expected, but produces a warning when compiled. I hate warnings, and want it to go away. What is the right way of making that happen?

#include <pthread.h>
#include <unistd.h>
#include <mex.h>

typedef struct MexFunArgs {
  int nrhs;
  mxArray *(*prhs)[];
} MexFunArgs;

void *do_thread(void *args) {
  MexFunArgs *mfa = (MexFunArgs*) args;

  mexCallMATLAB(0, NULL, mfa->nrhs, *mfa->prhs, "disp");

  pthread_exit(NULL);
}

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
  int num;

  if (nrhs < 1)
    mexErrMsgTxt("not enough input arguments");
  else
    num = mxGetScalar(prhs[0]);

  MexFunArgs mfa;

  mfa.nrhs = nrhs;
  mfa.prhs = &prhs[1]; /* <-- threads.c:29: warning: assignment from incompatible pointer type */

  pthread_t threads[num];

  int rc, t;
  for (t = 0; t < num; t++) {
    mexPrintf("In main: creating thread %d\n", t);
    rc = pthread_create(&threads[t], NULL, do_thread, (void *) &mfa);
    if (rc)
      mexErrMsgTxt("Problem with return code from pthread_create()");
  }
  return;
}
A: 

Taking a wild guess based on your headline I assume that you have not yet grasped the difference between the constness of a pointer vs. the constness of the object it points too.

See http://stackoverflow.com/questions/766386/why-does-this-allow-promotion-from-char-to-const-char/766406#766406 for an example that can guide you.

For the and other questions part, why don't you split them into seperate questions. That may help getting the answers you seek.

lothar
+1  A: 

The warning is due to assignment of

an array (name) of pointers to const mxArrays

to

a pointer to arrays of pointers of non-const mxArray.

Remember, you can only safely assign to a more qualifed type.

These are different types. You either disable the warning for that particular line or use a cast -- both equally dangerous.

Also note, if you are compiling with a C99-based compiler, the structure's empty [] in the mxArray declaration, declares a variable-length-array. Is this what you want?

dirkgently
+1  A: 

Figured out a way to get everything working happily. Because arrays and pointers are treated identically in function signatures, I just changed the mexFunction to take mxArray ** instead of mxArray *thing[]. Then there's no problem casting, since there's no need to cast to an array type (illegal).

Dan