Problems when comparing mwSize and mwIndex variables

Hello
I am slowly changing my old fortran-c codes to the new matlab standard. When changing one of the gateway funtions, I encounter the following
....
mwIndex nyt, nsuby;
mwSize YDA_COLS;
....
then nyt and YDA_COLS = nsuby = mxGetN(YDA_IN) take value 1, that is nyt=1 and YDA_COLS=1. When I issue the following comand
if (YDA_COLS < nyt)
{
mexErrMsgTxt("Number of Columns of Y is incompatible. ");
}
The number os Columns of Y is incompatible! I have no idea of what is wrong. If I change to mwSize nyt, nsuby, the same thing happens. It only works if I change to int nyt, nsuby.
Many thanks
Ed

10 comentarios

It is hard to advise without seeing more of your code. At the very least, I would print out the values of YDA_COLS and nyt before you call mexErrMsgTxt.
I do apologize for not replying before.
mexPrintf("%d %d\n",YDA_COLS,nyt)
resulted in the output
1 1
James Tursa
James Tursa el 29 de Abr. de 2019
Editada: James Tursa el 29 de Abr. de 2019
What is sizeof(mwSize) and sizeof(mwIndex)? Is mwSize unsigned (e.g., size_t)? Can you post the actual code where YDA_COLS and nyt are assigned values? I am thinking it could possibly be a signed/unsigned conversion issue.
Many thanks.
>> [x,m,ve]=olsml65(model,u,y,10,'c');
sizeof(YDA_COLS) = 8 sizeof(nyt) = 8
YDA_COLS=1 nyt=1
Error using olsml65
Number of Columns of Y is incompatible.
actual code:
YDA_ROWS = mxGetM(YDA_IN);
leng = YDA_ROWS;
YDA_COLS = mxGetN(YDA_IN);
nsuby= YDA_COLS;
YDA = yda = mxGetPr(YDA_IN);
if (YDA_COLS < nyt)
{
mexErrMsgTxt("Number of Columns of Y is incompatible. ");
}
and
maxlagm_(iext,&nump,&degree,&nsuby,&nst,npt,nnt,&nyt,
&nut,&net,&degreeo,&nsubyo,&nstr);
subroutine maxlagm(iext,nump,degree,nsuby,nst,npt,nnt,nyt,nut,net,
* degreeo,nsubyo)
integer nump,degree,nsuby
integer iext(nump,degree,nsuby)
integer npt(nsuby),nnt(nsuby),nst
integer nyt,nut,net,degreeo,nsubyo
The fortran code was previously compiled using gfortran -m64
Let's back up a step. What do you get when you run this code:
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
mwIndex nyt = 1, Itest = -1;
mwSize YDA_COLS = 1, Stest = -1;
mexPrintf("YDA_COLS = %llu , %zu bytes , is signed? %d\n",YDA_COLS,sizeof(YDA_COLS),Stest<0);
mexPrintf("nyt = %lld , %zu bytes , is signed? %d\n",nyt,sizeof(nyt),Itest<0);
if (YDA_COLS < nyt) {
mexErrMsgTxt("Number of Columns of Y is incompatible. ");
} else {
mexPrintf("Everything OK\n");
}
}
James Tursa
James Tursa el 30 de Abr. de 2019
Editada: James Tursa el 30 de Abr. de 2019
Also, not sure what difference this will make to you (if any), but the default INTEGER type in Fortran is typically 4-bytes, even with a 64-bit compiler. In your translation the integers you are using are apparently 8-bytes.
Here it is what I got by the running the code
YDA_COLS = 1 , 8 bytes , is signed? 0
nyt = 1 , 8 bytes , is signed? 0
Everything OK
I have modified my original ocde following your code and got
>> [x,m,ve]=olsml65(model,u,y,10,'c');
YDA_COLS = 1 , 8 bytes , is signed? 0
nyt = 4294967297 , 8 bytes , is signed? 0
Error using olsml65
Number of Columns of Y is incompatible.
I am almost sure that if I change integer to integer*8 in my fortran code, matlab will crash even if the mex compilation process is fine.
James Tursa
James Tursa el 30 de Abr. de 2019
Editada: James Tursa el 30 de Abr. de 2019
So, how to explain that 4294967297 output?
(Now that we know it is unsigned, change that %lld to %llu)
I have changed nyt in the fortran code from integer to integer*8 just to see what happens. The output was
>> [x,m,ve]=olsml65(model,u,y,10,'c');
YDA_COLS = 1 , 8 bytes , is signed? 0
nyt = 1 , 8 bytes , is signed? 1
Everything OK
for "mwIndex nyt"
Can you clarify? Are you linking compiled C-mex code to compiled Fortran code? How does changing integer to integer*8 on the Fortran side affect the "signed" output on the C side? I am confused about what you are actually doing.

Iniciar sesión para comentar.

 Respuesta aceptada

James Tursa
James Tursa el 30 de Abr. de 2019
Editada: James Tursa el 30 de Abr. de 2019
A couple of observations:
>> typecast(uint64(1),'uint8')
ans =
1 0 0 0 0 0 0 0
>> typecast(uint64(4294967297),'uint8')
ans =
1 0 0 0 1 0 0 0
So now I am thinking it may be a function signature problem. If a function is returning a value of 1 as an int (4-bytes), but you told the compiler it is returning an 8-byte integer, then an extra garbage 4-bytes may be picked up by the compiler and stuffed into nyt, accounting for that extra 1 in the bit pattern. This is just speculation, but I have seen this behavior before when prototypes/signatures are not correct.
I next would like to see the exact code where nyt is being set. And if your functions are involved, the prototypes/signatures of those functions.
Are you getting any compiler warnings about mismatched pointer types?
Do you have compiled C mex code calling compiled Fortran code? If so, then I would need to see the Fortran function/subroutine signature also. E.g., if it is the Fortran signature you show above, then I would expect all of the integers on the Fortran side to be 4-bytes. And if you are passing in pointers to 8-byte integers from the C-mex side then yes that would be a problem.

4 comentarios

Ed Mendes
Ed Mendes el 30 de Abr. de 2019
The gateway (wrapper) for the fortran code is written in C (That happens back in 92 when I decided to move from fortran to C) .
Yes, I absolutely right. There is a mismatch of types. I was passing 8-bytes c variables to 4-bytes fortran variables.
Once I changed the type of nyt in the fortran code (from integer to integer*8), there is no more crashes and "Everything OK". I have tested using "mwSize", "mwIndex" and "long long int" nyt. By the way, I am not sure from which one to choose.
I would check to make sure that ALL of the arguments are exactly the same type ... not just the one that caused the current problem. Otherwise you will probably have more problems later on.
As for using mwSize vs mxIndex, it depends. If you are for sure using integer*8 on the Fortran side, then I would probably opt for mwSignedIndex on the C side so that you have signed 8-byte integers on both sides. If you keep with default integer on the Fortran side, then I would opt for int on the C side, again so that you have signed 4-byte integers on both sides.
Ed Mendes
Ed Mendes el 3 de Mayo de 2019
Many thanks. I will certainly check all of the arguments painstakingly.
If I keep the default integer on the fortran sise, I will not make use of array length beyond 32-bit, will I? If that is the case, would you advise me what I need to pay attention to? I need to change all C-gateway and fortran-77 sources to make full use of 64-bit and to make them easily compiled in future versions of Matlab.
Ed Mendes
Ed Mendes el 3 de Mayo de 2019
I decided to shorten the fortran code to see if I could convert it to the new standard. Unfortunately I run into trouble. Attached are the sources files for the C-gateway and Fotran-77 with integer*8.
The fortran source was compiled with "gfortran -c calnpr.f" and then I used mex command to do the rest.
It has been a long time that I try to modify and compile my old source files and it is very likely that I am missing something or doing something stupid.
Many thanks

Iniciar sesión para comentar.

Más respuestas (0)

Categorías

Más información sobre Fortran with MATLAB en Centro de ayuda y File Exchange.

Etiquetas

Preguntada:

el 6 de Abr. de 2019

Comentada:

el 3 de Mayo de 2019

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by