"James Tursa" wrote in message <iiek4m$snu$1@fred.mathworks.com>...
> "Richard Crozier" wrote in message <iie4hv$f3n$1@fred.mathworks.com>...
> > I am creating a gateway function to a C file which uses the long integer type. I cannot...
snip
> > Thanks
>
> The easiest thing to do is to check the sizeof(long int), see how many bits it is, and then use that type on the MATLAB side for all of your mex argument inputs (e.g., int32). You can always but a check in your mex routine to make sure that the inputs are the correct bitlength for the dlsei_ routine or throw an error.
>
> The harder way is to convert all of your inputs inside the mex routine to the correct type, then pass *them* to the dlsei_ routine.
>
> Q: If your dlsei_ routine is using long int, why are you using int above instead of long int?
>
> You may have a problem with this line:
>
> > /* get the vector input/output X */
> > X = mxGetPr(prhs[7]);
>
> as it appears you are using the prhs[7] variable as both input/output to the routine. So I am guessing that dlsei_ changes X inplace? Then you later copy the results to the output here:
>
> > plhs[0] = mxDuplicateArray(prhs[7]);
>
> This will change the input argument on the MATLAB side, which I don't think you want. You need to copy the input *first*, and then pass the copy to the dlsei_ routine.
>
> Also, if all of your long int arguments are scalars, you are going about this the hard way. Just declare them as long int (not pointers) and then pass their addresses to dlsei_. e.g., instead of doing this for MDW:
>
> > int *MDW;
> :
> > /* get the scalar input MDW */
> > MDW = mxGetPr(prhs[1]);
> :
> > /* call the C subroutine */
> > dlsei_(W, MDW, ME, MA, MG, N, PRGOPT, X, RNORME, RNORML, MODE, WS, IP);
>
> it is easier to do this:
>
> long MDW;
> :
> /* get the scalar input MDW */
> MDW = mxGetScalar(prhs[1]);
> :
> /* call the C subroutine */
> dlsei_(W, &MDW, ME, MA, MG, N, PRGOPT, X, RNORME, RNORML, MODE, WS, IP);
>
> And, of course, do the same thing for all of your other scalar long int inputs (not shown above).
>
>
> James Tursa
Hi James, thanks for replying.
To answer you first question, that was just a mistake on my part, they should all be the long int type.
To reply to your more general comment about the variables being manipulated 'in place' this is indded the case, but this is dictated by the subroutine dlsei__. This routing was created from fortran source files via the conversion program f2c. In the original fortran program it is necesary to create arrays of the correct length for the output.
The variables W, PRGOPT, IP, MDW, ME, MA, MG, N ans IP are the real inputs
The variables X, RNORME, RNORML and MODE are the real outputs
The variables IP and WS are arrays used as workspace in dlsei__ and must be preallocated a certain minimum size based on the values on ME, MA, and N etc.
I'm not that hot on C programming and it is much simpler for me to preallocate all these variables in matlab to the correct sizes and pass these in.
I want also want to work on various machine architectures, including at least win32 and glnxa64 (64 bit linux). On my windowx XP machine a long int is 32 bits, on the linux machine a long int is 64 bits. I also have a 64 bit windows Vista machine I also want to work, I haven't tested the long int size on this yet. Matlab does not provide a command to get the size of a long int on the local machine, and this would probably be compiler specific anyway (correct me if I'm wrong though!).
So, based on this and your initial advice, I now have the following code
/* the gateway function */
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
double *W, *PRGOPT, *WS, *IP;
long MDW, ME, MA, MG, N, MODE;
double *X, *RNORME, *RNORML;
double *MODEOUT;
mwSize matm, matn;
/*
printf("long int size: %zu", sizeof(long));
*/
/* set the output pointers to the output matrices */
plhs[0] = mxDuplicateArray(prhs[7]);
plhs[1] = mxDuplicateArray(prhs[8]);
plhs[2] = mxDuplicateArray(prhs[9]);
/* create a pointer to the input vector W */
W = mxGetPr(prhs[0]);
/* get the scalar input MDW */
MDW = (long) mxGetScalar(prhs[1]);
/* get the scalar input ME */
ME = (long) mxGetScalar(prhs[2]);
/* get the scalar input MA */
MA = (long) mxGetScalar(prhs[3]);
/* get the scalar input MG */
MG = (long) mxGetScalar(prhs[4]);
/* get the scalar input N */
N = (long) mxGetScalar(prhs[5]);
/* get the vector input PRGOPT */
PRGOPT = mxGetPr(prhs[6]);
/* get the vector input/output X */
X = mxGetPr(plhs[0]);
/* get the scalar input RNORME */
RNORME = mxGetPr(plhs[1]);
/* get the scalar input RNORML */
RNORML = mxGetPr(plhs[2]);
/* get the scalar input MODE */
MODE = (long) mxGetScalar(prhs[10]);
/* get the vector input WS */
WS = mxGetPr(prhs[11]);
/* get the vector input IP */
IP = mxGetPr(prhs[12]);
plhs[3] = mxCreateDoubleMatrix(1, 1, mxREAL);
MODEOUT = mxGetPr(plhs[3]);
/* call the C subroutine */
dlsei_(W, &MDW, &ME, &MA, &MG, &N, PRGOPT, X, RNORME, RNORML, &MODE, WS, IP);
*MODEOUT = (double) MODE;
}
This does seem to work, but is there a better way to handle the X, RNORME and RNORML variables? RNORME and RNORML are always scalar doubles, X is an array of N doubles, i.e.they are created in the matlab calling function by:
rnorml = 0;
rnorme = 0;
x = zeros(N,1);
And will never have anything but zeros in them before being sent to dlsei__
Anyway, don't worry if you don't have time to answer this either, it's quite a long one! Thanks for your help so far anyway.
