# Iso\_c\_binding: interface to a C function returning a string

**URL:** <https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527>\
**Category:** Help\
**Created:** [December 30, 2020, 6:08pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527 "2020-12-30T18:08:37Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![epagone](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/epagone/32/252_2.png) [@epagone](https://fortran-lang.discourse.group/u/epagone)\
**Post date:** [December 30, 2020, 6:08pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527/1 "2020-12-30T18:08:37Z")

</div>

Is it possible to write an interface for a C function returning a string?

Example

```auto
char *foo(char *bar1, int baz1, char *bar2, int baz2, char *qux)

```

I can imagine that it is possible to write a wrapper C function returning `void` in this way

```auto
void wrapfoo(char *foo, char *bar1, int baz1, char *bar2, int baz2, char *qux)

```

and this should work

```auto
interface
  subroutine wrapfoo(foo, bar1, baz1, bar2, baz2, qux) bind(c, name="wrapfoo")
    character(kind=c_char) :: foo(*)
    character(c_char) :: bar1(*)
    int(c_long), value :: baz1
    character(c_char) :: bar2(*)
    int(c_long), value :: baz2
    character(kind=c_char) :: qux(*)
  end subroutine wrapfoo
end interface

```

but I would definitely like to avoid that. Any suggestions to directly interface function `foo` above?

---

<div class="post-metadata">

**Author:** ![ivanpribec](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ivanpribec/32/3290_2.png) [@ivanpribec](https://fortran-lang.discourse.group/u/ivanpribec)\
**Post date:** [December 30, 2020, 6:45pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527/2 "2020-12-30T18:45:56Z")

</div>

If you don’t mind creating a copy of the C string, then you can do something similar to:

```nohighlight
! C - function
interface
    ! char *nlopt_algorithm_name(int algorithm) 
    type(c_ptr) function nlopt_algorithm_name(algorithm) bind(c,name="nlopt_algorithm_name")
        import c_int, c_ptr
        integer(c_int), value :: algorithm
    end function
end interface

! Fortran wrapper
function algorithm_name(a) result(name)
    integer(c_int), intent(in) :: a
    character(len=:,kind=c_char), allocatable :: name
    character(len=256,kind=c_char), pointer :: buffer
    type(c_ptr) :: cstring
    cstring = nlopt_algorithm_name(a)
    call c_f_pointer(cstring,buffer)
    name = buffer(1:index(buffer,c_null_char))
end function

```

In this case I knew the returned string will not be longer than 256 characters by inspection of the original C code.

⚠  
EDIT: This wrapper likely creates a memory leak! See my post below for a second solution.

---

<div class="post-metadata">

**Author:** ![epagone](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/epagone/32/252_2.png) [@epagone](https://fortran-lang.discourse.group/u/epagone)\
**Post date:** [December 30, 2020, 7:34pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527/3 "2020-12-30T19:34:36Z")

</div>

Many thanks @ivanpribec! Unfortunately, `gfortran 10.2.0` segfaults

```bash
Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

```

at line

```auto
name = buffer(1:index(buffer,c_null_char))

```

I wonder if it’s a bug of gfortran or if I have done something wrong. I’ll try to test `ifort` but I don’t know if there might be incompatibilities since I have used the gcc toolchain to compile the C library. I’ll post an update as soon as I can test `ifort`.

**Update** : also `ifort 2021.1.2 20201208` segfaults. Almost certainly now I believe that I have made a mistake in adapting the example to my case. I’ll update again when I discover something relevant

---

<div class="post-metadata">

**Author:** ![ivanpribec](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ivanpribec/32/3290_2.png) [@ivanpribec](https://fortran-lang.discourse.group/u/ivanpribec)\
**Post date:** [December 30, 2020, 7:46pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527/4 "2020-12-30T19:46:45Z")

</div>

I noticed that I was wrongly including the terminating null string too. The line should be:

```auto
name = buffer(1:index(buffer,c_null_char)-1)

```

---

<div class="post-metadata">

**Author:** ![epagone](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/epagone/32/252_2.png) [@epagone](https://fortran-lang.discourse.group/u/epagone)\
**Post date:** [December 30, 2020, 7:52pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527/5 "2020-12-30T19:52:23Z")

</div>

Thanks @ivanpribec. Unfortunately, also the version with `buffer(1:index(buffer,c_null_char)-1)` segfaults both with `gfortran` and `ifort`.

---

<div class="post-metadata">

**Author:** ![FortranFan](https://avatars.discourse-cdn.com/v4/letter/f/96bed5/32.png) [@FortranFan](https://fortran-lang.discourse.group/u/FortranFan)\
**Post date:** [December 30, 2020, 7:52pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527/6 "2020-12-30T19:52:25Z")

</div>

> [@epagone](#):
>
> Is it possible to write an interface for a C function returning a string? …

For most people in scientific and technical computing who primarily aspire to bring about meaningful advances in their chosen domains rather than get into the weeds of stack and heap allocations and memory leaks and dangled pointers and so forth, functions in C, C++ whose return values are pointers are **fraught**.

So if it’s possible for library authors who may have more expertise in C, C++ to stay away from such return values, especially with `char *` and strings where the semantics in C gets further tricky, that will be rather kind of them toward the users of their libraries. And if the users are expected to be Fortranners as well, such expert library authors can use the enhanced interoperability facility introduced in Fortran 2018 to make it further easier for them. Here is a simple [**how-to example**](https://community.intel.com/t5/Intel-Fortran-Compiler/Calling-a-C-function-and-returning-a-string/m-p/1179874/highlight/true#M148382) of this from the Intel forum.

But now if a reauthoring of the C function is not viable, then eschewing some type safety by using `type(c_ptr)` as the return type is an option, as shown by @ivanpribec above.

As commented by @ivanpribec re: string copy, if it is to be avoided, then employ the C library function `strlen` that can be readily invoked from Fortran when it is interoperating with a C companion processor:

```Fortran
 ..
    character(len=:,kind=c_char), pointer :: buffer
    integer(c_int) :: lenbuffer
    type(c_ptr) :: cstring
    cstring = nlopt_algorithm_name( a )
    lenbuffer = strlen( cstring ) ! Elided is the interface for this C library function
    block
          character(len=lenbuffer, kind=c_char), pointer :: s
          call c_f_pointer(cstring, s)
          buffer => s
    end block
    print *, "Fortran string: ", buffer
..

```

Edit: removed the ‘function … end function’ construct from the code snippet per @ivanpribec’s comment.

---

<div class="post-metadata">

**Author:** ![ivanpribec](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ivanpribec/32/3290_2.png) [@ivanpribec](https://fortran-lang.discourse.group/u/ivanpribec)\
**Post date:** [December 30, 2020, 7:58pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527/7 "2020-12-30T19:58:17Z")

</div>

Should `buffer` be the result value in the function instead of `name`?

---

<div class="post-metadata">

**Author:** ![epagone](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/epagone/32/252_2.png) [@epagone](https://fortran-lang.discourse.group/u/epagone)\
**Post date:** [December 30, 2020, 8:24pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527/8 "2020-12-30T20:24:29Z")

</div>

Something weird is going on: when I use @FortranFan’s suggested version, I get the segfault at line

```auto
lenbuffer = strlen(cstring)

```

🤔

---

<div class="post-metadata">

**Author:** ![ivanpribec](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ivanpribec/32/3290_2.png) [@ivanpribec](https://fortran-lang.discourse.group/u/ivanpribec)\
**Post date:** [December 30, 2020, 8:31pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527/9 "2020-12-30T20:31:39Z")

</div>

I have create a more complete example. Let’s assume a C function which returns a string representation of an integer:

```auto
// int2str.c

#include <stdio.h>
#include <stdlib.h>

char *int2str(int i) {
    
    int length = snprintf( NULL, 0, "%d", i );
    char* str = malloc( length + 1 );
    snprintf( str, length + 1, "%d", i );
    return str;
}

```

This function first determines the length of the the character pointer necessary, before writing the integer value `i` to the instance `str`.

The next step is defining the Fortran interfaces:

```auto
! int2str_mod.f90
module int2str_mod

  use, intrinsic :: iso_c_binding

  interface
    type(c_ptr) function c_int2str(i) bind(c,name="int2str")
      import c_int, c_ptr
      integer(c_int), value :: i
    end function
    integer(c_size_t) function c_strlen(s) bind(c,name="strlen")
      import c_size_t, c_ptr
      type(c_ptr), intent(in), value :: s
    end function
    subroutine c_free(ptr) bind(c,name="free")
      import c_ptr
      type(c_ptr), value :: ptr
    end subroutine
  end interface

```

As per @FortranFan’s suggestion, this time I am using the C standard library function `strlen` to recover the length of the string in C. This function does _not_ count the trailing “\n” character used as the string terminator. Next we write a wrapper function in Fortran:

```auto
contains

  function int2str(i) result(str)
    integer(c_int), intent(in) :: i
    character(:,c_char), allocatable :: str
    type(c_ptr) :: cstr
    integer(c_size_t) :: n

    cstr = c_int2str(i)
    n = c_strlen(cstr)
    allocate(character(len=n,kind=c_char) :: str)
    block
      character(len=n,kind=c_char), pointer :: s
      call c_f_pointer(cstr,s) ! Recovers a view of the C string
      str = s ! Copies the string contents
    end block
    call c_free(cstr)
  end function

end module

```

We can use the `c_strlen` function to correctly allocate both the return value `str` and the temporary buffer within the `block` section. After running the code in my previous reply through `valgrind` I was surprised to find out it created a memory leak! It looks like for the C function defined above it is necessary to free the memory explicitly. This is done by calling the `void free(void * ptr)` function.

A short example program:

```nohighlight
! main.f90
program main
  use int2str_mod

  print *, int2str(11_c_int), len(int2str(11_c_int))
  print *, int2str(121_c_int), len(int2str(121_c_int))
  print *, int2str(1221_c_int), len(int2str(1221_c_int))
end program

```

Compiling and running the program:

```nohighlight
$ gfortran -Wall -ggdb3 int2str.c int2str_mod.f90 main.f90
$ ./a.out
 11 2
 121 3
 1221 4

```

Output with `valgrind`:

```nohighlight
$ valgrind --leak-check=full ./a.out
==30654== Memcheck, a memory error detector
==30654== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==30654== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==30654== Command: ./a.out
==30654== 
 11 2
 121 3
 1221 4
==30654== 
==30654== HEAP SUMMARY:
==30654== in use at exit: 0 bytes in 0 blocks
==30654== total heap usage: 33 allocs, 33 frees, 13,626 bytes allocated
==30654== 
==30654== All heap blocks were freed -- no leaks are possible
==30654== 
==30654== For counts of detected and suppressed errors, rerun with: -v
==30654== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

```

Edit: Removed an unneccesary call to `c_strlen`.

---

<div class="post-metadata">

**Author:** ![ivanpribec](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ivanpribec/32/3290_2.png) [@ivanpribec](https://fortran-lang.discourse.group/u/ivanpribec)\
**Post date:** [December 30, 2020, 8:56pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527/10 "2020-12-30T20:56:39Z")

</div>

On further inspection, you can also remove the unnecessary call to `allocate` in the Fortran `int2str` function.

I have tested the code going back to `gfortran-5`. With Intel Fortran it also appears to work.

---

<div class="post-metadata">

**Author:** ![epagone](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/epagone/32/252_2.png) [@epagone](https://fortran-lang.discourse.group/u/epagone)\
**Post date:** [December 30, 2020, 11:39pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527/11 "2020-12-30T23:39:39Z")

</div>

Many thanks to @ivanpribec and @FortranFan. I confirm that the suggested solution works perfectly on a test program. For some reason, the library that I’m trying to use causes a segfault and I still don’t understand why (maybe it is returning rubbish). I’ll investigate more but I guess the problem is not any more the one in the title of this thread.

---

<div class="post-metadata">

**Author:** ![epagone](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/epagone/32/252_2.png) [@epagone](https://fortran-lang.discourse.group/u/epagone)\
**Post date:** [December 31, 2020, 12:16pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527/12 "2020-12-31T12:16:39Z")

</div>

Just for the records, I’ve solved the problem: it was a documentation issue. The documents describing the library reported a wrong signature. Looking at the source code, I was able to write the correct interface that worked as expected.

It’s unsettling that the problem manifested with a mysterious segfault, but I guess that it’s just a consequence of dealing with C and it’s a stark reminder on the reason why I prefer so much developing code in Fortran.

---

<div class="post-metadata">

**Author:** ![FortranFan](https://avatars.discourse-cdn.com/v4/letter/f/96bed5/32.png) [@FortranFan](https://fortran-lang.discourse.group/u/FortranFan)\
**Post date:** [December 31, 2020, 9:26pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527/13 "2020-12-31T21:26:37Z")

</div>

> [@ivanpribec](#):
>
> … I have tested the code going back to `gfortran-5` . With Intel Fortran it also appears to work.

As I mentioned in my [**earlier post**](https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527/6), if it’s possible to look forward instead and work with Fortran 2018 and the C library author(s) are willing to be kind to Fortranners, it’ll be better to provide the **wrappers** on the C side itself where author(s) of such libraries can avail themselves of all their memory management approaches cleanly. See a modification of @ivanpribec’s example where the memory management is **modeled** for illustration purposes using basic C malloc, memcpy, and free:

```C
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "ISO_Fortran_binding.h"

char *int2str(int i) {
    
    int length = snprintf( NULL, 0, "%d", i );
    char* str = malloc( length + 1 );
    snprintf( str, length + 1, "%d", i );
    return str;
}

// Wrapper for Fortran users
void Fint2str( int i, CFI_cdesc_t *str ) {
    char *s = int2str(i);
    size_t lens = strlen(s);
    int irc = CFI_allocate(str, (CFI_index_t *)0, (CFI_index_t *)0, lens);
    memcpy(str->base_addr, s, lens);
    free(s);
}

```

Then the Fortran code becomes really straightforward and plays to Fortran’s major strength with de facto “smart pointer” plus assured “garbage collection” via the ALLOCATABLE attribute:

```Fortran
   use, intrinsic :: iso_c_binding, only : c_int, c_char

   interface
      subroutine Fint2str( i, str ) bind(C, name="Fint2str")
         import :: c_int, c_char
         integer(c_int), intent(in), value :: i
         character(kind=c_char, len=:), allocatable, intent(out) :: str
      end subroutine 
   end interface

   character(kind=c_char, len=:), allocatable :: s

   call Fint2str( 42_c_int, s )
   print *, "s: ", s, "; expected is 42"
   print *, "len(s): ", len(s), "; expected is 2"
   
end 

```

The above should have no “memory leak” issues; it does NOT with Intel oneAPI per my testing on Windows OS:

> C:\Temp\>cl /c /W3 /EHsc c.c  
> Microsoft (R) C/C++ Optimizing Compiler Version 19.26.28806 for x64  
> Copyright (C) Microsoft Corporation. All rights reserved.
> 
> c.c
> 
> C:\Temp\>ifort /c /standard-semantics /warn:all /stand:f18 fc.f90  
> Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.1.2 Build 20201208\_000000  
> Copyright (C) 1985-2020 Intel Corporation. All rights reserved.
> 
> C:\Temp\>link fc.obj c.obj /subsystem:console /out:fc.exe  
> Microsoft (R) Incremental Linker Version 14.26.28806.0  
> Copyright (C) Microsoft Corporation. All rights reserved.
> 
> C:\Temp\>fc.exe  
> s: 42; expected is 42  
> len(s): 2 ; expected is 2
> 
> C:\Temp\>

---

<div class="post-metadata">

**Author:** ![ivanpribec](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ivanpribec/32/3290_2.png) [@ivanpribec](https://fortran-lang.discourse.group/u/ivanpribec)\
**Post date:** [January 1, 2021, 6:27pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527/14 "2021-01-01T18:27:08Z")

</div>

I experimented with a very similar solution, that appeared to work with the Intel Fortran compiler:

```nohighlight
  interface
    subroutine int2str_helper(fstr,i) bind(c,name="int2str_helper")
      import c_char, c_int
      character(:,c_char), allocatable, intent(inout) :: fstr
      integer(c_int), intent(in), value :: i
    end subroutine
  end interface

```

But compiling with gfortran leads to a (IMO) spurious error:

```nohighlight
$ gfortran int2str_mod.f90 -c
int2str_mod.f90:22:34:

  22 | subroutine int2str_helper(fstr,i) bind(c,name="int2str_helper")
     | 1
Error: Character argument ‘fstr’ at (1) must be length 1 because procedure ‘int2str_helper’ is BIND(C)

```

I definitely agree with your conclusion once you do the memory management on the C side, the code in Fortran is very simple and clean. Unfortunately, so far I don’t see many C developers using the capabilities to provide “native” Fortran API’s for their libraries.

---

<div class="post-metadata">

**Author:** ![FortranFan](https://avatars.discourse-cdn.com/v4/letter/f/96bed5/32.png) [@FortranFan](https://fortran-lang.discourse.group/u/FortranFan)\
**Post date:** [January 2, 2021, 2:22am UTC](https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527/15 "2021-01-02T02:22:34Z")

</div>

> [@ivanpribec](#):
>
> … gfortran leads to a (IMO) spurious error …

Yes, notwithstanding the availability of `ISO_Fortran_binding.h` and associated types and procedures with GCC toolset, gfortran has gaps.

When it comes to `Section 18.3.6 Interoperability of procedures and procedure interfaces` in the Fortran standard, gfortran does not conform to some of the Fortran 2018 semantics and misses out on key aspects.

---

<div class="post-metadata">

**Author:** ![une](https://avatars.discourse-cdn.com/v4/letter/u/b5e925/32.png) [@une](https://fortran-lang.discourse.group/u/une)\
**Post date:** [February 6, 2021, 8:56pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527/16 "2021-02-06T20:56:32Z")

</div>

Hi @ivanpribec. It would be nice to have this functionality available as _fpm_ package. If you agree, I can create a pull request.

---

<div class="post-metadata">

**Author:** ![ivanpribec](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ivanpribec/32/3290_2.png) [@ivanpribec](https://fortran-lang.discourse.group/u/ivanpribec)\
**Post date:** [February 6, 2021, 10:00pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527/17 "2021-02-06T22:00:50Z")

</div>

Hi @une, feel free to use the code as desired. I would encourage you to propose a specification for the `stdlib` project. The workflow is described here: [stdlib/WORKFLOW.md at master · fortran-lang/stdlib · GitHub](https://github.com/fortran-lang/stdlib/blob/master/WORKFLOW.md)

A Fortran implementation for a similar int to string function can be found here: [String handling routines · Issue #69 · fortran-lang/stdlib · GitHub](https://github.com/fortran-lang/stdlib/issues/69#issuecomment-570563373)

---

<div class="post-metadata">

**Author:** ![mEm](https://avatars.discourse-cdn.com/v4/letter/m/90ced4/32.png) [@mEm](https://fortran-lang.discourse.group/u/mEm)\
**Post date:** [February 12, 2025, 9:59am UTC](https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527/18 "2025-02-12T09:59:43Z")

</div>

Stumbled upon this thread since I am hitting a very strange issue (maybe a bug in `gfortran-12`?).

We happen to have put in place the same logic:

```fortran
   module function xbsf_get_error_string(ierr) result(str)
      integer(xbsf_int_t), value :: ierr
      character(len = :), allocatable :: str
      type(c_ptr) :: cstr
      integer(c_size_t) :: cstr_len

      interface
         function xbsf_get_error_string_c(err) result(cptr) bind(c, name="xbsf_get_error_string")
            import :: c_int, c_ptr
            integer(c_int), value :: err
            type(c_ptr) :: cptr
         end function
         function strlen_c(ptr) result(l) bind(c, name="strlen")
            import :: c_ptr, c_int
            type(c_ptr), value :: ptr
            integer(c_int) :: l
         end function
      end interface

      cstr = xbsf_get_error_string_c(int(ierr, c_int))
      cstr_len = strlen_c(cstr)
      block
         character(len = cstr_len, kind = c_char), pointer :: str_ptr
         call c_f_pointer(cstr, str_ptr)
         str = str_ptr
      end block
      print *, '"', str, '"', len(str), allocated(str)
   end function

```

On the callee side, that `print *` statement reports everything correct as supposed to be.  
However, on the caller side, the return value string becomes an empty allocated string, with 0 length.

---

<div class="post-metadata">

**Author:** ![PierU](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pieru/32/1848_2.png) [@PierU](https://fortran-lang.discourse.group/u/PierU)\
**Post date:** [February 12, 2025, 10:24am UTC](https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527/19 "2025-02-12T10:24:10Z")

</div>

> [@mEm](#):
>
> ```auto
> block
> character(len = cstr_len, kind = c_char), pointer :: str_ptr
> call c_f_pointer(cstr, str_ptr)
> str = str_ptr
> end block
> 
> ```

What about instead:

```auto
      block
         character(kind = c_char), pointer :: str_ptr(:)
         integer :: i
         call c_f_pointer(cstr, str_ptr, shape=[cstr_len])
         allocate( character(cstr_len-1) :: str )
         do i = 1,cstr_len-1
            str(i:i) = str_ptr(i)
         end do
      end block

```

the `cstr_len - 1` accounts for the `c_null_char` character at the end of the C “string”.

---

<div class="post-metadata">

**Author:** ![mEm](https://avatars.discourse-cdn.com/v4/letter/m/90ced4/32.png) [@mEm](https://fortran-lang.discourse.group/u/mEm)\
**Post date:** [February 12, 2025, 10:50am UTC](https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527/20 "2025-02-12T10:50:09Z")

</div>

I don’t think you need the `-1`, since `strlen` should already give you the strlen **up to** the null char. In fact, doing as you suggest, on the callee side, the allocated `str` has the last string character missing.  
In any case, regardless of this aspect, the behavior does not change. Still the caller at the return site sees an allocated 0-length string.

[Next page](https://fortran-lang.discourse.group/t/iso-c-binding-interface-to-a-c-function-returning-a-string/527.md?page=2)
