Skip to content

Commit 4e9b244

Browse files
Merge pull request #82 from musm/ginit
Make package precompile safe
2 parents d742965 + e660dcf commit 4e9b244

File tree

6 files changed

+309
-244
lines changed

6 files changed

+309
-244
lines changed

src/MATLAB.jl

Lines changed: 105 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
module MATLAB
1+
__precompile__()
22

3-
using Base.Libdl: dlopen, dlsym, RTLD_LAZY, RTLD_GLOBAL
3+
module MATLAB
44

55
import Base: eltype, close, size, copy, ndims, unsafe_convert
66

@@ -38,26 +38,125 @@ type MEngineError <: Exception
3838
message::String
3939
end
4040

41+
include("init.jl") # initialize Refs
4142
include("mxbase.jl")
4243
include("mxarray.jl")
4344
include("matfile.jl")
44-
4545
include("mstatements.jl")
4646
include("engine.jl")
4747
include("matstr.jl")
4848

4949
function __init__()
50+
51+
# initialize library paths
52+
53+
lib_path = matlab_lib_path()
54+
55+
# load libraries
56+
57+
libmx[] = Libdl.dlopen(joinpath(lib_path, "libmx"), Libdl.RTLD_GLOBAL)
58+
libmat[] = Libdl.dlopen(joinpath(lib_path, "libmat"), Libdl.RTLD_GLOBAL)
59+
libeng[] = Libdl.dlopen(joinpath(lib_path, "libeng"), Libdl.RTLD_GLOBAL)
60+
61+
# mxarray function
62+
63+
mx_destroy_array[] = mxfunc(:mxDestroyArray)
64+
mx_duplicate_array[] = mxfunc(:mxDuplicateArray)
65+
66+
# load functions to access mxarray
67+
68+
mx_free[] = mxfunc(:mxFree)
69+
70+
mx_get_classid[] = mxfunc(:mxGetClassID)
71+
mx_get_m[] = mxfunc(:mxGetM)
72+
mx_get_n[] = mxfunc(:mxGetN)
73+
mx_get_nelems[] = mxfunc(:mxGetNumberOfElements)
74+
mx_get_ndims[] = mxfunc(:mxGetNumberOfDimensions_730)
75+
mx_get_elemsize[] = mxfunc(:mxGetElementSize)
76+
mx_get_data[] = mxfunc(:mxGetData)
77+
mx_get_dims[] = mxfunc(:mxGetDimensions_730)
78+
mx_get_nfields[] = mxfunc(:mxGetNumberOfFields)
79+
mx_get_pr[] = mxfunc(:mxGetPr)
80+
mx_get_pi[] = mxfunc(:mxGetPi)
81+
mx_get_ir[] = mxfunc(:mxGetIr_730)
82+
mx_get_jc[] = mxfunc(:mxGetJc_730)
83+
84+
mx_is_double[] = mxfunc(:mxIsDouble)
85+
mx_is_single[] = mxfunc(:mxIsSingle)
86+
mx_is_int64[] = mxfunc(:mxIsInt64)
87+
mx_is_uint64[] = mxfunc(:mxIsUint64)
88+
mx_is_int32[] = mxfunc(:mxIsInt32)
89+
mx_is_uint32[] = mxfunc(:mxIsUint32)
90+
mx_is_int16[] = mxfunc(:mxIsInt16)
91+
mx_is_uint16[] = mxfunc(:mxIsUint16)
92+
mx_is_int8[] = mxfunc(:mxIsInt8)
93+
mx_is_uint8[] = mxfunc(:mxIsUint8)
94+
mx_is_char[] = mxfunc(:mxIsChar)
95+
96+
mx_is_numeric[] = mxfunc(:mxIsNumeric)
97+
mx_is_logical[] = mxfunc(:mxIsLogical)
98+
mx_is_complex[] = mxfunc(:mxIsComplex)
99+
mx_is_sparse[] = mxfunc(:mxIsSparse)
100+
mx_is_empty[] = mxfunc(:mxIsEmpty)
101+
mx_is_struct[] = mxfunc(:mxIsStruct)
102+
mx_is_cell[] = mxfunc(:mxIsCell)
103+
104+
105+
# load functions to create & delete MATLAB array
106+
107+
mx_create_numeric_matrix[] = mxfunc(:mxCreateNumericMatrix_730)
108+
mx_create_numeric_array[] = mxfunc(:mxCreateNumericArray_730)
109+
110+
mx_create_double_scalar[] = mxfunc(:mxCreateDoubleScalar)
111+
mx_create_logical_scalar[] = mxfunc(:mxCreateLogicalScalar)
112+
113+
mx_create_sparse[] = mxfunc(:mxCreateSparse_730)
114+
mx_create_sparse_logical[] = mxfunc(:mxCreateSparseLogicalMatrix_730)
115+
116+
mx_create_string[] = mxfunc(:mxCreateString)
117+
mx_create_char_array[] = mxfunc(:mxCreateCharArray_730)
118+
119+
mx_create_cell_array[] = mxfunc(:mxCreateCellArray_730)
120+
121+
mx_create_struct_matrix[] = mxfunc(:mxCreateStructMatrix_730)
122+
mx_create_struct_array[] = mxfunc(:mxCreateStructArray_730)
123+
124+
mx_get_cell[] = mxfunc(:mxGetCell_730)
125+
mx_set_cell[] = mxfunc(:mxSetCell_730)
126+
127+
mx_get_field[] = mxfunc(:mxGetField_730)
128+
mx_set_field[] = mxfunc(:mxSetField_730)
129+
mx_get_field_bynum[] = mxfunc(:mxGetFieldByNumber_730)
130+
mx_get_fieldname[] = mxfunc(:mxGetFieldNameByNumber)
131+
132+
mx_get_string[] = mxfunc(:mxGetString_730)
133+
134+
135+
# load I/O mat functions
136+
137+
mat_open[] = matfunc(:matOpen)
138+
mat_close[] = matfunc(:matClose)
139+
mat_get_variable[] = matfunc(:matGetVariable)
140+
mat_put_variable[] = matfunc(:matPutVariable)
141+
mat_get_dir[] = matfunc(:matGetDir)
142+
143+
50144
if is_windows()
51-
global persistent_msession
52145
# workaround "primary message table for module 77" error
53146
# creates a dummy Engine session and keeps it open so the libraries used by all other
54147
# Engine clients are not loaded and unloaded repeatedly
55148
# see: https://www.mathworks.com/matlabcentral/answers/305877-what-is-the-primary-message-table-for-module-77
56-
persistent_msession = MSession(0)
149+
global persistent_msession = MSession(0)
57150
end
58151
end
59152

60-
# deprecations
153+
154+
###########################################################
155+
#
156+
# deprecations
157+
#
158+
###########################################################
159+
61160
function nfields(mx::MxArray)
62161
Base.depwarn("MATLAB.nfields is deprecated, use mxnfields instead.", :nfields)
63162
return mxfields(mx)
@@ -76,5 +175,4 @@ end
76175

77176
@deprecate mxempty() mxarray(Float64,0,0)
78177

79-
80178
end

src/engine.jl

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
# Session open & close
66
#
77
###########################################################
8+
const default_startcmd = matlab_startcmd() * " -nosplash"
89

910
# 64 K buffer should be sufficient to store the output text in most cases
1011
const default_output_buffer_size = 64 * 1024
@@ -15,17 +16,12 @@ type MSession
1516
bufptr::Ptr{UInt8}
1617

1718
function MSession(bufsize::Integer = default_output_buffer_size)
18-
global libeng
19-
libeng == C_NULL && load_libeng()
20-
@assert libeng != C_NULL
21-
2219
ep = ccall(engfunc(:engOpen), Ptr{Void}, (Ptr{UInt8},), default_startcmd)
2320
ep == C_NULL && throw(MEngineError("failed to open a MATLAB engine session"))
2421
# hide the MATLAB command window on Windows
2522
is_windows() && ccall(engfunc(:engSetVisible ), Cint, (Ptr{Void}, Cint), ep, 0)
2623

2724
buf = Array(UInt8, bufsize)
28-
2925
if bufsize > 0
3026
bufptr = pointer(buf)
3127
ccall(engfunc(:engOutputBuffer), Cint, (Ptr{Void}, Ptr{UInt8}, Cint),
@@ -56,8 +52,7 @@ function release(session::MSession)
5652
end
5753

5854
function close(session::MSession)
59-
# Close a MATLAB Engine session
60-
@assert libeng::Ptr{Void} != C_NULL
55+
# close a MATLAB Engine session
6156
ret = ccall(engfunc(:engClose), Cint, (Ptr{Void},), session)
6257
ret != 0 && throw(MEngineError("failed to close a MATLAB engine session (err = $ret)"))
6358
session.ptr = C_NULL
@@ -115,27 +110,25 @@ end
115110
###########################################################
116111

117112
function eval_string(session::MSession, stmt::String)
118-
# Evaluate a MATLAB statement in a given MATLAB session
119-
@assert libeng::Ptr{Void} != C_NULL
120-
113+
# evaluate a MATLAB statement in a given MATLAB session
121114
ret = ccall(engfunc(:engEvalString), Cint, (Ptr{Void}, Ptr{UInt8}), session, stmt)
122115
ret != 0 && throw(MEngineError("invalid engine session (err = $ret)"))
123116

124-
bufptr::Ptr{UInt8} = session.bufptr
117+
bufptr = session.bufptr
125118
if bufptr != C_NULL
126119
bs = unsafe_string(bufptr)
127120
if ~isempty(bs)
128121
print(bs)
129122
end
130123
end
124+
return nothing
131125
end
132126

133127
eval_string(stmt::String) = eval_string(get_default_msession(), stmt)
134128

135129

136130
function put_variable(session::MSession, name::Symbol, v::MxArray)
137-
# Put a variable into a MATLAB engine session
138-
@assert libeng::Ptr{Void} != C_NULL
131+
# put a variable into a MATLAB engine session
139132
ret = ccall(engfunc(:engPutVariable), Cint, (Ptr{Void}, Ptr{UInt8}, Ptr{Void}), session, string(name), v)
140133
ret != 0 && throw(MEngineError("failed to put the variable $(name) into a MATLAB session (err = $ret)"))
141134
return nothing
@@ -147,7 +140,6 @@ put_variable(name::Symbol, v) = put_variable(get_default_msession(), name, v)
147140

148141

149142
function get_mvariable(session::MSession, name::Symbol)
150-
@assert libeng::Ptr{Void} != C_NULL
151143
pv = ccall(engfunc(:engGetVariable), Ptr{Void}, (Ptr{Void}, Ptr{UInt8}), session, string(name))
152144
pv == C_NULL && throw(MEngineError("failed to get the variable $(name) from a MATLAB session"))
153145
return MxArray(pv)
@@ -307,5 +299,3 @@ function mxcall(session::MSession, mfun::Symbol, nout::Integer, in_args...)
307299
end
308300

309301
mxcall(mfun::Symbol, nout::Integer, in_args...) = mxcall(get_default_msession(), mfun, nout, in_args...)
310-
311-

src/init.jl

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# libraries
2+
3+
const libeng = Ref{Ptr{Void}}()
4+
const libmx = Ref{Ptr{Void}}()
5+
const libmat = Ref{Ptr{Void}}()
6+
7+
# mxarray function
8+
9+
const mx_destroy_array = Ref{Ptr{Void}}()
10+
const mx_duplicate_array = Ref{Ptr{Void}}()
11+
12+
# functions to access mxarray
13+
14+
const mx_free = Ref{Ptr{Void}}()
15+
16+
const mx_get_classid = Ref{Ptr{Void}}()
17+
const mx_get_m = Ref{Ptr{Void}}()
18+
const mx_get_n = Ref{Ptr{Void}}()
19+
const mx_get_nelems = Ref{Ptr{Void}}()
20+
const mx_get_ndims = Ref{Ptr{Void}}()
21+
const mx_get_elemsize = Ref{Ptr{Void}}()
22+
const mx_get_data = Ref{Ptr{Void}}()
23+
const mx_get_dims = Ref{Ptr{Void}}()
24+
const mx_get_nfields = Ref{Ptr{Void}}()
25+
const mx_get_pr = Ref{Ptr{Void}}()
26+
const mx_get_pi = Ref{Ptr{Void}}()
27+
const mx_get_ir = Ref{Ptr{Void}}()
28+
const mx_get_jc = Ref{Ptr{Void}}()
29+
30+
const mx_is_double = Ref{Ptr{Void}}()
31+
const mx_is_single = Ref{Ptr{Void}}()
32+
const mx_is_int64 = Ref{Ptr{Void}}()
33+
const mx_is_uint64 = Ref{Ptr{Void}}()
34+
const mx_is_int32 = Ref{Ptr{Void}}()
35+
const mx_is_uint32 = Ref{Ptr{Void}}()
36+
const mx_is_int16 = Ref{Ptr{Void}}()
37+
const mx_is_uint16 = Ref{Ptr{Void}}()
38+
const mx_is_int8 = Ref{Ptr{Void}}()
39+
const mx_is_uint8 = Ref{Ptr{Void}}()
40+
const mx_is_char = Ref{Ptr{Void}}()
41+
42+
const mx_is_numeric = Ref{Ptr{Void}}()
43+
const mx_is_logical = Ref{Ptr{Void}}()
44+
const mx_is_complex = Ref{Ptr{Void}}()
45+
const mx_is_sparse = Ref{Ptr{Void}}()
46+
const mx_is_empty = Ref{Ptr{Void}}()
47+
const mx_is_struct = Ref{Ptr{Void}}()
48+
const mx_is_cell = Ref{Ptr{Void}}()
49+
50+
# functions to create & delete MATLAB arrays
51+
52+
const mx_create_numeric_matrix = Ref{Ptr{Void}}()
53+
const mx_create_numeric_array = Ref{Ptr{Void}}()
54+
55+
const mx_create_double_scalar = Ref{Ptr{Void}}()
56+
const mx_create_logical_scalar = Ref{Ptr{Void}}()
57+
58+
const mx_create_sparse = Ref{Ptr{Void}}()
59+
const mx_create_sparse_logical = Ref{Ptr{Void}}()
60+
61+
const mx_create_string = Ref{Ptr{Void}}()
62+
const mx_create_char_array = Ref{Ptr{Void}}()
63+
64+
const mx_create_cell_array = Ref{Ptr{Void}}()
65+
66+
const mx_create_struct_matrix = Ref{Ptr{Void}}()
67+
const mx_create_struct_array = Ref{Ptr{Void}}()
68+
69+
const mx_get_cell = Ref{Ptr{Void}}()
70+
const mx_set_cell = Ref{Ptr{Void}}()
71+
72+
const mx_get_field = Ref{Ptr{Void}}()
73+
const mx_set_field = Ref{Ptr{Void}}()
74+
const mx_get_field_bynum = Ref{Ptr{Void}}()
75+
const mx_get_fieldname = Ref{Ptr{Void}}()
76+
77+
const mx_get_string = Ref{Ptr{Void}}(0)
78+
79+
# load I/O mat functions
80+
81+
const mat_open = Ref{Ptr{Void}}()
82+
const mat_close = Ref{Ptr{Void}}()
83+
const mat_get_variable = Ref{Ptr{Void}}()
84+
const mat_put_variable = Ref{Ptr{Void}}()
85+
const mat_get_dir = Ref{Ptr{Void}}()

src/matfile.jl

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,11 @@
1-
# I/O with mat files
2-
3-
const _mat_open = matfunc(:matOpen)
4-
const _mat_close = matfunc(:matClose)
5-
const _mat_get_variable = matfunc(:matGetVariable)
6-
const _mat_put_variable = matfunc(:matPutVariable)
7-
const _mat_get_dir = matfunc(:matGetDir)
8-
91
# mat file open & close
102

113
type MatFile
124
ptr::Ptr{Void}
135
filename::String
146

157
function MatFile(filename::String, mode::String)
16-
p = ccall(_mat_open, Ptr{Void}, (Ptr{Cchar}, Ptr{Cchar}),
8+
p = ccall(mat_open[], Ptr{Void}, (Ptr{Cchar}, Ptr{Cchar}),
179
filename, mode)
1810
new(p, filename)
1911
end
@@ -22,7 +14,7 @@ MatFile(filename::String) = MatFile(filename, "r")
2214

2315
function close(f::MatFile)
2416
if f.ptr != C_NULL
25-
ret = ccall(_mat_close, Cint, (Ptr{Void},), f.ptr)
17+
ret = ccall(mat_close[], Cint, (Ptr{Void},), f.ptr)
2618
ret == 0 || error("Failed to close file.")
2719
end
2820
end
@@ -31,7 +23,7 @@ end
3123

3224
function get_mvariable(f::MatFile, name::String)
3325
f.ptr != C_NULL || error("Cannot get variable from a null file.")
34-
pm = ccall(_mat_get_variable, Ptr{Void}, (Ptr{Void}, Ptr{Cchar}),
26+
pm = ccall(mat_get_variable[], Ptr{Void}, (Ptr{Void}, Ptr{Cchar}),
3527
f.ptr, name)
3628
pm != C_NULL || error("Attempt to get variable $(name) failed.")
3729
MxArray(pm)
@@ -45,7 +37,7 @@ get_variable(f::MatFile, name::Symbol) = jvalue(get_mvariable(f, name))
4537
function put_variable(f::MatFile, name::String, v::MxArray)
4638
f.ptr != C_NULL || error("Cannot put variable to a null file.")
4739
v.ptr != C_NULL || error("Cannot put an null variable.")
48-
ret = ccall(_mat_put_variable, Cint, (Ptr{Void}, Ptr{Cchar}, Ptr{Void}),
40+
ret = ccall(mat_put_variable[], Cint, (Ptr{Void}, Ptr{Cchar}, Ptr{Void}),
4941
f.ptr, name, v.ptr)
5042
ret == 0 || error("Attempt to put variable $(name) failed.")
5143
end
@@ -75,14 +67,14 @@ end
7567
function variable_names(f::MatFile)
7668
# get a list of all variable names
7769
_n = Cint[0]
78-
_a = ccall(_mat_get_dir, Ptr{Ptr{Cchar}}, (Ptr{Void}, Ptr{Cint}),
70+
_a = ccall(mat_get_dir[], Ptr{Ptr{Cchar}}, (Ptr{Void}, Ptr{Cint}),
7971
f.ptr, _n)
8072

8173
n = Int(_n[1])
8274
a = unsafe_wrap(Array, _a, (n,))
8375

8476
names = String[unsafe_string(s) for s in a]
85-
ccall(_mx_free, Void, (Ptr{Void},), _a)
77+
ccall(mx_free[], Void, (Ptr{Void},), _a)
8678
return names
8779
end
8880

@@ -107,4 +99,3 @@ function read_matfile(filename::String)
10799
end
108100
return r
109101
end
110-

0 commit comments

Comments
 (0)