- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Today I had some trouble calling qsort with derived types or characters.
Because qsort is a c-function the different calling conventions have to be considerd.
Here is my solution. If someone knows a better one please let me know.
Because qsort is a c-function the different calling conventions have to be considerd.
Here is my solution. If someone knows a better one please let me know.
[bash] MODULE TEST__MOD
TYPE T_DAT
CHARACTER(16) NAME
CHARACTER(24) DESC
INTEGER IHND
ENDTYPE T_DAT
ENDMODULE TEST__MOD
PROGRAM TESTPRJ_FORTRAN
USE TEST__MOD
USE IFPORT
INTERFACE
SUBROUTINE QSORT_DAT( ARRAY, LEN, ISIZE, COMPDAT )
USE TEST__MOD
!DEC$ ATTRIBUTES DEFAULT,DECORATE,ALIAS:'QSORT' :: QSORT_DAT
INTEGER LEN, ISIZE
! TYPE (T_DAT),ALLOCATABLE:: ARRAY(:)fails because FORTRAN will pass an array descriptor to C
TYPE (T_DAT) ARRAY(*)
INTEGER(2), EXTERNAL :: COMPDAT
END SUBROUTINE
END INTERFACE
INTEGER LEN
INTEGER ISIZE
INTEGER(2),EXTERNAL:: COMPDAT
TYPE (T_DAT),ALLOCATABLE:: DAT(:)
!
ALLOCATE(DAT(26))
DO I=1,26
DAT(I)%NAME=CHAR(ICHAR('Z')-I+1)
DAT(I)%DESC="Descrpition"
DAT(I)%IHND=0
ENDDO
ISIZE = SIZEOF(DAT(1)) !get size of each array element
LEN=SIZE(DAT) !get number ov array elements
CALL QSORT_DAT(DAT, LEN, ISIZE, COMPDAT)
DO I=1,LEN
WRITE(*,*) DAT(I)%NAME
ENDDO
READ(*,*) LEN
END PROGRAM TESTPRJ_FORTRAN
INTEGER(2) FUNCTION COMPDAT(DAT1,DAT2)
! Following DECs are required because this function is called from C
! If DAT1 and DAT2 are characters this is also required, but be careful: DAT1
! and DAT2 must be declared with fixed length because the length of DAT1 and DAT2
! will not be passed!
!DEC$ ATTRIBUTES C,ALIAS:'_COMPDAT'::COMPDAT
!DEC$ ATTRIBUTES REFERENCE::DAT1
!DEC$ ATTRIBUTES REFERENCE::DAT2
USE TEST__MOD
TYPE(T_DAT) DAT1
TYPE(T_DAT) DAT2
IF(DAT1%NAME.LT.DAT2%NAME) THEN
COMPDAT=-1
ELSEIF(DAT1%NAME.EQ.DAT2%NAME) THEN
COMPDAT=0
ELSE
COMPDAT=1
ENDIF
ENDFUNCTION COMPDAT
[/bash]
Link Copied
2 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The most portable way of mingling C and Fortran would be to use the F2003 C-interoperability features.
You have, however, chosen the older way, which requires you to know the calling conventions of C.
A C routine such as qsort from libc has to be called using C-conventions; in particular, scalars are passed by value.
These changes will make your code run on Linux. There are many other ways, and this is just one.
1. Change INTEGER(2) to INTEGER throughout.
2. Use correct aliases for your platform. For Linux:
!DEC$ ATTRIBUTES DEFAULT,DECORATE,ALIAS:'qsort' :: QSORT_DAT
and
!DEC$ ATTRIBUTES C,ALIAS:'compdat_'::COMPDAT
3. Pass scalars by value:
CALL QSORT_DAT(DAT, %val(LEN), %val(ISIZE), COMPDAT)
You have, however, chosen the older way, which requires you to know the calling conventions of C.
A C routine such as qsort from libc has to be called using C-conventions; in particular, scalars are passed by value.
These changes will make your code run on Linux. There are many other ways, and this is just one.
1. Change INTEGER(2) to INTEGER throughout.
2. Use correct aliases for your platform. For Linux:
!DEC$ ATTRIBUTES DEFAULT,DECORATE,ALIAS:'qsort' :: QSORT_DAT
and
!DEC$ ATTRIBUTES C,ALIAS:'compdat_'::COMPDAT
3. Pass scalars by value:
CALL QSORT_DAT(DAT, %val(LEN), %val(ISIZE), COMPDAT)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
There is also a QSORT provided in the IFPORT library.
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page