Skip to content

Instantly share code, notes, and snippets.

@rdeits
Created June 24, 2018 21:54
Show Gist options
  • Save rdeits/db130355fc55c72b6827f9c6371ce288 to your computer and use it in GitHub Desktop.
Save rdeits/db130355fc55c72b6827f9c6371ce288 to your computer and use it in GitHub Desktop.
Converting an Int64 vector into a C-compatibile Int32 array in-place
# Let's say we have a vector of Int64s, and we need to pass it to a C
# function which expects a vector of Int32s. We could just convert
# every element, but that would allocate an entire new copy of the
# vector, which could be expensive. Instead, we can just shuffle the
# data around in-place, relying on the fact that we can fit two
# Int32s into a single Int64.
function pack_as_int32!(v::Vector{Int64})
p = convert(Ptr{Int32}, pointer(v))
@inbounds for i in eachindex(v)
unsafe_store!(p, v[i], i)
end
p
end
function unpack_as_int32!(v::Vector{Int64})
p = convert(Ptr{Int32}, pointer(v))
@inbounds for i in length(v):-1:1
v[i] = unsafe_load(p, i)
end
end
x = [1,2,3,4,5]
p = pack_as_int32!(x)
@assert p isa Ptr{Int32}
# The data in `x` has been rearranged, and it looks corrupted when viewed
# as Int64s:
x
# But now we can send `x` to a C function which expects an array of Int32s
# by passing the pointer `p`.
# We can even get an unsafe view into the Int32 array with `unsafe_wrap`:
unsafe_wrap(Array, p, (length(x),))
# After calling the C function, we can put all the data back in its
# original location:
unpack_as_int32!(x)
@assert x == [1,2,3,4,5]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment