Using getenv without USE DFPORT

Using getenv without USE DFPORT

Imagen de Emilio M.

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

publicaciones de 12 / 0 nuevos
Último envío
Para obtener más información sobre las optimizaciones del compilador, consulte el aviso sobre la optimización.
Imagen de Steve Lionel (Intel)

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.

Steve
Imagen de Emilio M.

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

Imagen de David White

What about the Instrinsic function GET_ENVIRONMENT_VARIABLE?

Imagen de Emilio M.

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...

Imagen de IanH

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.

Imagen de Emilio M.

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

Imagen de Emilio M.

*** 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:


	SUBROUTINE READDLL (TTL)
*	USE DFPORT, ONLY: GETENV
	!DEC$ ATTRIBUTES DLLEXPORT :: READDLL
	IMPLICIT NONE

	CHARACTER TTL*(*)
	CALL GETENV ('WINDIR',TTL)
	RETURN
	END

Adjuntos: 

AdjuntoTamaño
Descargar test.for133 bytes
Descargar code-dll.for177 bytes
Descargar test-vb.for502 bytes
Imagen de Steve Lionel (Intel)

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.

Steve
Imagen de jimdempseyatthecove

>>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

www.quickthreadprogramming.com
Imagen de Emilio M.

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

Cita:

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

Imagen de Emilio M.

Steve,

Thank you for your answer.
I just tried your solution and it worked perfectly.

Best regards,
Emilio Murcia

Cita:

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.

Inicie sesión para dejar un comentario.