Skip to content

Commit 4235610

Browse files
committed
2 parents 5be275e + a774ff6 commit 4235610

File tree

14 files changed

+120
-114
lines changed

14 files changed

+120
-114
lines changed

README.md

Lines changed: 44 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ x = mxarray(["a", 1, 2.3]) # converts a Julia array to a MATLAB cell array
8686
x = mxarray(Dict("a"=>1, "b"=>"string", "c"=>[1,2,3])) # converts a Julia dictionary to a MATLAB struct
8787
```
8888

89-
The function ``mxarray`` can also converts a compound type to a Julia struct:
89+
The function ``mxarray`` can also convert a compound type to a Julia struct:
9090
```julia
9191
type S
9292
x::Float64
@@ -196,19 +196,19 @@ Both ``read_matfile`` and ``write_matfile`` will close the MAT file handle befor
196196
**Examples:**
197197

198198
```julia
199-
immutable S
200-
x::Float64
201-
y::Bool
202-
z::Vector{Float64}
199+
struct S
200+
x::Float64
201+
y::Bool
202+
z::Vector{Float64}
203203
end
204204

205205
write_matfile("test.mat";
206-
a = Int32[1 2 3; 4 5 6],
207-
b = [1.2, 3.4, 5.6, 7.8],
208-
c = [[0.0, 1.0], [1.0, 2.0], [1.0, 2.0, 3.0]],
209-
d = Dict("name"=>"MATLAB", "score"=>100.0),
210-
s = "abcde",
211-
ss = [S(1.0, true, [1., 2.]), S(2.0, false, [3., 4.])] )
206+
a = Int32[1 2 3; 4 5 6],
207+
b = [1.2, 3.4, 5.6, 7.8],
208+
c = [[0.0, 1.0], [1.0, 2.0], [1.0, 2.0, 3.0]],
209+
d = Dict("name"=>"MATLAB", "score"=>100.0),
210+
s = "abcde",
211+
ss = [S(1.0, true, [1., 2.]), S(2.0, false, [3., 4.])] )
212212
```
213213

214214
This example will create a MAT file called ``test.mat``, which contains six MATLAB variables:
@@ -228,9 +228,11 @@ This example will create a MAT file called ``test.mat``, which contains six MATL
228228
To evaluate expressions in MATLAB, one may open a MATLAB engine session and communicate with it. There are three ways to call MATLAB from Julia:
229229

230230
- The `mat""` custom string literal allows you to write MATLAB syntax inside Julia and use Julia variables directly from MATLAB via interpolation
231-
- The `@matlab` macro, in combination with `@mput` and `@mget`, translates Julia syntax to MATLAB
231+
- The `eval_string` evaluate a string containing MATLAB expressions (typically used with the helper macros `@mget` and `@mput`
232232
- The `mxcall` function calls a given MATLAB function and returns the result
233233

234+
In general, the `mat""` custom string literal is the preferred method to interact with the MATLAB engine.
235+
234236
*Note:* There can be multiple (reasonable) ways to convert a MATLAB variable to Julia array. For example, MATLAB represents a scalar using a 1-by-1 matrix. Here we have two choices in terms of converting such a matrix back to Julia: (1) convert to a scalar number, or (2) convert to a matrix of size 1-by-1.
235237

236238
##### The `mat""` custom string literal
@@ -253,49 +255,19 @@ mat"""
253255

254256
As with ordinary string literals, you can also interpolate whole Julia expressions, e.g. `mat"$(x[1]) = $(x[2]) + $(binomial(5, 2))"`.
255257

256-
##### The `@matlab` macro
257-
258-
The example above can also be written using the `@matlab` macro in combination with `@mput` and `@mget`.
259-
260-
```julia
261-
using MATLAB
262-
263-
x = linspace(-10., 10., 500)
264-
@mput x # put x to MATLAB's workspace
265-
@matlab plot(x, sin(x)) # evaluate a MATLAB function
266-
267-
y = linspace(2., 3., 500)
268-
@mput y
269-
@matlab begin
270-
u = x + y
271-
v = x - y
272-
end
273-
@mget u v
274-
@show u v
275-
```
276-
277-
###### Caveats of @matlab
278-
279-
Note that some MATLAB expressions are not valid Julia expressions. This package provides some ways to work around this in the ``@matlab`` macro:
258+
##### `eval_string`
280259

281-
```julia
282-
# MATLAB uses single-quote for strings, while Julia uses double-quote.
283-
@matlab sprintf("%d", 10) # ==> MATLAB: sprintf('%d', 10)
284-
285-
# MATLAB does not allow [x, y] on the left hand side
286-
x = linspace(-5.0, 5.0, 100)
287-
y = x
288-
@mput x y
289-
@matlab begin
290-
(xx, yy) = meshgrid(x, y) # ==> MATLAB: [xx, yy] = meshgrid(x, y)
291-
mesh(xx, yy, xx.^2 + yy.^2)
292-
end
260+
You may also use the `eval_string` function to evaluate MATLAB code as follows
261+
```julia
262+
eval_string("a = sum([1,2,3])")
293263
```
294264

295-
While we try to cover most MATLAB statements, some valid MATLAB statements remain unsupported by ``@matlab``. For this case, one may always call the ``eval_string`` function, as follows
296-
265+
The `eval_string` function also takes an optional argument that specifies which MATLAB session to evaluate the code in, e.g.
297266
```julia
298-
eval_string("[u, v] = myfun(x, y);")
267+
julia> s = MSession();
268+
julia> eval_string(s, "a = sum([1,2,3])")
269+
a =
270+
6
299271
```
300272

301273
##### `mxcall`
@@ -309,7 +281,27 @@ xx, yy = mxcall(:meshgrid, 2, x, y)
309281
```
310282
*Note:* Since MATLAB functions behavior depends on the number of outputs, you have to specify the number of output arguments in ``mxcall`` as the second argument.
311283

312-
``mxcall`` puts the input arguments to the MATLAB workspace (using mangled names), evaluates the function call in MATLAB, and retrievs the variable from the MATLAB session. This function is mainly provided for convenience. However, you should keep in mind that it may incur considerable overhead due to the communication between MATLAB and Julia domain.
284+
``mxcall`` puts the input arguments to the MATLAB workspace (using mangled names), evaluates the function call in MATLAB, and retrieves the variable from the MATLAB session. This function is mainly provided for convenience. However, you should keep in mind that it may incur considerable overhead due to the communication between MATLAB and Julia domain.
285+
286+
##### `@mget` and `@mput`
287+
288+
The macro `@mget` can be used to extract the value of a MATLAB variable into Julia
289+
```julia
290+
julia> mat"a = 6"
291+
julia> @mget a
292+
6.0
293+
```
294+
295+
The macro `@mput` can be used to translate a Julia variable into MATLAB
296+
```julia
297+
julia> x = [1,2,3]
298+
julia> @mput x
299+
julia> eval_string("y = sum(x)")
300+
julia> @mget y
301+
6.0
302+
julia> @show y
303+
a = 63.0
304+
```
313305

314306
#### Viewing the MATLAB Session (Windows only)
315307

REQUIRE

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
julia 0.5
2-
Compat 0.9.5
1+
julia 0.6
2+
Compat 0.33.0

src/MATLAB.jl

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ __precompile__()
22

33
module MATLAB
44

5-
using Compat.take!
5+
using Compat
6+
using Compat.Sys: islinux, iswindows, isapple
67

78
import Base: eltype, close, size, copy, ndims, unsafe_convert
89

@@ -31,14 +32,14 @@ export MSession, MatFile,
3132
eval_string, get_mvariable, get_variable, put_variable, put_variables,
3233
variable_names, read_matfile, write_matfile,
3334
mxcall,
34-
@mput, @mget, @matlab, @mat_str
35+
@mput, @mget, @mat_str
3536

36-
if is_windows()
37+
if iswindows()
3738
export show_msession, hide_msession, get_msession_visiblity
3839
end
3940

4041
# exceptions
41-
type MEngineError <: Exception
42+
struct MEngineError <: Exception
4243
message::String
4344
end
4445

@@ -156,7 +157,7 @@ function __init__()
156157
mat_get_dir[] = matfunc(:matGetDir)
157158

158159

159-
if is_windows()
160+
if iswindows()
160161
# workaround "primary message table for module 77" error
161162
# creates a dummy Engine session and keeps it open so the libraries used by all other
162163
# Engine clients are not loaded and unloaded repeatedly
@@ -190,4 +191,10 @@ end
190191

191192
@deprecate mxempty() mxarray(Float64,0,0)
192193

194+
export @matlab
195+
macro matlab(ex)
196+
Base.depwarn("@matlab is deprecated, use custom string literal mat\"\" instead.", :matlab)
197+
:( MATLAB.eval_string($(mstatement(ex))) )
198+
end
199+
193200
end

src/engine.jl

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,28 @@ const default_startcmd = matlab_startcmd() * " -nosplash"
1010
# 64 K buffer should be sufficient to store the output text in most cases
1111
const default_output_buffer_size = 64 * 1024
1212

13-
type MSession
13+
mutable struct MSession
1414
ptr::Ptr{Void}
1515
buffer::Vector{UInt8}
1616
bufptr::Ptr{UInt8}
1717

1818
function MSession(bufsize::Integer = default_output_buffer_size)
1919
ep = ccall(eng_open[], Ptr{Void}, (Ptr{UInt8},), default_startcmd)
20-
ep == C_NULL && throw(MEngineError("failed to open a MATLAB engine session"))
21-
# hide the MATLAB command window on Windows
22-
is_windows() && ccall(eng_set_visible[], Cint, (Ptr{Void}, Cint), ep, 0)
23-
20+
if ep == C_NULL
21+
Base.warn_once("Confirm MATLAB is installed and discoverable.")
22+
if iswindows()
23+
Base.warn_once("Ensure `matlab -regserver` has been run in a Command Prompt as Administrator.")
24+
elseif islinux()
25+
Base.warn_once("Ensure `csh` is installed; this may require running `sudo apt-get install csh`.")
26+
end
27+
throw(MEngineError("failed to open MATLAB engine session"))
28+
end
29+
if iswindows()
30+
# hide the MATLAB command window on Windows and change to current directory
31+
ccall(eng_set_visible[], Cint, (Ptr{Void}, Cint), ep, 0)
32+
ccall(eng_eval_string[], Cint, (Ptr{Void}, Ptr{UInt8}),
33+
ep, "try cd('$(escape_string(pwd()))'); end")
34+
end
2435
buf = Vector{UInt8}(bufsize)
2536
if bufsize > 0
2637
bufptr = pointer(buf)
@@ -54,7 +65,7 @@ end
5465
function close(session::MSession)
5566
# close a MATLAB Engine session
5667
ret = ccall(eng_close[], Cint, (Ptr{Void},), session)
57-
ret != 0 && throw(MEngineError("failed to close a MATLAB engine session (err = $ret)"))
68+
ret != 0 && throw(MEngineError("failed to close MATLAB engine session (err = $ret)"))
5869
session.ptr = C_NULL
5970
return nothing
6071
end
@@ -90,7 +101,7 @@ function close_default_msession()
90101
return nothing
91102
end
92103

93-
if is_windows()
104+
if iswindows()
94105
function show_msession(m::MSession = get_default_msession())
95106
ret = ccall(eng_set_visible[], Cint, (Ptr{Void}, Cint), m, 1)
96107
ret != 0 && throw(MEngineError("failed to show MATLAB engine session (err = $ret)"))
@@ -137,7 +148,7 @@ eval_string(stmt::String) = eval_string(get_default_msession(), stmt)
137148
function put_variable(session::MSession, name::Symbol, v::MxArray)
138149
# put a variable into a MATLAB engine session
139150
ret = ccall(eng_put_variable[], Cint, (Ptr{Void}, Ptr{UInt8}, Ptr{Void}), session, string(name), v)
140-
ret != 0 && throw(MEngineError("failed to put the variable $(name) into a MATLAB session (err = $ret)"))
151+
ret != 0 && throw(MEngineError("failed to put variable $(name) into MATLAB session (err = $ret)"))
141152
return nothing
142153
end
143154

@@ -148,7 +159,7 @@ put_variable(name::Symbol, v) = put_variable(get_default_msession(), name, v)
148159

149160
function get_mvariable(session::MSession, name::Symbol)
150161
pv = ccall(eng_get_variable[], Ptr{Void}, (Ptr{Void}, Ptr{UInt8}), session, string(name))
151-
pv == C_NULL && throw(MEngineError("failed to get the variable $(name) from a MATLAB session"))
162+
pv == C_NULL && throw(MEngineError("failed to get variable $(name) from MATLAB session"))
152163
return MxArray(pv)
153164
end
154165

@@ -215,10 +226,6 @@ macro mget(vs...)
215226
esc( _mget_multi(vs...) )
216227
end
217228

218-
macro matlab(ex)
219-
:( MATLAB.eval_string($(mstatement(ex))) )
220-
end
221-
222229

223230
###########################################################
224231
#

src/matfile.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# mat file open & close
22

3-
type MatFile
3+
mutable struct MatFile
44
ptr::Ptr{Void}
55
filename::String
66

src/matstr.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
# A really basic parser intended only to handle checking whether
44
# a variable is on the left or right hand side of an expression
5-
type DumbParserState
5+
mutable struct DumbParserState
66
paren_depth::Int
77
in_string::Bool
88
end

0 commit comments

Comments
 (0)