问题
I want to call a C function from Fortran and receive a string of characters defined in the C function. I searched, but I couldn't find a working, straightforward answer, so far.
Actually I have found a workaround: receiving an array of characters instead, then using the intrinsic function transfer
to put the result into a Fortran string.
Here is my working code.
Fortran main program:
program pr
implicit none
character(200) :: stringa
call strfromc(stringa)
write (6,*) 'FPR stringa: "', trim(stringa),'"'
stop
end program pr
Fortran subroutine:
subroutine strfromc(stringa)
use iso_c_binding
implicit none
character(200) :: stringa
interface
subroutine getstrfromc(ld,d) bind(c,name='getString')
import :: c_int, c_ptr
integer(c_int) :: ld
type(c_ptr), value :: d
end subroutine getstrfromc
end interface
! declare a character array of type c_char and sufficient length:
character(c_char), dimension(200), target :: d1
integer :: ld1 ! will contain the string length
integer :: i
! the C pointer of character array d1 is passed:
call getstrfromc(ld1, c_loc(d1))
! read the first ld1 elements of array d1 as a character string, which will be returned:
stringa= transfer(d1(1:ld1), stringa)
write (6,*) 'SF d1: ', (d1(i),i=1,ld1)
write (6,*) 'SF stringa: "', trim(stringa),'"'
write (6,*) ''
return
end subroutine
C function:
#include <stdio.h>
#include <string.h>
void getString(int * lw, char * w) {
printf("Enter a string:\n");
scanf("%[^\n]", w); //scanning the whole string, including the white spaces
*lw= strlen(w);
printf("C: w: %s\n", w);
printf("C: lw: %d\n", *lw);
printf("\n");
return;
}
Can anyone suggest a more direct way?
回答1:
Why not simply use C_CHAR
kind? I "compressed" your code a bit:
program main
use, intrinsic :: iso_c_binding, only: C_INT, C_CHAR
implicit none
integer :: lw ! will contain the string length
character(256) :: w = "" ! will contain the string; Initialize to empty
! C interface
interface
subroutine getstrfromc( lw, w ) bind( c, name='getString' )
import :: C_INT, C_CHAR
implicit none
integer(C_INT), intent(out) :: lw
character(C_CHAR), intent(out) :: w(*)
end subroutine getstrfromc
end interface
! In Fortran variables are passed by default as "pointers".
call getstrfromc( lw, w )
! Write string
write (*,*) "Fortran: w: ", trim(w)
write (*,*) "Fortran: lw:", lw
end program main
The C function remains the same.
回答2:
I post this in an answer because it appears cleaner. Here is my modified code following @francescalus' suggestion.
Fortran main program:
program pr
use sfc
implicit none
character(200) :: stringa
call strfromc(stringa)
write (6,*) 'FPR stringa: "', trim(stringa),'"'
stop
end program pr
Fortran module including the interface to the C function and the Fortran subroutine:
module sfc
use iso_c_binding
implicit none
interface
subroutine getstrfromc(ld,d) bind(c,name='getString')
import :: c_int, c_ptr
integer(c_int) :: ld
type(c_ptr), value :: d
end subroutine getstrfromc
end interface
contains
subroutine strfromc(d1)
use iso_c_binding
implicit none
! declare a character array of type c_char and sufficient length:
character(c_char), dimension(200), target :: d1
integer :: ld1 ! will contain the string length
integer :: i
! the C pointer of character array d1 is passed:
call getstrfromc(ld1, c_loc(d1))
! clean elements after the ld1-th:
d1(ld1+1:)= ''
write (6,*) 'SF d1: ', (d1(i),i=1,ld1)
write (6,*) ''
return
end subroutine
end module sfc
The C function remains the same.
... other suggestions?!?
来源:https://stackoverflow.com/questions/59247212/how-to-receive-a-string-from-a-c-function-called-by-fortran-by-iso-c-binding