Mutating fields of an array of structs originating from C

I am calling a C library that returns a pointer to an array of
structs. My goal is to make views that are arrays of the field
values, much like StructArrays does. However, StructArrays does not let
to mutate the underlying structure but generates a copy. The same
seems to apply to StructViews.

Something like this in pseudocode (working MWE is a bit hard to generate):

struct Ex
    a::Float64
    b::Int64
end

exptr = ccall((:new_ex, libex), Ptr{Ex}, (Cstring, Cdouble), filename, par)

# exptr:
# Ptr{Ex} @0x0000000002f8de20

ex = unsafe_wrap(Array{Ex}, exptr, 2) 
2-element Vector{Ex}:
 Ex(1.0, 1)
 Ex(2.0, 2)

sa_ex = StructArrayLike(ex);

sa_ex.a
2-element Vector{Float64}:
 1.0
 2.0

sa_ex.a[2] = 100.0

ex = unsafe_wrap(Array{Ex}, exptr, 2) 
2-element Vector{Ex}:
 Ex(1.0, 1)
 Ex(100.0, 2)

# The mutated structure could then be passed to a C function: 
retval = ccall((:dosomething, libex), Cint, (Ptr{Ex}, Cint), exptr, k)

Has this been implemented in any package? Could the arrays e.g. be ‘stitched up’ from field value pointers? There are not so many arrays so a less general solution would be acceptable.

It seems that this is not possible, at least with Clang.jl.

Another possibility to work with the library would be to generate and allocate a new structure and call the library with a pointer to that. But if I have understood correctly, it is possible to get pointers only to arrays and not to other objects, right?

Is the only possibility then to write a C helper function that returns pointer to a simple array? CBinding.jl?

I am not exactly sure what you are wanting to do, but StructViews works for your example code. An important detail is if you are using unsafe_wrap multiple times on the same pointer, you should use unsafe_wrap(..., own = false).

julia> using StructViews

julia> struct Ex
           a::Float64
           b::Int64
       end

julia> exptr = reinterpret(Ptr{Ex}, Libc.malloc(1000))
Ptr{Ex} @0x0000000000fe5360

julia> ex = unsafe_wrap(Array{Ex}, exptr, 2, own = false)
2-element Vector{Ex}:
 Ex(6.811895e-317, 0)
 Ex(0.0, 0)

julia> sa_ex = StructView(ex);

julia> sa_ex.a
2-element FieldView{Float64, :a, 1, IndexLinear(), :immutable}:
 6.811895e-317
 0.0

julia> sa_ex.a[2] = 100.0
100.0

julia> ex = unsafe_wrap(Array{Ex}, exptr, 2, own = false)
2-element Vector{Ex}:
 Ex(6.811895e-317, 0)
 Ex(100.0, 0)
1 Like