// offset allows linking the data object to a sub-volume (in the z direction)
	// offset is measured in floats.
	CFloat32CustomMemoryMatlab3D(const mxArray* _pArray, bool bUnshare, size_t iOffset)
	{
		// Convert from slice to offset
		mwSize dims[3];
		get3DMatrixDims(_pArray, dims);
		iOffset *= dims[0];
		iOffset *= dims[1];

		//fprintf(stderr, "Passed:\narray: %p\tdata: %p\n", (void*)_pArray, (void*)mxGetData(_pArray));
		// First unshare the input array, so that we may modify it.
		if (bUnshare) {
#if 0
			// Unsupported in Matlab R2014b
			if (mxIsSharedArray(_pArray)) {
				fprintf(stderr, "Performance note: unsharing shared array in link\n");
			}
#endif
			mxUnshareArray(_pArray, false);
			//fprintf(stderr, "Unshared:\narray: %p\tdata: %p\n", (void*)_pArray, (void*)mxGetData(_pArray));
		}
		// Then create a (persistent) copy so the data won't be deleted
		// or changed.
		m_pLink = mxCreateSharedDataCopy(_pArray);
		//fprintf(stderr, "SharedDataCopy:\narray: %p\tdata: %p\n", (void*)m_pLink, (void*)mxGetData(m_pLink));
		mexMakeArrayPersistent(m_pLink);
		m_fPtr = (float *)mxGetData(m_pLink);
		m_fPtr += iOffset;
	}
Пример #2
0
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
	struct mxArray_Tag *mx;
    mwSize inbytes, outbytes, i, k, idim, ndim;
	mwSize *dims_old, *dims_new;
    char *outstring;
    mxClassID outclass;
	int out_numeric;

/* Check input arguments */

	if( nrhs > 2 ) {
        mexErrMsgTxt("Too many input arguments.");
	}
	if( nrhs < 2 ) {
        mexErrMsgTxt("Not enough input arguments.");
	}
	if( nlhs > 1 ) {
        mexErrMsgTxt("Too many output arguments.");
	}
	if( mxIsSparse(prhs[0]) || (!mxIsNumeric(prhs[0]) && !mxIsChar(prhs[0]) && !mxIsLogical(prhs[0])) ) {
        mexErrMsgTxt("The first input argument must be a full numeric value, or char, or logical.");
	}
	if( !mxIsChar(prhs[1]) ) {
        mexErrMsgTxt("The second input argument must be a character array.");
	}

/* Get input argument byte length */

   inbytes = mxGetElementSize(prhs[0]);

/* Check second input argument for desired output type */

   outstring = mxArrayToString(prhs[1]);

   out_numeric = 1;
   if(        strcmp(outstring,"int8") == 0 ) {
       outclass = mxINT8_CLASS;
       outbytes = 1;
   } else if( strcmp(outstring,"uint8") == 0 ) {
       outclass = mxUINT8_CLASS;
       outbytes = 1;
   } else if( strcmp(outstring,"int16") == 0 ) {
       outclass = mxINT16_CLASS;
       outbytes = 2;
   } else if( strcmp(outstring,"uint16") == 0 ) {
       outclass = mxUINT16_CLASS;
       outbytes = 2;
   } else if( strcmp(outstring,"int32") == 0 ) {
       outclass = mxINT32_CLASS;
       outbytes = 4;
   } else if( strcmp(outstring,"uint32") == 0 ) {
       outclass = mxUINT32_CLASS;
       outbytes = 4;
   } else if( strcmp(outstring,"int64") == 0 ) {
       outclass = mxINT64_CLASS;
       outbytes = 8;
   } else if( strcmp(outstring,"uint64") == 0 ) {
       outclass = mxUINT64_CLASS;
       outbytes = 8;
   } else if( strcmp(outstring,"double") == 0 ) {
       outclass = mxDOUBLE_CLASS;
       outbytes = 8;
   } else if( strcmp(outstring,"single") == 0 ) {
       outclass = mxSINGLE_CLASS;
       outbytes = 4;
   } else if( strcmp(outstring,"char") == 0 ) {
       outclass = mxCHAR_CLASS;
       outbytes = 2;
	   out_numeric = 0;
   } else if( strcmp(outstring,"logical") == 0 ) {
       outclass = mxLOGICAL_CLASS;
       outbytes = 1;
	   out_numeric = 0;
   } else {
       mxFree(outstring);
       mexErrMsgTxt("Unsupported class.\n");
   }
   mxFree(outstring);

/* Check for complex coversion to non-numeric */

   if( mxIsComplex(prhs[0]) && !out_numeric ) {
       mexErrMsgTxt("Cannot typecast a complex input to a non-numeric class.\n");
   }

/* Check for empty input. No data to share, so simply create a new empty variable */

    if( mxIsEmpty(prhs[0]) ) {
	    if( out_numeric ) {
		    plhs[0] = mxCreateNumericArray(mxGetNumberOfDimensions(prhs[0]),
			                               mxGetDimensions(prhs[0]),
							               outclass, mxREAL);
	    } else if( outclass == mxCHAR_CLASS ) {
		    plhs[0] = mxCreateCharArray(mxGetNumberOfDimensions(prhs[0]),
		 	                            mxGetDimensions(prhs[0]));
	    } else {
		    plhs[0] = mxCreateLogicalArray(mxGetNumberOfDimensions(prhs[0]),
			                              mxGetDimensions(prhs[0]));
	    }
	    return;
    }

/* Check the old & new sizes for compatibility */

    ndim = mxGetNumberOfDimensions(prhs[0]);
    dims_old = mxGetDimensions(prhs[0]);
    for( i=0; i<ndim; i++ ) {
	    if( dims_old[i] != 1 || i == ndim-1 ) {
		    k = (dims_old[i] * inbytes) / outbytes;
			if( k * outbytes != dims_old[i] * inbytes ) {
                mexErrMsgTxt("Too few input values to make output type.\n");
			}
			idim = i;
		    break;
	    }
    }
	dims_new = mxMalloc(ndim * sizeof(*dims_new));
    for( i=0; i<ndim; i++ ) {
		dims_new[i] = dims_old[i];
    }
	dims_new[idim] = k;

/* Create the output array as a shared data copy, then manually set the class
 * and size parameters by accessing the structure fields directly. Note that
 * this is using undocumented MATLAB API functions and hacking of the
 * mxArray_tag structure, so this may not work in future versions of MATLAB.
 */
   // mx = (struct mxArray_Tag *) prhs[0];
   // printf("old flags: %#6x\n", mx->flags);

   plhs[0] = mxCreateSharedDataCopy(prhs[0]);
   mx = (struct mxArray_Tag *) plhs[0];
   mx->ClassID = outclass;
   mx->VariableType = VariableType_Temporary;
   mxSetDimensions(plhs[0],dims_new,ndim);
   mxFree(dims_new);

	//mexPrintf("post shared data copy\n");

   // printf("new flags: %#6x\n", mx->flags);
   return;

   // this breaks in R2018a, @djoshea removing
/* Also need to fix up the flags */

   if( outclass == mxDOUBLE_CLASS ) {
	   if( mxGetNumberOfElements(plhs[0]) == 1 ) {
		   mx->flags = 0x0211;  /* Set numeric, temporary, and full double scalar bits */
	   } else {
		   mx->flags = 0x0210;  /* Set numeric and temporary bits */
	   }
   } else if( out_numeric ) {
	   mx->flags = 0x0210;  /* Set numeric and temporary bits */
   } else {
	   mx->flags = 0x0010;  /* Set the temporary bit */
   }
}