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

Further problem with using 'interface' for accessing C from Fortran

andy_in_oxford
New Contributor I
640 Views

 

I have a further problem with accessing C from Fortran. This follows on from my early problem that was solved. The program compiles but crashes on running. I am building and running the following in Windows using the Intel Fortran compiler. My program compiles eccodes.f90 and grib_f90.f90 correctly and grib_copy_msg.f90 compiles correctly. But when I try to run it an error is thrown:

 

I have the following: 

 

In the top part of the program grib_copy_msg.f90 I have:

 

program copy

 

  use eccodes

  implicit none

  integer  :: infile, igrib_in, status

 

  print *,'I am here 1'

  call codes_grib_new_from_file(infile, igrib_in, status)

  print *,'I am here 2'

 

.....

 

 

In eccodes.f90 there is:

 

 

subroutine codes_grib_new_from_file ( ifile, gribid , status)

    integer(kind=kindOfInt),intent(in)              :: ifile

    integer(kind=kindOfInt),intent(out)             :: gribid

    integer(kind=kindOfInt),optional,intent(out)    :: status

    !DIR$ ATTRIBUTES DLLEXPORT :: codes_grib_new_from_file

    print *,'I am here 1.1'

    call grib_new_from_file ( ifile, gribid , status)

end subroutine codes_grib_new_from_file 

 

 

codes_grib_new_from_file  is in a file called grib_f90.f90: 

 

 

 

  subroutine grib_new_from_file ( ifile, gribid , status)

      integer(kind=kindOfInt),intent(in)              :: ifile

      integer(kind=kindOfInt),intent(out)             :: gribid

      integer(kind=kindOfInt),optional,intent(out)    :: status

      integer(kind=kindOfInt)                         :: iret

 

      interface

        integer(c_int) function grib_f_new_from_file(ifile,&

                       gribid) bind(C, name="grib_f_new_from_file_")

          use iso_c_binding, only: c_int

          integer(c_int), intent(in) :: ifile

          integer(c_int), intent(out) :: gribid

        end function grib_f_new_from_file

      end interface

 

      print *,'I am here 1.2'

      iret=grib_f_new_from_file( ifile, gribid )

      print *,'I am here 1.3'

 

      if (present(status)) then

         status = iret

      else

         call grib_check(iret,'grib_new_from_file','')

      endif

  end subroutine grib_new_from_file

 

 

grib_f_new_from_file is in a C file called grib_fortran.c:

 

int grib_f_new_from_file_(int* fid, int* gid){

    int err = 0;

    FILE* f = get_file(*fid);

 

    grib_handle *h = NULL;

 

    if(f){

        h = grib_handle_new_from_file(0,f,&err);

        if(h){

            push_handle(h,gid);

            return GRIB_SUCCESS;

        } else {

            *gid=-1;

            return GRIB_END_OF_FILE;

        }

    }

 

    *gid=-1;

    return GRIB_INVALID_FILE;

}

int grib_f_new_from_file__(int* fid, int* gid){

    return grib_f_new_from_file_( fid, gid);

}

int grib_f_new_from_file(int* fid, int* gid){

    return grib_f_new_from_file_( fid, gid);

}

 

When I try to run it, I get the output:

 

I am here 1

I am here 1.1

I am here 1.2

 

The program then crashes.

 

What mistake have I made with the interface?  I read that I don't need to add an interface in if I use capitals for  GRIB_F_NEW_FROM_FILE, could someone provide an example in this context please?

0 Kudos
1 Solution
andy_in_oxford
New Contributor I
534 Views

Thank you Arjen and Jim for your replies on this topic. I have solved this now. 

The problem actually was that I hadn't set an environmental variable, the ECCODES_DEFINITION_PATH variable.

View solution in original post

0 Kudos
4 Replies
jimdempseyatthecove
Honored Contributor III
605 Views

Experiment by commenting out push_handle in your .c function and see if you make it to 'I am here 2'

If you do, then the problem is within push_handle.

--------------

Also, while your file has type .c, is it compiled as C or as C++?  If as C++ then attribute the function with extern "C"

IOW (if C++) while the entry point name can be resolved in C++ using C naming convention (compiler option), the calling API might not be resolved without the appropriate measures taken.

Jim Dempsey

0 Kudos
andy_in_oxford
New Contributor I
593 Views

Thanks Jim. I have tried running it with push_handle commented out and it still doesn't reach 'I am here 2'.

It is compiled as 'C'.

0 Kudos
Arjen_Markus
Honored Contributor I
584 Views

Just a few thoughts:

  • Has the argument ifile been given a value?
  • Can you add print statements to the C code to see where in the C function things go poof?
0 Kudos
andy_in_oxford
New Contributor I
535 Views

Thank you Arjen and Jim for your replies on this topic. I have solved this now. 

The problem actually was that I hadn't set an environmental variable, the ECCODES_DEFINITION_PATH variable.

0 Kudos
Reply