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

Access a C library interface from F90 using iso_c_binding

nhodge
Beginner
809 Views

So, I am trying to access a C function from F90, with the following code:

SUBROUTINE sub1()

    USE,INTRINSIC :: iso_c_binding

    ! interface to c library
    INTERFACE
        ! library function prototype
        ! DBfile *DBCreate (char *pathname, int mode, int target, char *fileinfo, int filetype)
        TYPE(C_PTR) FUNCTION DBCreate_f(pathname,mode,fileformat,fileinfo,filetype) BIND(C,NAME="DBCreate")
            IMPORT :: C_PTR,C_CHAR,C_INT
            IMPLICIT NONE
            CHARACTER(KIND=C_CHAR) :: pathname(*)
            INTEGER(KIND=C_INT),VALUE :: mode
            INTEGER(KIND=C_INT),VALUE :: fileformat
            CHARACTER(KIND=C_CHAR) :: fileinfo(*)
            INTEGER(KIND=C_INT),VALUE :: filetype
        END FUNCTION DBCreate_f

        ! library function prototype
        ! int DBClose (DBfile *dbfile)
        INTEGER(KIND=C_INT) FUNCTION DBClose_f(dbfile) BIND(C,NAME="DBClose")
            IMPORT :: C_INT,C_PTR
            IMPLICIT NONE
            TYPE(C_PTR) :: dbfile
        END FUNCTION DBClose_f
    END INTERFACE


    CHARACTER(LEN=...) :: string11
    CHARACTER(LEN=...,KIND=C_CHAR) :: string1
    INTEGER(C_INT) :: val1,val2,val3
    CHARACTER(LEN=...) :: string21
    CHARACTER(LEN=...,KIND=C_CHAR) :: string2

    TYPE(C_PTR) :: retval1_ptr
    INTEGER(C_INT) :: retval2


    retval1_ptr=C_NULL_PTR


    !======================================================================
    ! call to first interface function
    !======================================================================
    WRITE(string11,FMT='(a)') "blahblahblah"
    WRITE(UNIT=string1,FMT='(a,a)') TRIM(string11),C_NULL_CHAR
    val1=1
    val2=2
    WRITE(string21,FMT='(a)') "BLAHBLAHBLAH"
    WRITE(UNIT=string2,FMT='(a,a)') TRIM(string21),C_NULL_CHAR
    val3=3
    retval1_ptr=DBCreate_f(string1,val1,val2,string2,val3)      ! this is line 372 in the original file
    ! DBCreate returns a DBfile pointer on success and NULL on failure. 
    IF (.NOT.C_ASSOCIATED(retval1_ptr)) CALL terminate(...)

    !======================================================================
    ! call to second interface function
    !======================================================================
    retval2=DBClose_f(retval1_ptr)
    ! DBClose returns zero on success and -1 on failure.
    IF (retval2==-1) CALL terminate(...)


END SUBROUTINE sub1

 

However, in the link stage, I get the error:

module1.o: In function `sub1':
module1.f90:372: undefined reference to `DBCreate'

Several notes:

  • It is my understanding that C_PTR can be used to return scalar pointers of _any_ type, and since I don't need to access any of the data pointed at by this pointer directly, I thought the above would be ok.
  • There are two calls to the library, and only one of them is having a problem.  However, running nm on the .a file verified that the function DBCreate is actually in the file.
  • I tried this with various versions of ifort, from early 12.xxx to 14.xxx, and they all exhibit the same problem.
     

Any thoughts?  Thanks.

 

0 Kudos
2 Replies
mecej4
Honored Contributor III
809 Views

You did not show the link command line, so we do not know if you specified that the library containing the function DBCreate should be searched while building the application.

It is not the type of the returned value from DBCreate that is an issue, but the address of the routine itself, which the linker needs to resolve in order to produce a valid a.out.

0 Kudos
nhodge
Beginner
809 Views

So, it turns out that the developers of this library do some strange munging of the name of that single function . . .

Thanks!

0 Kudos
Reply