Yep, that’s done it. The only difference I can see in the code I wrote before
and this code is that previously I had
convert(Ptr{T}, pointer(raw, byte_number))
whereas here we have
convert(Ptr{T}, pointer(raw) + byte_number - 1)
The former construction seems to emit a call to a Julia-intrinsic function,
while the latter executes the more expected simple machine loads. Is there a
subtle difference between the two calls to pointer?
Thanks all for your help!
On March 24, 2015 at 12:19:00 PM, Matt Bauman ([email protected]) wrote:
(The key is to ensure that the method gets specialized for different types with
the parametric `::Type{T}` in the signature instead of `T::DataType`).
On Tuesday, March 24, 2015 at 12:10:59 PM UTC-4, Stefan Karpinski wrote:
This seems like it works fine to me (on both 0.3 and 0.4):
immutable Test
x::Float32
y::Int64
z::Int8
end
julia> a = [Test(1,2,3)]
1-element Array{Test,1}:
Test(1.0f0,2,3)
julia> b = copy(reinterpret(UInt8, a))
24-element Array{UInt8,1}:
0x00
0x00
0x80
0x3f
0x03
0x00
0x00
0x00
0x02
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x03
0xe0
0x82
0x10
0x01
0x00
0x00
0x00
julia> prim_read{T}(::Type{T}, data::Array{Uint8,1}, offset::Int) =
unsafe_load(convert(Ptr{T}, pointer(data) + offset))
prim_read (generic function with 1 method)
julia> prim_read(Test, b, 0)
Test(1.0f0,2,3)
julia> @code_native prim_read(Test, b, 0)
.section __TEXT,__text,regular,pure_instructions
Filename: none
Source line: 1
push RBP
mov RBP, RSP
Source line: 1
mov RCX, QWORD PTR [RSI + 8]
vmovss XMM0, DWORD PTR [RCX + RDX]
mov RAX, QWORD PTR [RCX + RDX + 8]
mov DL, BYTE PTR [RCX + RDX + 16]
pop RBP
ret
On Tue, Mar 24, 2015 at 5:04 PM, Simon Danisch <[email protected]> wrote:
There is a high chance that I simply don't understand llvmcall well enough,
though ;)
Am Montag, 23. März 2015 20:20:09 UTC+1 schrieb Sebastian Good:
I'm trying to read some binary formatted data. In C, I would define an
appropriately padded struct and cast away. Is is possible to do something
similar in Julia, though for only one value at a time? Philosophically, I'd
like to approximate the following, for some simple bittypes T (Int32, Float32,
etc.)
T read<T>(char* data, size_t offset) { return *(T*)(data + offset); }
The transliteration of this brain-dead approach results in the following, which
seems to allocate a boxed Pointer object on every invocation. The pointer
function comes with ample warnings about how it shouldn't be used, and I
imagine that it's not polite to the garbage collector.
prim_read{T}(::Type{T},
data::AbstractArray{Uint8,
1},
byte_number)
=
unsafe_load(convert(Ptr{T},
pointer(data,
byte_number)))
I can reinterpret the whole array, but this will involve a division of the
offset to calculate the new offset relative to the reinterpreted array, and it
allocates an array object.
Is there a better way to simply read the machine word at a particular offset in
a byte array? I would think it should inline to a single assembly instruction
if done right.