Skip to content

Commit

Permalink
Fixed an error which caused matlab to relaunch repeatedly
Browse files Browse the repository at this point in the history
A com object was being repeatedly instantiated which caused matlab
instances to be repeatedly launched when there wasn't a previously
launched "matlab.exe -automation"
  • Loading branch information
Rickasaurus committed Aug 30, 2013
1 parent 21a3f50 commit 401de60
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<WarningLevel>3</WarningLevel>
<DocumentationFile>bin\Debug\MatlabTypeProvider.Tests.XML</DocumentationFile>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
Expand All @@ -30,6 +31,7 @@
<DefineConstants>TRACE</DefineConstants>
<WarningLevel>3</WarningLevel>
<DocumentationFile>bin\Release\MatlabTypeProvider.Tests.XML</DocumentationFile>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<PropertyGroup>
<MinimumVisualStudioVersion Condition="'$(MinimumVisualStudioVersion)' == ''">11</MinimumVisualStudioVersion>
Expand Down
2 changes: 1 addition & 1 deletion MatlabTypeProvider/MatlabTypeProvider/MatlabInterface.fs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ type MatlabCommandExecutor(proxy: MatlabCOMProxy) =
// proxy.GetFullMatrix(vname,sx,sy) |> fst

member private t.GetLargeMatrix<'T> (mvi: MatlabVariableInfo) =
let max_bytes = 8388608 // ~8mb at a time
let max_bytes = 8388608 // ~8 mb at a time
let m_height = mvi.Size.[0]
let m_width = mvi.Size.[1]
let output_matrix = Array2D.zeroCreate m_height m_width
Expand Down
28 changes: 17 additions & 11 deletions MatlabTypeProvider/MatlabTypeProvider/MatlabManualCOM.fs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,14 @@ module MatlabCOM =

let comType = Type.GetTypeFromProgID(progid, true)

let getComObject () = Activator.CreateInstance(comType)
[<ThreadStatic>] [<DefaultValue>]
static val mutable private instance:Option<Object>

static let lockObj = new Object()
let getComObject () =
match MatlabCOMProxy.instance with
| None -> let v = Activator.CreateInstance(comType) in MatlabCOMProxy.instance <- Some (v); v
| Some(v) -> v

//let __comObject =
//try Marshal.GetActiveObject(progid)
Expand All @@ -34,7 +41,7 @@ module MatlabCOM =

/// The server returns output from the command in the string, result. The result string also contains any warning or error messages that might have been issued by MATLAB software as a result of the command.
member t.Execute (args: obj[]) =
lock (comType) (fun _ ->
lock (lockObj) (fun _ ->
let comObject = getComObject ()
match comType.InvokeMember("Execute", Reflection.BindingFlags.InvokeMethod ||| Reflection.BindingFlags.Public, null, comObject, args) with
| :? string as strres -> removeAns strres :> obj
Expand All @@ -45,7 +52,7 @@ module MatlabCOM =
/// To reference a variable defined in the server, specify the variable name followed by an equals (=) sign:
/// a = h.Feval('sin', 1, 'x=');
member t.Feval (name: string) (numoutparams: int) (args: obj []) : obj =
lock (comType) (fun _ ->
lock (lockObj) (fun _ ->
let comObject = getComObject ()
//[| name; noutparams; result, arg1 ... argn |]
let prms : obj [] = Array.append [| name; numoutparams; null |] args
Expand All @@ -60,7 +67,7 @@ module MatlabCOM =

/// Read a char array from matlab as a string
member t.GetCharArray (var: string) =
lock (comType) (fun _ ->
lock (lockObj) (fun _ ->
let comObject = getComObject ()
comType.InvokeMember("GetCharArray", Reflection.BindingFlags.InvokeMethod ||| Reflection.BindingFlags.Public, null, comObject, [|var; "base"|] ) :?> string
)
Expand All @@ -69,15 +76,14 @@ module MatlabCOM =
/// If your scripting language requires a result be returned explicitly, use the GetVariable function in place of GetWorkspaceData, GetFullMatrix or GetCharArray.
/// Do not use GetVariable on sparse arrays, structures, or function handles.
member t.GetVariable (var: string) =

lock (comType) (fun _ ->
lock (lockObj) (fun _ ->
let comObject = getComObject ()
comType.InvokeMember("GetVariable", Reflection.BindingFlags.InvokeMethod ||| Reflection.BindingFlags.Public, null, comObject, [|var; "base"|] )
)

/// Get both the real and imaginary parts of a matrix from matlab, not currently working
member t.GetFullMatrix (var: string, xsize: int, ?ysize: int, ?hasImag: bool) =
lock (comType) (fun _ ->
lock (lockObj) (fun _ ->
let comObject = getComObject ()
let ysize = defaultArg ysize 0
let hasImag = defaultArg hasImag false
Expand All @@ -97,7 +103,7 @@ module MatlabCOM =
/// Use GetWorkspaceData instead of GetFullMatrix and GetCharArray to get numeric and character array data, respectively. Do not use GetWorkspaceData on sparse arrays, structures, or function handles.
/// These functions use the variant data type instead of the safearray data type used by GetFullMatrix and PutFullMatrix.
member t.GetWorkspaceData (var: string) =
lock (comType) (fun _ ->
lock (lockObj) (fun _ ->
let comObject = getComObject ()
let mutable res : obj = null
do comType.InvokeMember("GetWorkspaceData", Reflection.BindingFlags.InvokeMethod ||| Reflection.BindingFlags.Public, null, comObject, [|var; "base", res|] ) |> ignore
Expand All @@ -108,14 +114,14 @@ module MatlabCOM =
// !!! NOTE: Put* Methods have not been tested
//
member t.PutCharArray (var:string) (value:string) : unit =
lock (comType) (fun _ ->
lock (lockObj) (fun _ ->
let comObject = getComObject ()
comType.InvokeMember("PutCharArray", Reflection.BindingFlags.InvokeMethod ||| Reflection.BindingFlags.Public, null, comObject, [|var; "base"; value|] )
|> ignore
)

member t.PutFullMatrix (var: string, xreal: double [,], ?ximag: double [,]) : unit =
lock (comType) (fun _ ->
lock (lockObj) (fun _ ->
let comObject = getComObject ()
let ximag : obj =
match ximag with
Expand All @@ -128,7 +134,7 @@ module MatlabCOM =

/// Use PutWorkspaceData to pass numeric and character array data respectively to the server. Do not use PutWorkspaceData on sparse arrays, structures, or function handles. Use the Execute method for these data types.
member t.PutWorkspaceData (var: string) (data: obj) : unit =
lock (comType) (fun _ ->
lock (lockObj) (fun _ ->
let comObject = getComObject ()
comType.InvokeMember("PutWorkspaceData", Reflection.BindingFlags.InvokeMethod, null, comObject, [|var; "base"; data|] )
|> ignore
Expand Down
8 changes: 5 additions & 3 deletions MatlabTypeProvider/MatlabTypeProvider/Provider.fs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ open Samples.FSharp.ProvidedTypes
open FSMatlab.InterfaceTypes
open FSMatlab.Interface

module MatlabInterface =
let executor = MatlabCommandExecutor(new FSMatlab.MatlabCOM.MatlabCOMProxy("Matlab.Desktop.Application"))
module MatlabInterface =
let private comProxy = new FSMatlab.MatlabCOM.MatlabCOMProxy("Matlab.Desktop.Application")
let executor = MatlabCommandExecutor(comProxy)
let toolboxeCache = lazy (executor.GetToolboxes() |> Seq.toList |> InterfaceHelpers.MatlabFunctionHelpers.nestAllToolboxes)

module ProviderHelpers =
let internal getParamsForFunctionInputs (mlfun: MatlabFunctionInfo) =
Expand Down Expand Up @@ -128,7 +130,7 @@ type SimpleMatlabProvider (config: TypeProviderConfig) as this =
//
let fty = ProvidedTypeDefinition(thisAssembly, lazyRootNamespace, "Toolboxes", Some(typeof<obj>))
do fty.AddMembersDelayed(fun () ->
let toolboxes = executor.GetToolboxes() |> Seq.toList |> InterfaceHelpers.MatlabFunctionHelpers.nestAllToolboxes in
let toolboxes = MatlabInterface.toolboxeCache.Value in
LazyProviderHelpers.generateToolboxes executor toolboxes)
do fty.AddXmlDoc("Matlab toolboxes with function handles")
do this.AddNamespace(lazyRootNamespace, [fty])
Expand Down

0 comments on commit 401de60

Please sign in to comment.