Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
Welcome to the Intel Community. If you get an answer you like, please mark it as an Accepted Solution to help others. Thank you!
26758 Discussions

Problem passing pointer from C to Intel FORTRAN and back to C

Thomas_W_
Beginner
128 Views

Hi there,

I am having an issue with FORTRAN/C interop using Intel FORTRAN that I'm hoping someone can help me with.

It is illustrated by the contrived example below:

library.f90:

module m

    implicit none

    abstract interface
        subroutine callback(data_ptr) bind (c)
            use iso_c_binding
            type(c_ptr), intent(in), value :: data_ptr
        end subroutine callback
    end interface

end module

subroutine library_fn(c_fn_ptr, data_ptr) bind(c)
    ! Is this still the recommended way to indicate the exported symbols even with FORTRAN 2003 support?
    !DEC$ ATTRIBUTES DLLEXPORT :: library_fn
    use iso_c_binding
    use m
    implicit none

    type(c_funptr), intent (in), value :: c_fn_ptr
    type(c_ptr), intent (in), value :: data_ptr
    integer(kind=C_INTPTR_T) :: address
    procedure(callback), pointer :: f_fn_ptr

    address = transfer(data_ptr, address)
    write(*,'("library::library_fn::address = ", "0x",Z12)') address

    call c_f_procpointer(c_fn_ptr, f_fn_ptr)
    call f_fn_ptr(data_ptr)
end subroutine library_fn

main.cxx:

#include <iostream>

using namespace std;

// Implemented by FORTRAN dll
extern "C" void library_fn(void (*fn_ptr)(void*), void* data_ptr);

void callback(void* data_ptr) {
    cout << "main::callback::data_ptr     = " << data_ptr << endl;
    int i = *static_cast<int*>(data_ptr);
    cout << "main::callback::i            = " <<  i << endl;
}

int main() {
    int i = 792;
    cout << "main::main::i                = " <<  i << endl;
    void* data_ptr = static_cast<void*>(&i);
    cout << "main::main::data_ptr         = " << data_ptr << endl;
    library_fn(&callback, data_ptr);
}

Building on Win64:

Intel(R) Visual Fortran Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 12.0.3.175 Build 20110309

ifort /c library.f90
lib /out:library.lib library.obj
cl main.cxx library.lib

Building on Linux:

GNU Fortran (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)

gfortran -shared -fPIC library.f90 -o library.so
g++ main.cxx library.so

Sample run on Win64:

[thwill@PSEUK1149(master)]$ ./main.exe
main::main::i                = 792
main::main::data_ptr         = 00000000002CFE70
library::library_fn::address = 0x      2CFE70
main::callback::data_ptr     = 00000000002CFE58 <---- INCORRECT!
main::callback::i            = 2948720

Sample run on 64-bit Linux:

[thwill@pseuk1149-centos7-vm(master)]$ ./a.out
main::main::i                = 792
main::main::data_ptr         = 0x7ffc97963a54
library::library_fn::address = 0x7FFC97963A54
main::callback::data_ptr     = 0x7ffc97963a54 <---- CORRECT!
main::callback::i            = 792

As you can see the data pointer has become "corrupted" on Win64 when it is passed back from the FORTRAN into the C.

FORTRAN is not something I use very often and until a fortnight ago I restricted myself to FORTRAN-77, so I may be making a stupid mistake, but given it works with gfortran perhaps not?

Any ideas?

Regards,

Tom Williams

0 Kudos
5 Replies
mecej4
Black Belt
128 Views

I do not see the error with the 15.0 and later compilers.

FortranFan
Honored Contributor II
128 Views

Thomas W. wrote:

.. FORTRAN is not something I use very often and until a fortnight ago I restricted myself to FORTRAN-77, so I may be making a stupid mistake, but given it works with gfortran perhaps not?

Note it's "Fortran" now!  https://en.wikipedia.org/wiki/Fortran

As mentioned by mecej4, more recent incarnations of the compiler including the current release, compiler 17 update 1, work as expected.

By the way, with respect to name-mangling that can take across the compilers and platforms with mixed language applications, you may want to look into the optional NAME= specifier with BIND(C attribute: https://software.intel.com/en-us/node/678426

[fortran]

subroutine library_fn(c_fn_ptr, data_ptr) bind(c)
    ! Is this still the recommended way to indicate the exported symbols even with FORTRAN 2003 support?
    !DEC$ ATTRIBUTES DLLEXPORT :: library_fn
[/fortran]

Note this has mostly to do with OS, not the language and on Windows, you may want to keep the option of DEF files in mind: https://msdn.microsoft.com/en-us/library/28d6s79h.aspx

Thomas_W_
Beginner
128 Views

Hi folks,

Thanks for the replies. I have tried out the latest Intel Fortran compiler and can confirm that it seems to fix the issue, so I guess this was a compiler bug?

Regards,

Tom

Kevin_D_Intel
Employee
128 Views

Good to hear Tom. Yes, this is an apparent defect in the older 12.0 compiler fixed in a later release. Nothing in the example code shown can be attributed to the incorrect pointer value.

Many thanks to everyone who contributed here.

Thomas_W_
Beginner
128 Views

Just a final note that it actually works with Intel Fortran 12 update 9; the failing version was update 3.

Regards,

Tom

Reply