Skip to content

Commit 6e6c3f2

Browse files
authored
Merge pull request #93 from musm/matfile
Improve matfile handling
2 parents c56e9e5 + 8cdd6fc commit 6e6c3f2

File tree

2 files changed

+38
-29
lines changed

2 files changed

+38
-29
lines changed

src/matfile.jl

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,42 @@ type MatFile
55
filename::String
66

77
function MatFile(filename::String, mode::String)
8-
p = ccall(mat_open[], Ptr{Void}, (Ptr{Cchar}, Ptr{Cchar}),
9-
filename, mode)
10-
new(p, filename)
8+
p = ccall(mat_open[], Ptr{Void}, (Ptr{Cchar}, Ptr{Cchar}), filename, mode)
9+
self = new(p, filename)
10+
finalizer(self, release)
11+
return self
1112
end
1213
end
1314
MatFile(filename::String) = MatFile(filename, "r")
1415

15-
function close(f::MatFile)
16-
if f.ptr != C_NULL
17-
ret = ccall(mat_close[], Cint, (Ptr{Void},), f.ptr)
18-
ret == 0 || error("Failed to close file.")
16+
function unsafe_convert(::Type{Ptr{Void}}, f::MatFile)
17+
ptr = f.ptr
18+
ptr == C_NULL && throw(UndefRefError())
19+
return ptr
20+
end
21+
22+
function release(f::MatFile)
23+
ptr = f.ptr
24+
if ptr != C_NULL
25+
ccall(mat_close[], Cint, (Ptr{Void},), ptr)
1926
end
27+
f.ptr = C_NULL
28+
return nothing
29+
end
30+
31+
function close(f::MatFile)
32+
ret = ccall(mat_close[], Cint, (Ptr{Void},), f)
33+
ret != 0 && throw(MEngineError("failed to close file (err = $ret)"))
34+
f.ptr = C_NULL
35+
return nothing
2036
end
2137

38+
2239
# get & put variables
2340

2441
function get_mvariable(f::MatFile, name::String)
25-
f.ptr != C_NULL || error("Cannot get variable from a null file.")
26-
pm = ccall(mat_get_variable[], Ptr{Void}, (Ptr{Void}, Ptr{Cchar}),
27-
f.ptr, name)
28-
pm != C_NULL || error("Attempt to get variable $(name) failed.")
42+
pm = ccall(mat_get_variable[], Ptr{Void}, (Ptr{Void}, Ptr{Cchar}), f, name)
43+
pm == C_NULL && error("Attempt to get variable $(name) failed.")
2944
MxArray(pm)
3045
end
3146

@@ -35,11 +50,9 @@ get_variable(f::MatFile, name::String) = jvalue(get_mvariable(f, name))
3550
get_variable(f::MatFile, name::Symbol) = jvalue(get_mvariable(f, name))
3651

3752
function put_variable(f::MatFile, name::String, v::MxArray)
38-
f.ptr != C_NULL || error("Cannot put variable to a null file.")
39-
v.ptr != C_NULL || error("Cannot put an null variable.")
40-
ret = ccall(mat_put_variable[], Cint, (Ptr{Void}, Ptr{Cchar}, Ptr{Void}),
41-
f.ptr, name, v.ptr)
42-
ret == 0 || error("Attempt to put variable $(name) failed.")
53+
ret = ccall(mat_put_variable[], Cint, (Ptr{Void}, Ptr{Cchar}, Ptr{Void}), f, name, v)
54+
ret != 0 && error("Attempt to put variable $(name) failed.")
55+
return nothing
4356
end
4457

4558
put_variable(f::MatFile, name::Symbol, v::MxArray) = put_variable(f, string(name), v)
@@ -57,18 +70,14 @@ end
5770

5871
function write_matfile(filename::String; kwargs...)
5972
mf = MatFile(filename, "w")
60-
try
61-
put_variables(mf; kwargs...)
62-
finally
63-
close(mf)
64-
end
73+
put_variables(mf; kwargs...)
74+
close(mf)
6575
end
6676

6777
function variable_names(f::MatFile)
6878
# get a list of all variable names
6979
_n = Cint[0]
70-
_a = ccall(mat_get_dir[], Ptr{Ptr{Cchar}}, (Ptr{Void}, Ptr{Cint}),
71-
f.ptr, _n)
80+
_a = ccall(mat_get_dir[], Ptr{Ptr{Cchar}}, (Ptr{Void}, Ptr{Cint}), f, _n)
7281

7382
n = Int(_n[1])
7483
a = unsafe_wrap(Array, _a, (n,))
@@ -91,11 +100,7 @@ end
91100

92101
function read_matfile(filename::String)
93102
f = MatFile(filename, "r")
94-
local r
95-
try
96-
r = read_matfile(f)
97-
finally
98-
close(f)
99-
end
103+
r = read_matfile(f)
104+
close(f)
100105
return r
101106
end

test/matfile.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,7 @@ gc() # make sure that ra, rb, rc, rd remain valid
4848
@test !jscalar(get_field(rss, 2, "y"))
4949
@test jvector(get_field(rss, 2, "z")) == ss[2].z
5050

51+
# segfault on deleted references
52+
s = MatFile("test.mat", "r")
53+
close(s)
54+
@test_throws UndefRefError close(s)

0 commit comments

Comments
 (0)