I’m calling a C function from Fortran that takes a C struct as argument:
struct Params
{
char p1[64];
char p2[64];
}
void my_function(const struct Params *);
I’m binding it this way:
use iso_c_binding, only: c_char, c_null_char
type, bind(c) :: Params
character(kind=c_char) p1(64), p2(64)
end type
interface
subroutine my_function(p) bind(c)
import :: Params
type(Params), intent(in) :: p
end
end interface
But I can’t figure out how to initialize the string members:
type(Params) :: p
p%p1 = "abcdef" // c_null_char
p%p2 = "/dev/ttyUSB0" // c_null_char
This generates a CHARACTER expression will be truncated in assignment compilation warning, and this result is p%p1 being completly filled with a (and p%p2 with /), which is logical to given the array nature of p1.
This only way I found to make my assignment is by a loop and an intermediate string:
integer i
character(len=64) tmp
tmp = "abcdef" // c_null_char
do i=1,len_trim(tmp)
p%p1(i:i) = tmp(i:i)
enddo
But this is somewhat tedious. Isn’t there a simpler way to do this?
Full example
Fortran code:
program test_binding
use iso_c_binding, only: c_char, c_null_char
type, bind(c) :: Params
character(kind=c_char) p1(64), p2(64)
end type
interface
subroutine my_function(p) bind(c)
import :: Params
type(Params), intent(in) :: p
end
end interface
type(Params) :: p
integer i
character(len=64) tmp
tmp = "abcdef" // c_null_char
do i=1,len_trim(tmp)
p%p1(i:i) = tmp(i:i)
enddo
tmp = "/dev/ttyUSB0" // c_null_char
do i=1,len_trim(tmp)
p%p2(i:i) = tmp(i:i)
enddo
print *, p%p1
print *, p%p2
call my_function(p)
end program
C code:
#include <stdio.h>
struct Params
{
char p1[64];
char p2[64];
};
void my_function(const struct Params * p)
{
printf("In C : '%s'\n", p->p1);
printf("In C : '%s'\n", p->p2);
}
Build with e.g. gfortran -Wall -ffree-line-length-none test_binding.f90 test_c.c -o test_binding.