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

Unlimited polymorphic I/O

Blane_J_
New Contributor I
440 Views

Since the standard allows us to use User-Defined Derived-Type I/O (The Formatted/Unformatted Read/Write), Is there any good ideas that It can be accomplished for unlimited polymorphic entities? unlimited polymorphic entities can be any type, intrinsic and derived. So should all the possibilities be evaluated in a SELECT TYPE structure or is there any shortcuts for doing that ? The former indeed could be a massive amount of work if there's a lot of user-defined derived types waits. Appriciate any suggestion.

0 Kudos
6 Replies
Steve_Lionel
Honored Contributor III
440 Views

All I can think of is to have SELECT TYPE cases for possible intrinsic types (and kinds), and then for derived types use TYPE DEFAULT and reference a type-bound procedure for the type that does whatever is needed for the output. I agree it is a lot of work and maybe there's a different approach to structuring your application that would make this unnecessary.

0 Kudos
Blane_J_
New Contributor I
440 Views

Thanks, Steve. It seems this maybe the only way. I'll rethink about the structure issues.

0 Kudos
Paul_Curtis
Valued Contributor I
440 Views

File i/0 with derived types can be very straightforward if you use the WinAPI functions directly, since they provide the granular control which is needed (and is missing from Fortran); on Windows, this is what the Fortran functions are converted to anyway by the compiler. So file i/o for an array of a UDT with arbitrary content becomes:

CALL rw_file ('W', ihandl, array_size*SIZEOF(yourUDT), LOC(yourUDT), 0)

where the file has previously been opened and is denoted by handle ihandl.

RECURSIVE SUBROUTINE rw_file (rwmode, ihandl, nbytes, loc_pointer, offset)
	IMPLICIT NONE
	SAVE
	CHARACTER(LEN=1), INTENT(IN)	:: rwmode
	INTEGER(HANDLE), INTENT(IN)     :: ihandl
	INTEGER, INTENT(IN)				:: nbytes, loc_pointer
	INTEGER, INTENT(IN), OPTIONAL	:: offset
	INTEGER                         :: rval
	INTEGER     					:: nact

	! position pointer if offset is provided
	IF (PRESENT(offset)) rval = SetFilePointer (ihandl, offset, NULL, FILE_BEGIN)

	IF (rwmode == 'R') THEN
		IF (ReadFile (ihandl,			&  ! file handle
			     	  loc_pointer,		&  ! address of data
					  nbytes,			&  ! byte count to read
					  LOC(nact),		&  ! actual bytes read
					  NULL_OVERLAPPED) == 0) THEN
		  	banner(1) = 'Error reading file'
			CALL API_error (851, 1)
		END IF
	
	ELSE
		IF (WriteFile (ihandl,			&  ! file handle
					   loc_pointer,		&  ! address of data
					   nbytes,			&  ! byte count to write
					   LOC(nact),		&  ! actual bytes written
					   NULL_OVERLAPPED) == 0) THEN
		  	banner(1) = 'Error writing file'
			CALL API_error (852, 1)
		END IF
	END IF
			
END SUBROUTINE rw_file

 

0 Kudos
IanH
Honored Contributor II
440 Views

Paul Curtis wrote:

File i/0 with derived types can be very straightforward if you use the WinAPI functions directly, since they provide the granular control which is needed (and is missing from Fortran); on Windows, this is what the Fortran functions are converted to anyway by the compiler. So file i/o for an array of a UDT with arbitrary content becomes:

CALL rw_file ('W', ihandl, array_size*SIZEOF(yourUDT), LOC(yourUDT), 0)

This approach excludes derived types with type parameters, ultimate pointer components, or ultimate allocatable components - which is an approximate superset of the types that require user defined io procedures in the first place (otherwise Fortran unformatted io pretty much already does this).

0 Kudos
Paul_Curtis
Valued Contributor I
440 Views

@Ianh--  why yes, my approach "excludes derived types with type parameters, ultimate pointer components, or ultimate allocatable components..."

I must be a newbie, only written maybe a million lines of Fortran over the last 40+ years, but I cannot imagine a context for which any of that stuff would be appropriate, and which would clearly render a program completely unfixable when it goes off the rails.  Only my minority report; good luck to you.

0 Kudos
Blane_J_
New Contributor I
440 Views

The API approach solves the problem. I'm here more to seek a Fortran way to do that, thanks for your suggestion, Paul and lanH.

0 Kudos
Reply