Hi,
I’m trying to port over some C++ & IDL code to Julia, the code basically opens up a binary file which has a 512 byte header described by a c++ struct. The reaminder of the file is a stack of 8-bit greyscale images, the details of the stack are given in elements of the header.
I can create a struct in Julia to hold the header data, but trying to read in the file fails. This is the code I’m trying.
mutable struct tomheader
xsize::UInt16
ysize::UInt16
zsize::UInt16
lmarg::UInt16
rmarg::UInt16
tmarg::UInt16
bmarg::UInt16
tzmarg::UInt16
bzmarg::UInt16
num_samples::UInt16
num_proj::UInt16
num_blocks::UInt16
num_slices::UInt16
bin::UInt16
gain::UInt16
speed::UInt16
pepper::UInt16
calibrationissue::UInt16
num_frames::UInt16
machine::UInt16
spare_int::Array{UInt16,12}
scale::Float32
offset::Float32
voltage::Float32
current::Float32
thickness::Float32
pixel_size::Float32
distance::Float32
exposure::Float32
mag_factor::Float32
filterb::Float32
correction_factor::Float32
spare_float::Array{Float32,2}
z_shift::UInt32
z::UInt32
theta::UInt32
time::Array{UInt8,26}
duration::Array{UInt8,12}
owner::Array{UInt8,21}
user::Array{UInt8,5}
specimen::Array{UInt8,32}
scan::Array{UInt8,32}
comment::Array{UInt8,64}
spare_char::Array{UInt8,192}
end
f = open(“testfile.tom”,“r”)
th = Ref{tomheader}() // fails with Base.RefValue{tomheader}(undef)
read!(f, th,512)
Unless the C++ code is using Julia arrays you are using the wrong types, for example: Array{UInt8,192}
This is a 192 dimensional Julia array. If the c code you are using specifies unsigned char[192] then the corresponding type is NTuple{192, Uint8} instead.
I don’t do much C interop, but I think you should be using a plain struct rather then a mutable one.
I am on my phone and don’t have a compiler to test with but assuming you made the above changes then
Thank you for the pointer on not needing mutable struct and NTuple for an array of bytes.
It almost works!
I had to add a , to the buffer setup to make it
buffer = Vector{UInt8},(512) It only produced an error otherwise.
Attempting the readbytes line gives the following:
MethodError: no method matching readbytes!(::IOStream, ::Tuple{DataType,Int64}, ::Int64)
Closest candidates are:
readbytes!(::IOStream, !Matched::Array{UInt8,N} where N, ::Any; all) at iostream.jl:484
readbytes!(::IO, !Matched::AbstractArray{UInt8,N} where N, ::Any) at io.jl:913
readbytes!(::IOStream, !Matched::Array{UInt8,N} where N) at iostream.jl:484
buffer = Vector{UInt8},(512) - That won’t really work. It’ll just make buffer a tuple of the Vector{UInt8} type as the first element, and the integer 512 as the second.
To initialize an empty array of length 512, use Vector{UInt8}(undef, 512).
Some code that loads your type from the first 512 bytes of a file may look like:
open("my_file.txt") do file
buffer = Vector{UInt8}(undef, 512)
readbytes!(file, buffer)
return reinterpret(TomHeader, buffer)[1]
end