My question is extremely specific for the Arcana of the Matlab compiler and runtime. As soon as people familiar with the Matlab API can answer, I cut down a lot of the details. Please let me know if I will be more detailed.
Introduction
Using the Matlab compiler and runtime, I can call a function written in m-code from a C # program. Let me say:
function [result] = foo(n)
%[
result = 0;
for k = 1:n,
pause(1.0); % simulate long processing
result = result + 42;
end
%]
with (somewhere behind some dllimports in C # code):
mclFeval(IntPtr inst, string name, IntPtr[] plhs, IntPtr[] prhs)
So far, so good, I have no problem with this (for example, to initialize the runtime, load the .cft file, sort MxArray using .Net types, etc.)
My problem
I would like to view the progress of my function foousing some callbacks canceland progress:
function [result] = foo(n, cancelCB, progressCB)
%[
if (nargin < 3), progressCB = @(ratio, msg) disp(sprintf('Ratio = %f, Msg = %s', ratio, msg)); end
if (nargin < 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
%]
, , , #, m-one.
"mclmcr.h", , :
extern mxArray* mclCreateSimpleFunctionHandle(mxFunctionPtr fcn);
extern bool mclRegisterExternalFunction(HMCRINSTANCE inst, const char* varname, mxFunctionPtr fcn);
, , , , , .
COM # matlab:
var survey = new ComSurvey();
survey.SetCancelCallback = () => { if () throw new OperationCancelException(); };
survey.SetProgressCallback = (ratio, msg) => { };
function [result] = foo(n, survey)
%[
if (nargin < 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
%]
:
extern mxArray *mxCreateNumericArray(...)
extern mxArray *mxCreateStructArray(...)
, COM- MxArrays, ?
+ 1
, Matlab #, , mclCreateSimpleFunctionHandle - .
. . , , . (.. ).
mxFunctionPtr, :
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
delegate void MCRInteropDelegate(int nlhs, IntPtr[] plhs, int nrhs, IntPtr[] prhs);
delegate void MCRDelegate(MxArray[] varargouts, MxArray[] varargins);
:
[DllImport("mclmcrrt74.dll", EntryPoint = "mclCreateSimpleFunctionHandle", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
static extern IntPtr _mclCreateSimpleFunctionHandle(MCRInteropDelegate fctn);
, MxArray .NET-, mxArray*, :
static MxArray CreateFromDelegate(MCRDelegate del)
{
MCRInteropDelegate interopDel = (nlhs, plhs, nrhs, prhs) =>
{
int k = 0;
var varargouts = new MxArray[nlhs];
var varargins = new MxArray[nrhs];
Array.ForEach(varargins, x => new MxArray(prhs[k++], false));
del(varargouts, varargins);
k = 0;
Array.ForEach(plhs, x => varargouts[k++].getPointer());
};
return new MxArray(MCRInterop.mclCreateSimpleFunctionHandle(interopDel));
}
, , module MCRModule ( , hInst* API mclFeval), foo .NET cancel :
// Create cancel callback in .NET
MCRDelegate cancel = (varargouts, varargins) =>
{
if ((varargouts != null) && (varargouts.Length != 0) { throw new ArgumentException("'cancel' callback called with too many output arguments"); }
if ((varargins != null) && (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);
.NET- , foo cancel .
, . , , , , ...
(, - ).
, , , mclCreateSimpleFunctionHandle.