1

I have a Fortran subroutine that calls a C function. One of the arguments to the C function is a fortran string. This is initialized as an empty string of length 512 bytes, and is passed to the C function as trim(str)//char(0) , i.e. it is trimmed and a \0 is appended so that C sees its strlen as 0.

character(len=512)  :: str = ""
call C_foo (  trim(str)//char(0)  )

Now inside the C function, can I do this

strncpy (str, "something", strlen("something") )

What I want to know is that since trim is a transformational function as mentioned in its docs , does passing it to C actually alter the space allocated to it? Inside the C function, will a strncpy ever fail (as far as length of source string < 512) ? I tried it and it works fine, but I want to be sure it is safe.

Korizon
  • 3,677
  • 7
  • 37
  • 52
  • trim returns a zero length string in this case, so no it is not safe at all. More likely what you want to do is not use trim at all but set str(1:1)=char(0) .. – agentp Sep 26 '13 at 16:14
  • @george could you post your comment as an answer? – Korizon Sep 26 '13 at 16:38

2 Answers2

4

Why not use the ISO_C_BINDING and initialize the string via:

character(len=512)  :: str = C_NULL_CHAR

Then the string will be be 512 long, with the first character being the C string null character and the remainder blanks.

M. S. B.
  • 28,968
  • 2
  • 46
  • 73
  • I see. Thats a possible solution. But without the ISO_C_BINDING, will it work? I am curious to know how the space allocation works. – Korizon Sep 26 '13 at 16:05
  • You could do `str = char(0)` without the ISO_C_BINDING. Standard Fortran strings are fixed length. If the RHS side is shorter than the string in an assignment statement, the string is padded with trailing spaces. – M. S. B. Sep 26 '13 at 16:12
2

elaborating on my comment, without getting into what "C" does, consider this pure fortran example:

character(len=512) :: g=""
call f(trim(g))
end

subroutine f(s)
character(len=*) :: s
integer :: i
do i=1,100
 s(i:i)="0"
enddo
end

This compiles fine but seg faults, while just

call f(g)

is just fine. Alternately if we assign g to be a sufficiently long nonblank string, eg add

g(100:100)="0"

it works a well.

what you see is the string passed by trim() has only the required lenght (which is zero in the first case), or 1 if you add //char(0) )

Incidentally a simple assignment in the subroutine

s=" ... 512 characters .. "

works..assiging only however many character will fit in the supplied space. Interesting that (gfortran) somehow knows how much space to fill.. but I wouldnt count on it.

agentp
  • 6,849
  • 2
  • 19
  • 37
  • Separate to the length of the result of trim, note that `trim(g)` is an expression, the result of which here is a value, not a variable. It is not conforming for a procedure to try and define a dummy argument that is associated with a value. Beyond that - a procedure with a character(*) dummy argument knows the length of the actual argument (usually it is passed as a hidden argument) - hence the last assignment "works". – IanH Sep 26 '13 at 20:52
  • well my long winded point was to say "don't do it"..it is a curious thing how that string length is known by the subroutine. Going back tho the "C" question there seems to be no way for the C routine to access that information. – agentp Sep 27 '13 at 14:13