diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml new file mode 100644 index 0000000..442b9af --- /dev/null +++ b/.JuliaFormatter.toml @@ -0,0 +1,12 @@ +whitespace_typedefs = false +whitespace_ops_in_indices = false +whitespace_in_kwargs = false +remove_extra_newlines = true + +format_docstrings = true +annotate_untyped_fields_with_any = true +join_lines_based_on_source = true + +align_assignment = true +align_pair_arrow = true +align_struct_field = true diff --git a/.github/workflows/Format.yml b/.github/workflows/Format.yml new file mode 100644 index 0000000..9853f82 --- /dev/null +++ b/.github/workflows/Format.yml @@ -0,0 +1,13 @@ +name: Format suggestions +on: + pull_request: + # this argument is not required if you don't use the `suggestion-label` input + types: [opened, reopened, synchronize, labeled, unlabeled] +jobs: + code-style: + runs-on: ubuntu-latest + steps: + - uses: julia-actions/julia-format@v3 + with: + version: "1" # Set `version` to '1.0.54' if you need to use JuliaFormatter.jl v1.0.54 (default: '1') + suggestion-label: "format-suggest" # leave this unset or empty to show suggestions for all PRs diff --git a/deps/build.jl b/deps/build.jl index c849a69..218881c 100644 --- a/deps/build.jl +++ b/deps/build.jl @@ -5,7 +5,7 @@ const depsfile = joinpath(@__DIR__, "deps.jl") function find_matlab_root() # Determine MATLAB library path and provide facilities to load libraries with this path matlab_root = get(ENV, "MATLAB_ROOT", - get(ENV, "MATLAB_HOME", nothing)) + get(ENV, "MATLAB_HOME", nothing)) if isnothing(matlab_root) matlab_exe = Sys.which("matlab") if !isnothing(matlab_exe) @@ -22,7 +22,9 @@ function find_matlab_root() end end elseif Sys.iswindows() - default_dir = Sys.WORD_SIZE == 32 ? "C:\\Program Files (x86)\\MATLAB" : "C:\\Program Files\\MATLAB" + default_dir = + Sys.WORD_SIZE == 32 ? "C:\\Program Files (x86)\\MATLAB" : + "C:\\Program Files\\MATLAB" if isdir(default_dir) dirs = readdir(default_dir) filter!(dir -> occursin(r"^R[0-9]+[ab]$", dir), dirs) @@ -42,7 +44,8 @@ function find_matlab_root() end end end - !isnothing(matlab_root) && isdir(matlab_root) && @info("Detected MATLAB root folder at \"$matlab_root\"") + !isnothing(matlab_root) && isdir(matlab_root) && + @info("Detected MATLAB root folder at \"$matlab_root\"") return matlab_root end @@ -63,7 +66,12 @@ end function find_matlab_cmd(matlab_root) if Sys.iswindows() - matlab_cmd = joinpath(matlab_root, "bin", (Sys.WORD_SIZE == 32 ? "win32" : "win64"), "matlab.exe") + matlab_cmd = joinpath( + matlab_root, + "bin", + (Sys.WORD_SIZE == 32 ? "win32" : "win64"), + "matlab.exe", + ) isfile(matlab_cmd) && @info("Detected MATLAB executable at \"$matlab_cmd\"") else matlab_exe = joinpath(matlab_root, "bin", "matlab") @@ -89,13 +97,14 @@ if !isnothing(matlab_root) error("MATLAB library has changed, re-run Pkg.build(\\\"MATLAB\\\")") end end - """ - ) - println(io, "const matlab_libpath = \"$(escape_string(matlab_libpath))\"") - println(io, "const matlab_cmd = \"$(escape_string(matlab_cmd))\"") - println(io, "const libmx_size = $libmx_size") + """, + ) + println(io, "const matlab_libpath = \"$(escape_string(matlab_libpath))\"") + println(io, "const matlab_cmd = \"$(escape_string(matlab_cmd))\"") + println(io, "const libmx_size = $libmx_size") end -elseif get(ENV, "JULIA_REGISTRYCI_AUTOMERGE", nothing) == "true" || get(ENV, "CI", nothing) == "true" +elseif get(ENV, "JULIA_REGISTRYCI_AUTOMERGE", nothing) == "true" || + get(ENV, "CI", nothing) == "true" # We need to be able to install and load this package without error for # Julia's registry AutoMerge to work, so we just use dummy values. # Similarly we want to also be able to install and load this package for CI. @@ -109,12 +118,14 @@ elseif get(ENV, "JULIA_REGISTRYCI_AUTOMERGE", nothing) == "true" || get(ENV, "CI # This file is automatically generated, do not edit. check_deps() = nothing - """ - ) - println(io, "const matlab_libpath = \"$(escape_string(matlab_libpath))\"") - println(io, "const matlab_cmd = \"$(escape_string(matlab_cmd))\"") - println(io, "const libmx_size = $libmx_size") + """, + ) + println(io, "const matlab_libpath = \"$(escape_string(matlab_libpath))\"") + println(io, "const matlab_cmd = \"$(escape_string(matlab_cmd))\"") + println(io, "const libmx_size = $libmx_size") end else - error("MATLAB cannot be found. Set the \"MATLAB_ROOT\" environment variable to the MATLAB root directory and re-run Pkg.build(\"MATLAB\").") + error( + "MATLAB cannot be found. Set the \"MATLAB_ROOT\" environment variable to the MATLAB root directory and re-run Pkg.build(\"MATLAB\").", + ) end diff --git a/src/MATLAB.jl b/src/MATLAB.jl index f3a7d9b..40408cb 100644 --- a/src/MATLAB.jl +++ b/src/MATLAB.jl @@ -6,28 +6,29 @@ using SparseArrays import Base: eltype, close, size, copy, ndims, unsafe_convert # mxarray -export MxArray, mxClassID, mxComplexity, - mxclassid, data_ptr, - classid, nrows, ncols, nelems, elsize +export MxArray, + mxClassID, mxComplexity, + mxclassid, data_ptr, + classid, nrows, ncols, nelems, elsize export is_double, is_single, - is_int8, is_uint8, is_int16, is_uint16, - is_int32, is_uint32, is_int64, is_uint64, - is_numeric, is_complex, is_sparse, is_empty, - is_logical, is_char, is_struct, is_cell + is_int8, is_uint8, is_int16, is_uint16, + is_int32, is_uint32, is_int64, is_uint64, + is_numeric, is_complex, is_sparse, is_empty, + is_logical, is_char, is_struct, is_cell export mxarray, mxsparse, delete, - mxcellarray, get_cell, set_cell, - mxstruct, mxstructarray, mxnfields, get_fieldname, get_field, set_field, - jvalue, jarray, jscalar, jvector, jmatrix, jsparse, jstring, jdict + mxcellarray, get_cell, set_cell, + mxstruct, mxstructarray, mxnfields, get_fieldname, get_field, set_field, + jvalue, jarray, jscalar, jvector, jmatrix, jsparse, jstring, jdict # engine & matfile export MSession, MatFile, - get_default_msession, restart_default_msession, close_default_msession, - eval_string, get_mvariable, get_variable, put_variable, put_variables, - variable_names, read_matfile, write_matfile, - mxcall, - @mput, @mget, @mat_str + get_default_msession, restart_default_msession, close_default_msession, + eval_string, get_mvariable, get_variable, put_variable, put_variables, + variable_names, read_matfile, write_matfile, + mxcall, + @mput, @mget, @mat_str if Sys.iswindows() export show_msession, hide_msession, get_msession_visiblity @@ -37,7 +38,9 @@ const depsfile = joinpath(dirname(@__DIR__), "deps", "deps.jl") if isfile(depsfile) include(depsfile) else - error("MATLAB is not properly installed. Please run Pkg.build(\"MATLAB\") and restart Julia.") + error( + "MATLAB is not properly installed. Please run Pkg.build(\"MATLAB\") and restart Julia.", + ) end # exceptions @@ -79,119 +82,114 @@ function __init__() if libmx_size > 0 # non-zero size library path - # load libraries - # workaround for https://github.com/JuliaInterop/MATLAB.jl/issues/200 - if Sys.iswindows() - ENV["PATH"] = string(matlab_libpath, ";", ENV["PATH"]) - elseif Sys.islinux() - ENV["PATH"] = string(matlab_libpath, ":", ENV["PATH"]) - end - libmx[] = Libdl.dlopen(joinpath(matlab_libpath, "libmx"), Libdl.RTLD_GLOBAL) - libmat[] = Libdl.dlopen(joinpath(matlab_libpath, "libmat"), Libdl.RTLD_GLOBAL) - libeng[] = Libdl.dlopen(joinpath(matlab_libpath, "libeng"), Libdl.RTLD_GLOBAL) - - # engine functions - - eng_open[] = engfunc(:engOpen) - eng_close[] = engfunc(:engClose) - eng_set_visible[] = engfunc(:engSetVisible) - eng_get_visible[] = engfunc(:engGetVisible) - eng_output_buffer[] = engfunc(:engOutputBuffer) - eng_eval_string[] = engfunc(:engEvalString) - eng_put_variable[] = engfunc(:engPutVariable) - eng_get_variable[] = engfunc(:engGetVariable) - - # mxarray functions - - mx_destroy_array[] = mxfunc(:mxDestroyArray) - mx_duplicate_array[] = mxfunc(:mxDuplicateArray) - - # load functions to access mxarray - - mx_free[] = mxfunc(:mxFree) - - mx_get_classid[] = mxfunc(:mxGetClassID) - mx_get_m[] = mxfunc(:mxGetM) - mx_get_n[] = mxfunc(:mxGetN) - mx_get_nelems[] = mxfunc(:mxGetNumberOfElements) - mx_get_ndims[] = mxfunc(:mxGetNumberOfDimensions_730) - mx_get_elemsize[] = mxfunc(:mxGetElementSize) - mx_get_data[] = mxfunc(:mxGetData) - mx_get_dims[] = mxfunc(:mxGetDimensions_730) - mx_get_nfields[] = mxfunc(:mxGetNumberOfFields) - mx_get_pr[] = mxfunc(:mxGetPr) - mx_get_pi[] = mxfunc(:mxGetPi) - mx_get_ir[] = mxfunc(:mxGetIr_730) - mx_get_jc[] = mxfunc(:mxGetJc_730) - - mx_is_double[] = mxfunc(:mxIsDouble) - mx_is_single[] = mxfunc(:mxIsSingle) - mx_is_int64[] = mxfunc(:mxIsInt64) - mx_is_uint64[] = mxfunc(:mxIsUint64) - mx_is_int32[] = mxfunc(:mxIsInt32) - mx_is_uint32[] = mxfunc(:mxIsUint32) - mx_is_int16[] = mxfunc(:mxIsInt16) - mx_is_uint16[] = mxfunc(:mxIsUint16) - mx_is_int8[] = mxfunc(:mxIsInt8) - mx_is_uint8[] = mxfunc(:mxIsUint8) - mx_is_char[] = mxfunc(:mxIsChar) - - mx_is_numeric[] = mxfunc(:mxIsNumeric) - mx_is_logical[] = mxfunc(:mxIsLogical) - mx_is_complex[] = mxfunc(:mxIsComplex) - mx_is_sparse[] = mxfunc(:mxIsSparse) - mx_is_empty[] = mxfunc(:mxIsEmpty) - mx_is_struct[] = mxfunc(:mxIsStruct) - mx_is_cell[] = mxfunc(:mxIsCell) - - - # load functions to create & delete MATLAB array - - mx_create_numeric_matrix[] = mxfunc(:mxCreateNumericMatrix_730) - mx_create_numeric_array[] = mxfunc(:mxCreateNumericArray_730) - - mx_create_double_scalar[] = mxfunc(:mxCreateDoubleScalar) - mx_create_logical_scalar[] = mxfunc(:mxCreateLogicalScalar) - - mx_create_sparse[] = mxfunc(:mxCreateSparse_730) - mx_create_sparse_logical[] = mxfunc(:mxCreateSparseLogicalMatrix_730) - - mx_create_string[] = mxfunc(:mxCreateString) - mx_create_char_array[] = mxfunc(:mxCreateCharArray_730) - - mx_create_cell_array[] = mxfunc(:mxCreateCellArray_730) - - mx_create_struct_matrix[] = mxfunc(:mxCreateStructMatrix_730) - mx_create_struct_array[] = mxfunc(:mxCreateStructArray_730) - - mx_get_cell[] = mxfunc(:mxGetCell_730) - mx_set_cell[] = mxfunc(:mxSetCell_730) - - mx_get_field[] = mxfunc(:mxGetField_730) - mx_set_field[] = mxfunc(:mxSetField_730) - mx_get_field_bynum[] = mxfunc(:mxGetFieldByNumber_730) - mx_get_fieldname[] = mxfunc(:mxGetFieldNameByNumber) - - mx_get_string[] = mxfunc(:mxGetString_730) - - - # load I/O mat functions - - mat_open[] = matfunc(:matOpen) - mat_close[] = matfunc(:matClose) - mat_get_variable[] = matfunc(:matGetVariable) - mat_put_variable[] = matfunc(:matPutVariable) - mat_get_dir[] = matfunc(:matGetDir) - + # load libraries + # workaround for https://github.com/JuliaInterop/MATLAB.jl/issues/200 + if Sys.iswindows() + ENV["PATH"] = string(matlab_libpath, ";", ENV["PATH"]) + elseif Sys.islinux() + ENV["PATH"] = string(matlab_libpath, ":", ENV["PATH"]) + end + libmx[] = Libdl.dlopen(joinpath(matlab_libpath, "libmx"), Libdl.RTLD_GLOBAL) + libmat[] = Libdl.dlopen(joinpath(matlab_libpath, "libmat"), Libdl.RTLD_GLOBAL) + libeng[] = Libdl.dlopen(joinpath(matlab_libpath, "libeng"), Libdl.RTLD_GLOBAL) + + # engine functions + + eng_open[] = engfunc(:engOpen) + eng_close[] = engfunc(:engClose) + eng_set_visible[] = engfunc(:engSetVisible) + eng_get_visible[] = engfunc(:engGetVisible) + eng_output_buffer[] = engfunc(:engOutputBuffer) + eng_eval_string[] = engfunc(:engEvalString) + eng_put_variable[] = engfunc(:engPutVariable) + eng_get_variable[] = engfunc(:engGetVariable) + + # mxarray functions + + mx_destroy_array[] = mxfunc(:mxDestroyArray) + mx_duplicate_array[] = mxfunc(:mxDuplicateArray) + + # load functions to access mxarray + + mx_free[] = mxfunc(:mxFree) + + mx_get_classid[] = mxfunc(:mxGetClassID) + mx_get_m[] = mxfunc(:mxGetM) + mx_get_n[] = mxfunc(:mxGetN) + mx_get_nelems[] = mxfunc(:mxGetNumberOfElements) + mx_get_ndims[] = mxfunc(:mxGetNumberOfDimensions_730) + mx_get_elemsize[] = mxfunc(:mxGetElementSize) + mx_get_data[] = mxfunc(:mxGetData) + mx_get_dims[] = mxfunc(:mxGetDimensions_730) + mx_get_nfields[] = mxfunc(:mxGetNumberOfFields) + mx_get_pr[] = mxfunc(:mxGetPr) + mx_get_pi[] = mxfunc(:mxGetPi) + mx_get_ir[] = mxfunc(:mxGetIr_730) + mx_get_jc[] = mxfunc(:mxGetJc_730) + + mx_is_double[] = mxfunc(:mxIsDouble) + mx_is_single[] = mxfunc(:mxIsSingle) + mx_is_int64[] = mxfunc(:mxIsInt64) + mx_is_uint64[] = mxfunc(:mxIsUint64) + mx_is_int32[] = mxfunc(:mxIsInt32) + mx_is_uint32[] = mxfunc(:mxIsUint32) + mx_is_int16[] = mxfunc(:mxIsInt16) + mx_is_uint16[] = mxfunc(:mxIsUint16) + mx_is_int8[] = mxfunc(:mxIsInt8) + mx_is_uint8[] = mxfunc(:mxIsUint8) + mx_is_char[] = mxfunc(:mxIsChar) + + mx_is_numeric[] = mxfunc(:mxIsNumeric) + mx_is_logical[] = mxfunc(:mxIsLogical) + mx_is_complex[] = mxfunc(:mxIsComplex) + mx_is_sparse[] = mxfunc(:mxIsSparse) + mx_is_empty[] = mxfunc(:mxIsEmpty) + mx_is_struct[] = mxfunc(:mxIsStruct) + mx_is_cell[] = mxfunc(:mxIsCell) + + # load functions to create & delete MATLAB array + + mx_create_numeric_matrix[] = mxfunc(:mxCreateNumericMatrix_730) + mx_create_numeric_array[] = mxfunc(:mxCreateNumericArray_730) + + mx_create_double_scalar[] = mxfunc(:mxCreateDoubleScalar) + mx_create_logical_scalar[] = mxfunc(:mxCreateLogicalScalar) + + mx_create_sparse[] = mxfunc(:mxCreateSparse_730) + mx_create_sparse_logical[] = mxfunc(:mxCreateSparseLogicalMatrix_730) + + mx_create_string[] = mxfunc(:mxCreateString) + mx_create_char_array[] = mxfunc(:mxCreateCharArray_730) + + mx_create_cell_array[] = mxfunc(:mxCreateCellArray_730) + + mx_create_struct_matrix[] = mxfunc(:mxCreateStructMatrix_730) + mx_create_struct_array[] = mxfunc(:mxCreateStructArray_730) + + mx_get_cell[] = mxfunc(:mxGetCell_730) + mx_set_cell[] = mxfunc(:mxSetCell_730) + + mx_get_field[] = mxfunc(:mxGetField_730) + mx_set_field[] = mxfunc(:mxSetField_730) + mx_get_field_bynum[] = mxfunc(:mxGetFieldByNumber_730) + mx_get_fieldname[] = mxfunc(:mxGetFieldNameByNumber) + + mx_get_string[] = mxfunc(:mxGetString_730) + + # load I/O mat functions + + mat_open[] = matfunc(:matOpen) + mat_close[] = matfunc(:matClose) + mat_get_variable[] = matfunc(:matGetVariable) + mat_put_variable[] = matfunc(:matPutVariable) + mat_get_dir[] = matfunc(:matGetDir) end end - ########################################################### # # deprecations # ########################################################### - end diff --git a/src/engine.jl b/src/engine.jl index f0ca5de..f42b6a1 100644 --- a/src/engine.jl +++ b/src/engine.jl @@ -8,8 +8,10 @@ const default_startflag = "-nodisplay -nosplash -nodesktop" # no additional flags const default_matlabcmd = matlab_cmd * " -nodisplay -nosplash -nodesktop" # pass matlab flags directly or as a Vector of flags, i.e. "-a" or ["-a", "-b", "-c"] -startcmd(flag::AbstractString = default_startflag) = isempty(flag) ? default_matlabcmd : default_matlabcmd * " " * flag -startcmd(flags::AbstractVector{<:AbstractString}) = isempty(flags) ? default_matlabcmd : default_matlabcmd * " " * join(flags, " ") +startcmd(flag::AbstractString=default_startflag) = + isempty(flag) ? default_matlabcmd : default_matlabcmd * " " * flag +startcmd(flags::AbstractVector{<:AbstractString}) = + isempty(flags) ? default_matlabcmd : default_matlabcmd * " " * join(flags, " ") # 64 K buffer should be sufficient to store the output text in most cases const default_output_buffer_size = 64 * 1024 @@ -19,17 +21,23 @@ mutable struct MSession buffer::Vector{UInt8} bufptr::Ptr{UInt8} - function MSession(bufsize::Integer = default_output_buffer_size; flags=default_startflag) + function MSession(bufsize::Integer=default_output_buffer_size; flags=default_startflag) if Sys.iswindows() assign_persistent_msession() end ep = ccall(eng_open[], Ptr{Cvoid}, (Ptr{UInt8},), startcmd(flags)) if ep == C_NULL - @warn("Confirm MATLAB is installed and discoverable.", maxlog=1) + @warn("Confirm MATLAB is installed and discoverable.", maxlog = 1) if Sys.iswindows() - @warn("Ensure `matlab -regserver` has been run in a Command Prompt as Administrator.", maxlog=1) + @warn( + "Ensure `matlab -regserver` has been run in a Command Prompt as Administrator.", + maxlog = 1 + ) elseif Sys.islinux() - @warn("Ensure `csh` is installed; this may require running `sudo apt-get install csh`.", maxlog=1) + @warn( + "Ensure `csh` is installed; this may require running `sudo apt-get install csh`.", + maxlog = 1 + ) end throw(MEngineError("failed to open MATLAB engine session")) end @@ -90,7 +98,7 @@ function get_default_msession() return default_msession_ref[] end -function restart_default_msession(bufsize::Integer = default_output_buffer_size) +function restart_default_msession(bufsize::Integer=default_output_buffer_size) close_default_msession() default_msession_ref[] = MSession(bufsize) return nothing @@ -104,19 +112,19 @@ function close_default_msession() end if Sys.iswindows() - function show_msession(m::MSession = get_default_msession()) + function show_msession(m::MSession=get_default_msession()) ret = ccall(eng_set_visible[], Cint, (Ptr{Cvoid}, Cint), m, 1) ret != 0 && throw(MEngineError("failed to show MATLAB engine session (err = $ret)")) return nothing end - function hide_msession(m::MSession = get_default_msession()) + function hide_msession(m::MSession=get_default_msession()) ret = ccall(eng_set_visible[], Cint, (Ptr{Cvoid}, Cint), m, 0) ret != 0 && throw(MEngineError("failed to hide MATLAB engine session (err = $ret)")) return nothing end - function get_msession_visiblity(m::MSession = get_default_msession()) + function get_msession_visiblity(m::MSession=get_default_msession()) vis = Ref{Cint}(true) ccall(eng_get_visible[], Int, (Ptr{Cvoid}, Ptr{Cint}), m, vis) return vis[] == 1 ? true : false @@ -146,11 +154,19 @@ end eval_string(stmt::String) = eval_string(get_default_msession(), stmt) - function put_variable(session::MSession, name::Symbol, v::MxArray) # put a variable into a MATLAB engine session - ret = ccall(eng_put_variable[], Cint, (Ptr{Cvoid}, Ptr{UInt8}, Ptr{Cvoid}), session, string(name), v) - ret != 0 && throw(MEngineError("failed to put variable $(name) into MATLAB session (err = $ret)")) + ret = ccall( + eng_put_variable[], + Cint, + (Ptr{Cvoid}, Ptr{UInt8}, Ptr{Cvoid}), + session, + string(name), + v, + ) + ret != 0 && throw( + MEngineError("failed to put variable $(name) into MATLAB session (err = $ret)"), + ) return nothing end @@ -158,10 +174,16 @@ put_variable(session::MSession, name::Symbol, v) = put_variable(session, name, m put_variable(name::Symbol, v) = put_variable(get_default_msession(), name, v) - function get_mvariable(session::MSession, name::Symbol) - pv = ccall(eng_get_variable[], Ptr{Cvoid}, (Ptr{Cvoid}, Ptr{UInt8}), session, string(name)) - pv == C_NULL && throw(MEngineError("failed to get variable $(name) from MATLAB session")) + pv = ccall( + eng_get_variable[], + Ptr{Cvoid}, + (Ptr{Cvoid}, Ptr{UInt8}), + session, + string(name), + ) + pv == C_NULL && + throw(MEngineError("failed to get variable $(name) from MATLAB session")) return MxArray(pv) end @@ -170,7 +192,6 @@ get_mvariable(name::Symbol) = get_mvariable(get_default_msession(), name) get_variable(name::Symbol) = jvalue(get_mvariable(name)) get_variable(name::Symbol, kind) = jvalue(get_mvariable(name), kind) - ########################################################### # # macro to simplify syntax @@ -181,24 +202,23 @@ function _mput_multi(vs::Symbol...) nv = length(vs) if nv == 1 v = vs[1] - :( MATLAB.put_variable($(Meta.quot(v)), $(v)) ) + :(MATLAB.put_variable($(Meta.quot(v)), $(v))) else stmts = Vector{Expr}(undef, nv) - for i = 1 : nv + for i = 1:nv v = vs[i] - stmts[i] = :( MATLAB.put_variable($(Meta.quot(v)), $(v)) ) + stmts[i] = :(MATLAB.put_variable($(Meta.quot(v)), $(v))) end Expr(:block, stmts...) end end macro mput(vs...) - esc( _mput_multi(vs...) ) + esc(_mput_multi(vs...)) end - function make_getvar_statement(v::Symbol) - :( $(v) = MATLAB.get_variable($(Meta.quot(v))) ) + :($(v) = MATLAB.get_variable($(Meta.quot(v)))) end function make_getvar_statement(ex::Expr) @@ -208,10 +228,10 @@ function make_getvar_statement(ex::Expr) v::Symbol = ex.args[1] k::Symbol = ex.args[2] - :( $(v) = MATLAB.get_variable($(Meta.quot(v)), $(k)) ) + :($(v) = MATLAB.get_variable($(Meta.quot(v)), $(k))) end -function _mget_multi(vs::Union{Symbol, Expr}...) +function _mget_multi(vs::Union{Symbol,Expr}...) nv = length(vs) if nv == 1 make_getvar_statement(vs[1]) @@ -225,10 +245,9 @@ function _mget_multi(vs::Union{Symbol, Expr}...) end macro mget(vs...) - esc( _mget_multi(vs...) ) + esc(_mget_multi(vs...)) end - ########################################################### # # mxcall @@ -314,4 +333,5 @@ function mxcall(session::MSession, mfun::Symbol, nout::Integer, in_args...) return ret end -mxcall(mfun::Symbol, nout::Integer, in_args...) = mxcall(get_default_msession(), mfun, nout, in_args...) +mxcall(mfun::Symbol, nout::Integer, in_args...) = + mxcall(get_default_msession(), mfun, nout, in_args...) diff --git a/src/init.jl b/src/init.jl index 63ef6f4..43f3994 100644 --- a/src/init.jl +++ b/src/init.jl @@ -22,7 +22,7 @@ const mx_duplicate_array = Ref{Ptr{Cvoid}}() # functions to access mxarray -const mx_free = Ref{Ptr{Cvoid}}() +const mx_free = Ref{Ptr{Cvoid}}() const mx_get_classid = Ref{Ptr{Cvoid}}() const mx_get_m = Ref{Ptr{Cvoid}}() @@ -38,25 +38,25 @@ const mx_get_pi = Ref{Ptr{Cvoid}}() const mx_get_ir = Ref{Ptr{Cvoid}}() const mx_get_jc = Ref{Ptr{Cvoid}}() -const mx_is_double = Ref{Ptr{Cvoid}}() -const mx_is_single = Ref{Ptr{Cvoid}}() -const mx_is_int64 = Ref{Ptr{Cvoid}}() -const mx_is_uint64 = Ref{Ptr{Cvoid}}() -const mx_is_int32 = Ref{Ptr{Cvoid}}() -const mx_is_uint32 = Ref{Ptr{Cvoid}}() -const mx_is_int16 = Ref{Ptr{Cvoid}}() -const mx_is_uint16 = Ref{Ptr{Cvoid}}() -const mx_is_int8 = Ref{Ptr{Cvoid}}() -const mx_is_uint8 = Ref{Ptr{Cvoid}}() -const mx_is_char = Ref{Ptr{Cvoid}}() - -const mx_is_numeric = Ref{Ptr{Cvoid}}() -const mx_is_logical = Ref{Ptr{Cvoid}}() -const mx_is_complex = Ref{Ptr{Cvoid}}() -const mx_is_sparse = Ref{Ptr{Cvoid}}() -const mx_is_empty = Ref{Ptr{Cvoid}}() -const mx_is_struct = Ref{Ptr{Cvoid}}() -const mx_is_cell = Ref{Ptr{Cvoid}}() +const mx_is_double = Ref{Ptr{Cvoid}}() +const mx_is_single = Ref{Ptr{Cvoid}}() +const mx_is_int64 = Ref{Ptr{Cvoid}}() +const mx_is_uint64 = Ref{Ptr{Cvoid}}() +const mx_is_int32 = Ref{Ptr{Cvoid}}() +const mx_is_uint32 = Ref{Ptr{Cvoid}}() +const mx_is_int16 = Ref{Ptr{Cvoid}}() +const mx_is_uint16 = Ref{Ptr{Cvoid}}() +const mx_is_int8 = Ref{Ptr{Cvoid}}() +const mx_is_uint8 = Ref{Ptr{Cvoid}}() +const mx_is_char = Ref{Ptr{Cvoid}}() + +const mx_is_numeric = Ref{Ptr{Cvoid}}() +const mx_is_logical = Ref{Ptr{Cvoid}}() +const mx_is_complex = Ref{Ptr{Cvoid}}() +const mx_is_sparse = Ref{Ptr{Cvoid}}() +const mx_is_empty = Ref{Ptr{Cvoid}}() +const mx_is_struct = Ref{Ptr{Cvoid}}() +const mx_is_cell = Ref{Ptr{Cvoid}}() # functions to create & delete MATLAB arrays @@ -69,21 +69,21 @@ const mx_create_logical_scalar = Ref{Ptr{Cvoid}}() const mx_create_sparse = Ref{Ptr{Cvoid}}() const mx_create_sparse_logical = Ref{Ptr{Cvoid}}() -const mx_create_string = Ref{Ptr{Cvoid}}() -const mx_create_char_array = Ref{Ptr{Cvoid}}() +const mx_create_string = Ref{Ptr{Cvoid}}() +const mx_create_char_array = Ref{Ptr{Cvoid}}() -const mx_create_cell_array = Ref{Ptr{Cvoid}}() +const mx_create_cell_array = Ref{Ptr{Cvoid}}() -const mx_create_struct_matrix = Ref{Ptr{Cvoid}}() -const mx_create_struct_array = Ref{Ptr{Cvoid}}() +const mx_create_struct_matrix = Ref{Ptr{Cvoid}}() +const mx_create_struct_array = Ref{Ptr{Cvoid}}() -const mx_get_cell = Ref{Ptr{Cvoid}}() -const mx_set_cell = Ref{Ptr{Cvoid}}() +const mx_get_cell = Ref{Ptr{Cvoid}}() +const mx_set_cell = Ref{Ptr{Cvoid}}() -const mx_get_field = Ref{Ptr{Cvoid}}() -const mx_set_field = Ref{Ptr{Cvoid}}() -const mx_get_field_bynum = Ref{Ptr{Cvoid}}() -const mx_get_fieldname = Ref{Ptr{Cvoid}}() +const mx_get_field = Ref{Ptr{Cvoid}}() +const mx_set_field = Ref{Ptr{Cvoid}}() +const mx_get_field_bynum = Ref{Ptr{Cvoid}}() +const mx_get_fieldname = Ref{Ptr{Cvoid}}() const mx_get_string = Ref{Ptr{Cvoid}}() diff --git a/src/matfile.jl b/src/matfile.jl index aa5cc03..a1b116d 100644 --- a/src/matfile.jl +++ b/src/matfile.jl @@ -35,7 +35,6 @@ function close(f::MatFile) return nothing end - # get & put variables function get_mvariable(f::MatFile, name::String) diff --git a/src/matstr.jl b/src/matstr.jl index 835f171..15baad9 100644 --- a/src/matstr.jl +++ b/src/matstr.jl @@ -56,11 +56,11 @@ end function check_assignment(interp, i) # Go back to the last newline before = String[] - for j = i-1:-1:1 + for j = (i-1):-1:1 if isa(interp[j], String) sp = split(interp[j], "\n") pushfirst!(before, sp[end]) - for k = length(sp)-1:-1:1 + for k = (length(sp)-1):-1:1 match(r"\.\.\.[ \t]*\r?$", sp[k]) === nothing && @goto done_before pushfirst!(before, sp[k]) end @@ -75,7 +75,7 @@ function check_assignment(interp, i) # Go until the next newline or comment after = String[] both_sides = false - for j = i+1:length(interp) + for j = (i+1):length(interp) if isa(interp[j], String) sp = split(interp[j], "\n") push!(after, sp[1]) @@ -90,7 +90,9 @@ function check_assignment(interp, i) @label done_after assigned = dumb_parse!(pstate, join(after)) - used = !assigned || both_sides || (i < length(interp) && match(r"^[ \t]*\(", interp[i+1]) != nothing) + used = + !assigned || both_sides || + (i < length(interp) && match(r"^[ \t]*\(", interp[i+1]) != nothing) return (assigned, used) end @@ -130,15 +132,24 @@ function do_mat_str(ex) if used && !(var in usedvars) push!(usedvars, var) - (var in assignedvars) || push!(putblock.args, :(put_variable($(Meta.quot(var)), $(esc(interp[i]))))) + (var in assignedvars) || push!( + putblock.args, + :(put_variable($(Meta.quot(var)), $(esc(interp[i])))), + ) end if assigned && !(var in assignedvars) push!(assignedvars, var) if isa(interp[i], Expr) && (interp[i].head == :ref) # Assignment to a sliced variable, e.g., x[1:3], must use broadcasting in v0.7+ - push!(getblock.args, Expr(:(.=), esc(interp[i]), :(get_variable($(Meta.quot(var)))))) + push!( + getblock.args, + Expr(:(.=), esc(interp[i]), :(get_variable($(Meta.quot(var))))), + ) else - push!(getblock.args, Expr(:(=), esc(interp[i]), :(get_variable($(Meta.quot(var)))))) + push!( + getblock.args, + Expr(:(=), esc(interp[i]), :(get_variable($(Meta.quot(var))))), + ) end end @@ -160,10 +171,14 @@ function do_mat_str(ex) $(putblock) eval_string($(join(interp))) $(getblock) - $(if !isempty(usedvars) || !isempty(assignedvars) - # Clear variables we created - :(eval_string($(string("clear ", join(union(usedvars, assignedvars), " "), ";")))) - end) + $( + if !isempty(usedvars) || !isempty(assignedvars) + # Clear variables we created + :(eval_string( + $(string("clear ", join(union(usedvars, assignedvars), " "), ";")), + )) + end + ) if get_variable(:matlab_jl_has_ans) != 0 # Return ans if it was set get_variable(:ans) diff --git a/src/mxarray.jl b/src/mxarray.jl index cb423bc..ec1113c 100644 --- a/src/mxarray.jl +++ b/src/mxarray.jl @@ -17,7 +17,6 @@ MxArray(p::Ptr{Cvoid}) = MxArray(p, true) mxarray(mx::MxArray) = mx - function release(mx::MxArray) if mx.own && mx.ptr != C_NULL ccall(mx_destroy_array[], Cvoid, (Ptr{Cvoid},), mx.ptr) @@ -48,9 +47,10 @@ function unsafe_convert(::Type{Ptr{Cvoid}}, mx::MxArray) end # functions to create mxArray from Julia values/arrays -const MxRealNum = Union{Float64, Float32, Int32, UInt32, Int64, UInt64, Int16, UInt16, Int8, UInt8, Bool} -const MxComplexNum = Union{ComplexF32, ComplexF64} -const MxNum = Union{MxRealNum, MxComplexNum} +const MxRealNum = + Union{Float64,Float32,Int32,UInt32,Int64,UInt64,Int16,UInt16,Int8,UInt8,Bool} +const MxComplexNum = Union{ComplexF32,ComplexF64} +const MxNum = Union{MxRealNum,MxComplexNum} ########################################################### # @@ -88,17 +88,17 @@ end mxCOMPLEX end -mxclassid(::Type{Bool}) = mxLOGICAL_CLASS -mxclassid(::Union{Type{Float64}, Type{ComplexF64}}) = mxDOUBLE_CLASS -mxclassid(::Union{Type{Float32}, Type{ComplexF32}}) = mxSINGLE_CLASS -mxclassid(::Type{Int8}) = mxINT8_CLASS -mxclassid(::Type{UInt8}) = mxUINT8_CLASS -mxclassid(::Type{Int16}) = mxINT16_CLASS -mxclassid(::Type{UInt16}) = mxUINT16_CLASS -mxclassid(::Type{Int32}) = mxINT32_CLASS -mxclassid(::Type{UInt32}) = mxUINT32_CLASS -mxclassid(::Type{Int64}) = mxINT64_CLASS -mxclassid(::Type{UInt64}) = mxUINT64_CLASS +mxclassid(::Type{Bool}) = mxLOGICAL_CLASS +mxclassid(::Union{Type{Float64},Type{ComplexF64}}) = mxDOUBLE_CLASS +mxclassid(::Union{Type{Float32},Type{ComplexF32}}) = mxSINGLE_CLASS +mxclassid(::Type{Int8}) = mxINT8_CLASS +mxclassid(::Type{UInt8}) = mxUINT8_CLASS +mxclassid(::Type{Int16}) = mxINT16_CLASS +mxclassid(::Type{UInt16}) = mxUINT16_CLASS +mxclassid(::Type{Int32}) = mxINT32_CLASS +mxclassid(::Type{UInt32}) = mxUINT32_CLASS +mxclassid(::Type{Int64}) = mxINT64_CLASS +mxclassid(::Type{UInt64}) = mxUINT64_CLASS mxcomplexflag(::Type{T}) where {T<:MxRealNum} = mxREAL mxcomplexflag(::Type{T}) where {T<:MxComplexNum} = mxCOMPLEX @@ -115,7 +115,7 @@ const classid_type_map = Dict{mxClassID,Type}( mxINT32_CLASS => Int32, mxUINT32_CLASS => UInt32, mxINT64_CLASS => Int64, - mxUINT64_CLASS => UInt64 + mxUINT64_CLASS => UInt64, ) function mxclassid_to_type(cid::mxClassID) @@ -124,7 +124,6 @@ function mxclassid_to_type(cid::mxClassID) return ty end - ########################################################### # # Functions to access mxArray @@ -145,8 +144,8 @@ ncols(mx::MxArray) = convert(Int, @mxget_attr(mx_get_n[], UInt, mx)) nelems(mx::MxArray) = convert(Int, @mxget_attr(mx_get_nelems[], UInt, mx)) ndims(mx::MxArray) = convert(Int, @mxget_attr(mx_get_ndims[], mwSize, mx)) -eltype(mx::MxArray) = mxclassid_to_type(classid(mx)) -elsize(mx::MxArray) = convert(Int, @mxget_attr(mx_get_elemsize[], UInt, mx)) +eltype(mx::MxArray) = mxclassid_to_type(classid(mx)) +elsize(mx::MxArray) = convert(Int, @mxget_attr(mx_get_elemsize[], UInt, mx)) data_ptr(mx::MxArray) = convert(Ptr{eltype(mx)}, @mxget_attr(mx_get_data[], Ptr{Cvoid}, mx)) real_ptr(mx::MxArray) = convert(Ptr{eltype(mx)}, @mxget_attr(mx_get_pr[], Ptr{Cvoid}, mx)) imag_ptr(mx::MxArray) = convert(Ptr{eltype(mx)}, @mxget_attr(mx_get_pi[], Ptr{Cvoid}, mx)) @@ -206,16 +205,14 @@ function size(mx::MxArray, d::Integer) end end - ########################################################### # # functions to create & delete MATLAB arrays # ########################################################### - function _dims_to_mwSize(dims::Tuple{Vararg{Integer,N}}) where {N} - _dims = Vector{mwSize}(undef,N) + _dims = Vector{mwSize}(undef, N) for i = 1:N _dims[i] = mwSize(dims[i]) end @@ -242,7 +239,7 @@ function mxarray(x::Bool) MxArray(pm) end -function mxarray(x::T) where T<:MxRealNum +function mxarray(x::T) where {T<:MxRealNum} pm = ccall(mx_create_numeric_matrix[], Ptr{Cvoid}, (mwSize, mwSize, mxClassID, mxComplexity), 1, 1, mxclassid(T), mxcomplexflag(T)) @@ -258,13 +255,19 @@ mxarray(x::T) where {T<:MxComplexNum} = mxarray([x]) # Note: the conversion is deep-copy, as there is no way to let # mxArray use Julia array's memory -function mxarray(a::Array{T}) where T<:MxRealNum +function mxarray(a::Array{T}) where {T<:MxRealNum} mx = mxarray(T, size(a)) - ccall(:memcpy, Ptr{Cvoid}, (Ptr{Cvoid}, Ptr{Cvoid}, UInt), data_ptr(mx), a, length(a)*sizeof(T)) + ccall( + :memcpy, + Ptr{Cvoid}, + (Ptr{Cvoid}, Ptr{Cvoid}, UInt), + data_ptr(mx), + a, + length(a) * sizeof(T), + ) return mx end - function mxarray(a::Array{T}) where {T<:MxComplexNum} mx = mxarray(T, size(a)) na = length(a) @@ -277,7 +280,6 @@ function mxarray(a::Array{T}) where {T<:MxComplexNum} mx end - function mxarray(a::AbstractArray{T}) where {T<:MxRealNum} mx = mxarray(T, size(a)) ptr = data_ptr(mx) @@ -289,7 +291,7 @@ function mxarray(a::AbstractArray{T}) where {T<:MxRealNum} return mx end -function mxarray(a::AbstractArray{T}) where {T <: MxComplexNum} +function mxarray(a::AbstractArray{T}) where {T<:MxComplexNum} mx = mxarray(T, size(a)) na = length(a) rdat = unsafe_wrap(Array, real_ptr(mx), na) @@ -301,18 +303,17 @@ function mxarray(a::AbstractArray{T}) where {T <: MxComplexNum} return mx end - -function mxarray(a::NTuple{N, T}) where {N, T <: MxRealNum} +function mxarray(a::NTuple{N,T}) where {N,T<:MxRealNum} mx = mxarray(T, N) pdat = ccall(mx_get_data[], Ptr{T}, (Ptr{Cvoid},), mx) dat = unsafe_wrap(Array, pdat, N) - for i in 1:N + for i = 1:N dat[i] = a[i] end return mx end -function mxarray(a::NTuple{N, T}) where {N, T <: MxComplexNum} +function mxarray(a::NTuple{N,T}) where {N,T<:MxComplexNum} mx = mxarray(T, size(a)) na = length(a) rdat = unsafe_wrap(Array, real_ptr(mx), na) @@ -326,7 +327,7 @@ end function mxarray(a::Tuple) mx = mxcellarray(length(a)) - for i in 1:length(a) + for i = 1:length(a) set_cell(mx, i, mxarray(a[i])) end return mx @@ -352,7 +353,13 @@ function mxsparse(ty::Type{Bool}, m::Integer, n::Integer, nzmax::Integer) MxArray(pm) end -function _copy_sparse_mat(a::SparseMatrixCSC{V,I}, ir_p::Ptr{mwIndex}, jc_p::Ptr{mwIndex}, pr_p::Ptr{Float64}, pi_p::Ptr{Float64}) where {V<:ComplexF64,I} +function _copy_sparse_mat( + a::SparseMatrixCSC{V,I}, + ir_p::Ptr{mwIndex}, + jc_p::Ptr{mwIndex}, + pr_p::Ptr{Float64}, + pi_p::Ptr{Float64}, +) where {V<:ComplexF64,I} colptr::Vector{I} = a.colptr rinds::Vector{I} = a.rowval vr::Vector{Float64} = real(a.nzval) @@ -367,8 +374,8 @@ function _copy_sparse_mat(a::SparseMatrixCSC{V,I}, ir_p::Ptr{mwIndex}, jc_p::Ptr ir[i] = rinds[i] - 1 end - jc = unsafe_wrap(Array, jc_p, (n+1,)) - for i = 1:n+1 + jc = unsafe_wrap(Array, jc_p, (n + 1,)) + for i = 1:(n+1) jc[i] = colptr[i] - 1 end @@ -376,7 +383,12 @@ function _copy_sparse_mat(a::SparseMatrixCSC{V,I}, ir_p::Ptr{mwIndex}, jc_p::Ptr copyto!(unsafe_wrap(Array, pi_p, (nnz,)), vi) end -function _copy_sparse_mat(a::SparseMatrixCSC{V,I}, ir_p::Ptr{mwIndex}, jc_p::Ptr{mwIndex}, pr_p::Ptr{V}) where {V,I} +function _copy_sparse_mat( + a::SparseMatrixCSC{V,I}, + ir_p::Ptr{mwIndex}, + jc_p::Ptr{mwIndex}, + pr_p::Ptr{V}, +) where {V,I} colptr::Vector{I} = a.colptr rinds::Vector{I} = a.rowval v::Vector{V} = a.nzval @@ -390,8 +402,8 @@ function _copy_sparse_mat(a::SparseMatrixCSC{V,I}, ir_p::Ptr{mwIndex}, jc_p::Ptr ir[i] = rinds[i] - 1 end - jc = unsafe_wrap(Array, jc_p, (n+1,)) - for i = 1:n+1 + jc = unsafe_wrap(Array, jc_p, (n + 1,)) + for i = 1:(n+1) jc[i] = colptr[i] - 1 end @@ -402,7 +414,7 @@ function mxarray(a::SparseMatrixCSC{V,I}) where {V<:Union{Float64,ComplexF64,Boo m::Int = a.m n::Int = a.n nnz = length(a.nzval) - @assert nnz == a.colptr[n+1]-1 + @assert nnz == a.colptr[n+1] - 1 mx = mxsparse(V, m, n, nnz) ir_p = ccall(mx_get_ir[], Ptr{mwIndex}, (Ptr{Cvoid},), mx) @@ -419,16 +431,15 @@ function mxarray(a::SparseMatrixCSC{V,I}) where {V<:Union{Float64,ComplexF64,Boo return mx end - # char arrays and string function mxarray(s::String) utf16string = transcode(UInt16, s) - pm = ccall(mx_create_char_array[], Ptr{Cvoid}, (mwSize, Ptr{mwSize},), 2, - _dims_to_mwSize((1, length(utf16string)))) + pm = ccall(mx_create_char_array[], Ptr{Cvoid}, (mwSize, Ptr{mwSize}), 2, + _dims_to_mwSize((1, length(utf16string)))) mx = MxArray(pm) ccall(:memcpy, Ptr{Cvoid}, (Ptr{Cvoid}, Ptr{Cvoid}, UInt), data_ptr(mx), utf16string, - length(utf16string)*sizeof(UInt16)) + length(utf16string) * sizeof(UInt16)) return mx end @@ -442,7 +453,7 @@ end mxcellarray(dims::Integer...) = mxcellarray(dims) function get_cell(mx::MxArray, i::Integer) - pm = ccall(mx_get_cell[], Ptr{Cvoid}, (Ptr{Cvoid}, mwIndex), mx, i-1) + pm = ccall(mx_get_cell[], Ptr{Cvoid}, (Ptr{Cvoid}, mwIndex), mx, i - 1) MxArray(pm, false) end @@ -489,14 +500,22 @@ end function set_field(mx::MxArray, i::Integer, f::String, v::MxArray) v.own = false - ccall(mx_set_field[], Cvoid, (Ptr{Cvoid}, mwIndex, Ptr{UInt8}, Ptr{Cvoid}), mx, i-1, f, v) + ccall( + mx_set_field[], + Cvoid, + (Ptr{Cvoid}, mwIndex, Ptr{UInt8}, Ptr{Cvoid}), + mx, + i - 1, + f, + v, + ) return nothing end set_field(mx::MxArray, f::String, v::MxArray) = set_field(mx, 1, f, v) function get_field(mx::MxArray, i::Integer, f::String) - pm = ccall(mx_get_field[], Ptr{Cvoid}, (Ptr{Cvoid}, mwIndex, Ptr{UInt8}), mx, i-1, f) + pm = ccall(mx_get_field[], Ptr{Cvoid}, (Ptr{Cvoid}, mwIndex, Ptr{UInt8}), mx, i - 1, f) pm == C_NULL && throw(ArgumentError("Failed to get field.")) MxArray(pm, false) end @@ -504,20 +523,26 @@ end get_field(mx::MxArray, f::String) = get_field(mx, 1, f) function get_field(mx::MxArray, i::Integer, fn::Integer) - pm = ccall(mx_get_field_bynum[], Ptr{Cvoid}, (Ptr{Cvoid}, mwIndex, Cint), mx, i-1, fn-1) + pm = ccall( + mx_get_field_bynum[], + Ptr{Cvoid}, + (Ptr{Cvoid}, mwIndex, Cint), + mx, + i - 1, + fn - 1, + ) pm == C_NULL && throw(ArgumentError("Failed to get field.")) MxArray(pm, false) end get_field(mx::MxArray, fn::Integer) = get_field(mx, 1, fn) - function get_fieldname(mx::MxArray, i::Integer) - p = ccall(mx_get_fieldname[], Ptr{UInt8}, (Ptr{Cvoid}, Cint), mx, i-1) + p = ccall(mx_get_fieldname[], Ptr{UInt8}, (Ptr{Cvoid}, Cint), mx, i - 1) unsafe_string(p) end -const Pairs = Union{Pair, NTuple{2}} +const Pairs = Union{Pair,NTuple{2}} function mxstruct(pairs::Pairs...) nf = length(pairs) @@ -533,7 +558,7 @@ function mxstruct(pairs::Pairs...) return mx end -function mxstruct(d::T) where T +function mxstruct(d::T) where {T} names = fieldnames(T) names_str = map(string, names) mx = mxstruct(names_str...) @@ -543,13 +568,14 @@ function mxstruct(d::T) where T return mx end -function mxstructarray(d::Array{T}) where T +function mxstructarray(d::Array{T}) where {T} names = fieldnames(T) names_str = map(string, names) a = _fieldname_array(names_str...) - pm = ccall(mx_create_struct_array[], Ptr{Cvoid}, (mwSize, Ptr{mwSize}, Cint, - Ptr{Ptr{UInt8}}), ndims(d), _dims_to_mwSize(size(d)), length(a), a) + pm = ccall(mx_create_struct_array[], Ptr{Cvoid}, + (mwSize, Ptr{mwSize}, Cint, + Ptr{Ptr{UInt8}}), ndims(d), _dims_to_mwSize(size(d)), length(a), a) mx = MxArray(pm) for i = 1:length(d), j = 1:length(names) @@ -561,7 +587,6 @@ end mxstruct(d::AbstractDict) = mxstruct(collect(d)...) mxarray(d) = mxstruct(d) - ########################################################### # # convert from MATLAB to Julia @@ -582,7 +607,14 @@ function _jarrayx(fun::String, mx::MxArray, siz::Tuple) else a = Array{T}(undef, siz) if !isempty(a) - ccall(:memcpy, Ptr{Cvoid}, (Ptr{Cvoid}, Ptr{Cvoid}, UInt), a, data_ptr(mx), length(a)*sizeof(T)) + ccall( + :memcpy, + Ptr{Cvoid}, + (Ptr{Cvoid}, Ptr{Cvoid}, UInt), + a, + data_ptr(mx), + length(a) * sizeof(T), + ) end end return a @@ -610,35 +642,40 @@ end function jscalar(mx::MxArray) if !(nelems(mx) == 1 && (is_logical(mx) || is_numeric(mx))) - throw(ArgumentError("jscalar only applies to numeric or logical arrays with exactly one element.")) + throw( + ArgumentError( + "jscalar only applies to numeric or logical arrays with exactly one element.", + ), + ) end @assert !is_sparse(mx) if is_complex(mx) - return unsafe_wrap(Array, real_ptr(mx), (1,))[1] + im*unsafe_wrap(Array, imag_ptr(mx), (1,))[1] + return unsafe_wrap(Array, real_ptr(mx), (1,))[1] + + im * unsafe_wrap(Array, imag_ptr(mx), (1,))[1] else return unsafe_wrap(Array, data_ptr(mx), (1,))[1] end end -function _jsparse(ty::Type{T}, mx::MxArray) where T<:MxRealNum +function _jsparse(ty::Type{T}, mx::MxArray) where {T<:MxRealNum} m = nrows(mx) n = ncols(mx) ir_ptr = ccall(mx_get_ir[], Ptr{mwIndex}, (Ptr{Cvoid},), mx) jc_ptr = ccall(mx_get_jc[], Ptr{mwIndex}, (Ptr{Cvoid},), mx) - jc_a::Vector{mwIndex} = unsafe_wrap(Array, jc_ptr, (n+1,)) + jc_a::Vector{mwIndex} = unsafe_wrap(Array, jc_ptr, (n + 1,)) nnz = jc_a[n+1] ir = Vector{Int}(undef, nnz) - jc = Vector{Int}(undef, n+1) + jc = Vector{Int}(undef, n + 1) ir_x = unsafe_wrap(Array, ir_ptr, (nnz,)) for i = 1:nnz ir[i] = ir_x[i] + 1 end - jc_x = unsafe_wrap(Array, jc_ptr, (n+1,)) - for i = 1:n+1 + jc_x = unsafe_wrap(Array, jc_ptr, (n + 1,)) + for i = 1:(n+1) jc[i] = jc_x[i] + 1 end @@ -647,7 +684,7 @@ function _jsparse(ty::Type{T}, mx::MxArray) where T<:MxRealNum if is_complex(mx) pi_ptr = ccall(mx_get_pi[], Ptr{T}, (Ptr{Cvoid},), mx) pi::Vector{T} = copy(unsafe_wrap(Array, pi_ptr, (nnz,))) - return SparseMatrixCSC(m, n, jc, ir, pr + im.*pi) + return SparseMatrixCSC(m, n, jc, ir, pr + im .* pi) else return SparseMatrixCSC(m, n, jc, ir, pr) end @@ -661,8 +698,14 @@ function jsparse(mx::MxArray) end function String(mx::MxArray) - if !(classid(mx) == mxCHAR_CLASS && ((ndims(mx) == 2 && nrows(mx) == 1) || is_empty(mx))) - throw(ArgumentError("String(mx::MxArray) only applies to strings (i.e. char vectors)")) + if !( + classid(mx) == mxCHAR_CLASS && ((ndims(mx) == 2 && nrows(mx) == 1) || is_empty(mx)) + ) + throw( + ArgumentError( + "String(mx::MxArray) only applies to strings (i.e. char vectors)", + ), + ) end return transcode(String, unsafe_wrap(Array, Ptr{UInt16}(data_ptr(mx)), ncols(mx))) end @@ -676,7 +719,15 @@ function Dict(mx::MxArray) fvals = Vector{Any}(undef, nf) for i = 1:nf fnames[i] = get_fieldname(mx, i) - pv = ccall(mx_get_field_bynum[], Ptr{Cvoid}, (Ptr{Cvoid}, mwIndex, Cint), mx, 0, i-1) + pv = + ccall( + mx_get_field_bynum[], + Ptr{Cvoid}, + (Ptr{Cvoid}, mwIndex, Cint), + mx, + 0, + i - 1, + ) fx = MxArray(pv, false) fvals[i] = jvalue(fx) end @@ -706,7 +757,7 @@ end # deep conversion from MATLAB variable to Julia array -jvalue(mx::MxArray, ::Type{Array}) = jarray(mx) +jvalue(mx::MxArray, ::Type{Array}) = jarray(mx) jvalue(mx::MxArray, ::Type{Vector}) = jvector(mx) jvalue(mx::MxArray, ::Type{Matrix}) = jmatrix(mx) jvalue(mx::MxArray, ::Type{Number}) = jscalar(mx)::Number diff --git a/test/engine.jl b/test/engine.jl index 54487a1..afc4595 100644 --- a/test/engine.jl +++ b/test/engine.jl @@ -6,8 +6,8 @@ using SparseArrays restart_default_msession() -a = [1. 2. 3.; 4. 5. 6.] -b = [2. 3. 4.; 8. 7. 6.] +a = [1.0 2.0 3.0; 4.0 5.0 6.0] +b = [2.0 3.0 4.0; 8.0 7.0 6.0] @mput a b mat""" @@ -22,7 +22,7 @@ mat""" @mget r1::Vector @test isequal(r1, vec(a .* b)) -s = sparse([1. 0. 0.; 2. 3. 0.; 0. 4. 5.]) +s = sparse([1.0 0.0 0.0; 2.0 3.0 0.0; 0.0 4.0 5.0]) put_variable(:s, s) s2 = get_variable(:s) @test isequal(s, s2) @@ -32,9 +32,9 @@ s2 = get_variable(:s) r = mxcall(:plus, 1, a, b) @test isequal(r, a + b) -(xx, yy) = mxcall(:meshgrid, 2, [1., 2.], [3., 4.]) -@test isequal(xx, [1. 2.; 1. 2.]) -@test isequal(yy, [3. 3.; 4. 4.]) +(xx, yy) = mxcall(:meshgrid, 2, [1.0, 2.0], [3.0, 4.0]) +@test isequal(xx, [1.0 2.0; 1.0 2.0]) +@test isequal(yy, [3.0 3.0; 4.0 4.0]) close_default_msession() @@ -44,7 +44,6 @@ s = MSession() close(s) @test_throws UndefRefError close(s) - # segfault on deleted references x = mxarray(3.0) delete(x) diff --git a/test/matfile.jl b/test/matfile.jl index 0792f19..86afcfc 100644 --- a/test/matfile.jl +++ b/test/matfile.jl @@ -7,8 +7,8 @@ fn = "$(tempname()).mat" a32 = Int32[1 2 3; 4 5 6] a64 = Int64[1 2 3; 4 5 6] b = [1.2, 3.4, 5.6, 7.8] -c = [[0., 1.], [1., 2.], [1., 2., 3.]] -d = Dict("name"=>"MATLAB", "score"=>100.) +c = [[0.0, 1.0], [1.0, 2.0], [1.0, 2.0, 3.0]] +d = Dict("name" => "MATLAB", "score" => 100.0) struct S x::Float64 @@ -16,12 +16,12 @@ struct S z::Vector{Float64} end -ss = S[S(1.0, true, [1., 2.]), S(2.0, false, [3., 4.])] +ss = S[S(1.0, true, [1.0, 2.0]), S(2.0, false, [3.0, 4.0])] write_matfile(fn; a32=a32, a64=a64, b=b, c=c, d=d, ss=mxstructarray(ss)) r = read_matfile(fn) -@test isa(r, Dict{String, MxArray}) +@test isa(r, Dict{String,MxArray}) @test length(r) == 6 ra32 = jmatrix(r["a32"]) diff --git a/test/mxarray.jl b/test/mxarray.jl index a712dd6..994bded 100644 --- a/test/mxarray.jl +++ b/test/mxarray.jl @@ -58,15 +58,15 @@ a = mxarray(Float64, 0, 0) @mx_test_basic_types Float64 is_double @mx_test_basic_types Float32 is_single -@mx_test_basic_types Int64 is_int64 -@mx_test_basic_types UInt64 is_uint64 -@mx_test_basic_types Int32 is_int32 -@mx_test_basic_types UInt32 is_uint32 -@mx_test_basic_types Int16 is_int16 -@mx_test_basic_types UInt16 is_uint16 -@mx_test_basic_types Int8 is_int8 -@mx_test_basic_types UInt8 is_uint8 -@mx_test_basic_types Bool is_logical +@mx_test_basic_types Int64 is_int64 +@mx_test_basic_types UInt64 is_uint64 +@mx_test_basic_types Int32 is_int32 +@mx_test_basic_types UInt32 is_uint32 +@mx_test_basic_types Int16 is_int16 +@mx_test_basic_types UInt16 is_uint16 +@mx_test_basic_types Int8 is_int8 +@mx_test_basic_types UInt8 is_uint8 +@mx_test_basic_types Bool is_logical # complex arrays @@ -176,7 +176,7 @@ a2 = jvector(a_mx) @test isequal([1:5;], a2) delete(a_mx) -a = rand(5, 6) + rand(5, 6)*im +a = rand(5, 6) + rand(5, 6) * im a_mx = mxarray(a) a2 = jarray(a_mx) @test isequal(a, a2) @@ -290,13 +290,13 @@ a = mxstruct("abc", "efg", "xyz") @test get_fieldname(a, 3) == "xyz" delete(a) -s = Dict("name"=>"MATLAB", "version"=>12.0, "data"=>[1,2,3]) +s = Dict("name" => "MATLAB", "version" => 12.0, "data" => [1, 2, 3]) a = mxstruct(s) @test is_struct(a) @test mxnfields(a) == 3 @test jstring(get_field(a, "name")) == "MATLAB" @test jscalar(get_field(a, "version")) == 12.0 -@test isequal(jvector(get_field(a, "data")), [1,2,3]) +@test isequal(jvector(get_field(a, "data")), [1, 2, 3]) delete(a) mutable struct TestType @@ -304,28 +304,27 @@ mutable struct TestType version::Float64 data::Vector{Int} end -t = TestType("MATLAB", 12.0, [1,2,3]) +t = TestType("MATLAB", 12.0, [1, 2, 3]) a = mxstruct(t) @test is_struct(a) @test mxnfields(a) == 3 @test jstring(get_field(a, "name")) == "MATLAB" @test jscalar(get_field(a, "version")) == 12.0 -@test isequal(jvector(get_field(a, "data")), [1,2,3]) +@test isequal(jvector(get_field(a, "data")), [1, 2, 3]) delete(a) -a = mxstructarray([TestType("MATLAB", 12.0, [1,2,3]), - TestType("Julia", 0.2, [4,5,6])]) +a = mxstructarray([TestType("MATLAB", 12.0, [1, 2, 3]), + TestType("Julia", 0.2, [4, 5, 6])]) @test is_struct(a) @test mxnfields(a) == 3 @test jstring(get_field(a, 1, "name")) == "MATLAB" @test jscalar(get_field(a, 1, "version")) == 12.0 -@test isequal(jvector(get_field(a, 1, "data")), [1,2,3]) +@test isequal(jvector(get_field(a, 1, "data")), [1, 2, 3]) @test jstring(get_field(a, 2, "name")) == "Julia" @test jscalar(get_field(a, 2, "version")) == 0.2 -@test isequal(jvector(get_field(a, 2, "data")), [4,5,6]) +@test isequal(jvector(get_field(a, 2, "data")), [4, 5, 6]) delete(a) - # bi-directional conversions x = mxarray(12.0) @@ -374,7 +373,7 @@ delete(x) @test size(y) == size(a) @test isequal(y, a) -a = rand(10,10) +a = rand(10, 10) a_ = @view a[3:7, 4:8] x = mxarray(a_) y = jvalue(x) @@ -398,7 +397,7 @@ delete(x) @test isa(y, Array{Int64,1}) @test isequal(y, collect(a)) -a = BitArray(rand(Bool, 5,20,10)) +a = BitArray(rand(Bool, 5, 20, 10)) x = mxarray(a) y = jvalue(x) delete(x) @@ -428,7 +427,6 @@ y = jvalue(x) @test length(y) == length(a) @test isequal(y, collect(a)) - ############################## # String Conversions ############################## @@ -450,11 +448,11 @@ delete(x) @test y[2] == a[2] @test y[3] == a[3] -a = Dict("abc"=>10.0, "efg"=>[1, 2, 3], "xyz"=>"MATLAB") +a = Dict("abc" => 10.0, "efg" => [1, 2, 3], "xyz" => "MATLAB") x = mxarray(a) y = jvalue(x) delete(x) -@test isa(y, Dict{String, Any}) +@test isa(y, Dict{String,Any}) @test y["abc"] == 10.0 @test isequal(y["efg"], [1, 2, 3])