- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Can anyone suggest how to go about this I have a dll project that is launched by an exe. I created this example project below where the dcalc array has values and passes the array to one dll. Then the next dll has the array defined in a module.
At the point where the Dll_2_mod is called the values in the array are wiped out.
The end goal in the real project is a number of dll's will be adding to the dcalc array and I did not want to change arguments to pass the array because the project already has a module layout.
Sample code:
program Module_Pass_Array
Real,dimension(10) :: Dcalc
Do I=1,10
Dcalc(i) = real(i+1)
Enddo
Call dll_1(dcalc)
end program Module_Pass_Array
subroutine Dll_1(dcalc)
!DEC$ ATTRIBUTES DLLEXPORT::Dll_1
Real, Dimension(10) :: Dcalc
Call Dll_2_mod()
end subroutine Dll_1
Module Module_dcalc
!DEC$ ATTRIBUTES DLLEXPORT::Module_Decalc
Real, dimension(10) :: Dcalc
End Module
subroutine Dll_2_mod
Use Module_dcalc
!DEC$ ATTRIBUTES DLLEXPORT::Dll_2_mod
Write(*,'(A, F7.2)') 'Dcalc', dcalc(2)
end subroutine Dll_2_mod
Thanks in advance for any help. Ken
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
As supplied, this doesn't have a lot to do with DLL's. The Dcalc variable in Module_dcalc is unrelated to the Dcalc variable in the main program and the Dcalc variable in the Dll_1 subroutine (those two are linked by argument association). The Dcalc variable in Module_dcalc never has a value set and so is undefined - there is nothing to "wipe out".
It might be worth providing more explanation about what it is you are trying to achieve.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for the comment. I was trying to make the variable associated by argument the same as in the module. This was for the reason I had an existing exe that lauched the project using the argument array. Then The dll's using a module I hope can maybe point to the initial memory. Perhaps using some sort of pointer allows the array in the module the same values as the exe array?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You need some way to explicitly associate Dcalc within the module Module_dcalc with the Dcalc that is in the main program. There are a couple of options, what's best depends on your specific situation. My view is that if you need to pass information to and from a procedure, then you explicitly pass that information to and from the procedure using arguments, but if you wanted to make the module variable a pointer, you could do something like this:
program Module_Pass_Array
Implicit None
Integer :: i
Real,dimension(10) :: Dcalc
Interface
Subroutine Dll_1(dcalc)
Implicit None
Real, Dimension(10), Target :: Dcalc
End Subroutine Dll_1
End Interface
Do i=1,10
Dcalc(i) = real(i+1)
Enddo
Call dll_1(dcalc)
end program Module_Pass_Array
subroutine Dll_1(dcalc)
Use Module_dcalc, Only: AssociateDcalc
!DEC$ ATTRIBUTES DLLEXPORT::Dll_1
Real, Dimension(10), Target :: Dcalc
Call AssociateDcalc(Dcalc)
Call Dll_2_mod()
end subroutine Dll_1
!-------------------------------------------------------------------------------
Module Module_dcalc
Implicit None
Real, Pointer :: Dcalc(:)
Contains
Subroutine AssociateDcalc(remote)
!DEC$ ATTRIBUTES DLLEXPORT :: AssociateDcalc
Real, Target :: remote(:)
Dcalc => remote
End Subroutine
End Module
subroutine Dll_2_mod
Use Module_dcalc
Implicit None
!DEC$ ATTRIBUTES DLLEXPORT::Dll_2_mod
Write(*,'(A, F7.2)') 'Dcalc', dcalc(2)
end subroutine Dll_2_mod
Note that with the above code, the association between the Dcalc that is the module variable and the dcalc that is the argument to the Dll_1 procedure only lasts as long as the invocation of the Dll_1 procedure. If you want the association to last longer than that, then you need to give the Dcalc in the main program the target attribute too. The use of the target attribute on procedure arguments necessitates an explicit interface, hence the interface block. This would be unnecessary if your procedures were declared within modules.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
IanH, I was able to get that to work with one exception.
I had to add an export like below; !DEC$ ATTRIBUTES DLLEXPORT :: Dcalc in the module.
Otherwise I would get a link error.
Module Module_dcalc
Implicit None
Real, Pointer :: Dcalc(:)
!DEC$ ATTRIBUTES DLLEXPORT :: Dcalc
Contains
Subroutine AssociateDcalc(remote)
!DEC$ ATTRIBUTES DLLEXPORT :: AssociateDcalc
Real, Target :: remote(:)
Dcalc => remote
End Subroutine
End Module
Zip attached if anyone needs as a reference.
Thanks for your help IanH.
Ken
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page