# Trouble with understanding bind(C)

**URL:** <https://fortran-lang.discourse.group/t/trouble-with-understanding-bind-c/7718>\
**Category:** Help\
**Created:** [March 28, 2024, 5:10pm UTC](https://fortran-lang.discourse.group/t/trouble-with-understanding-bind-c/7718 "2024-03-28T17:10:31Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![mskocic](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/mskocic/32/3378_2.png) [@mskocic](https://fortran-lang.discourse.group/u/mskocic)\
**Post date:** [March 28, 2024, 5:10pm UTC](https://fortran-lang.discourse.group/t/trouble-with-understanding-bind-c/7718/1 "2024-03-28T17:10:31Z")

</div>

I’m trying to understand the behaviour of `bind(C)` which I don’t really get when applied to functions or variables.  
When I compile a static library, functions and variables with `bind(C)` will be global (symbol types T and D) even if `public` is not used.  
However, when I create a shared library from the static one:

- functions with `bind(C)` will be global (symbol type T) even if I did not use `public`.
- variables (might be `protected`) will be local (symbol type d) except if I use `public`.

Did you have a similar experience? I’m really interested in understanding why is it working this way?

_N.B: Very often, I create shared libraries from the static libraries generated by fpm. I would like to avoid `public` for C API functions and variables to avoid polluting the Fortran side but still make C API functions and variables global._

---

<div class="post-metadata">

**Author:** ![Arjen](https://avatars.discourse-cdn.com/v4/letter/a/b9bd4f/32.png) [@Arjen](https://fortran-lang.discourse.group/u/Arjen)\
**Post date:** [March 29, 2024, 9:17am UTC](https://fortran-lang.discourse.group/t/trouble-with-understanding-bind-c/7718/2 "2024-03-29T09:17:34Z")

</div>

Just a few remarks:

- Functions, subroutines and module variables are public by default. You need to use the private attribute or statement explicitly to hide them.
- To ensure that bind(C) routines are not visible on the Fortran side, you might use a mixed-case C name. As Fortran is case-insensitive, a name like “FoO” is very unlikely to be visible. Fortran compilers sometimes use all-lowercase or all-uppercase names for their symbols, but I have never seen one with a mixture.

As I said though, just a few remarks.

---

<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:** [March 29, 2024, 9:44am UTC](https://fortran-lang.discourse.group/t/trouble-with-understanding-bind-c/7718/3 "2024-03-29T09:44:43Z")

</div>

I’d recommend having a closer look at the option [`-fvisibility=...`](https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-fvisibility), which controls the visibility of the symbols in the archive.

The article by Ulrich Drepper, [How To Write Shared Libraries](https://www.cs.dartmouth.edu/~sergey/cs258/ABI/UlrichDrepper-How-To-Write-Shared-Libraries.pdf), gives some advice on this topic in Section 2.2.2, page 18.

Perhaps you can try compiling with `-fvisibility=hidden`, and then check the symbols you expect are exported with `nm -D libfoo.so`?

---

<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:** [March 29, 2024, 7:14pm UTC](https://fortran-lang.discourse.group/t/trouble-with-understanding-bind-c/7718/4 "2024-03-29T19:14:47Z")

</div>

> [@mskocic](#):
>
> When I compile a static library, functions and variables with `bind(C)` will be global (symbol types T and D) even if `public` is not used.

Perhaps it helps to think of this in C language terms. Variables and procedures with `bind(C)` have external linkage, meaning the symbol is visible throughout the whole program.

It has to work this way for interoperability with C:

```auto
// foo.c
int bar = 42;

```

```auto
! foo.f90
module foo
use, intrinsic :: iso_c_binding, only: c_int
implicit none
private
integer(c_int), bind(c,name="bar") :: bar
end module

```

The `private` and `public` attributes in Fortran apply when importing from a module. But nothing prevents you from declaring a second module that binds to the same variable:

```auto
! foo.f90
module foo2
use, intrinsic :: iso_c_binding, only: c_int
implicit none
private
integer(c_int), bind(c,name="bar") :: bar ! same bar as in foo
end module

```

---

<div class="post-metadata">

**Author:** ![septc](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/septc/32/77_2.png) [@septc](https://fortran-lang.discourse.group/u/septc)\
**Post date:** [March 29, 2024, 8:16pm UTC](https://fortran-lang.discourse.group/t/trouble-with-understanding-bind-c/7718/5 "2024-03-29T20:16:59Z")

</div>

Just a related question: I’ve just tried this code (for learning C-interoperability),

```auto
!! lib1.f90
module test1_m
    use iso_c_binding
    private
    public show1

    integer(c_int), bind(c,name="bar") :: bar = 100_c_int
contains
    subroutine show1(); print *, bar; end
end module

!! lib2.f90
module test2_m
    use iso_c_binding
    private
    public show2

    integer(c_int), bind(c,name="bar") :: bar = 200_c_int
contains
    subroutine show2(); print *, bar; end
end module

!! main.f90
program main
    use test1_m
    use test2_m
    implicit none

    call show1()
    call show2()
end

```

But compilartion with gfortran-10 gives (on my mac):

```auto
$ gfortran lib1.f90 lib2.f90 main.f90 
duplicate symbol _bar in:
    /var/folders/9v/gx_yp_3913b9_kc8rzw0vtqc0000jb/T//cccB55Jw.o
    /var/folders/9v/gx_yp_3913b9_kc8rzw0vtqc0000jb/T//ccFVEx25.o
ld: 1 duplicate symbol for architecture x86_64
collect2: error: ld returned 1 exit status

```

with

```auto
$ gfortran -c lib1.f90
$ nm lib1.o
...
0000000000000074 D _bar
(similar for lib2.o)

```

So I wonder the two modules define the same symbol twice? (in contrast to `extern` vs definition in C?)

EDIT: If I remove the initialization (`100_c_int` and `200_c_int`), the code seems to compile without error. Also, if I remove only `200_c_int`, the code compiles and gives `100 100`. So if I do not give the initial value, it works as `extern` thing in C…?

---

<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:** [March 29, 2024, 8:35pm UTC](https://fortran-lang.discourse.group/t/trouble-with-understanding-bind-c/7718/6 "2024-03-29T20:35:17Z")

</div>

> [@septc](#):
>
> So if I do not give the initial value, it works as `extern` thing in C…?

Short answer - yes. You cannot perform the definition (initialization) twice.

In C, you will typically see this pattern as you’ve already alluded to:

```auto
// lib1.c
int bar = 100;
void show1(void) { printf("%d\n", bar); }

```

```auto
// lib2.c
extern int bar;
void show2(void) { printf("%d\n", bar); }

```

You often hit this problem if you define something in a header, which gets included from multiple translation units:

```auto
// name.h
char* surname = "Backus";

```

Generally speaking, global data is frowned upon, so if possible avoid using a global variable across multiple units.

---

<div class="post-metadata">

**Author:** ![mskocic](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/mskocic/32/3378_2.png) [@mskocic](https://fortran-lang.discourse.group/u/mskocic)\
**Post date:** [March 29, 2024, 11:09pm UTC](https://fortran-lang.discourse.group/t/trouble-with-understanding-bind-c/7718/7 "2024-03-29T23:09:31Z")

</div>

I prefix all my module variables and/or functions that will be C interoperable with `capi_*`. This clearly indicates that they are not “pure fortran” variables or functions.

```auto
module example
use iso_c_binding
use iso_fortran_env
private

real(real64), parameter, public :: p
real(c_double), protected, bind(C, name="C_name_for_p") :: capi_p = p
! capi_p will not be global in the shared library if I don't specify `public`

contains

function f(args)
...
end function

function capi_f(args)bind(C, name="C_name_for_f")
! This function will be global in the shared library even I did not use `public`
...
end function

```

From this simple example, I understand that `public` will imply `global` (symbol type T) but this is not the case for variables. I don’t really understand the difference between variables and functions when `bind(C)` is used.

---

<div class="post-metadata">

**Author:** ![mskocic](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/mskocic/32/3378_2.png) [@mskocic](https://fortran-lang.discourse.group/u/mskocic)\
**Post date:** [March 29, 2024, 11:11pm UTC](https://fortran-lang.discourse.group/t/trouble-with-understanding-bind-c/7718/8 "2024-03-29T23:11:43Z")

</div>

Thanks for the reference. I’ll try to dive deeper in understanding the `-fvisibility=hidden` option.
