Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

mwSize is ok but not a "constant" integer

pascal_M_
Beginner
830 Views

What follows takes place on x64.

I have two fortran files (both attached to this post) inside a fortran dll project inside visual studio. (Psxe 2019.3, mv2017 last update). The *g.F file is a mex gateway function routine, and includes matlab's `finrtf.h` attached to this post.

The *g.F file initially didn't contain declaration of `size33`, and the bit

    size33 = 1
    call mxCopyPtrToReal8(mkl_pr, mkl, size33)

was initially equal to

    call mxCopyPtrToReal8(mkl_pr, mkl, 1)

which was making my code crash only at release. I don't understand what is happening as in x64 the "type" mwSize is defined (in fintrf.h) as mwpointer which itself is defined as integer*4, which should treat the "constant" 1 correctly normally.

Somehow the file finrtf.h seems to clash with the `/Qm64` flag.

0 Kudos
1 Solution
mecej4
Honored Contributor III
830 Views

Pascal M. wrote:
I don't understand what is happening as in x64 the "type" mwSize is defined (in fintrf.h) as mwpointer which itself is defined as integer*4, which should treat the "constant" 1 correctly normally.

Sorry, that reasoning is incorrect. Here we have a Fortran subroutine for which the implicit interface in

call mxCopyPtrToReal8(mkl_pr, mkl, 1)

is wrong.

Are you doing cross-compiling? If not, why do you need /Qm64?

When you link your code with a prebuilt library (such as the Matlab libraries) your code must adhere to the ABI published by the creators of the library. Look carefully at the declaration of MWPOINTER in fintrf.h. For x64 (assuming your Matlab is 64-bit), the type of MWPOINTER is INTEGER*8, not INTEGER*4. An integer constant of default type, i.e., "1", is not the correct type for the third argument to mxCopyPtrToReal8(), and using an incorrect type will probably crash the Mex DLL.

The compiler would have caught the mismatch if FINTRF.H or your Fortran code had provided interfaces to the Matlab API routines. As it is, the declarations seem to follow the old C philosophy ("the programmer is probably right"), so you have to be prepared to live dangerously.

View solution in original post

0 Kudos
5 Replies
mecej4
Honored Contributor III
831 Views

Pascal M. wrote:
I don't understand what is happening as in x64 the "type" mwSize is defined (in fintrf.h) as mwpointer which itself is defined as integer*4, which should treat the "constant" 1 correctly normally.

Sorry, that reasoning is incorrect. Here we have a Fortran subroutine for which the implicit interface in

call mxCopyPtrToReal8(mkl_pr, mkl, 1)

is wrong.

Are you doing cross-compiling? If not, why do you need /Qm64?

When you link your code with a prebuilt library (such as the Matlab libraries) your code must adhere to the ABI published by the creators of the library. Look carefully at the declaration of MWPOINTER in fintrf.h. For x64 (assuming your Matlab is 64-bit), the type of MWPOINTER is INTEGER*8, not INTEGER*4. An integer constant of default type, i.e., "1", is not the correct type for the third argument to mxCopyPtrToReal8(), and using an incorrect type will probably crash the Mex DLL.

The compiler would have caught the mismatch if FINTRF.H or your Fortran code had provided interfaces to the Matlab API routines. As it is, the declarations seem to follow the old C philosophy ("the programmer is probably right"), so you have to be prepared to live dangerously.

0 Kudos
pascal_M_
Beginner
830 Views

No I am not cross-compiling at all (I am under win10 64, matlab 64), the option /Qm64 is the one visual studio imposes in a 64bits plateform. (Well, this platform isn't readily available in an intel visual fortran project, so you have to create it by "copying" from x86 in visual studio configuration properties.) And I naïvely thought it has the following effect : make the compiler understand integer and real litterals as 64bits, so that I wouldn't have to write 1_8 instead of 1. I was wrong.

0 Kudos
pascal_M_
Beginner
830 Views

How do I know though if the compiler understands "1" as 1_2, 1_4 or 1_8 ? (In my case it doesn't understand it as 1_8 for sure, but that leaves two other possibilities.)

0 Kudos
mecej4
Honored Contributor III
830 Views

The problems related to the the use of more than one kind of integer have quite a bit to do with history. Before "byte-oriented" machines arrived in the 1960s, the mainframe computer manufacturer set the sizes of the native types, and an integer could be 16, 24, 32, 36, 48 or 64 bits long. For Fortran on such machines, the integer size was whatever the manufacturer provided. The computer manufacturer provided the Fortran compiler, and source code was in general not portable to other manufacturers' machines.

Since Fortran has always been a higher level language, in contrast to C, and had no pointer types before Fortran 90, and does not use raw pointers as C does, the integer size becomes an issue only when you have to interface your Fortran code with C (which is, in effect, what the Matlab interface is) or another such lower level language. F2003 and later provides a way of doing so in a portable but rather verbose way, as you can read at https://software.intel.com/en-us/fortran-compiler-developer-guide-and-reference-standard-fortran-and-c-interoperability .

The Intel compiler provides options to control default sizes, as you can see at https://software.intel.com/en-us/fortran-compiler-developer-guide-and-reference-integer-size# , but the use of this option is often a heavy handed response with adverse consequences.

Try running the following program without and with various /integer-size=<nn> options.

implicit none
print *,kind(1234),kind(32768),kind(2147483648)
end program

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
830 Views

/Qm64 generates code for 64-bit platform. This option has nothing to do with data bit-ness.

/integer-size:{16|32|64} specifies default integer (and logical) variable size but not literal size

There is no option to make literals a specific type. Literals are after all "literal".

What you may be able to do (I will leave this up to you) is to create a generic interface mxCopyPtrToReal8 that contains two actual interfaces, one with integer(4) and one with integer(8) where the integer(4) version is essentially a shell function converting the integer(4) to integer(8) to make the actual call to the subroutine in the DLL.

Jim Dempsey

 

0 Kudos
Reply