7

I am writing a mex-file (using C++) that will accept a memory address as an input, and operate on data at that memory address. Because I am forced to use MATLAB as my environment, my program can only accept MATLAB data types as inputs (char, bool, float, double, and int). How can I go about assigning my input value to a pointer?

Pseudocode:

// Outside of program
// double input_arg = hex2dec('00C2E4E8')

double *pointer;
pointer = (double *)input_arg;
// pointer == hex2dec('00C2E4E8')

Basically, this can be seen as me hardcoding the value of a pointer similar to:

double *pointer = (double *)hex2dec('00C2E4E8');

I am receiving the error:

error C2440: '=' : cannot convert from 'double' to 'double *'

I have also tried using static/const/reinterpret/dynamic_cast, but I don't really understand how they work (and I couldn't get them to work). Is it possible at all to manually assign memory address values to pointers?

2
  • If it's an address, why use a double? C will let you cast an integer type to a pointer, possibly warning if the integer is a different size from your pointer type.
    – Matt K
    Commented Aug 8, 2011 at 17:49
  • 4
    To everyone who's answered below - please do not jump in start voicing your opinions on why the OP is getting the error simply because the question is tagged C & C++! The question is about MATLAB and MEX files, and how to pass data between the MATLAB and C++ worlds. Type safety is not always possible when it comes to this.
    – Praetorian
    Commented Aug 8, 2011 at 18:17

4 Answers 4

6

It seems that you cannot use a double, which is a floating point type, as a representation of an address in memory, which is inherently an integer value.

I guess that your input_arg should be defined as a MATLAB int type, not as a double.

1
  • This solved the problem. I had been using a double, because that is what MATLAB defaults things to, and it hadn't occurred to me that I would be able to cast an int as a pointer, but not a double.
    – Brian
    Commented Aug 8, 2011 at 21:32
5

What you're trying to do is dangerous because you're passing raw pointers to some C++ code, making assumptions about what exists at that location and executing code based on those assumptions. But let's say you've taken care of all those security issues.

You probably want to pass the pointer to your MEX file as a UINT64 (so that the code can be recompiled and used as is on a 64-bit installation of MATLAB).

On the MATLAB side:

ptrArg = uint64(hex2dec( '00C2E4E8' ));
myMexFile( ptrArg );

Within your mex function:

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
  if( nrhs < 1 ) {
    // error

  } else {
    // Verify that the address argument is a UINT64 
    if( mxGetClassID( prhs[0] ) != mxUINT64_CLASS ) {
      // error

    }
  }

  // Done with error checking, now perform the cast
  uint64_T mlData = *static_cast<unsigned long long *>( mxGetData( prhs[0] ) );
  double *p = reinterpret_cast<double *>( mlData );

  // Do whatever with p
}

Note: You can do the same with a double as well, just change the mxGetClassID check to look for mxDOUBLE_CLASS. In this case the cast expression becomes:

double *p = reinterpret_cast<double *>( *mxGetPr( prhs[0] ) );

EDIT:
What I've said about being about to get this code to work on a 32 or 64-bit machine is only true if both machines are little endian. Otherwise, if you pass a 32-bit pointer in a 64-bit uint on a big-endian machine and cast it to a double * you'll get a pointer that is 0x00000000.

You can handle the endianness issues by using the MATLAB function computer to detect machine endianness. If byte swapping is needed you can use swapbytes. To execute these functions from your C++ code use mexCallMATLABWithTrap.

3
  • 2
    This is not quite right either. mxGetData returns a pointer to the array of data in the Matlab array that was allocated by Matlab, not the value in its first element. You need another step of dereferencing, like (*(mxGetData( prhs[0]))). And if this is running on 32-bit, reinterpret_cast is going to be wrong because it'll be chunk the upper and lower halves of that uint64 in to 32-bit pointer values. Need to either copy the value to an int, or assume caller will pass address values the same width as sizeof(void*) and use typedefs. Commented Aug 8, 2011 at 20:28
  • @Andrew Janke Thanks for pointing out the additional dereferening that was required. And I corrected the part about the 64-bit value on a big-endian machine a few seconds before you commented :-)
    – Praetorian
    Commented Aug 8, 2011 at 20:32
  • Endianness issues actually hadn't occurred to me - I haven't run in to a big-endian machine in a while - but was thinking of what would happen if OP wanted to extend the signature to take an array of addresses. Looks like just copying the input to mlData like you do or being careful with array indexing (index before cast) would take care of it. +1 Commented Aug 8, 2011 at 21:59
5

Try:

double *pointer = (double *)0x00C2E4E8;

(add 0x)

3
  • From my read of the text, it sounds like the OP is not trying to put a literal address into a double * but put an argument to a function into a double *
    – Matt K
    Commented Aug 8, 2011 at 17:51
  • This answer is completely wrong (yes the syntax is correct, but this is not what the OP is asking).
    – Praetorian
    Commented Aug 8, 2011 at 18:02
  • Original post edited for clarity. I was trying to pass in the decimal value, and it was receiving the error
    – Brian
    Commented Aug 8, 2011 at 21:31
5

Why is input_arg a double? Pointers are always of some integer type.

This may solve the "conversion of double to double *"

1
  • Pointers are never of some integer type. Pointers are of pointer type. (Converting integers to pointers and vice versa is likely to be meaningful on most systems, though.) Commented Aug 8, 2011 at 21:53

Not the answer you're looking for? Browse other questions tagged or ask your own question.