# Allocatable Multidimensional Arrays in Fortran

**URL:** <https://discourse.julialang.org/t/allocatable-multidimensional-arrays-in-fortran/119535>\
**Category:** General Usage\
**Tags:** ccall, fortran\
**Created:** [September 18, 2024, 5:47am UTC](https://discourse.julialang.org/t/allocatable-multidimensional-arrays-in-fortran/119535 "2024-09-18T05:47:33Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jason\_Meziere](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jason_meziere/32/207966_2.png) [@Jason\_Meziere](https://discourse.julialang.org/u/Jason_Meziere)\
**Post date:** [September 18, 2024, 5:47am UTC](https://discourse.julialang.org/t/allocatable-multidimensional-arrays-in-fortran/119535/1 "2024-09-18T05:47:33Z")

</div>

I am attempting to wrap a fortran package in Julia. In many of the functions, there are 2D arrays that are specified as `ALLOCATABLE`. Does Julia have a way to handle this? And what is the proper way to pass these values in?

For example, if in the fortran code we have

```julia
REAL(dp),DIMENSION(:,:),ALLOCATABLE:: P !dp has 64-bits precision 

```

and then in Julia, would we do something like

```julia
P=zeros(n,m)
ccall((fun_name_, "path/to/so"), Cvoid, (Ref{Cdouble}), P)

```

---

<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:** [September 18, 2024, 12:38pm UTC](https://discourse.julialang.org/t/allocatable-multidimensional-arrays-in-fortran/119535/3 "2024-09-18T12:38:38Z")

</div>

I don’t think there is a portable way to do this. It’s better to first modify/wrap your Fortran package to use an `ISO_C_BINDING` API. See e.g. [c++ - Allocating memory in C for a Fortran allocatable - Stack Overflow](https://stackoverflow.com/questions/23891769/allocating-memory-in-c-for-a-fortran-allocatable)

---

<div class="post-metadata">

**Author:** ![Jason\_Meziere](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jason_meziere/32/207966_2.png) [@Jason\_Meziere](https://discourse.julialang.org/u/Jason_Meziere)\
**Post date:** [September 18, 2024, 11:26pm UTC](https://discourse.julialang.org/t/allocatable-multidimensional-arrays-in-fortran/119535/4 "2024-09-18T23:26:32Z")

</div>

Do we need to wrap this because of the name mangling only, or are there issues with the data types as well?

---

<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:** [September 19, 2024, 3:07am UTC](https://discourse.julialang.org/t/allocatable-multidimensional-arrays-in-fortran/119535/5 "2024-09-19T03:07:26Z")

</div>

As I understand it, the problem is the data type. Fortran compilers represent `allocatable` arrays with some internal data structure that they don’t document.

---

<div class="post-metadata">

**Author:** ![Jason\_Meziere](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jason_meziere/32/207966_2.png) [@Jason\_Meziere](https://discourse.julialang.org/u/Jason_Meziere)\
**Post date:** [September 19, 2024, 8:58pm UTC](https://discourse.julialang.org/t/allocatable-multidimensional-arrays-in-fortran/119535/6 "2024-09-19T20:58:51Z")

</div>

I think I’m almost getting it here.

So I settled on fortran code that looks like

```julia
module tester
!
use iso_c_binding
!
contains
!
subroutine test1(n,arr) BIND(C)
!
implicit none
integer(c_int):: n
type(c_ptr),intent(inout):: arr
real(SELECTED_REAL_KIND(15,307)),pointer:: farr(:)
integer:: i
!
allocate(farr(4))
n=4
do i=1,n
    farr(i)=i
end do
arr = c_loc(farr)
!
end subroutine test1
!
end module tester

```

I’m able to call it in Julia with

```julia
n = Ref(Int32(2))
arr=pointer_from_objref([2.0,3.0])
a=ccall((:test1,"/home/jmezier2/test/test.so"),Cvoid,(Ptr{Int32},Ptr{Float64}),n,arr)
println(unsafe_pointer_to_objref(arr))

```

but this only prints the first 2 elements of my array, instead of the 4 expected after allocating. Is there a way to recover the other 2 elements?

---

<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:** [September 19, 2024, 9:00pm UTC](https://discourse.julialang.org/t/allocatable-multidimensional-arrays-in-fortran/119535/7 "2024-09-19T21:00:19Z")

</div>

> [@Jason\_Meziere](#):
>
> ```julia
> n = Ref(Int32(2))
> arr=pointer_from_objref([2.0,3.0])
> a=ccall((:test1,"/home/jmezier2/test/test.so"),Cvoid,(Ptr{Int32},Ptr{Float64}),n,arr)
> 
> ```

Don’t do use `pointer_from_objref`. That gives you a pointer to an internal Julia datastructure, not raw array data. To pass an array, you would normally just do:

```julia
arr = [2.0, 3.0]
ccall((:test1,"/home/jmezier2/test/test.so"),Cvoid,(Ref{Int32},Ptr{Float64}),n,arr)

```

Except here, that’s not right either, because `arr` is a pointer argument passed by reference in Fortran, so it should be a `Ref{Ptr{Float64}}` (corresponding to a `double**` in C).

So I think you need something like:

```julia
arr = Ref{Ptr{Float64}}() # uninitialized pointer
ccall((:test1,"/home/jmezier2/test/test.so"),Cvoid,(Ref{Int32},Ref{Ptr{Float64}}),n,arr)
a = unsafe_wrap(Array, arr[], Int(n[]))

```

to get the pointer back and wrap it in an `Array`.

However, you’ll have to be careful about de-allocating the array. You’ll eventually need to deallocate it on the Fortran side, but make sure you don’t reference the Julia array `a` after that.

Note also that you declared `arr` as `inout` but you are only using it as an output argument? Similarly with `n`?

```julia

```

---

<div class="post-metadata">

**Author:** ![Jason\_Meziere](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jason_meziere/32/207966_2.png) [@Jason\_Meziere](https://discourse.julialang.org/u/Jason_Meziere)\
**Post date:** [September 20, 2024, 2:13am UTC](https://discourse.julialang.org/t/allocatable-multidimensional-arrays-in-fortran/119535/8 "2024-09-20T02:13:17Z")

</div>

Ok, wow that works directly as advertised. But why can’t we do something like

```julia
arr = Ptr{Float64}} # uninitialized pointer
ccall((:test1,"/home/jmezier2/test/test.so"),Cvoid,(Ref{Int32},Ref{Ptr{Float64}}),n,arr)

```

Isn’t `convert` supposed to handle this? Or does it get confused with the Ref{Ptr}?

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [September 20, 2024, 7:49am UTC](https://discourse.julialang.org/t/allocatable-multidimensional-arrays-in-fortran/119535/9 "2024-09-20T07:49:47Z")

</div>

> [@Jason\_Meziere](#):
>
> ```julia
> arr = Ptr{Float64}} # uninitialized pointer
> 
> ```

Besides the fact there are unbalanced braces so what you wrote is a syntactic error, there’s no such a thing as an uninitialised pointer in Julia. Side note, I personally find the [`@ccall`](https://docs.julialang.org/en/v1/base/c/#Base.@ccall) macro much more readable than plain `ccall`

---

<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:** [September 20, 2024, 1:14pm UTC](https://discourse.julialang.org/t/allocatable-multidimensional-arrays-in-fortran/119535/10 "2024-09-20T13:14:18Z")

</div>

> [@Jason\_Meziere](#):
>
> Isn’t `convert` supposed to handle this? Or does it get confused with the Ref{Ptr}?

No. Even if you corrected the code to `arr = Ptr{Float64}(0)`, it won’t work because `arr` is bound to an immutable object.

The problem is that passing this `arr` for a `Ref{Ptr{Float64}}` argument doesn’t pass a “pointer to `arr`” — it’s not analogous to passing `&arr` in C. What it does is to construct a _new_ `Ref(arr)` mutable object that wraps a _copy_ of `arr`’s value, and the contents of this _new_ object are what get mutated inside the Fortran subroutine. However, you can’t access the mutated contents after the `ccall` returns, because you didn’t give a name to this new `Ref` object.

To give a simpler example, suppose you have a [C function](https://xkcd.com/221/):

```c
void getRandomNumber(int *x) { 
    *x = 4; // chosen by fair dice roll, guaranteed to be random
}

```

Suppose we call it in Julia by:

```julia
ccall(:getRandomNumber, Cvoid, (Ref{Cint},), 17)

```

How would you get the value `4` out? Clearly, you can’t (and don’t want) to “change the value of `17`” … `17` is an immutable value. What the `ccall` does is to construct a `Ref{Cint}(17)` object, which gets passed as a pointer to the C function, and the contents of _that_ object get mutated.

But if you do

```julia
x = 17
ccall(:getRandomNumber, Cvoid, (Ref{Cint},), x)

```

it is _exactly_ equivalent to passing `17` directly. The function call cannot change the value of `x`, for the same reason that

```julia
y = x
y = 4

```

does not change the value of `x` to `4`. See also the [manual section on assignment vs. mutation](https://docs.julialang.org/en/v1/manual/variables/#man-assignment-expressions).

Instead, you do:

```julia
xref = Ref{Cint}(17)
ccall(:getRandomNumber, Cvoid, (Ref{Cint},), xref)

```

after which `xref[]` (the contents of the `Ref` object) should be `4`.

This is analogous in C to:

```c
int xref[] = {17}; // a mutable container for 17, analogous to Ref{Cint}(17)
getRandomNumber(xref);

```

after which `*xref` should be `4`.

---

<div class="post-metadata">

**Author:** ![Jason\_Meziere](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jason_meziere/32/207966_2.png) [@Jason\_Meziere](https://discourse.julialang.org/u/Jason_Meziere)\
**Post date:** [September 20, 2024, 2:43pm UTC](https://discourse.julialang.org/t/allocatable-multidimensional-arrays-in-fortran/119535/11 "2024-09-20T14:43:06Z")

</div>

Ah, I see, so Julia will automatically convert everything for you, but then you lose access to the reference. So if I just passed a pointer in, I would have access to the old pointer. But I changed to a new pointer in the fortran function and the old pointer would have no knowledge of this. But a reference to that pointer would.

This makes sense. Thank you.
