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

Fortran DLL Changes in newer compiler?

PlettB
New Contributor I
1,950 Views

I am working on some code that was last compiled a number of years ago, and building and running beautifully using an older version of Intel's Fortran.  I'm reopening it now with the latest compiler and running into numerous difficulties.  Here are two that, if answered, might solve all the problems at once:

  • It seems I can no longer export a "subroutine".  Is that right?
  • It seems that if I have a "print *" in my function, the DLL will fail to load.

Let me provide a little more context.  I have a large, complicated Fortran DLL that I'm calling from C# using P/Invoke.  The strange thing is that if I set the C# project as my "startup", the DLL will fail to load with practically no useful information - just "The specified module could not be found. (Exception from HRESULT: 0x8007007E)", despite the fact that the DLL is definitely there (and even provides the right results with "dumpbin").  However, if I set the Fortran DLL as the startup and set the C# executable as the "command", I can debug the Fortran DLL just fine.

That's great for debugging, but it means that when all is said and done I can't actually run the code, since it is always called from the C# launcher.

Any help would be MUCH appreciated!!!

0 Kudos
16 Replies
Steve_Lionel
Honored Contributor III
1,892 Views
  • It seems I can no longer export a "subroutine".  Is that right?

No.

  • It seems that if I have a "print *" in my function, the DLL will fail to load. 

The most common reason for this is that a dependent DLL was not found. If you built the DLL as a Debug configuration, this is the expected result as the debug run-time DLLs are available only from within a Visual Studio session or a compiler command line environment. Make sure you are building a Release configuration of your DLL.

0 Kudos
PlettB
New Contributor I
1,886 Views

Thank-you very much for your reply.  Sadly it doesn't seem to be helping me at all.


@Steve_Lionel wrote:
  • It seems I can no longer export a "subroutine".  Is that right?

No.


I'm confused.  So I CAN still export a "subroutine"?  What do I have to do to make it work?


@Steve_Lionel wrote:
  • It seems that if I have a "print *" in my function, the DLL will fail to load. 

The most common reason for this is that a dependent DLL was not found. If you built the DLL as a Debug configuration, this is the expected result as the debug run-time DLLs are available only from within a Visual Studio session or a compiler command line environment. Make sure you are building a Release configuration of your DLL.


This doesn't appear to have made any difference.  I can compile everything in "Release" and I still get the useless "Unable to load DLL 'xxxxx.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)".

Any more ideas?

 

P.S. Regardless of the final resolution, it is clear something has fundamentally changed with the compiler.  This used to work just fine.  If only I could figure out what it was.  At this point it looks like I have to go back to an older compiler, and the difficulty will be knowing which one.  Assuming the older versions are still available, it's going to be tedious try each one!

0 Kudos
andrew_4619
Honored Contributor III
1,865 Views

You haven't shown anything for people to comment on. Some sample code would be useful maybe.

 

0 Kudos
PlettB
New Contributor I
1,852 Views

That's fair.  Here's the code in my DLL:

    !DEC$ ATTRIBUTES DLLEXPORT::add_numbers
    function add_numbers(a, b) bind(C, name="add_numbers")
    integer, value, intent(in) :: a, b
    integer :: add_numbers

    add_numbers = a + b

    ! This will cause an error when the DLL is loaded in the C# program
    ! "Unable to load DLL 'SimpleDll.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)"
    ! Comment the line out and everythng will work
    ! print *, "Adding ", a, " and ", b, " gives ", add_numbers

    end function add_numbers

Here's my calling program:

using System;
using System.Runtime.InteropServices;

namespace PInvoke
{
    internal class Program
    {
        [DllImport("SimpleDll.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int add_numbers(int a, int b);

        static void Main(string[] args)
        {
            try
            {
                var result = add_numbers(10, 20);
                Console.WriteLine(result);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

 I've attached a zip file containing the above.  Just remember, if you want to try the zip, you'll need to:

  • Set "PInvoke" as the startup project
  • Make sure "PInvoke" is building to "x64" (rather than "Any CPU")

 

0 Kudos
Steve_Lionel
Honored Contributor III
1,860 Views

An example:

 

 

subroutine test
!DIR$ ATTRIBUTES DLLEXPORT :: test
end subroutine test
D:\Projects>ifx /dll test.f90
Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 2025.0.0 Build 20241008
Copyright (C) 1985-2024 Intel Corporation. All rights reserved.

Microsoft (R) Incremental Linker Version 14.42.34435.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:test.dll
-dll
-implib:test.lib
test.obj
   Creating library test.lib and object test.exp
D:\Projects>dumpbin -exports test.dll
Microsoft (R) COFF/PE Dumper Version 14.42.34435.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file test.dll

File Type: DLL

  Section contains the following exports for test.dll

    00000000 characteristics
    FFFFFFFF time date stamp
        0.00 version
           1 ordinal base
           1 number of functions
           1 number of names

    ordinal hint RVA      name

          1    0 00001000 TEST

 

 

 

0 Kudos
PlettB
New Contributor I
1,851 Views

Oddly today I wasn't able to recreate the "subroutine" issue I was having yesterday, but the issue with "print" is still there.

0 Kudos
PlettB
New Contributor I
1,833 Views

I just realized the last time I had it working was with "Intel Parallel Studio XE 2018".  I'm now trying to get it working with "Intel One API".  Unfortunately the machine I had "Intel Parallel Studio" installed on is no more.  Is there a place I can still download ""Intel Parallel Studio"?  We used to have a paid license for it, but obviously that has expired.

I need to get this working, and if downgrading to "Intel Parallel Studio" is the only way, that's what I'll have to do (at least for now).

0 Kudos
Steve_Lionel
Honored Contributor III
1,823 Views
 Adding           10  and           20  gives           30
30

D:\Projects\MinimalExample\PInvoke\bin\x64\Debug\PInvoke.exe (process 30084) exited with code 0 (0x0).

I didn't make any changes other than the ones you specified.

0 Kudos
PlettB
New Contributor I
1,780 Views

Oh that's just weird!  But it's not the first time I've experienced "it works on my machine".  So that leaves me wondering what on earth I have wrong!  There must be a dependency that you're picking up that I'm not - that's about all I can figure out.  Any guesses what that might me?  I've tried running "depends" on the DLL, but nothing jumps out at me.

0 Kudos
PlettB
New Contributor I
1,775 Views

Out of curiosity, have you tried running the executable at a command line?

As I mentioned previously, if I set the DLL as the startup project and the executable as the command, I can debug the Fortran.  However, that's the only way I can get it to work.  If I set the startup to the C# program OR if I try to run the executable from a command prompt, I get the useless error.  Somehow I need to figure out what the difference is.

I guess I'm very slowly narrowing it down, but I'm out of ideas.  What's special about the "print" command?  What dependencies does it need that it gets during a Fortran debug session, but not in a C# debug session nor at the command prompt?!

0 Kudos
PlettB
New Contributor I
1,767 Views

Further findings:  if I run the executable from the "Intel oneAPI command prompt", it works!  Now I just have to figure out what to extract from that so that I can actually distribute my application.  Any help on the would be greatly appreciated!

0 Kudos
Steve_Lionel
Honored Contributor III
1,762 Views

OK, I dug a bit deeper.

The results I showed were for the Debug configuration, but for the Release configuration, I get the same error you do. It was then I noticed a difference in how the Pinvoke project built.  You properly have the DLL being created in:

..\PInvoke\bin\$(PlatformName)\$(ConfigurationName)

so it will go in either Pinvoke\bin\x64\Debug or Pinvoke\x64\Release. Given that's where the Pinvoke executable should be, that's correct. But when I build the two configurations, I see:

1> PInvoke -> D:\Projects\MinimalExample\PInvoke\bin\x64\Debug\PInvoke.exe
and
1> PInvoke -> D:\Projects\MinimalExample\PInvoke\bin\Release\PInvoke.exe

Where did the x64 go?

Somehow, the Release Pinvoke.exe isn't going to the proper folder, but the output property gives bin\x64\Release\ The result is that the DLL is in one folder and the EXE in another, and that's why you get the error.

This is not a Fortran issue. I am not familiar with building C# apps, so you'll need to look into that.

0 Kudos
PlettB
New Contributor I
1,758 Views

Yes, I'm well aware of that quirk, and have been taking it into account.  Still, thanks for digging deeper.

Since I now have everything working properly if I run it from the "Intel oneAPI command prompt", I just need to figure out what I need to replicate from that environment in order to distribute the application without the Intel oneAPI package.

0 Kudos
PlettB
New Contributor I
1,739 Views

Two days of pain and hassle and I've finally figured it out!  And, as I was expecting, it's essentially a trivial fix!  All I needed to do was copy a few files to the folder my executable lives in.  In my case those are:

  • "C:\Program Files (x86)\Intel\oneAPI\compiler\2025.0\bin\libifportmd.dll"
  • "C:\Program Files (x86)\Intel\oneAPI\compiler\2025.0\bin\libifcoremdd.dll"
  • "C:\Program Files (x86)\Intel\oneAPI\compiler\2025.0\bin\libmmd.dll"

It's all so obvious once I figured it out.  It's just too bad there was NOTHING to point me in that direction (e.g. a message indicating failure attempting to load one of those).  Even the trusty "Process Monitor" (from SysInternals) wasn't showing a failure.

Oh, well, on to the next challenge.

Thanks to all who tried to help.

0 Kudos
andrew_4619
Honored Contributor III
1,714 Views

Those are debug dll's, you must have made a debug build if you need those. Those are only available in VS or the Fortran build environment. For release you need the release dlls and should on a none build machine install the Fortran redistributable package.

0 Kudos
Steve_Lionel
Honored Contributor III
1,676 Views

No, those aren't debug DLLs (well, the second one is but I think that was a typo), but you should not need to copy those DLLs. The installer is supposed to add the folders containing the runtime DLLs into the PATH system environment variable, but sometimes it doesn't. Nevertheless, you can't run Debug configuration code outside the build environment.

Check the value of PATH to make sure it includes the folder you got those DLLs from, except that it should have Latest rather than 2025.0 in the path.

0 Kudos
Reply