Create Mex files for Matlab, from .FOR files of Fortran
10 views (last 30 days)
Show older comments
Hello. there are files with the .FOR extension, in which the subroutine codes are written in the Fortran language. I want to create Mex files from these files, which can be run in matlab. how to do it?
0 Comments
Answers (4)
dpb
on 12 Aug 2023
Edited: dpb
on 13 Aug 2023
Which OS? For Linux, the GNU Fortran compiler is supported, for Windows and Mac only a recent version of the Intel compiler is supported.
It's unconscionable that TMW supports GNU for Linux but not for Windows and Mac; I, at least, have had no success in figuring out how to link although since it supports the GNU C compiler that the Fortran compiler is built on, it surely should be possible -- excepting for the name-mangling issues.
And, TMW has essentially quit supporting Fortran at all; the example files are still horribly outdated F77-style fixed-format with archaic at best non-standard syntax and other style problems.
You probably have a real challenge on your hands; the alternative may be to write interface routines in C and then have those call the Fortran code instead of trying to build direct Fortran mex interfaces.
@James Tursa is the real guru; hopefully he'll see and comment and have better pointers; my patience was exhausted some years ago and, fortunately, the need for additional support for the application I supported for a client while still consulting has, apparently, either gone away or they've found an alternate way so I've just given up.
0 Comments
James Tursa
on 12 Aug 2023
Edited: James Tursa
on 12 Aug 2023
So, I haven't had access to a Fortran compiler in over 10 years. And as a result I haven't been maintaining any of my Fortran FEX submissions. Kinda sad that this very fast matrix/array based language with the same memory-element order as MATLAB does not have free solutions for connecting with MATLAB, at least not for Windows, but that's the way it is. And @dpb, the Fortran examples supplied by TMW still have the same bugs in them, and the compile files probably still have the stupid /fixed option (forces free form source code to be compiled as fixed form source code ... generating lots of faux errors), that I pointed out over 10 years ago. I just submitted another request that they change this. Sigh ...
My suggestion depends on what your Fortran code does, and whether it has user I/O. If it is just number crunching, I would probably use whatever Fortran compiler you have to create .obj files. Then write a simple wrapper mex file in C that acts as a conduit for the input & output variables. Then just mex the wrapper C file and Fortran .obj files together.
If your code has user I/O, that is a whole different ball game ...
So, what does your Fortran code do? What are the inputs and outputs? Can you post the interface function signatures for us? Maybe we can quickly write the wrapper code for you.
13 Comments
dpb
on 16 Aug 2023
Edited: dpb
on 16 Aug 2023
The above seems peculiar, <the Intel doc> still says that .f and .for are both assumed by the compiler to be fixed format source form (as well as .ftn and .i).
While the /fixed switch is there in the shipped .xml files, if you've removed it, then I wonder where TMW has managed to override that behavior in the mex configuration scripts -- stuff like that that is so obfuscated is what finally drove me nuts and to just give up when couldn't still use the old CVF compiler which wouldn't run on the 64-bit OS since no longer had a paying client to foot the bills and make the effort worthwhile other than just having the facility when wanted it.
Hmmmm....does it somehow have something to do with the preprocessor, maybe? I never got into the habit of preprocessing Fortran files but mex does it automagically because the include files have lot of #defines in them for type definitions, etc., ... I hate their style, but it is what it is.
dpb
on 17 Aug 2023
Edited: dpb
on 4 Oct 2023
Well, I download/installed, too, and mex -setup fails to find the Intel 2023 compiler...it's installed and works as
C:\Users\owner>ifx hello.f90
Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 2023.2.0 Build 20230627
Copyright (C) 1985-2023 Intel Corporation. All rights reserved.
Microsoft (R) Incremental Linker Version 14.29.30151.0
Copyright (C) Microsoft Corporation. All rights reserved.
-out:hello.exe
-subsystem:console
hello.obj
C:\Users\owner>hello
Hello, world!
C:\Users\owner>
illustrates, but
>> strvcat(supported.MexOpt)
ans =
10×58 char array
'C:\ML_R2021b\bin\win64\mexopts\intel_fortran_18_vs2015.xml'
'C:\ML_R2021b\bin\win64\mexopts\intel_fortran_18_vs2017.xml'
'C:\ML_R2021b\bin\win64\mexopts\intel_fortran_18_vs2019.xml'
'C:\ML_R2021b\bin\win64\mexopts\intel_fortran_19_vs2015.xml'
'C:\ML_R2021b\bin\win64\mexopts\intel_fortran_19_vs2017.xml'
'C:\ML_R2021b\bin\win64\mexopts\intel_fortran_19_vs2019.xml'
'C:\ML_R2021b\bin\win64\mexopts\intel_fortran_20_vs2017.xml'
'C:\ML_R2021b\bin\win64\mexopts\intel_fortran_20_vs2019.xml'
'C:\ML_R2021b\bin\win64\mexopts\intel_fortran_21_vs2017.xml'
'C:\ML_R2021b\bin\win64\mexopts\intel_fortran_21_vs2019.xml'
>> mex -setup FORTRAN
Error using mex
Supported compiler not detected. For options, visit https://www.mathworks.com/support/compilers.
>>
I've no klew at this point yet as to how to make it find it...I'm pretty sure it must have to do with where/how mex searches, but they give no hints as to how that does/does not work in order to be able to prod it in the right direction.
I let the install use the default location...
I dunno, did you use VS and build inside it instead, maybe? I've never tried that; always just wrote code with my preferred toolset and then compiled/linked. W/ CVF in the olden days I could do all that inside the Brief editor but it also won't run on these systems any more, sadly.
roborrr
on 16 Aug 2023
Edited: roborrr
on 16 Aug 2023
6 Comments
dpb
on 16 Aug 2023
Actually one can see the switches used for gfortran on the unix platform using the above; but I couldn't figure out a way to get a copy of the saved struct variable to a local file from the remote platform to be able to poke at it in a more leisurely fashion. At some point, might retry that exercise again with that guiding light...
dpb
on 17 Aug 2023
@dpb wrote earlier "There's a define in the .xml file for the compiler location $FORTRANROOT where it expects the installation to be; I'm not positive who is responsible for defining that variable;"
Aha! I just found it; I had quite scrolling in the .xml files after the compiler/linker definitions; there's a very convoluted search logic written in xml as
<locationFinder>
<FORTRANROOT>
<or>
<and>
<or>
<envVarExists name="IFORT_COMPILER22" />
</or>
<fileExists name="$$/Bin/intel64/ifort.exe" />
<dirExists name="$$/../.." />
</and>
<and>
<or>
<envVarExists name="ONEAPI_ROOT" />
</or>
<fileExists name="$$/compiler/latest/windows/Bin/intel64/ifort.exe" />
<dirExists name="$$/../.." />
</and>
<and>
<or>
<envVarExists name="ONEAPI_ROOT" />
</or>
<fileExists name="$$/compiler/2021.1.1/windows/Bin/intel64/ifort.exe" />
<dirExists name="$$/../.." />
</and>
</or>
</FORTRANROOT>
<VCROOT>
<or>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,18.0)" -products Microsoft.VisualStudio.Product.Enterprise -property installationPath -format value" />
<cmdReturns name="set "vcroot=$$"&for /f "delims= " %a in ('type "$$\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"') do @if exist "$$\VC\Tools\MSVC\%a\bin\HostX64\x64\cl.exe" call echo %vcroot%" />
</and>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,18.0)" -products Microsoft.VisualStudio.Product.Professional -property installationPath -format value" />
<cmdReturns name="set "vcroot=$$"&for /f "delims= " %a in ('type "$$\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"') do @if exist "$$\VC\Tools\MSVC\%a\bin\HostX64\x64\cl.exe" call echo %vcroot%" />
</and>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,18.0)" -products Microsoft.VisualStudio.Product.Community -property installationPath -format value" />
<cmdReturns name="set "vcroot=$$"&for /f "delims= " %a in ('type "$$\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"') do @if exist "$$\VC\Tools\MSVC\%a\bin\HostX64\x64\cl.exe" call echo %vcroot%" />
</and>
</or>
</VCROOT>
<SDKROOT>
<or>
<hklmExists path="SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0" name="InstallationFolder" />
<hkcuExists path="SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0" name="InstallationFolder" />
<hklmExists path="SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v10.0" name="InstallationFolder" />
<hkcuExists path="SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v10.0" name="InstallationFolder" />
</or>
</SDKROOT>
<VSINSTALLDIR>
<or>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,18.0)" -products Microsoft.VisualStudio.Product.Enterprise -property installationPath -format value" />
</and>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,18.0)" -products Microsoft.VisualStudio.Product.Professional -property installationPath -format value" />
</and>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,18.0)" -products Microsoft.VisualStudio.Product.Community -property installationPath -format value" />
</and>
</or>
</VSINSTALLDIR>
<VCINSTALLDIR>
<or>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,18.0)" -products Microsoft.VisualStudio.Product.Enterprise -property installationPath -format value" />
<cmdReturns name="set "vcroot=$$"&for /f "delims= " %a in ('type "$$\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"') do @if exist "$$\VC\Tools\MSVC\%a\bin\HostX64\x64\cl.exe" call echo %vcroot%\VC\Tools\MSVC\%a" />
</and>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,18.0)" -products Microsoft.VisualStudio.Product.Professional -property installationPath -format value" />
<cmdReturns name="set "vcroot=$$"&for /f "delims= " %a in ('type "$$\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"') do @if exist "$$\VC\Tools\MSVC\%a\bin\HostX64\x64\cl.exe" call echo %vcroot%\VC\Tools\MSVC\%a" />
</and>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,18.0)" -products Microsoft.VisualStudio.Product.Community -property installationPath -format value" />
<cmdReturns name="set "vcroot=$$"&for /f "delims= " %a in ('type "$$\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"') do @if exist "$$\VC\Tools\MSVC\%a\bin\HostX64\x64\cl.exe" call echo %vcroot%\VC\Tools\MSVC\%a" />
</and>
</or>
</VCINSTALLDIR>
<VCVARSALLDIR>
<or>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,18.0)" -products Microsoft.VisualStudio.Product.Enterprise -property installationPath -format value" />
<fileExists name="$$\VC\Auxiliary\Build\vcvarsall.bat" />
<dirExists name="$$"/>
</and>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,18.0)" -products Microsoft.VisualStudio.Product.Professional -property installationPath -format value" />
<fileExists name="$$\VC\Auxiliary\Build\vcvarsall.bat" />
<dirExists name="$$"/>
</and>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,18.0)" -products Microsoft.VisualStudio.Product.Community -property installationPath -format value" />
<fileExists name="$$\VC\Auxiliary\Build\vcvarsall.bat" />
<dirExists name="$$"/>
</and>
</or>
</VCVARSALLDIR>
<KITSROOT>
<or>
<hklmExists path="SOFTWARE\Wow6432Node\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
<hkcuExists path="SOFTWARE\Wow6432Node\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
<hklmExists path="SOFTWARE\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
<hkcuExists path="SOFTWARE\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
</or>
</KITSROOT>
<SDKVERSION>
<and>
<or>
<hklmExists path="SOFTWARE\Wow6432Node\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
<hkcuExists path="SOFTWARE\Wow6432Node\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
<hklmExists path="SOFTWARE\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
<hkcuExists path="SOFTWARE\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
</or>
<!-- For each folder inside '<KITSROOT>\include' check for 'ucrt' and if exists return that folder name -->
<cmdReturns name="echo off&set "sdkversion="&(for /f %a IN ('dir "$$\include\" /b /ad-h /on') do ( @if exist "$$\include\%a\ucrt\" set "sdkversion=%a" ))&call echo %sdkversion%" />
</and>
</SDKVERSION>
</locationFinder>
The above has buried in it expected install paths and version numbers; I've yet to dive totally into the constants here but looks like one copy of the ifort.exe compiler on the installed path should match this expected one; the ONEAPI_ROOT environment variable is set. The version returned is
C:\Program Files (x86)\Intel\oneAPI\compiler\latest\windows\bin\intel64>ifort
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.10.0 Build 20230609_000000
which returns 2021.10 as a version whereas the xml file just says "21.0". I'm not sure if that's an/the issue or not or whether the fact it installed in a folder ..\2023.2.1 instead of ..\2021.1.1 that's buried in the script. Although superfiically it looks like it should have matched the earlier <or> under "../latest/windows/Bin/intel64/" because there's a copy of ifort.exe there, too.
Why they have to make this so complicated...and give no diagnostics nor ways to fix if something does go wrong....
roborrr
on 19 Aug 2023
7 Comments
Walter Roberson
on 20 Aug 2023
The document I was looking for said that size could differ for blank common but that the types needed to be the same for all versions; for named common it said the size and types had to be identical.
dpb
on 20 Aug 2023
Edited: dpb
on 20 Aug 2023
The restriction that named common blocks be the same size is so. Names can change positionally and type punning by EQUIVALENCE.
I'd guess it's pretty unlikely those are used in OP's code, but it's always possible and the safest (and simplest to try to mex this) route is to simply duplicate COMMON as is...the listing doesn't show an INCLUDE statement to bring in the COMMON; that could be original source doesn't use it or the posted came from listing that doesn't reflect preprocessing.
NOT using INCLUDE but having duplicate code in multiple program units is one of the most common ways to mess up and unintentionally change variables via common; a change in the block definition has to be faithfully duplicated everywhere in that case; it's all too easy to miss one or make a typo when are many to do.
A code I supported for years I've referred to often in the past deliberately uses the type punning in its database to, in various program units or for various purposes, refer to same memory locations as REAL or INTEGER variable types; I'd've never designed it that way, but the original authors did and it works very well; is just difficult to grasp initially. It, however, also uses C helper routines that move those data bytes by straight bit copying via memmove() when storing. Anyways, gotten way off track for OP's issues...
See Also
Categories
Find more on Fortran with MATLAB in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!