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

Using getenv without USE DFPORT

Emilio_M_
Beginner
2,211 Views

Hi,

In our company we use a big number of critical programs written in pure Fortran 77, and we are nowadays successfully performing a transition from CVF to IVF (XE 2013) because of the transition to x64.

99,9% of the times the source code remains compatible, and that is great news.

However, we are facing a problem that we did not have with CVF: some of our subroutines callgetenv, and until now we were able of using these system calls with no USE DFPORT sentence but now, with IVF, this statement is needed.

This sentence is not desired because our software is multiplatform, while DFPORT is --afaik-- Windows-specific. Basically, from the same source files we build:

  • Windows executables (Win32 / x64)
  • Windows dll (static) (Win32 / x64) -- same source as above, except that the "main" program is not included in the project <-- the problem appears with the dlls
  • Solaris SPARC executables

Our dll's are called by a GUI writen with MS VS2008 Express --it could be migrated to VS2010 Professional if that would help--.

In Windows, both exe and dll build with no comments. However, calling the dll from the GUI causes an error and the GUI informs of a write attempt into protected memory. On the other hand, adding a USE DFPORT sentence in the subroutine works, but as I commented this is undesired.

Can we somehow "initialize" the system calls so that the Fortran code also works in the dll, while keeping compatibility with Unix?

Another option would be to create two versions of a subroutine just containing the "getenv" call. In the subroutine version for the dll, an USE DFPORT statement would be added, while in the other version --for Windows and Unix executables-- no USE would be needed... but this solution would imply forking the code.

Best regards,

Emilio Murcia

P.D.: The development platform is: Visual Studio 2010 Professional + Intel Parallel Studio XE 2013 running on Windows XP SP3

0 Kudos
11 Replies
Steven_L_Intel1
Employee
2,212 Views
I'd like to see a small but complete test program that shows the problem. I know of no reason why USE DFPORT should be needed to call GETENV. It is possible that there is some other portability routine you are calling with an argument list that requires the USE to get the right signature - this happens for a very few routines where implementations differ on the routine interface. As an interesting experiment, you might try replacing the USE DFPORT with: USE DFPORT, ONLY: GETENV and see what the behavior is. If it is the same as without the ONLY, then it is indeed somehow GETENV. Otherwise, it's something else.
0 Kudos
Emilio_M_
Beginner
2,212 Views
Thanks for the quick reply. I just tried with the USE DFPORT, ONLY: GETENV, and the behavior is the same as without the ONLY. Now I am creating, as you propose, the same kind of project, but with simplified code, and see if the problem persist. Best regards, Emilio
0 Kudos
DavidWhite
Valued Contributor II
2,212 Views
What about the Instrinsic function GET_ENVIRONMENT_VARIABLE?
0 Kudos
Emilio_M_
Beginner
2,212 Views
This works for the windows version, and this also confirms that the problem is related to the getenv call. However, it is not compliant with Fortran 77 and the executable cannot be built on Solaris. I am still trying to create a small but functional program that reproduces the error. No success at the moment...
0 Kudos
IanH
Honored Contributor III
2,212 Views
Note that GETENV is similarly not "compliant" with Fortran 77, though it is a common extension. The Fortran 2003 standard intrinsic GET_ENVIRONMENT_VARIABLE suggested by David is supported by current Solaris Studio.
0 Kudos
Emilio_M_
Beginner
2,212 Views
Thank you Ian. On Solaris we are using Sun Fortran 95 8.4 SunOS_sparc 2009/06/03, invoked with "f95 -f77". However, we are not administrators of this machine, which is widely accesed in our company, and a change of the development platform although feasible, is not inmediate. On the other hand, we already found a way of making the software work, and this is creating two versions of the subroutine. What I am doing now is trying to isolate and reproduce the problem, we might get some interesting result from this. Best regards, Emilio Murcia
0 Kudos
Emilio_M_
Beginner
2,212 Views
*** Please rename test-vb.for to Test.vb *** Here there is a very simple case of the DLL call. Calling the READDLL from the VB program causes the error under certain conditions, related with the /iface: option. In this case of just one string in the argument list, the default calling convention and string length argument passing after all arguments work. In a more realistic case, we would need to rewrite our VB call. Changing the options in the "External Procedures" page did not provide a working solution. I guess the key would be to choose an appropriate option or property for the ATTRIBUTES compiler directive so that the code is minimally changed and still works with CVF and Solaris... but I lack the necessary expertise: Here is the Code_dll.for: [fortran] SUBROUTINE READDLL (TTL) * USE DFPORT, ONLY: GETENV !DEC$ ATTRIBUTES DLLEXPORT :: READDLL IMPLICIT NONE CHARACTER TTL*(*) CALL GETENV ('WINDIR',TTL) RETURN END [/fortran]
0 Kudos
Steven_L_Intel1
Employee
2,212 Views
OH! Now I see. The missing piece is that you compile your source with /iface:cvf or something that changes the default calling convention to STDCALL. This will cause the call to GETENV to corrupt the stack because it wants the default (C) calling convention. The solution here is to not use /iface:cvf but rather to change the ATTRIBUTES line to: !DEC$ ATTRIBUTES DLLEXPORT, CVF:: READDLL The reason the USE DFPORT fixes the problem is that its declaration of GETENV has ATTRIBUTES DEFAULT, changing the convention back to the default.
0 Kudos
jimdempseyatthecove
Honored Contributor III
2,212 Views
>>CALL GETENV ('WINDIR',TTL) Emilio, If the above call is indicative of the environment variable "get" calls, then I would have to assume for portability between Windows and Solaris, that the above call to getenv is in a conditional code section or seperate compile source for your Windows build as opposed to for Solaris build. Meaning you already are performing platform specific build (compile time) customizations, and adding the appropriate platform appropriate USE would be of no consequence. Note, the specified module could be a common wrapper of your own creation (USE YourGetEnvironmentVariable_module). Jim Dempsey
0 Kudos
Emilio_M_
Beginner
2,212 Views
Jim, Thanks for the comment, I agree. Anyway, in the example above the "WINDIR" was just a "dummy variable" that would work for any of you trying to build the dll. In our real case, we are getting the content of a variable called "BASES_DATOS" (in perfect Spanish), which is available for our users in both Windows and Solaris. Best regards, Emilio Murcia
jimdempseyatthecove wrote:

>>CALL GETENV ('WINDIR',TTL)

Emilio,

If the above call is indicative of the environment variable "get" calls, then I would have to assume for portability between Windows and Solaris, that the above call to getenv is in a conditional code section or seperate compile source for your Windows build as opposed to for Solaris build. Meaning you already are performing platform specific build (compile time) customizations, and adding the appropriate platform appropriate USE would be of no consequence. Note, the specified module could be a common wrapper of your own creation (USE YourGetEnvironmentVariable_module).

Jim Dempsey

0 Kudos
Emilio_M_
Beginner
2,212 Views
Steve, Thank you for your answer. I just tried your solution and it worked perfectly. Best regards, Emilio Murcia
Steve Lionel (Intel) wrote:

OH! Now I see. The missing piece is that you compile your source with /iface:cvf or something that changes the default calling convention to STDCALL. This will cause the call to GETENV to corrupt the stack because it wants the default (C) calling convention.

The solution here is to not use /iface:cvf but rather to change the ATTRIBUTES line to:

!DEC$ ATTRIBUTES DLLEXPORT, CVF:: READDLL

The reason the USE DFPORT fixes the problem is that its declaration of GETENV has ATTRIBUTES DEFAULT, changing the convention back to the default.

0 Kudos
Reply