Return matrix of Cchar from Fortran library

I have been having difficulty getting a Fortran subroutine return a matrix of Cchar to Julia (contained in a struct; in practice there are other components in s_t below). On the Fortran side I have

module test

    use iso_c_binding

    type, bind(c) :: s_t
        character(kind = c_char) :: fmat(8, 2)
    end type

contains

    pure function copy_s2a(s) result(a)
        implicit none
        character(len = *), intent(in) :: s
        character(kind = c_char) :: a(len(s))
        integer :: i
        do i = 1, len(s)
            a(i) = s(i:i)
        end do
    end function copy_s2a

    subroutine c_matrixChar(s) bind(C, name = "C_MatrixChar")
        implicit none
        type(s_t), intent(out) :: s
        s%fmat(:, 1) = copy_s2a('mat1' // c_null_char)
        s%fmat(:, 2) = copy_s2a('mat2' // c_null_char)
    end subroutine c_matrixChar

end module

While on the Julia side I have

using StaticArrays

struct s_t
    fmat::SMatrix{8,2,Cchar}
end

function test()
    sref = Ref{s_t}()
    ccall((:C_MatrixChar, /path/to/lib.so), Cvoid, (Ref{s_t},), sref)
    return sref[]
end

s = test()
println("s.fmat")
println(s.fmat[:,1])

This results in a segmentation fault whenever I try to access fmat. (So this would occur in the final line of the code.)

Note that if I just had a vector of Cchar, e.g. I had fvec::SVector(8) and character(kind = c_char) :: fvec(8) then this would run as expected and I would be able to convert the Cchar array to a string.

What am I doing wrong here?

I wonder if it’s because SMatrix{8, 2, Cchar} isn’t concrete. This catches me a lot. There’s a fourth type parameter that needs to be set to the total number of elements, in this case 16. Try making the type of that field SMatrix{8, 2, Cchar, 16}.

3 Likes

This works. Thanks a lot. This had been driving me crazy trying to figure this one out…

1 Like