Hello everyone. I’ve been performing some tests to try and port some functionality from a Fortran module to Julia.
While testing out some of Julia’s interoperability features with Fortran I have run into some issues when dealing with Fortran derived types with nested derived types. My objective is to initialize the structure in Fortran and then access the information from Julia.
I have the following Fortran code:
MODULE derived_types
USE iso_c_binding
IMPLICIT NONE
TYPE :: Point
INTEGER :: x, y, z
END TYPE Point
TYPE :: ContainerPointerDerived
TYPE(Point), POINTER :: x(:)
END TYPE ContainerPointerDerived
TYPE :: ContainerAllocatableDerived
TYPE(Point), ALLOCATABLE :: x(:)
END TYPE ContainerAllocatableDerived
CONTAINS
SUBROUTINE initialize_point(p, i) BIND(C)
TYPE(Point), INTENT(INOUT) :: p
INTEGER, INTENT(IN) :: i
p%x = i
p%y = i * 2
p%z = i * 4
END SUBROUTINE initialize_point
SUBROUTINE initialize_container_pointer_derived(c, l) BIND(C)
TYPE(ContainerPointerDerived), INTENT(INOUT) :: c
INTEGER, INTENT(IN) :: l
INTEGER :: i
ALLOCATE(c%x(l))
DO i = 1, l
CALL initialize_point(c%x(i), i)
END DO
END SUBROUTINE initialize_container_pointer_derived
SUBROUTINE initialize_container_allocatable_derived(c, l) BIND(C)
TYPE(ContainerAllocatableDerived), INTENT(INOUT) :: c
INTEGER, INTENT(IN) :: l
INTEGER :: i
ALLOCATE(c%x(l))
DO i = 1, l
CALL initialize_point(c%x(i), i)
END DO
END SUBROUTINE initialize_container_allocatable_derived
END MODULE derived_types
And the following Julia code:
mutable struct Point
x::Cint
y::Cint
z::Cint
function Point()
p = new()
return p
end
end
mutable struct ContainerPointerDerived
x::Ptr{Ptr{Point}}
function ContainerPointerDerived()
cpd = new()
return cpd
end
end
mutable struct ContainerAllocatableDerived
x::Ptr{Ptr{Point}}
function ContainerAllocatableDerived()
cad = new()
return cad
end
end
cpd = ContainerPointerDerived()
ccall((:initialize_container_pointer_derived, "./lib/derived-types.so"), Cvoid, (Ref{ContainerPointerDerived}, Ref{Cint}), cpd, array_len)
println("- Result: ", cpd)
println("- Result wrapping: ", unsafe_wrap(Vector{Ptr{Point}}, cpd.x, array_len))
cad = ContainerAllocatableDerived()
ccall((:initialize_container_allocatable_derived, "./lib/derived-types.so"), Cvoid, (Ref{ContainerAllocatableDerived}, Ref{Cint}), cad, array_len)
println("- Result: ", cad)
println("- Result wrapping: ", unsafe_wrap(Vector{Ptr{Point}}, cad.x, array_len))
This gives the following result:
- Result: ContainerPointerDerived(Ptr{Ptr{Point}} @0x0000000001673240)
- Result wrapping: Ptr{Point}[Ptr{Point} @0x0000000200000001, Ptr{Point} @0x0000000200000004, Ptr{Point} @0x0000000800000004, Ptr{Point} @0x0000000600000003]
forrtl: severe (151): allocatable array is already allocated
Image PC Routine Line Source
derived-types.so 00007F77F78355B7 initialize_contai Unknown Unknown
Unknown 00007F77E1710DB6 Unknown Unknown Unknown
libjulia-internal 00007F77F7A3151C Unknown Unknown Unknown
libjulia-internal 00007F77F7A319BA Unknown Unknown Unknown
libjulia-internal 00007F77F7A32D3B ijl_toplevel_eval Unknown Unknown
sys.so 00007F77E3DBBE68 Unknown Unknown Unknown
libjulia-internal 00007F77F79F8F1E ijl_apply_generic Unknown Unknown
sys.so 00007F77E3BC430E Unknown Unknown Unknown
sys.so 00007F77E3423AF4 Unknown Unknown Unknown
sys.so 00007F77E3423B10 Unknown Unknown Unknown
libjulia-internal 00007F77F79F8F1E ijl_apply_generic Unknown Unknown
sys.so 00007F77E3DF96AB Unknown Unknown Unknown
sys.so 00007F77E3826020 Unknown Unknown Unknown
sys.so 00007F77E3826129 Unknown Unknown Unknown
libjulia-internal 00007F77F79F8F1E ijl_apply_generic Unknown Unknown
libjulia-internal 00007F77F7A5D846 Unknown Unknown Unknown
libjulia-internal 00007F77F7A5E28F jl_repl_entrypoin Unknown Unknown
julia 0000000000401069 main Unknown Unknown
libc.so.6 00007F77F8620D90 Unknown Unknown Unknown
libc.so.6 00007F77F8620E40 __libc_start_main Unknown Unknown
julia 0000000000401099 Unknown Unknown Unknown
My questions are the following:
- How could I extract the contents of the struct? As you can see, I’m currently able to perform the
unsafe_wrap
and obtain the pointers to eachPoint
type, but how I don’t know how to convert thePtr
into the object itself. - The Fortran error indicating that the array is already allocated disappears if I comment the call to the first subroutine. What could be causing this?
Thanks in advance