# Julia passing a string to Fortran

**URL:** <https://discourse.julialang.org/t/julia-passing-a-string-to-fortran/74781>\
**Category:** General Usage\
**Tags:** fortran\
**Created:** [January 18, 2022, 3:29am UTC](https://discourse.julialang.org/t/julia-passing-a-string-to-fortran/74781 "2022-01-18T03:29:59Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Chong\_Wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chong_wang/32/20307_2.png) [@Chong\_Wang](https://discourse.julialang.org/u/Chong_Wang)\
**Post date:** [January 18, 2022, 3:29am UTC](https://discourse.julialang.org/t/julia-passing-a-string-to-fortran/74781/1 "2022-01-18T03:29:59Z")

</div>

How can I pass a string to Fortran? The following methods doesn’t seem to work

```julia
julia> T = Ref{Char}
Ref{Char}

julia> Base.unsafe_convert(T, Base.cconvert(T, "foo"))
ERROR: MethodError: Cannot `convert` an object of type String to an object of type Char

```

Here, If I choose `T` to be `Ref{Char}, Ref{String}, Ref{Cstring}`, `unsafe_convert` errors. If instead I choose `T` to be `Cstring` or `String`, the Fortran side seems to get an empty string.

Minimum example:

```fortran
module julia_interface

implicit none

public :: print_name

private

CONTAINS

subroutine print_name(name)
    character(len=*), intent(in) :: name
    print *, name
end subroutine print_name

end module julia_interface

```

```julia
ccall(
    (:julia_interface_mp_print_name_, "./julia_interface.so"),
    Cvoid,
    (Cstring,),
    "foo"
)

```

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [January 18, 2022, 3:57am UTC](https://discourse.julialang.org/t/julia-passing-a-string-to-fortran/74781/2 "2022-01-18T03:57:36Z")

</div>

Fortran strings are fix-length so `Vector{Char}` instead of `String / Cstring`? (which are null terminated)

---

<div class="post-metadata">

**Author:** ![Chong\_Wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chong_wang/32/20307_2.png) [@Chong\_Wang](https://discourse.julialang.org/u/Chong_Wang)\
**Post date:** [January 18, 2022, 4:01am UTC](https://discourse.julialang.org/t/julia-passing-a-string-to-fortran/74781/3 "2022-01-18T04:01:32Z")

</div>

Here’s what I get:

```julia
ERROR: LoadError: MethodError: Cannot `convert` an object of type String to an object of type Vector{Char}

```

---

<div class="post-metadata">

**Author:** ![Ralph\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ralph_smith/32/10344_2.png) [@Ralph\_Smith](https://discourse.julialang.org/u/Ralph_Smith)\
**Post date:** [January 18, 2022, 4:03am UTC](https://discourse.julialang.org/t/julia-passing-a-string-to-fortran/74781/4 "2022-01-18T04:03:32Z")

</div>

with recent gfortran,

```julia
ccall((:__julia_interface_MOD_print_name, "./libx.so"), Cvoid, (Ptr{UInt8}, Clong), str, length(str))

```

works.  
Otherwise, you may need to read the fine print in your compiler manual.

---

<div class="post-metadata">

**Author:** ![Chong\_Wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chong_wang/32/20307_2.png) [@Chong\_Wang](https://discourse.julialang.org/u/Chong_Wang)\
**Post date:** [January 18, 2022, 4:10am UTC](https://discourse.julialang.org/t/julia-passing-a-string-to-fortran/74781/5 "2022-01-18T04:10:12Z")

</div>

Care to share `Mod_print_name`?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 18, 2022, 4:11am UTC](https://discourse.julialang.org/t/julia-passing-a-string-to-fortran/74781/6 "2022-01-18T04:11:21Z")

</div>

The best thing is to define `ISO_C_BINDING` interfaces on the Fortran side. Otherwise the string-passing ABI is compiler-dependent AFAIK.

---

<div class="post-metadata">

**Author:** ![Ralph\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ralph_smith/32/10344_2.png) [@Ralph\_Smith](https://discourse.julialang.org/u/Ralph_Smith)\
**Post date:** [January 18, 2022, 4:17am UTC](https://discourse.julialang.org/t/julia-passing-a-string-to-fortran/74781/7 "2022-01-18T04:17:11Z")

</div>

> [@Chong\_Wang](#):
>
> Care to share `Mod_print_name` ?

That’s just the linkage symbol I got by compiling your Fortran code with gfortran.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 18, 2022, 4:19am UTC](https://discourse.julialang.org/t/julia-passing-a-string-to-fortran/74781/8 "2022-01-18T04:19:27Z")

</div>

> [@jling](#):
>
> Fortran strings are fix-length so `Vector{Char}` instead of `String / Cstring` ?

No. `Char` is 4 bytes but uses a Julia-specific encoding (that maps directly to UTF8). Fortran characters are 1-byte by default in most compilers, and were intended originally for ASCII but maybe could be used for UTF-8 encoded Unicode if the Fortran code doesn’t look at them too closely. Some Fortran compilers also support UTF32 or UTF16 (sometimes archaically called ucs4 and ucs2) via different character “kinds”, but only if the Fortran code declares it explicitly.

But never pass `Char` data directly. If the Fortran code is expecting UTF32, you can get it via `[UInt32(c) for c in str]`

---

<div class="post-metadata">

**Author:** ![Chong\_Wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chong_wang/32/20307_2.png) [@Chong\_Wang](https://discourse.julialang.org/u/Chong_Wang)\
**Post date:** [January 20, 2022, 4:52am UTC](https://discourse.julialang.org/t/julia-passing-a-string-to-fortran/74781/9 "2022-01-20T04:52:46Z")

</div>

Here is how it works for me:

Fortran interface

```fortran
module julia_interface

use ISO_C_BINDING

implicit none

public :: print_name

private

CONTAINS

subroutine print_name(name, length)
    character(kind=C_CHAR, len=length), intent(in) :: name
    integer, intent(in) :: length
    print *, name
end subroutine print_name

end module julia_interface

```

Julia `ccall`

```julia
str = "foo"
ccall(
    (:julia_interface_mp_print_name_, "./julia_interface.so"),
    Cvoid,
    (Cstring, Ref{Int32}),
    str, length(str)
)

```

Honestly, I still don’t understand exactly what is happening under the hook. I learned a bit about Fortran during the past two days, with the sole purpose of wrapping a subroutine in Julia. I assume Julia will automatically add a `\0` to `foo` so the actual length is 4, which is not needed on the Fortran side?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 21, 2022, 2:32am UTC](https://discourse.julialang.org/t/julia-passing-a-string-to-fortran/74781/10 "2022-01-21T02:32:55Z")

</div>

> [@Chong\_Wang](#):
>
> I assume Julia will automatically add a `\0` to `foo` so the actual length is 4, which is not needed on the Fortran side?

Actually, Julia strings internally _already_ have a zero byte at the end of their data, to make it easier to pass them to C libraries without copying the data.

When you declare the argument as `Cstring`, however, it checks that the string contains no 0 bytes (and throws an error if there are), since this would lead to a corrupted string in a C routine expecting NUL-terminated data. You don’t want that here because Fortran doesn’t treat 0 as the end of the string, and you are passing the length explicitly. So you should declare the argument as `Ptr{UInt8}` instead.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 21, 2022, 2:44am UTC](https://discourse.julialang.org/t/julia-passing-a-string-to-fortran/74781/11 "2022-01-21T02:44:05Z")

</div>

> [@Chong\_Wang](#):
>
> ```julia
> subroutine print_name(name, length)
> 
> ```

You should declare this as `subroutine print_name(name, length) bind(C)`. That way you should be able to `ccall` it as `:print_name` without compiler-specific name-mangling (`:julia_interface_mp_print_name_` is not portable). See e.g. [the gfortran docs](https://gcc.gnu.org/onlinedocs/gfortran/Interoperable-Subroutines-and-Functions.html) on interoperating with C.

> [@Chong\_Wang](#):
>
> `integer, intent(in) :: length`

I would declare this as `integer(C_INT)` rather than `integer`, in which case you can use `Cint` (rather than `Int32`) as the argument type in Julia and be sure that will work, even if the Fortran code is compiled in ILP64 mode.

Better yet, declare it as `integer(C_INTPTR_T)`, in which case you can simply pass the size as `Int` (the corresponding type in Julia) and it will work on a 64-bit machine even in the unlikely event that your string is more than 2GiB in length.

You can also use the `VALUE` attribute for the variable, in which case you don’t need `Ref` in the `ccall` (the value is passed directly, not as a pointer).

---

<div class="post-metadata">

**Author:** ![Chong\_Wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chong_wang/32/20307_2.png) [@Chong\_Wang](https://discourse.julialang.org/u/Chong_Wang)\
**Post date:** [January 23, 2022, 9:17pm UTC](https://discourse.julialang.org/t/julia-passing-a-string-to-fortran/74781/12 "2022-01-23T21:17:08Z")

</div>

Thanks, here is my new interface

```fortran
module julia_interface

use ISO_C_BINDING

implicit none

public :: print_name

private

CONTAINS

subroutine print_name(name, length) bind(C)
    character(kind=C_CHAR), dimension(*), intent(in) :: name
    integer(kind=C_Int), value, intent(in) :: length
    print *, name(1:length)
end subroutine print_name

end module julia_interface

```

and `ccall`

```julia
str = "foo"
ccall(
    (:print_name, "./julia_interface.so"),
    Cvoid,
    (Ptr{UInt8}, Cint),
    str, length(str)
)

```

Just want to mention I have to change `name` to assumed-size array because otherwise the compiler complains “A character dummy argument with length other than 1 is not interoperable”.
