title: Matlab: How to survey compiled m-code progression from external API?
body: <p>My question is extremely specific to the arcanes of the matlab compiler and runtime. As only people familiar with matlab runtime API may answer, I shortened much details. Please let me know if I should be more verbose.</p>
  
  <h1>Introduction</h1>
  
  <p>Using the matlab compiler &amp; runtime I can call a function written in m-code from a C# program. Let's say calling:</p>
  
  <pre><code>function [result] = foo(n)
  %[
      result = 0;
      for k = 1:n,
          pause(1.0); % simulate long processing
          result = result + 42;
      end
  %]
  </code></pre>
  
  <p>with (somewhere behind some dllimports in the C# code):</p>
  
  <pre><code>mclFeval(IntPtr inst, string name, IntPtr[] plhs, IntPtr[] prhs)
  </code></pre>
  
  <p>So far, so good, I have no issue with this (i.e intializing the runtime, loading the '.cft' file, marshalling back and forth MxArray with .Net types, etc...)</p>
  
  <h1>My Problem</h1>
  
  <p>I would like to survey the progression of my <code>foo</code> function using some <code>cancel</code> and <code>progress</code> callbacks:</p>
  
  <pre><code>function [result] = foo(n, cancelCB, progressCB)
  %[
      if (nargin &lt; 3), progressCB = @(ratio, msg) disp(sprintf('Ratio = %f, Msg = %s', ratio, msg)); end
      if (nargin &lt; 2), cancelCB = @() disp('Checking cancel...'); end
  
      result = 0;
      for k = 1:n,
  
          if (~isempty(cancelCB)), 
              cancelCB(); % Up to the callback to raise some error('cancel');
          end;
          if (~isempty(progressCB)),  
             progressCB(k/n, sprintf('Processing (%i/%i)', k, n));
          end
  
          pause(1.0); % simulate long processing
          result = result + 42;
      end
  %]
  </code></pre>
  
  <p>But of course I would like these callbacks to be in the C# code, not within the m-one.</p>
  
  <h1>Investigations</h1>
  
  <ol>
  <li><p>Looking at 'mclmcr.h' header file, it looks like these functions may be of help:</p>
  
  <pre><code>extern mxArray* mclCreateSimpleFunctionHandle(mxFunctionPtr fcn);
  extern bool mclRegisterExternalFunction(HMCRINSTANCE inst, const char* varname, mxFunctionPtr fcn);
  </code></pre>
  
  <p>Unfortunatly these are fully undocumented and I found no use case I could mimic to understand how they work.</p></li>
  <li><p>I've also thought about creating a COM visible object in C# and pass it as a parameter to the matlab code:</p>
  
  <pre><code>// Somewhere within C# code:
  var survey = new ComSurvey();
  survey.SetCancelCallback =  () =&gt; { if (/**/) throw new OperationCancelException(); };
  survey.SetProgressCallback = (ratio, msg) =&gt; { /* do something */ };
  </code></pre>
  
  <p>&nbsp;</p>
  
  <pre><code>function [result] = foo(n, survey)
  %[
      if (nargin &lt; 2), survey = []; end
  
      result = 0;
      for k = 1:n,
  
          if (~isempty(survey)),
             survey.CheckCancel(); % up to the COM object to raise exception
             survey.SetProgress(k/n, sprintf('Processing... %i/%i', k, n));
          end
  
          pause(1.0); % simulate long processing
          result = result + 42;
      end
  %]
  </code></pre>
  
  <p>I'm very familiar with functions to create numeric and structure arrays and know how to use them:</p>
  
  <pre><code>extern mxArray *mxCreateNumericArray(...)
  extern mxArray *mxCreateStructArray(...)
  </code></pre>
  
  <p>Anyhow, how COM objects are packaged to MxArrays, I don't know?</p></li>
  </ol>
  
  <h1>Further investigations</h1>
  
  <p><strong>Day+1</strong></p>
  
  <p>Even if still unstable, I succeeded to have matlab to callback into my C# code and it seems that <code>mclCreateSimpleFunctionHandle</code> is the direction to go. </p>
  
  <p><strong>Note: Below code is for reference only. It may not be suitable in your own context as is. I'll provide simpler code later on (i.e. once I'll get stable solution).</strong></p>
  
  <ol>
  <li><p>Looking to the signature of the <code>mxFunctionPtr</code>, I created two delegates like this:</p>
  
  <pre><code>// Mimic low level signature for a Matlab function pointer
  [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
  delegate void MCRInteropDelegate(int nlhs, IntPtr[] plhs, int nrhs, IntPtr[] prhs);
  </code></pre>
  
  <p>and</p>
  
  <pre><code>// Same signature (but far more elegant from .NET perspective)
  delegate void MCRDelegate(MxArray[] varargouts, MxArray[] varargins);  
  </code></pre></li>
  <li><p>I also linked to the runtime like this:</p>
  
  <pre><code>[DllImport("mclmcrrt74.dll", EntryPoint = "mclCreateSimpleFunctionHandle", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
  static extern IntPtr _mclCreateSimpleFunctionHandle(MCRInteropDelegate fctn);
  </code></pre></li>
  <li><p>Assuming <code>MxArray</code> is a .NET class of mine that simply encapsulate for <code>mxArray*</code> handles, I then marshaled my delegates like this:</p>
  
  <pre><code>// Create MxArray from corresponding .NET delegate
  static MxArray CreateFromDelegate(MCRDelegate del)
  {
      // Package high level delegate signature to a 'dllimport' signature
      MCRInteropDelegate interopDel = (nlhs, plhs, nrhs, prhs) =&gt;
      {
          int k = 0;
  
          var varargouts = new MxArray[nlhs];
          var varargins = new MxArray[nrhs];
  
          // (nrhs, prhs) =&gt; MxArray[] varargins 
          Array.ForEach(varargins, x =&gt; new MxArray(prhs[k++], false)); // false = is to indicate that MxArray must not be disposed on .NET side
  
          // Call delegate
          del(varargouts, varargins); // Todo: varargouts created by the delegate must be destroyed by matlab, not by .NET !!
  
          // MxArray[] varargouts =&gt; (nlhs, plhs)
          k = 0;
          Array.ForEach(plhs, x =&gt; varargouts[k++].getPointer());
      };
  
      // Create the 1x1 array of 'function pointer' type
      return new MxArray(MCRInterop.mclCreateSimpleFunctionHandle(interopDel));
  }
  </code></pre></li>
  <li><p>Finally, assuming <code>module</code> is an instance of <code>MCRModule</code> (again, a class of mine to encapsulate <code>hInst*</code> in low level <code>mclFeval</code> API), I was able to call <code>foo</code> function and have it to enter my .NET <code>cancel</code> delegate like this:</p>
  
  <pre><code>// Create cancel callback in .NET
  MCRDelegate cancel = (varargouts, varargins) =&gt;
  {
      if ((varargouts != null) &amp;&amp; (varargouts.Length != 0) { throw new ArgumentException("'cancel' callback called with too many output arguments"); } 
      if ((varargins != null) &amp;&amp; (varargins.Length != 0) { throw new ArgumentException("'cancel' callback called with too many input arguments"); }
  
      if (...mustCancel...) { throw new OperationCanceledException(); }
  }
  
  // Enter the m-code
  // NB: Below function automatically converts its parameters to MxArray
  // and then call low level mclFeval with correct 'mxArray*' handles
  module.Evaluate("foo", (double)10, cancel);
  </code></pre>
  
  <p><strong>This .NET code worked fine, and <code>foo</code> really made callback to the <code>cancel</code> delegate properly.</strong></p>
  
  <p>Only problem, is that it is quite unstable. My guess is that I used too many anonymous functions, and probably some of them are disposed too early ...</p>
  
  <p><strong>Will try to provide with stable solution within the next few days</strong> (hopefully with simpler code to read and copy-paste in your own context for immediate testing).</p>
  
  <p>Please let me know if you think I'm going the wrong direction with <code>mclCreateSimpleFunctionHandle</code>.</p></li>
  </ol>