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

Porting Linux Fortran code to Windows

Lucero
Beginner
5,136 Views

Hello

About 12 years ago, I was asked to port Linux Fortran (gfortran) code to Windows. Back then, the Intel Fortran compiler was ifort. It took some time to get it working with a bunch of help from Steve, but now I am having some issues getting the code to run. We stopped working on this after one month that we had it working, and we did not revisit this project until now. The main concern is the shared memory. I already took a look at the notes on:

Porting Guide for ifort Users to ifx

But I did not find anything about changes on how to set shared memory. For example, I have the following variables that need to be shared between multiple processes:

c <datcol_globals> module defines/exports data defined by the "Data Collection" process to be shared between the parent and child process(es).
c The "Data Collection" process data is built into <datcol_globals.dll> and linked into the application.
c
c In order for the data to be read-write shared, the following must be done:
c
c 1. The variables must be initialized to a non-zero value so that they are placed
c in the .data image section.
c
c 2. The linker command line options are modified to add: /section:.data,RWS
c
c This tells the linker to make the .data section of the DLL read-write shared.
c If this isn't done, then each process will have its own copy of the data.

module data_collection_globals
use ifwin, only: DWORD
use simulation_globals
implicit none

INTEGER(DWORD),DIMENSION(numdcbuf,maxsizedcbuf) :: dc_buffers=999
INTEGER(DWORD),DIMENSION(max_msgtyp,max_tasks) :: last_flushed=99
INTEGER(DWORD),DIMENSION(numdcbuf) :: buff_swap = 999
INTEGER(DWORD),DIMENSION(numdcbuf) :: write_to_point = 999

logical(4),DIMENSION(numdcbuf) :: buf_full = .TRUE.
logical(4) :: dcshutdown = .TRUE.

!dec$ attributes dllexport :: buf_full
!dec$ attributes dllexport :: buff_swap
!dec$ attributes dllexport :: dc_buffers
!dec$ attributes dllexport :: dcshutdown
!dec$ attributes dllexport :: last_flushed
!dec$ attributes dllexport :: write_to_point

end module data_collection_globals

Initially, I was getting the control process to start one of the other processes using the CreateProcess() function, and it was successfully starting the process, but once I noticed that the data was not being shared between the processes, I noticed the note about recompiling the module using /section:.data,RWS. Once I did that, the process is no longer created. 

I know this is a loaded question with not much information but does setting up the shared memory between processes still the same with the new compiler. Mind that I had this working 12 years ago, and I know many things might have changed. Sorry, I am very naive in Windows as much of our projects have been done in Linux with the GNU compiler. We are not trying to port the code for good to Windows. Please let me know if you have any questions.

I am using Visual Studio 2022 with the Intel Windows Fortran compiler 2025.1

Any comments/suggestions will be greatly appreciated

 

Thanks you

Aldo L.

0 Kudos
17 Replies
Lucero
Beginner
5,060 Views

Sorry, 

To add to my previous post, I noticed that in the old project, I was getting *.exp files for my shared memory DLLs. For example, I was getting files like:

data_collection_globals.dll

data_collection_globals.mod

data_collection_globals.lib

data_collection_globals.exp

I am getting the first 3 file types, but not the data_collection_globals.exp file. Would this be a change because of the new compiler or am I not setting the project correctly? I am not even sure if data_collection_globals.exp is important, but if it is, then maybe that is the reason why I am having issues creating the second process.

Thanks,

Aldo L.

0 Kudos
Lucero
Beginner
4,881 Views

Sorry,

In trying to research my problem, I found the following on this link:

https://www.intel.com/content/www/us/en/developer/articles/guide/porting-guide-for-ifort-to-ifx.html

The statement is:

  • Support added in ifx 2022.3.0... On Windows* the ATTRIBUTES DLLEXPORT and DLLIMPORT are not yet supported.

This is under the COMMON Block heading.

I am just trying to make I understand this correctly. The ATTRIBUTES DLLEXPORT and DLLIMPORT are not supported when defining a Common Block or is it not supported at all?? If the latter, then how do you create shared memory using a DLL?

Any feedback will be greatly appreciated. I have been trying to get this to work for the last couple of weeks.

Thanks,

Aldo L.

 

 

0 Kudos
Steve_Lionel
Honored Contributor III
4,829 Views

DLLIMPORT/DLLEXPORT is supported in the current compiler for COMMON blocks - it works.

subroutine dllsub
!DIR$ ATTRIBUTES DLLEXPORT :: dllsub
integer :: cvar
common /cmn/ cvar
!DIR$ ATTRIBUTES DLLEXPORT :: /cmn/
cvar = cvar + 1
return
end subroutine dllsub
program test
implicit none
integer :: cvar
common /cmn/ cvar
!DIR$ ATTRIBUTES DLLIMPORT :: /cmn/
interface
  subroutine dllsub
  !DIR$ ATTRIBUTES DLLIMPORT :: dllsub
  end subroutine dllsub
end interface
cvar = 123
call dllsub
print *, cvar
end program test
:\Projects>ifx /dll dllsub.f90
Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 2025.1.0 Build 20250317
Copyright (C) 1985-2025 Intel Corporation. All rights reserved.

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

-out:dllsub.dll
-dll
-implib:dllsub.lib
dllsub.obj
   Creating library dllsub.lib and object dllsub.exp
D:\Projects>ifx test.f90 dllsub.lib
Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 2025.1.0 Build 20250317
Copyright (C) 1985-2025 Intel Corporation. All rights reserved.

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

-out:test.exe
-subsystem:console
test.obj
dllsub.lib

D:\Projects>test.exe
         124
0 Kudos
Lucero
Beginner
4,808 Views

Steve,

Thank you for your reply!!!

Back in 2014, you also answered several of my questions, and I really appreciate your help once again!

I will try your solution right now. With the ifort compiler in 2014, I did not have to use the common statement, but if this is the only change, it should be easy to update what I had working back then. 

Aldo L.

0 Kudos
Lucero
Beginner
4,781 Views

Steve,

I apologize upfront because I am probably being very naive, but this is what I am trying to get to work, but no luck so far:

This is the code for my DLL - data_collection.F. The DLL was linked using the Command Line /section:.data,RWS

I am creating 2 processes that are supposed to share the data - MainProcess and SecondProcess. The SecondProcess is executed by calling CreateProcess from MainProcess.

If I create the DLL by using the Command Line /section:.data,RWS, MainProcess has issues successfully creating SecondProcess. If I create the DLL without Command Line /section:.data,RWS, then MainProcess can successfully create SecondProcess, but I obviously do not expect the shared data to work, and it does not work.

The data being shared is buf_full, which is supposed to be a boolean array of size 10. I am just using the first array element to test if the variable is being shared between the 2 processes.

This used to work back in 2014. 

Thanks,

Aldo L.

 

0 Kudos
Steve_Lionel
Honored Contributor III
4,761 Views

OK, you've now thrown a very important wrench into the works, with wanting to share data across processes. It's been a VERY long time since I played with this, but it can be done by tweaking a linker setting. There's a worked example in the "unsupported" samples package, which I have attached here.  It builds but the child process exits quickly - I have not yet figured out why. The linker setting change is noted in the comments.

0 Kudos
Lucero
Beginner
4,744 Views

Steve,

Thank you for the feedback and the example!

From what I understand, you have already retired, therefore, I really appreciate you taking the time to help me on this.

I have downloaded, compiled, linked and tested the sample code you uploaded. I can replicate the issue you mentioned. It appears to be the same problem I am having even when using CreateProcess instead of ShellExecute. For what is worth, I get a similar result (compared to my code) when I create the DLL without the /section:.data,RWS Command Line option. The child process comes up and runs longer, but obviously, there are no shared data between the 2 processes (from main.f90). It would appear as if the child process is unable to attach to the shared memory from the DLL and it crashes, but I do not have any solid proof for this. It is just based on the fact that the child process does run when not sharing data.

For now, I am trying to revive the old Visual Studio/Intel Fortran compiler from back in 2014 and see if I can make that work again. If I can, I will need to figure out how to be able to run 32-bit executables in a 64-bit Windows OS. 

One more question, are there any other alternatives to setup shared memory between processes besides creating the shared memory DLL? Looking back in my notes, the other alternative was using OpenFileMapping, MapViewOfFile, etc., but it is not as easy as the DLL. Not a problem, I will just have to do the research on how to make that work with all the variables we have in shared memory.

Thanks again,

Aldo L.

0 Kudos
Steve_Lionel
Honored Contributor III
4,682 Views

Unfortunately, I don't have time to research this further right now. My guess is that the data sharing does work, but something is killing off the child process early. You could take the earlier example I posted, tweak the linker option, and run the program in two separate processes (in the debugger, ideally). and explore the behavior.

MapViewOfFile is certainly an option as well.

0 Kudos
jimdempseyatthecove
Honored Contributor III
4,664 Views

Stranger than fiction.

 

I inserted:

  ! Run a copy of ourself. The copy will find that the mutex already exists, 
  ! and will fall into the alternate codepath
  call execute_command_line('dir '//self_filename(1:ret),wait=.false., cmdstat=statcmd, cmdmsg=msgcmd)
  print *,"execute_command_line", statcmd, msgcmd

  call execute_command_line(self_filename(1:ret),wait=.false., cmdstat=statcmd, cmdmsg=msgcmd)
  print *,"execute_command_line", statcmd, msgcmd

Where statcmd and msgcmd declared to receive the results of the call to execute_command_line

The first call shows the expected data:

Creating/opening mutex
Parent process, mutex ID = 372
Our file name is C:\Downloads\Intel\DLL_Shared_Data\DLL_Shared_Data\msvs\x64\Debug\DLL_Shared_Data.exe
 execute_command_line           0




 Volume in drive C has no label.
 Volume Serial Number is B461-32E0

 Directory of C:\Downloads\Intel\DLL_Shared_Data\DLL_Shared_Data\msvs\x64\Debug

06/19/2025  04:50 PM         1,819,648 DLL_Shared_Data.exe
               1 File(s)      1,819,648 bytes
               0 Dir(s)  1,485,334,630,400 bytes free

The second call shows

 execute_command_line           0

IOW the text "Creating/opening mutex" is not displayed.

The program hasn't started (or run to the point of the WRITE(*,...

 

Jim Dempsey

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
4,660 Views

I've since tried copying DLL_Shared_Data.exe to DLL_Shared_Data2.exe and trying to run that (for test of file in use).

Still did not run (output the initial write(*,...)

 

Jim Dempsey

0 Kudos
Lucero
Beginner
4,577 Views

Steve/Jim,

I was able to find my old programs (Visual Studio 2010) and Intel Fortran Compiler (2015.0.0.108) and the sample program DLL_Shared_Data.zip works fine when compiled with that version of the Intel Windows Fortran compiler. I compiled and tested using both, Win32 and x64, and it worked fine both times.

Even the projects I uploaded for testing (data_collection.F, MainProcess.F and SecondProcess.F) worked with this older compiler.

I know I am not the right person to be stating this, but it looks like this capability is no longer supported with the latest compiler, or I am missing flags when creating the DLL and applications with the latest compiler. For now, I am going to continue with the compiler from 2015, but somehow that does not seem like it should be the answer.

Thank you guys for the time you spent looking at this. 

Aldo L.

0 Kudos
jimdempseyatthecove
Honored Contributor III
4,521 Views

You could try this:

 

In your test program, isolate the code that launches the child process from the main code. Compile the isolated code using the old programs into a static library. Then compile the remainder of the application using the new ifx, and link in the old/launching library.

 

If this works, then this may be indicative of an issue with the new compiler generated code executing ShellExecute as well as execute_command_line.

 

For the symptoms of the original code posted, it is curious that a CMD window briefly appears (but first message does not).

.... (running further test) ...

**** forget the above ****

 

Ok, I think I have additional information to pass on.

 

I recall that debug build program will not run outside of the debugger. This is an issue with missing (Intel/MS) runtime library.

 

When I build in Release mode, and click Debug tab | Start Without Debugging

jimdempseyatthecove_0-1750521578329.png

The program runs as expected.

Jim Dempsey

 

0 Kudos
Steve_Lionel
Honored Contributor III
4,495 Views

@jimdempseyatthecove wrote:

 

I recall that debug build program will not run outside of the debugger. This is an issue with missing (Intel/MS) runtime library.


You can run these from a Fortran compiler command prompt window.

0 Kudos
jimdempseyatthecove
Honored Contributor III
4,517 Views

What you can do for debugging is replace "program DLL_Shared_Data" with "subroutine DLL_Shared_Data" (and end program).

Make DLL_Shared_Data a static library

Add two projects, one called master, the other child.

program master_test
  use Module_DLL_Shared_Data
  implicit non
  call DLL_Shared_Data()
end program master_test

...and another project...

program child_test
  use Module_DLL_Shared_Data
  implicit non
  call DLL_Shared_Data()
end program child_test

*** you may need to place these into separate Solutions as opposed to using different Set as Startup Project in a single solution. ***

 

Jim Dempsey

0 Kudos
jimdempseyatthecove
Honored Contributor III
4,475 Views

Good to know.

In the OP's case, he is running this from ShellExecute. So he would have to add the Fortran (ifort/oneAPI) environment variables global (at least those the locate the DLL's).

 

Jim Dempsey

0 Kudos
Steve_Lionel
Honored Contributor III
4,370 Views

I don't recommend doing that - just build a Release configuration, or change the Fortrtan Libraries project property to use the non-debug libraries.

0 Kudos
Lucero
Beginner
3,904 Views

Jim/Steve,

I will try some of the suggestions you provided, but I will try it on my simple programs that I uploaded. This more closely resembles what I am trying to do in my bigger project. For now, I am trying to catch up using the old compiler. Once I get to a good point, I will try what you guys suggested. I will probably start by using the DLL compiled with the older compiler and the applications with the newer compiler. I do not know if the linker will complain about DLL being built with a different/older compiler, but I will find out once I try it.

Thanks again for looking into this issue with me. You have no idea how much I really appreciate it. I felt abandoned there for a while. Not much resources out there for trying to figure this out.

Thanks!

Aldo L. 

0 Kudos
Reply