# Iso\_c\_binding: Looking for practical example of how it helps with mangling

**URL:** <https://fortran-lang.discourse.group/t/iso-c-binding-looking-for-practical-example-of-how-it-helps-with-mangling/3393>\
**Category:** Uncategorized\
**Created:** [May 6, 2022, 1:29pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-looking-for-practical-example-of-how-it-helps-with-mangling/3393 "2022-05-06T13:29:56Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![giraffe](https://avatars.discourse-cdn.com/v4/letter/g/f1d935/32.png) [@giraffe](https://fortran-lang.discourse.group/u/giraffe)\
**Post date:** [May 6, 2022, 1:29pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-looking-for-practical-example-of-how-it-helps-with-mangling/3393/1 "2022-05-06T13:29:56Z")

</div>

After reading a wikipedia about [mangling](https://en.m.wikipedia.org/wiki/Name_mangling), I feel that I don’t understand the need for iso\_c\_binding.

Question: Can you give me a simple practical example which shows the importance of iso\_c\_binding.

Basically, I’d like to know what can happen without it.

I’m looking for intuition in an explanation.

I’m looking for a complete example. I want to really really understand it, so give me your best explanation.

Thank you,

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [May 6, 2022, 1:45pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-looking-for-practical-example-of-how-it-helps-with-mangling/3393/2 "2022-05-06T13:45:01Z")

</div>

I have been tweeting about Fortran interoperability with C. Here are two simple examples.

> Arguments corresponding to non-pointer arguments of C functions must have the VALUE attribute in the Fortran interface. A C const argument can be INTENT(IN) in the Fortran interface.

xsum\_vec.f90

```auto
program test_sum_vec
use iso_c_binding, only: c_double, c_int
implicit none
interface
pure function sum_vec(x, n) result(xsum) bind(c)
import c_double, c_int
integer(kind=c_int), intent(in), value :: n
real(kind=c_double), intent(in) :: x(n)
real(kind=c_double) :: xsum
end function sum_vec
end interface
integer(kind=c_int), parameter :: n = 3
real(kind=c_double) :: x(n) = real([10,20,30], kind=c_double)
print "(*(1x,f0.1))",x,sum_vec(x,n) ! 10.0 20.0 30.0 60.0
end program test_sum_vec

```

sum\_vec.c

```auto
double sum_vec(double x[], const int n) {
	double xsum = 0.0;
	for (int i=0; i<n; i++)
		xsum += x[i];
	return xsum;
}

```

compile with

```auto
gcc -c -o sum_vec.o sum_vec.c
gfortran sum_vec.o xsum_vec.f90

```

Here is an example of Fortran passing a derived type to C.

> Use the bind(c) attribute to make a derived type compatible with C, with restrictions listed at [Derived Types and struct (The GNU Fortran Compiler)](https://gcc.gnu.org/onlinedocs/gfortran/Derived-Types-and-struct.html)

date\_type.f90

```auto
program date_type
use iso_c_binding, only: c_int
implicit none
type, bind(c) :: date
   integer (kind=c_int) :: year, month, day
end type date
interface
subroutine print_date(d) bind(c)
import date
type(date), intent(in), value :: d
end subroutine print_date
end interface
call print_date(date(2022,5,4)) ! 2022-05-04
end program date_type

```

date\_type.c

```auto
#include <stdio.h>
typedef struct date {
	int year, month, day;
} date;

void print_date(date d)
{
	printf("%d-%02d-%02d\n",d.year,d.month,d.day);
}

```

Compile with

```auto
gcc -c date_type.c
gfortran date_type.o date_type.f90

```

---

<div class="post-metadata">

**Author:** ![everythingfunctional](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/everythingfunctional/32/176_2.png) [@everythingfunctional](https://fortran-lang.discourse.group/u/everythingfunctional)\
**Post date:** [May 6, 2022, 1:52pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-looking-for-practical-example-of-how-it-helps-with-mangling/3393/3 "2022-05-06T13:52:37Z")

</div>

The `iso_c_binding` module has nothing at all to do with name mangling. The use of `bind(c)` is what **prevents** name mangling from occurring, so that one can rely on the names of procedures between C and Fortran.

For example, two different compilers may mangle procedure names in two different ways, making it impossible to reliably call those procedures from C. I.e.

```auto
function add_one(x) result(plus_one)
  integer, intent(in) :: x
  integer :: plus_one

  plus_one = x + 1
end function

```

When compiled with gfortran may end up with the name `add_one_`, and thus need to be called from C like

```auto
extern int function add_one_(int*);
y = add_one_(*x);

```

but when compiled with ifort, may end up with the name `_add_one` and thus the C code no longer works. If you say that the procedure is `bind(c)`, (which it can only be if the kinds of the arguments are C interoperable, hence where the `iso_c_binding` module comes in), then the compiler is obliged not to mangle the name, or use the one provided. I.e.

```fortran
function add_one(x) bind(c, name="foo")
  use iso_c_binding, only: c_int
  integer(c_int), intent(in), value :: x
  integer(c_int) :: add_one
  add_one = x + 1
end function

```

Can then be called on any system with any compiler as

```auto
extern int function foo(int);
y = foo(x);

```

---

<div class="post-metadata">

**Author:** ![rwmsu](https://avatars.discourse-cdn.com/v4/letter/r/48db29/32.png) [@rwmsu](https://fortran-lang.discourse.group/u/rwmsu)\
**Post date:** [May 6, 2022, 2:01pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-looking-for-practical-example-of-how-it-helps-with-mangling/3393/4 "2022-05-06T14:01:31Z")

</div>

The issue with mangling arises from how different OS’s (Windows, Linux, AIX, etc) and related compilers handled the naming of Fortran objects. In Linux/Unix Fortran names usually had either one or two underscores appended at the end of the name. ie

void some\_function\_  
or  
void some\_function\_

If I remember correctly, IBM AIX assumed all lower case names and Cray T3E, C90 etc. assumed all uppercase with no extra characters (underscores etc). Therefore, if you wanted to support a wide range of OS’s and compilers you had to write #ifdef’s to handle each case. Not sure about Window’s since I haven’t written anything for Windows in over 27 years. The greatest importance of ISO\_C\_BINDING is that it specifies a standard way of interfacing Fortran with C and this goes beyond just the name mangling. It defines what variables in Fortran can be directly passed to C and vice-versa and a way to handle C pointers etc in Fortran and provides explicit interfaces that can be checked by the compiler to decide if it needs to do a copy in etc. There is also the issue of pass by reference vs pass by value. Many C procedures will pass some of its argument by value etc. Without ISO\_C\_BINDING, you will have to write a your own C wrappers etc.

If you want complete examples of how ISO\_C\_BINDING is used in real world applications, Look at the HDF5 interfaces

[https://www.hdfgroup.org/solutions/hdf5](https://www.hdfgroup.org/solutions/hdf5)

my part of the netCDF fortran interfaces

> **[Release netCDF-Fortran v4.5.4 · Unidata/netcdf-fortran](https://github.com/Unidata/netcdf-fortran/releases/v4.5.4)**
>
> 4.5.4 - January 7, 2022
> Requirements
> 
> netCDF-C: 4.7.4+
> 
> Changes
> 
> Various bug fixes and updates.
> Now allow setting of parallel I/O test launcher to something other than mpiexec with the --with-mpiex...

my Fortran interfaces to the SINTEF SISL NURBS library

> **[GitHub - rweed/forSISL: Modern Fortran interfaces to the SINTEF Spline...](https://github.com/rweed/forSISL)**
>
> Modern Fortran interfaces to the SINTEF Spline Library (SISL) - GitHub - rweed/forSISL: Modern Fortran interfaces to the SINTEF Spline Library (SISL)

and @vmagnin’s GTK interfaces

> **[Home · vmagnin/gtk-fortran Wiki](https://github.com/vmagnin/gtk-fortran/wiki)**
>
> A GTK / Fortran binding. Contribute to vmagnin/gtk-fortran development by creating an account on GitHub.

I’m sure several other examples will pop up if you do a web search

---

<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:** [May 6, 2022, 2:04pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-looking-for-practical-example-of-how-it-helps-with-mangling/3393/5 "2022-05-06T14:04:44Z")

</div>

To add to Brad’s (@everythingfunctional ) answer, you can take a look at the name mangling in action via Godbolt: [Compiler Explorer](https://godbolt.org/z/713n89aE9). The mangling problems get worse if you want to use module subprograms, which however bring a lot of advantages including interface checking, encapsulation and data hiding.

If you only ever plan to work with a specific version of one compiler on a single operating system, then you could _pretend_ that `bind(c)` doesn’t matter, and just account for the name mangling differences manually.

However using `bind(c)` and interoperable type definitions is a portability enhancement and form of insurance. Just consider how much pain a shift from 32-bit to 64-bit OS is causing you (and us at Discourse). Using `bind(c)` is essentially protecting yourself against such problems in the future by relying upon established calling conventions.

---

<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:** [May 6, 2022, 2:05pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-looking-for-practical-example-of-how-it-helps-with-mangling/3393/6 "2022-05-06T14:05:23Z")

</div>

Note it is **not** `iso_c_binding` that is relevant, it is `BIND(C, name=..)` clause.

Say you are on **64-bit Windows** and have a Fortran subroutine like so:

```fortran
subroutine sub( s )
   character(len=*), intent(in) :: s
   print *, s
end subroutine 

```

And toward this an unsuspecting user writes a C caller:

```auto
extern void sub(char *, int);
int main() {
    char s[] = "Hello World!";
    sub(s, 12);
}

```

The user will fail to create a program:

```auto
C:\temp>gfortran -c c.c

C:\temp>gfortran -c f.f90

C:\temp>gfortran c.o f.o -o c.exe
c:/program files/codeblocks/gfortran/bin/../lib/gcc/x86_64-w64-mingw32/11.0.0/../../../../x86_64-w64-mingw32/bin/ld.exe: c.o:c.c:(.text+0x33): undefined reference to `sub'
collect2.exe: error: ld returned 1 exit status

```

because the name is “mangled” to `SUB`, though it is simple enough in this case as all uppercase version of the Fortran subprogram. But that is on 64-bit Windows with more streamlined convention from Microsoft.

Instead if the user were to be on 32-bit Windows where different calling conventions are possible - e.g., `STDCALL` or `C` - the name mangling involves further “decorations” e.g., `_SUB` or `_SUB@8`, etc. that will be confusing to the user.

Similar issues arise on different platforms each with its own variations.

With standard interoperability with `BIND(C, name=..)` clause, the coder can choose to christen the subprogram interoperably with the C processor in a portable manner.

---

<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:** [May 6, 2022, 9:29pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-looking-for-practical-example-of-how-it-helps-with-mangling/3393/7 "2022-05-06T21:29:11Z")

</div>

Building upon my earlier post, if you have the following function in a module

```auto
module m
  use, intrinsic :: iso_c_binding, only: c_int
  implicit none
contains

integer(c_int) function add_one(x)
  integer(c_int), intent(in), value :: x
  integer(c_int) :: add_one
  add_one = x + 1
end function

end module

```

the output with x86-64 gfortran 11.3 will be named `__m_MOD_add_one`, however with x86-64 ifort 2021.5 it will be named `m_mp_add_one_`.

If you add `bind(c)` it will be called `add_one` in both cases, just as the C caller would expect. You could interpret this as a friendship gesture towards C programmers who will be using the Fortran routine as a black-box, and they will not need to worry about name mangling, if they will ever need a different Fortran compiler.

From the snippets of code you (@giraffe) have shown before, it appears your project isn’t using modules, but only external subprograms. The Fortran compilers I could test on GodBolt all used the mangling convention of appending a single underscore in this case, i.e. the output would be named `add_one_`.

In an earlier thread you wrote:

> ISO\_C\_BINDING involves more code which can be considered clutter by some people, not me of course! 👩‍🏭
> 
> I do believe that people can be prejudiced to what they perceive to be unnecessary clutter if they only want the code to work on a specific operating system and aren’t planning for other contingencies.

You could certainly go down this route, but along the lines of @themos, the technical debt will come to bite those people at some point, just as they have been bitten now when porting from a 32- to a 64-bit operating system (albeit on a different issue of widths). Out of curiosity, in which language are you (or your company) planning to do the rewrite in?

Concerning unneccesary clutter, you can reduce it by packing your subroutines in a module, then you will need only a single `use, intrinsic :: iso_c_binding` statement. If you are annoyed by the verbose parameter constants such as `c_double` and `c_int`, use renaming upon import, i.e.

```auto
use, intrinsic :: iso_c_binding, only: dp => c_double, ip => c_int

```

---

<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:** [May 6, 2022, 9:49pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-looking-for-practical-example-of-how-it-helps-with-mangling/3393/8 "2022-05-06T21:49:40Z")

</div>

For the record, you can try to “protect” yourself from name mangling issues by the disciplined use of C preprocessor macros. Take a look at how NLopt solves this: [nlopt/f77api.c at 4a0e93ce177dc8bf0f7cf7e3f3e52521b0553958 · stevengj/nlopt · GitHub](https://github.com/stevengj/nlopt/blob/4a0e93ce177dc8bf0f7cf7e3f3e52521b0553958/src/api/f77api.c#L94)  
The preprocessing is spread over three files in total, but would still fail if a new name-mangling scheme were introduced. Using `bind(c)` however, you can write a fully compatible and type-safe interface: [GitHub - grimme-lab/nlopt-f: Fortran bindings for the NLopt library](https://github.com/grimme-lab/nlopt-f). (note in this case, the wrapping goes in the “other” direction, Fortran calling C, but the issues are the same)
