I’m wondering if this is a correct usage of these unsafe functions:
julia> using StaticArrays
julia> a = MVector{4,UInt}(1,2,3,4);
julia> b = UInt.((5,6,7,8));
julia> function f(a, b)
dst = Base.unsafe_convert(Ptr{MVector{4, UInt64}}, a)
unsafe_store!(dst, b)
return a
end
julia> f(a, b)
4-element MVector{4, UInt64} with indices SOneTo(4):
0x0000000000000005
0x0000000000000006
0x0000000000000007
0x0000000000000008
is it?
Should I use instead
julia> function f(a, b)
GC.@preserve a begin
dst = Base.unsafe_convert(Ptr{MVector{4, UInt64}}, a)
unsafe_store!(dst, b)
end
return a
end
Certainly better, although these things can be very tricky and I don’t think we’re guaranteeing the memory layout here. If at all possible, try to use the APIs provided by the package (which may do similar things, but will likely get caught in PkgEval if we break an implicit assumption). If the issue is performance, file an issue.
To expand on this, you can just use a.data = b here:
julia> using StaticArrays
julia> a = MVector{4, UInt}(1,2,3,4);
julia> b = UInt.((5,6,7,8));
julia> a.data = b;
julia> a
4-element MVector{4, UInt64} with indices SOneTo(4):
0x0000000000000005
0x0000000000000006
0x0000000000000007
0x0000000000000008
If you’re exploring unsafe pointer shenanigans though, it’s perhaps also worth noting if you’re going down this path that you can’t unsafe_load a Ptr{T} when T is a mutable type (like MVector), since the GC will incorrectly reason about the loaded object.