Created
June 24, 2018 21:54
-
-
Save rdeits/db130355fc55c72b6827f9c6371ce288 to your computer and use it in GitHub Desktop.
Converting an Int64 vector into a C-compatibile Int32 array in-place
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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