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

parameter in dlls

Blane_J_
New Contributor I
2,178 Views

Hi to all,

     When I linking my program with a compiled dll which is also written in Fortran and contains lots of modules with some integer and real parameters defind within, I recognized that a write statement in the main program could also output those parameters, I know that one can't use directive "dllexport" to deal with parameters in the dll, and what happened here shows an alternative way to "dllexport an parameter within a dll", is that correct ? Appriciate any suggestions.

0 Kudos
12 Replies
mecej4
Honored Contributor III
2,178 Views

You are using the word 'parameter' in an ambiguous way. If the entities that you write of are, indeed, parameters in the Fortran sense, i.e., named constants of various types, declared with statements such as 'REAL, PARAMETER :: PI = 3.1415926', you can simply declare all of them in modules, and USE the one module in both the DLL and the EXE. You can use these parameters in WRITE statements, expressions, etc., but you cannot attempt to change their value at run time. In this case, no DLLEXPORT/DLLIMPORT directives are needed.

Please clarify.

0 Kudos
Blane_J_
New Contributor I
2,178 Views

Thanks, mecej4. Perhaps I didn't make myself clear. I understand the way you suggest, but what I want to implement is to store the named constants (defined with PARAMETER attribute) IN THE DLL rather than writing another module to predefine them. So is it the case that I just define the named constants in the dll and do nothing else, just leavel it there, then I would use them in the main program by import the dll? Is it like this?

0 Kudos
mecej4
Honored Contributor III
2,178 Views

I don't quite understand why there is a problem. Let us suppose that all the named constants ("parameters") are placed in a module called CONSTS. In the DLL and the EXE, you place USE CONSTS statements in any subprograms that reference the constants. After the DLL and EXE are built, each will have a read-only section called .rdata containing the constants and, because the same module was used to build both, the .rdata sections, although separate rather than shared, will have identical contents.

In the scheme that I just outlined, there is no need for importing and exporting data. Of course, if you change the CONSTS module, you will have to rebuild both the DLL and the EXE.

If this state of affairs does not fit your needs, please explain why.

0 Kudos
Blane_J_
New Contributor I
2,178 Views

mecej4 wrote:

I don't quite understand why there is a problem. Let us suppose that all the named constants ("parameters") are placed in a module called CONSTS. In the DLL and the EXE, you place USE CONSTS statements in any subprograms that reference the constants. After the DLL and EXE are built, each will have a read-only section called .rdata containing the constants and, because the same module was used to build both, the .rdata sections, although separate rather than shared, will have identical contents.

In the scheme that I just outlined, there is no need for importing and exporting data. Of course, if you change the CONSTS module, you will have to rebuild both the DLL and the EXE.

If this state of affairs does not fit your needs, please explain why.

OK, I think it is the common way to use constants in a DLL or EXE and it's simple to understand. Let me explain my opinion even more straight. Assume the situation, I create a DLL project  called "TestLibrary" (be aware of the project type), and in it I write a module named "Constants" with only one statement "INTEGER, PARAMETER :: PI=3.1415926". I compile the project and there comes out "TestLibrary.dll". Here comes the question that how could I manage to use the named constant "PI" in the main program through "TestLibrary.dll" ?

0 Kudos
mecej4
Honored Contributor III
2,178 Views

If, when you build the DLL, there are no other entities/subprograms that use the parameter PI, the DLL will not contain Pi in an initialized data segment; that is, unused/unneeded parameters do not survive the compile/link stage. The DLL built as you described in #5, it seems to me, is of no use since it has nothing, either code or data, to export.

0 Kudos
Arjen_Markus
Honored Contributor II
2,178 Views

If I understand it correctly, parameters (named constants) are a compile-time concept. Whether they are stored in a DLL or not makes no difference (in fact, as posted in a recent thread on comp.lang.fortran, parameters may not be present at all in the compiled code, that is, they are not entities that you can point to because they are not present as actual data).

To be able to use a parameter in the code, you must tell the _compiler_ what its definition is, and since your parameters are defined in a module, you will have to give the compiler access to the module, via a use statement. The _linker_ which would get things from the DLL does not come into play.

0 Kudos
JVanB
Valued Contributor II
2,178 Views

arjenmarkus has the key observation here. In Fortran, a named constant can be used at compile time do ultimately detemine a KIND type parameter, so it must be made available when the compiler is making decisions about how much memory to assign to each variable, which specific forms of generic procedures to invoke, and which machine instructions to encode. Thus a Fortran PARAMETER simply can't be made available from a DLL because the DLL may not even have existed at compile time.

Given that insight, we can rephrase the question as to whether we can put values in a .rdata section that Fortran can read. I can't see any way for a Fortran compiler to directly do this as the only way would be via a PARAMETER statement and as stated above, Fortran isn't going to do what we want in that instance. It can be done in C however, so we could put the initialization in a C file and then it works as intended.

// gcc -c const.c
const float PI = 3.1415926;
! ifort /nologo /libs:dll /threads /c TestLibrary.f90
! link /nologo /subsystem:windows /dll /out:TestLibrary.dll TestLibrary.obj const.o
module M
   use ISO_C_BINDING
   implicit none
   private
   REAL(C_FLOAT), PUBLIC, BIND(C,NAME='PI') :: PI
!DEC$ ATTRIBUTES DLLEXPORT :: PI
end module M
! ifort /nologo TestProg.f90 TestLibrary.lib
module M1
   use ISO_C_BINDING
   implicit none
   private
   REAL(C_FLOAT), PUBLIC, BIND(C,NAME='PI') :: PI
!DEC$ ATTRIBUTES DLLIMPORT :: PI
end module M1

program P
   use M1
   implicit none
   write(*,*) PI
   call S(PI)
   write(*,*) PI
end program P

subroutine S(x)
   use ISO_C_BINDING
   implicit none
   REAL(C_FLOAT) x
   x = 0.69314718
end subroutine S

Output:

   3.141593
forrtl: severe (157): Program Exception - access violation
Image              PC                Routine            Line        Source

TestProg.exe       00007FF679B91092  Unknown               Unknown  Unknown
TestProg.exe       00007FF679BE336E  Unknown               Unknown  Unknown
TestProg.exe       00007FF679BCD4AB  Unknown               Unknown  Unknown
KERNEL32.DLL       00007FFB81B116AD  Unknown               Unknown  Unknown
ntdll.dll          00007FFB824B4409  Unknown               Unknown  Unknown

So in this case PI seems to have been initialized as desired and then stored in .rdata.

If initialization at runtime is allowed, there are lots of ways to put the values in read-only sections of memory and then access them via Fortran pointers.

 

0 Kudos
Blane_J_
New Contributor I
2,178 Views

arjenmarkus wrote:

If I understand it correctly, parameters (named constants) are a compile-time concept. Whether they are stored in a DLL or not makes no difference (in fact, as posted in a recent thread on comp.lang.fortran, parameters may not be present at all in the compiled code, that is, they are not entities that you can point to because they are not present as actual data).

To be able to use a parameter in the code, you must tell the _compiler_ what its definition is, and since your parameters are defined in a module, you will have to give the compiler access to the module, via a use statement. The _linker_ which would get things from the DLL does not come into play.

Thanks to all the replies above and really appriciate your demonstration, Repeat Offender. I finally get a little understanding about the issue. SO, it is to say that the PARAMETER attribute is only work in compiled time. I used to think that fortran can do things like this at the beginning: entities within the DLL can dynamically load into the memory when they are in use and out of the memory when they are done, like once I need the value of the PARAMETER within the DLL, I load it from the DLL, get the value, and then release it. NOW is the situation that fortran can't do as what I wanted: you want to use the PARAMETER, all right, you have to COMPILE IT INTO THE EXE or DLL and pemenently stored there rather than dynamically load it from elsewhere at runtime. Is my opinion correct this time?

0 Kudos
mecej4
Honored Contributor III
2,178 Views

Let me try to rephrase: Parameters (in the narrow Fortran sense, not as subroutine arguments!), as Arjen clearly articulated, exist only at compile time. If there are no variables present that were initialized by setting them equal to parameters, there is probably nothing in the OBJ file from which you can detect even that the parameter existed, let alone its value. Therefore, in these circumstances you cannot "compile it into the DLL or EXE" and, consequently, there is no question of sharing parameters between DLLs and an EXE -- you cannot share something which neither exists nor is known to have existed in the source code.

That said, let us recognize that, to help the debugger, the compiler can put information in the PDB file about parameters if the /debug-parameters compiler option is used. That information, however, is not available inside a standard Fortran program.

0 Kudos
Blane_J_
New Contributor I
2,178 Views

mecej4 wrote:

Let me try to rephrase: Parameters (in the narrow Fortran sense, not as subroutine arguments!), as Arjen clearly articulated, exist only at compile time. If there are no variables present that were initialized by setting them equal to parameters, there is probably nothing in the OBJ file from which you can detect even that the parameter existed, let alone its value. Therefore, in these circumstances you cannot "compile it into the DLL or EXE" and, consequently, there is no question of sharing parameters between DLLs and an EXE -- you cannot share something which neither exists nor is known to have existed in the source code.

That said, let us recognize that, to help the debugger, the compiler can put information in the PDB file about parameters if the /debug-parameters compiler option is used. That information, however, is not available inside a standard Fortran program.

So, the only problem is that whether you have used the PARAMETER or not in source code. You used it in the DLL or EXE, it existed through assignment (with '=' operator) or output (with 'write' keyword) statements; you didn't use it at all, it would nerver survive the compilation even you predefined it, that is the defination would be meaningless. Am I right?

0 Kudos
mecej4
Honored Contributor III
2,178 Views

You are mostly right. However, an optimizing compiler can transfer the code in many ways. Just as it can eliminate dead code, it can also eliminate unused variables. That is why we have to code in such a way that tells the compiler: 'we need this variable in some other place that you do not know about yet, so keep it as it is'. That is one of the things that putting variables into modules accomplishes.

0 Kudos
Blane_J_
New Contributor I
2,178 Views

mecej4 wrote:

You are mostly right. However, an optimizing compiler can transfer the code in many ways. Just as it can eliminate dead code, it can also eliminate unused variables. That is why we have to code in such a way that tells the compiler: 'we need this variable in some other place that you do not know about yet, so keep it as it is'. That is one of the things that putting variables into modules accomplishes.

So, that is the difference between PARAMTEER and variable in fortran module. The former must be referenced in order to survive and the latter surives anyway. Thank you so much for helping me with my confusion, mecej4.

0 Kudos
Reply