You can cast the memory region. However, notice that this is somewhat unsafe and you will need to take care for Julia GC do not deallocate xdata:
function myfunc3(n::Int)
xdata = Vector{Tuple{Int,Int,Int}}(undef, n)
GC.@preserve xdata begin
p = Base.unsafe_convert(Ptr{Int}, xdata)
x = unsafe_wrap(Array, p, 3 * n)
for i in eachindex(x)
x[i] = i
end
end
return xdata
end
julia> @btime myfunc1($n);
2.484 ms (2 allocations: 22.89 MiB)
julia> @btime myfunc2($n);
16.915 ms (2 allocations: 22.89 MiB)
julia> @btime myfunc3($n);
2.487 ms (3 allocations: 22.89 MiB)