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

DLL R/W Shared data DLL mixing Fortran and C

prandf
Beginner
2,408 Views

I have a legacy system (powerstation4) which comprises both Fortran and MS C/C++ source code. Both fortran and C access the same shared data DLL. The data is defined in a Common in Fortran and there is an equivalent mapping
of the variables in a C definition. Amazingly it works!

If in migrating to the Intel Fortran compiler, I implement the shared memory example (shared globals) in the documentation (under DLL),how do I build/link the Ctasks so that they also reference the same global data/DLL (R/W)
The mixed language examples do not cover this design.
Is it possible to build/link the C tasks with the same options (/section:,data,RWS)

regards

Peter

0 Kudos
18 Replies
Steven_L_Intel1
Employee
2,408 Views
It should work the same as it did before. The /section option is a linker option, so it is not language-specific. It's the DLL that defines the shared globals that needs to be built with this, not the executables that reference it.

See the provided Fortran sample DLL\DLL_Shared_Data for an example. As long as you're properly matching the COMMON name in C, it should work there too.
0 Kudos
jeremy_h
New Contributor I
2,408 Views
I'm not sure if our case was subtely different in some way, but we had to put a non-zero default initialization in each of the global commons that are shared across processes. Without this, the second process that tries to attach to the global memory always crashed. I fiddled endlessly with /section etc until I stumbled across this fix. Anyway, worth bearing in mind if this happens to you.
0 Kudos
psantos
Beginner
2,408 Views
Hello jeremy_h,

if you don't initialize the variables to a non-zero value, they will not be shared across processes. So, each process that load the dll will have its own copy of the variables. This is probably why your application was crashing.

Pedro
0 Kudos
prandf
Beginner
2,408 Views
Thanks everyone.
I am trying this out with a small set of programs built in .F90 , .F90+C, and C

regards

Peter
0 Kudos
prandf
Beginner
2,408 Views

hi
I have just u/g to parallel studio and I cannot get shared data across exe's to work
I have taken the sample dll program and created my own little test programs both fortran.
below is the module source, the program source 1 and 2, and the batch compile/link file
If I build and run it, the data is not global across prog1 and 2
Am I missing something?

module globaldata
implicit none

integer*4 :: aaa = 777

!DEC$ ATTRIBUTES DLLEXPORT :: aaa

integer*4 :: bbb = 888

!DEC$ ATTRIBUTES DLLEXPORT :: bbb

integer*4 :: ccc = 999

!DEC$ ATTRIBUTES DLLEXPORT :: ccc

end module globaldata

program F90pure1

use globaldata

implicit none

do while (aaa .ne. 0)

write (*, "('I am F90Pure1 and aaa = ',I6,' bbb = ',I6,' ccc = ',I6)")aaa,bbb,ccc

write (*, "('enter the new value of aaa')")

read (*,"(I6)") aaa

write (*, "('enter the new value of bbb')")

read (*,"(I6)") bbb

write (*, "('enter the new value of ccc')")

read (*,"(I6)") ccc

write (*, "('I am F90Pure1 now aaa = ',I6,' bbb = ',I6,' ccc = ',I6)")aaa,bbb,ccc

pause

enddo

end

program F90pure2

use globaldata

implicit none

do while (aaa .ne. 0)

write (*, "('I am F90Pure2 and aaa = ',I6,' bbb = ',I6,' ccc = ',I6)")aaa,bbb,ccc

write (*, "('enter the new value of aaa')")

read (*,"(I6)") aaa

write (*, "('enter the new value of bbb')")

read (*,"(I6)") bbb

write (*, "('enter the new value of ccc')")

read (*,"(I6)") ccc

write (*, "('I am F90Pure2 now aaa = ',I6,' bbb = ',I6,' ccc = ',I6)")aaa,bbb,ccc

pause

enddo

end

rem build globaldata

ifort /nologo /dll globaldata.f90 /link /section:.data,RWS

rem build F90Pure1

ifort /nologo /libs:dll F90Pure1.f90 globaldata.lib

rem build F90Pure2

ifort /nologo /libs:dll F90Pure2.f90 globaldata.lib

rem "all done"

0 Kudos
prandf
Beginner
2,408 Views
hi everyone

I have just built and run the DLL_Shared_data example from the sample programs.
It Works!

I have not implemented the mutex in F90Pure1 and 2, however I cannot see that making a difference.
I fail to see why my F90Pure1 and F90Pure2 progs have their own copies of the shared memory (dll) instead of sharing the same shared data (dll). If you run F90Pure1 and F90Pure2 and change the values of aaa bbb & ccc in one prog, the changes do not show in the other.

regards

Peter Taylor
0 Kudos
Steven_L_Intel1
Employee
2,408 Views
The mutex is not required to share the data - I added that to make the program run properly.

I haven't examined your post carefully, but will note that having the data to be shared in its own DLL that is referenced by the applications seems to be what is needed. Trying to use a DLL with a mixture of code and data hasn't been successful for me.
0 Kudos
IanH
Honored Contributor III
2,408 Views
Are you sure? Your example worked for me.

Note that you could have just run two instances of F90Pure1 at the same time - there's no need to have a separate executable for the other process.
0 Kudos
prandf
Beginner
2,408 Views
hi Ian and steve

they are in separate files

I am running windows XP Pro SP3

I have also tried running 2 copies og F90Pure1.exe and it still wont share the dll.

In case I am doing something wrong (brain fade is becoming a problem)
When I run this I simply run F90Pure1.exe and the dll looks after itself
I then run another F90Pure1.exe (or F90Pure2.exe) and I finish up with 2 command prompt windows and changing the values of aaa bbb ccc in one window does not change the other window when I change to it and press return to get a freash set of values.

peter
0 Kudos
IanH
Honored Contributor III
2,408 Views
Same OS level as you. Make sure you've not got another copy of globaldata.dll floating around that might be getting picked up first.



(Not that I'd rely on these "linker tricks" as a way of sharing data between processes - better to have the DLL export procedures that provide a way to access the shared data. Those procedures can then use win32 api's to explicitly put the data into shared memory and also deal with synchronisation.)
0 Kudos
prandf
Beginner
2,408 Views
hi Ian

I have replicated your results.
If I am correct,
1.started F90Pure1 and it had 777 etc
2. changed it to 111 etc.
3. started FPure1 in a second command prompt window and it had 111 etc.

I have replicated this.
However if you continue changing values in either window, the changes do not appear in the other window.

It is as if the second load gets the current state of the dll data and from then on they go their own ways.

I have changed the dll and program names by changing the source and .bat file
I copied it into a new directory
and rebuilt it so that there can be no old versions laying around.
I still get the same problem.

I also found some old versions of the previous dll and have renamed them

The problem persists

Also how did you cut/paste the windows?
Adding files to the forum does not seem to work.


peter



0 Kudos
IanH
Honored Contributor III
2,408 Views
Ahh... You need to add the volatile attribute to the module variables. Otherwise the compiler's optimiser doesn't realise that they can change without the program's knowledge, so it doesn't always refetch them from the shared memory.

I just inserted the (png) images using the "Add Files" thing ("in-line" or whatever it is caused, not as attachments).
0 Kudos
prandf
Beginner
2,408 Views
hi Ian
The VOLATILE attribute works perfectly.

Thanks for your help.

I am now proceeding to test if I can add a C program and share the data across them all.

regards

Peter
0 Kudos
onkelhotte
New Contributor II
2,408 Views
Hi prandf,

does yoursharing data inC and Fortran work?

Im trying the same. I have a Fortran QuickWin program that gets data from a Fortran DLL. A C# program uses the same DLL and alters data. The C# can see the changes it makes, but these changes arent recognized by the Fortran program.

I addedvolatile to the variables. Do I have to set some otherproject settings for this?

Markus

PS: Here is my code...

First the DLL:

[bash]      module sharedMemoryStructures

        type TimeStamp_
        sequence
            integer*4   year
            integer*4   month
            integer*4   day
            integer*4   hour
            integer*4   minute
            integer*4   second
            integer*4   milisecond
        end type TimeStamp_
        
      end module sharedMemoryStructures
!      
! *********************************************************************
      module sharedMemory

        use sharedMemoryStructures
        type(TimeStamp_), volatile :: now
        !DEC$ ATTRIBUTES DLLEXPORT :: now
        logical, volatile :: bNewData        
        !DEC$ ATTRIBUTES DLLEXPORT :: bNewData
        
      end module sharedMemory
!      
! *********************************************************************
      subroutine setTime(year,month,day,hour,minute,second,milisecond)
      !DEC$ ATTRIBUTES DLLEXPORT :: setTime
      !DEC$ ATTRIBUTES ALIAS:'setTime'::setTime
      !DEC$ ATTRIBUTES VALUE :: year,month,day,hour,minute,second,milisecond
      
      use sharedMemory
        
      implicit none

      integer*4 year,month,day,hour,minute,second,milisecond

      bNewData = .true.
      now%year = year
      now%month = month
      now%day = day
      now%hour = hour
      now%minute = minute
      now%second = second
      now%milisecond = milisecond

      end subroutine setTime
!      
! *********************************************************************
      integer function getSomeData()
      !DEC$ ATTRIBUTES DLLEXPORT :: getSomeData
      !DEC$ ATTRIBUTES ALIAS:'getSomeData'::getSomeData
      
      use sharedMemory
      
      getSomeData = now%year * now%month + now%day - now%hour + now%minute * now%second - now%milisecond
      
      return
      
      end function getSomeData[/bash]


Here is my C# program:

[bash]using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace Level_1_Data_Generator
{
    public partial class Form1 : Form
    {

        [DllImport("sharedmemory.dll")]
        private static extern void setTime(
            [MarshalAs(UnmanagedType.I4)]int year,
            [MarshalAs(UnmanagedType.I4)]int month,
            [MarshalAs(UnmanagedType.I4)]int day,
            [MarshalAs(UnmanagedType.I4)]int hour,
            [MarshalAs(UnmanagedType.I4)]int minute,
            [MarshalAs(UnmanagedType.I4)]int second,
            [MarshalAs(UnmanagedType.I4)]int milisecond);

        [DllImport("sharedmemory.dll")]
        private static extern int getSomeData();

        public Form1()
        {
            InitializeComponent();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            DateTime clock = DateTime.Now;

            label_Uhrzeit.Text = clock.ToLongTimeString();
            setTime(clock.Year, clock.Month, clock.Day, clock.Hour, clock.Minute, clock.Second, clock.Millisecond);
            label_bNewData.Text = getSomeData().ToString();
        }
    }
}
[/bash]


And last but not least the call of the Fortran program:

[bash]subroutine writeSharedData()

use sharedMemory
!
implicit none
!
if(bNewData) then
  bNewData = .false.
  write(6,'(i2,a,i2,a,i2)') now%hour,'.',now%minute,':',now%second
end if

end subroutine writeSharedData[/bash]
0 Kudos
onkelhotte
New Contributor II
2,408 Views

Ive found some posts and I think there are 2 problems: First, Windows7 (and Vista too) uses Shared Memory differently than WindowsXP. Furthermore, .NET programs run in seperate "application domains".

Im on it :-)

Markus

0 Kudos
onkelhotte
New Contributor II
2,408 Views
I tried both a C# DLL and a Fortran DLL.

Both DLLs will be accessed by both a C# and a Fortran program. But the Fortran program doesnt see the changes, the C# program makes and vice versa.

It seems, that there are still two copies of the DLLs im memory and each program uses its own copy of the DLL...

Markus
0 Kudos
Steven_L_Intel1
Employee
2,408 Views
Markus, you have to be careful to set the image section properties of the DLL to be read-write shared. My guess is that you have not done this. Look at the DLL_SHARED_DATA sample we provide to see how this is done.
0 Kudos
onkelhotte
New Contributor II
2,408 Views
I should have read the comments... Now it works, great!

This monday doesnt seem to be bad :-)

Markus
0 Kudos
Reply