MATLAB: Byte ordering in calls from C/C++ to a Matlab-compiled DLL

byte orderccompileddoubleendiannessfloatMATLAB Compilermcc

I am having a strange issue with passing information to and from a compiled MATLAB DLL from C/C++.
First, here is my function:
function y = foo(x)
a=0.5;
y=x.*a;
And here is how I compile it using Microsoft VS 9.0:
mcc -B csharedlib:foolib foo.m -C
And here is my C++ pseudo-code:
In header
mxArray *x_ptr, *y_ptr;
In constructor
mclInitializeApplication(NULL,0);
foolibInitialize();
In main
// note: myBuffer is a float* of length numSamples
x_ptr = mxCreateDoubleMatrix(numSamples, 1, mxREAL);
y_ptr = mxCreateDoubleMatrix(numSamples, 1, mxREAL);
memcpy(mxGetPr(x_ptr), (double*)myBuffer, numSamples*sizeof(double));
mlfFoo(1, &y_ptr, x_ptr);
memcpy(myBuffer, (float*)mxGetPr(y_ptr), numSamples*sizeof(float));
My deconstructor
foolibTerminate();
mxDestroyArray(x_ptr); x_ptr=NULL;
mxDestroy(y_ptr); y_ptr = NULL;
mclTerminateApplication();
But here is the weird part – if a (in foo.m) is 1/2 or 1/4 or 1/8, etc. then while it doesn't sound like gain is really being applied (in fact it sounds slightly distorted), at least it is passing through the input. However, if I use ANY other gain values, e.g. 0.51 instead of 0.50, the output is complete and utter garbage.
In researching this problem, I realized that the fractions listed above only alter the exponent of a float, and doing an odd fraction such as 0.51 also changes the mantissa.
So my thoughts are that there is some sort of endianness or byte-ordering problem going on?!? Does anyone have any thoughts on this?!?!?

Best Answer

I don't think you understood what Walter was getting at. These lines will not work if myBuffer is supposed to contain float data:
memcpy(mxGetPr(x_ptr), (double*)myBuffer, numSamples*sizeof(double));
memcpy(myBuffer, (float*)mxGetPr(y_ptr), numSamples*sizeof(float));
Simply casting the result of mxGetPr, a double * , to a float * , does not change the fact that the underlying data that it is pointing to is still double. And vice-versa for the double * cast you have on myBuffer. You will need to physically write a for-loop and do the conversion from single-to-double (or the reverse) manually one element at a time. You cannot use memcpy for this.
As a side note, it is pointless to put any cast at all for the 2nd argument to memcpy since the compiler will immediately turn around and cast it to a void * per the prototype. (You did include the prototype, right?).