Iso_c_binding: interface to a C function returning a string

As I mentioned in my earlier post, 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:

#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:

   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>

2 Likes