Derived type in Fortran is for object programming.s In my experience , almost my derived type used in my games or software have over 10 variables in it.
In the first time, when i want save some objects in a file ,and changed some variables, i must repeatedly write all the variables with line format following .
In game development or GUI software, have a big loop in program. All the big derived type variable will have hard time when it repeatedly used 60 times in a second. Have some case when you want write big object derived type to a buffer file and read it again when need it .
That is why this user defined I/O derived type come on table ! It make my code easy to understand and do not need to remember all the format need to write my 10 variables derived type to somewhere . It is really a disaster when you need change , add something to derived type and detected it contains another 10 procedure need to check in about 10000 lines of code.
Now, for example, we have a derive type about a monster object like under code. For simple i ready cut 10s variables about graphic and action step in this TYPE define.
TYPE monster
CHARACTER(len = :) , ALLOCATABLE :: name
CHARACTER(len = :) , ALLOCATABLE :: filepath
TYPE(c_ptr) :: name_texture
INTEGER :: hitpoint
REAL :: speed
TYPE(sdl_rect) :: position
CONTAINS
PROCEDURE :: goleft
PROCEDURE :: gorigh
PROCEDURE :: goup
PROCEDURE :: godown
END TYPE
We want to defined User-Defined I/O generic procedures for this object . Add 4 lines defined 2 generic function read/write in middle of CONTAINS and END TYPE . This time we go with unformatted type User-Defined I/O .
PROCEDURE :: monster_write_unformat
GENERIC :: write(unformatted) => monster_write_unformat
PROCEDURE :: monster_read_unformat
GENERIC :: read(unformatted) => monster_read_unformat
And this 2 procedures will be defined like under code. Please remember that , this generic define procedure must have 4 dummy variables (this, unit, iostat, iomsg) with intent(inout) like this code for unformatted inout case. And because it is for unformatted case , all read write statement in it should be for unformatted data type either.
SUBROUTINE monnster_write_unformat(this,unit,IOSTAT,IOMSG)
implicit none
CLASS(monster),INTENT(IN) :: this
INTEGER,INTENT(IN) :: unit
INTEGER,INTENT(OUT) :: IOSTAT
CHARACTER(LEN=*),INTENT(INOUT):: IOMSG
WRITE(unit,iostat = IOSTAT, iomsg = IOMSG) LEN(this%name)
WRITE(unit,iostat = IOSTAT, iomsg = IOMSG) this%name
WRITE(unit,iostat = IOSTAT, iomsg = IOMSG) LEN(this%file_path)
WRITE(unit,iostat = IOSTAT, iomsg = IOMSG) this%file_path
CALL texture_write_unformatted(unit,this%name_pic)
WRITE(unit,iostat = IOSTAT, iomsg = IOMSG) this%hitpoint
END SUBROUTINE
SUBROUTINE monster_read_unformat(this,unit,IOSTAT,IOMSG)
implicit none
CLASS(monster),INTENT(INOUT) :: this
INTEGER,INTENT(IN) :: unit
INTEGER,INTENT(OUT) :: IOSTAT
CHARACTER(LEN=*),INTENT(INOUT):: IOMSG
INTEGER :: size_of_something
INTEGER :: i
READ(unit,iostat = IOSTAT, iomsg = IOMSG) size_of_something
if (ALLOCATED(this%name)) DEALLOCATE(this%name)
ALLOCATE(CHARACTER(len = size_of_something) :: this%name)
READ(unit,iostat = IOSTAT, iomsg = IOMSG) this%name
READ(unit,iostat = IOSTAT, iomsg = IOMSG) size_of_something
if (ALLOCATED(this%file_path)) DEALLOCATE(this%file_path)
ALLOCATE(CHARACTER(len = size_of_something) :: this%file_path)
READ(unit,iostat = IOSTAT, iomsg = IOMSG) this%file_path
CALL texture_read_unformatted(unit,this%name_pic)
READ(unit,iostat = IOSTAT, iomsg = IOMSG) this%hitpoint
END SUBROUTINE
And now we can write , read it on-the-fly like this under code . monster_array is array of this monster type , we want to write it to a file “monster1” for example , save all monsters data about their hitpoint and position in a map to buffer file ,easy like as a normal variable.
OPEN(newunit = memory_unit, file = "monster1", status = "replace",form="unformatted")
WRITE(memory_unit) size(monster_array
do i = 1, size(monster_array)
WRITE(memory_unit) monster_array(i)
end do
CLOSE(memory_unit)
Thanks for reading this.
Leave a Reply