1

Frist off I'm new to combining C (and cpp) with Fortran. And I'm new to Fortran in general. I've been looking at other examples and reading about iso c bind. But I'm confused why this doesn't work. I currently don't have a strong grasp on how pointers work in Fortran with C. I think I'm just not getting the syntax or keywords right or something.

Can someone please explain what I'm doing wrong here?

program main
    use iso_c_binding
    implicit none
    character (len=100) :: string
    interface
        !char *foo2()
        character (kind=c_char, len=1) function foo2() bind(c,name='foo2')
            use iso_c_binding
            implicit none
            character (kind=c_char, len=1) :: output
        end function foo2
        !void foo(char *in)
        subroutine foo(input) bind(c,name='foo')
            use iso_c_binding
            implicit none
            character (kind=c_char, len=1) :: input
        end subroutine foo
        !char *foo3(char *in)
        !TODO:
    end interface
    write(*,'(A)') "In fortran now."
    string = "msg from fortran!"
    write(*,'(A)') "In fortran again."
    call foo(trim(string))
    string = foo2() !WHY DOES THIS NOT WORK?
    write(*,'(A)') trim(string)
end program main
#include <stdio.h>
//Test
void foo(char *in);
char *foo2();

void foo(char *in)
{
    printf("I am in C now.\n");
    printf("%s\n",in);
}

char *foo2() {
    printf("I am in C again.\n");    
    return "msg from C!";
}
#makefile
FC=gfortran
CC=gcc
FFLAGS=-O3 -Wall -Wextra
SRC=main.f90
SRCH=test.c
OBJ=${SRC:.f90=.o} $(SRCH:.h=.o)
TARGET=out

$(TARGET): $(OBJ)
    $(FC) $(FFLAGS) -o $@ $(OBJ)
%.o: %.c
    $(CC) -o $@ -c $<
%.o: %.f90
    $(FC) $(FFLAGS) -o $@ -c $<

clean:
    rm *.o *.mod $(TARGET)
output:
In fortran now.
I am in C now.
msg from fortran!
In fortran again.        
I am in C again.

Expected output:
In fortran now.
I am in C now.
msg from fortran!
In fortran again.        
I am in C again.
msg from C!
2
  • 1
    Leaving aside lifetime issues of the C return value, your Fortran foo2 interface says the function result is a length-1 character. It isn't (see also this). Commented Sep 10, 2021 at 10:12
  • 1
    Also, character (kind=c_char, len=1) :: output is a declaration which doesn't relate to a dummy argument or function result: it's serving no purpose in that interface block. Commented Sep 10, 2021 at 10:13

1 Answer 1

1

Returning type from foo2() is not C_CHAR but C_PTR.
Here is modified fortran code snippet (C code stays the same):

program main
  use iso_c_binding, only: C_PTR, C_NULL_CHAR, c_f_pointer
  implicit none
  type(C_PTR)             :: cpointer
  character(128), pointer :: fpointer
  character(128)          :: string

  interface ! C interface
    !char *foo2()
    type(C_PTR) function foo2() bind(C, NAME='foo2')
      use iso_c_binding, only: C_PTR
      implicit none
    end function foo2
  end interface ! C interface
   
  ! Get C pointer
  cpointer = foo2()

  ! Convert C into Fortran pointer   
  call c_f_pointer(cpointer, fpointer)

  ! Remove NULL character at the end
  string = fpointer(1:index(fpointer,C_NULL_CHAR)-1)

  write (*,'(A)') trim(string)

end program main
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.