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

New Interoperability: Fortran to C++ (String case)

Maia__Nycholas
Beginner
2,697 Views

I would like to send a Fortran string to my C++ application, I tried to to this, but I got this linker error:

unresolved external symbol for_cpystr referenced in function my_long_calc

My Fortran Static Lib Code (Visual Fortran):

module my_interfaces
    use iso_c_binding
        interface
            subroutine fortran_message(msg) bind(C, name = 'fortran_message')
                use, intrinsic :: iso_c_binding
                
                character(kind = c_char), dimension(*), intent(out) :: msg
                
            end subroutine fortran_message
        end interface
end module my_interfaces

! My long calc subroutine
subroutine my_long_calc() BIND(C, name = 'my_long_calc')
    use, intrinsic :: ISO_C_BINDING
    use my_interfaces
    implicit none
    
    ! A single variable:
    character(len = 40, kind = c_char) :: msg
    
    msg = "this is a msg from fortran"
    
    ! Send a message to the C++ application:
    call fortran_message(msg)
end subroutine my_long_calc

My C++ Code:
 

#include <iostream>

extern "C" {
  void my_long_calc(void);
  void fortran_message(char* msg);
}

void fortran_message(char* msg)
{
  std::cout << *msg << std::endl;
}

int main(int argc, char *argv[])
{
    my_long_calc();

    return 0;
}

Please, what I have to do to link this library and get the "msg" string inside the C++ application?

0 Kudos
1 Solution
Steve_Lionel
Honored Contributor III
2,669 Views
extern "C" {
	void fortran_subroutine(char* jpath, char* lpath);
}

int main(void)
{
	char json_path[100] = "../files/json/my_example.json";
	char log_path[100] = "../files/log/my_log.json";

	fortran_subroutine(json_path, log_path);

	return 0;
}
module str_routines
    contains
    subroutine C_F_STRPOINTER (STRARRAY, FSTRPTR, MAXLEN)
    use, intrinsic :: ISO_C_BINDING
    implicit none
    character, dimension(*), target, intent(in) :: STRARRAY
    character(:), pointer, intent(out) :: FSTRPTR
    integer, intent(in), optional :: MAXLEN

    integer :: curlen

    curlen = 0
    
    do
        curlen = curlen +1
        if (PRESENT(MAXLEN)) THEN
            if (curlen > MAXLEN) exit
        end if
        if (STRARRAY(CURLEN) == CHAR(0)) exit
    end do

    call doassign(C_LOC(STRARRAY), FSTRPTR, curlen-1)

    contains

    subroutine doassign(CSTRPTR, FSTRPTR, STRLEN)
        type(C_PTR), intent(in) :: CSTRPTR
        character(:), pointer, intent(out) :: FSTRPTR
        integer, intent(in) :: STRLEN

        character(STRLEN), pointer :: p

        call C_F_POINTER(CSTRPTR, p)
        FSTRPTR => p
        return
    end subroutine doassign
    end subroutine C_F_STRPOINTER
    end module str_routines
    
    
subroutine fortran_subroutine(json_path, log_path) bind(C)
    use, intrinsic :: ISO_C_BINDING
                
!        use json_module
         use str_routines
        
        implicit none
        character(kind=C_CHAR), target, intent(in) :: json_path(*)
        character(kind=C_CHAR), target, intent(in) :: log_path(*)
        
        character(kind=C_CHAR, len=:), pointer :: jpath, lpath
        
        call C_F_STRPOINTER (json_path, jpath, 80)
        call C_F_STRPOINTER (log_path, lpath, 80)
        
        print "('""',A,'""')", jpath, lpath
        
!        type(json_file) :: my_data, my_log
        
        ! initialize the class
!        call my_data%initialize()
!        call my_log%initialize()
        
        ! read the file: SHOUD BE filename = json_path
!        call my_data%load_file(filename = 'inout.json')

        ! read the file: SHOUD BE filename = log_path
!        call my_log%load_file(filename = 'inout.json')

end subroutine fortran_subroutine

 

View solution in original post

0 Kudos
25 Replies
FortranFan
Honored Contributor II
315 Views

gib wrote:

This example gives lots of C++ compile warnings, but works, with old tools - MSVC 14 (i.e. VS 8) and IVF 11.0.075.  ..

Do you get warnings with /W4 in the C++ compiler?  See below with an older set, not the same as yours but no warnings with a reasonable set of options either:

C:\Temp>type m.f90
module m

   use, intrinsic :: iso_c_binding, only : c_char, c_size_t, c_f_pointer, c_loc

   implicit none

contains

   subroutine Fsub(json_path, len_json, log_path, len_log) bind(C, name="Fortran_subroutine")

      ! Argument list
      character(kind=c_char,len=1), target, intent(in) :: json_path(*)
      integer(c_size_t), intent(in), value             :: len_json
      character(kind=c_char,len=1), target, intent(in) :: log_path(*)
      integer(c_size_t), intent(in), value             :: len_log

      ! Local variables
      character(kind=c_char,len=len_json), pointer :: path_json
      character(kind=c_char,len=len_log), pointer :: path_log

      call c_f_pointer( cptr=c_loc(json_path), fptr=path_json )
      print *, "path_json = ", path_json
      print *, "length: ", len(path_json), "; expected is ", len_json

      call c_f_pointer( cptr=c_loc(log_path), fptr=path_log )
      print *, "path_log = ", path_log
      print *, "length: ", len(path_log), "; expected is ", len_log

      path_json => null()
      path_log => null()

      return

   end subroutine

end module

C:\Temp>ifort /c /standard-semantics /warn:all m.f90
Intel(R) Visual Fortran Compiler XE for applications running on IA-32, Version
12.0.3.175 Build 20110309
Copyright (C) 1985-2011 Intel Corporation.  All rights reserved.


C:\Temp>type main.cpp
#include <cstring>
#include <iostream>

extern "C" {

   // Function prototype
   void Fortran_subroutine( const char *, size_t, const char *, size_t );

}

int main(void)
{

   std::cout << "Option 1 using C-style char array" << std::endl;
   {
      char json_path[] = "../files/json/my_example.json";
      char log_path[] = "../files/log/my_log.json";

      Fortran_subroutine(json_path, strlen(json_path), log_path, strlen(log_path) );
   }

   std::cout << "Option 2 using std::string C++ class" << std::endl;
   {
      std::string JsonFilePath = "../files/json/my_example.json";
      std::string LogFilePath = "../files/log/my_log.json";

      Fortran_subroutine(JsonFilePath.c_str(), JsonFilePath.length(), LogFilePath.c_str(), LogFilePath.length() );
   }

   return 0;

}

C:\Temp>cl /c /W4 /EHsc main.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 17.00.61232.400 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

main.cpp

C:\Temp>link main.obj m.obj /LIBPATH:"C:\Program Files (x86)\Intel\ComposerXE-
2011\compiler\lib\ia32" /subsystem:console /out:main.exe
Microsoft (R) Incremental Linker Version 11.00.61232.400
Copyright (C) Microsoft Corporation.  All rights reserved.


C:\Temp>main.exe
Option 1 using C-style char array
 path_json = ../files/json/my_example.json
 length:  29 ; expected is  29
 path_log = ../files/log/my_log.json
 length:  24 ; expected is  24
Option 2 using std::string C++ class
 path_json = ../files/json/my_example.json
 length:  29 ; expected is  29
 path_log = ../files/log/my_log.json
 length:  24 ; expected is  24

C:\Temp>

 

0 Kudos
gib
New Contributor II
315 Views

Yes, /W4 doesn't seem to change anything:

D:\testing\C-Fortran>cl/W4 main.cpp fsub.obj
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86

Copyright (C) Microsoft Corporation.  All rights reserved.

main.cpp
C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\xlocale(326) : warni
ng C4530: C++ exception handler used, but unwind semantics are not enabled. Spec
ify /EHsc
C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\xlocale(341) : warni
ng C4530: C++ exception handler used, but unwind semantics are not enabled. Spec
ify /EHsc
C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\xlocale(358) : warni
ng C4530: C++ exception handler used, but unwind semantics are not enabled. Spec
ify /EHsc
C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\istream(1075) : warn
ing C4530: C++ exception handler used, but unwind semantics are not enabled. Spe
cify /EHsc
C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\ostream(520) : warni
ng C4530: C++ exception handler used, but unwind semantics are not enabled. Spec
ify /EHsc
        C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\ostream(512)
 : while compiling class template member function 'std::basic_ostream<_Elem,_Tra
its> &std::basic_ostream<_Elem,_Traits>::put(_Elem)'
        with
        [
            _Elem=char,
            _Traits=std::char_traits<char>
        ]
        C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\ostream(971)
 : see reference to class template instantiation 'std::basic_ostream<_Elem,_Trai
ts>' being compiled
        with
        [
            _Elem=char,
            _Traits=std::char_traits<char>
        ]
C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\ostream(520) : warni
ng C4530: C++ exception handler used, but unwind semantics are not enabled. Spec
ify /EHsc
        C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\ostream(512)
 : while compiling class template member function 'std::basic_ostream<_Elem,_Tra
its> &std::basic_ostream<_Elem,_Traits>::put(_Elem)'
        with
        [
            _Elem=wchar_t,
            _Traits=std::char_traits<wchar_t>
        ]
        C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\ostream(980)
 : see reference to class template instantiation 'std::basic_ostream<_Elem,_Trai
ts>' being compiled
        with
        [
            _Elem=wchar_t,
            _Traits=std::char_traits<wchar_t>
        ]
C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\istream(102) : warni
ng C4530: C++ exception handler used, but unwind semantics are not enabled. Spec
ify /EHsc
        C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\istream(92)
: while compiling class template member function 'bool std::basic_istream<_Elem,
_Traits>::_Ipfx(bool)'
        with
        [
            _Elem=char,
            _Traits=std::char_traits<char>
        ]
        C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\istream(1065
) : see reference to class template instantiation 'std::basic_istream<_Elem,_Tra
its>' being compiled
        with
        [
            _Elem=char,
            _Traits=std::char_traits<char>
        ]
C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\istream(102) : warni
ng C4530: C++ exception handler used, but unwind semantics are not enabled. Spec
ify /EHsc
        C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\istream(92)
: while compiling class template member function 'bool std::basic_istream<_Elem,
_Traits>::_Ipfx(bool)'
        with
        [
            _Elem=wchar_t,
            _Traits=std::char_traits<wchar_t>
        ]
        C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\istream(1100
) : see reference to class template instantiation 'std::basic_istream<_Elem,_Tra
its>' being compiled
        with
        [
            _Elem=wchar_t,
            _Traits=std::char_traits<wchar_t>
        ]
C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\ostream(144) : warni
ng C4530: C++ exception handler used, but unwind semantics are not enabled. Spec
ify /EHsc
        C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\ostream(143)
 : while compiling class template member function 'void std::basic_ostream<_Elem
,_Traits>::_Osfx(void)'
        with
        [
            _Elem=char,
            _Traits=std::char_traits<char>
        ]
C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\ostream(144) : warni
ng C4530: C++ exception handler used, but unwind semantics are not enabled. Spec
ify /EHsc
        C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\ostream(143)
 : while compiling class template member function 'void std::basic_ostream<_Elem
,_Traits>::_Osfx(void)'
        with
        [
            _Elem=wchar_t,
            _Traits=std::char_traits<wchar_t>
        ]
C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\xstring(2009) : warn
ing C4530: C++ exception handler used, but unwind semantics are not enabled. Spe
cify /EHsc
        C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\xstring(2000
) : while compiling class template member function 'void std::basic_string<_Elem
,_Traits,_Ax>::_Copy(unsigned int,unsigned int)'
        with
        [
            _Elem=char,
            _Traits=std::char_traits<char>,
            _Ax=std::allocator<char>
        ]
        C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\stdexcept(48
) : see reference to class template instantiation 'std::basic_string<_Elem,_Trai
ts,_Ax>' being compiled
        with
        [
            _Elem=char,
            _Traits=std::char_traits<char>,
            _Ax=std::allocator<char>
        ]
C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\ostream(757) : warni
ng C4530: C++ exception handler used, but unwind semantics are not enabled. Spec
ify /EHsc
        main.cpp(14) : see reference to function template instantiation 'std::ba
sic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_
ostream<_Elem,_Traits> &,const char *)' being compiled
        with
        [
            _Elem=char,
            _Traits=std::char_traits<char>
        ]
Microsoft (R) Incremental Linker Version 8.00.50727.762
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:main.exe
main.obj
fsub.obj

0 Kudos
gib
New Contributor II
315 Views

But when I use /EHsc as advised, no warnings.

0 Kudos
Maia__Nycholas
Beginner
315 Views

Hi @Steve, thank you for your str_module that can convert a C string to a Fortran string. It works good on Windows x64.

I just copied the file and tried to use the same sour-code in a Linux Ubuntu 18 x64 environment, but I got a Segmentation Fault error inside this module.

module str_routines
    contains        
        subroutine C_F_STRPOINTER (STRARRAY, FSTRPTR, MAXLEN)
            use, intrinsic :: ISO_C_BINDING
            implicit none
            character, dimension(*), target, intent(in) :: STRARRAY
            character(:), pointer, intent(out) :: FSTRPTR
            integer, intent(in), optional :: MAXLEN

            integer :: curlen

            curlen = 0
           
            do
                curlen = curlen +1
                if (PRESENT(MAXLEN)) THEN
                    if (curlen > MAXLEN) exit
                end if
                if (STRARRAY(CURLEN) == CHAR(0)) exit
            end do

            call doassign(C_LOC(STRARRAY), FSTRPTR, curlen-1)

            contains

                subroutine doassign(CSTRPTR, FSTRPTR, STRLEN)
                    type(C_PTR), intent(in) :: CSTRPTR
                    character(:), pointer, intent(out) :: FSTRPTR
                    integer, intent(in) :: STRLEN

                    character(STRLEN), pointer :: p

                    call C_F_POINTER(CSTRPTR, p)
                    FSTRPTR => p
                    return
                end subroutine doassign
        end subroutine C_F_STRPOINTER
end module str_routines

The Seg-fault occours in line 34:
 

FSTRPTR => p

Do you know what it can be?

My Linux system is:
Ubuntu 18 x64
gcc/gfortran 7.4

0 Kudos
Steve_Lionel
Honored Contributor III
315 Views

Sorry, I have no idea, and I don't have a Linux system I can test on. Maybe another user can figure out what is wrong.

0 Kudos
Reply