Search code examples
c#matlabmarshalling

C# Struct for Matlab function


I have a very simple matlab function:

function [x,y] = myfunc(a,b,myStruct) 
x = a + b + myStruct.score; 
y = sprintf('Hello %s',myStruct.name); 

I am then trying to call this from c# by doing the following:

class Program
{
    static void Main(string[] args)
    {
        MLApp.MLApp matlab = new MLApp.MLApp();
        matlab.Execute(@"c:\matlab");
        object result = null;
        var student= new Student {grade = "A", name = "StudentName", score = 90};
        matlab.Feval("myfunc", 2, out result, 3.14, 42.0, student);
        var res = result as object[];
    }
    public struct Student
    {
        public string name;
        private string gr;
        private int sc;
        public string grade
        {
            get { return gr; }
            set { gr = value; }
        }
        public int score
        {
            get { return sc; }
            set { sc = value; }
        }
    }
}

Unfortunately this always results in a:

An unhandled exception of type 'System.ArgumentException' occurred in mscorlib.dll
Additional information: Value does not fall within the expected range.

Anyone got any ideas what i'm missing out? I followed the matlab documentation, which basically said as long as you have a publicly accessible fields then you're good to go.

StackTrace:

at System.RuntimeType.InvokeDispMethod(String name, BindingFlags invokeAttr, Object target, Object[] args, Boolean[] byrefModifiers, Int32 culture, String[] namedParameters) at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams) at System.RuntimeType.ForwardCallToInvokeMember(String memberName, BindingFlags flags, Object target, Int32[] aWrapperTypes, MessageData& msgData) at MLApp.DIMLApp.Feval(String bstrName, Int32 nargout, Object& pvarArgOut, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, Object arg15, Object arg16, Object arg17, Object arg18, Object arg19, Object arg20, Object arg21, Object arg22, Object arg23, Object arg24, Object arg25, Object arg26, Object arg27, Object arg28, Object arg29, Object arg30, Object arg31, Object arg32) at rmtest.Program.Main(String[] args) in C:\Users{username}\documents\visual studio 2015\Projects\rmtest\rmtest\Program.cs:line 20 at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart()


Solution

  • This did the trick:

    IntPtr pnt = Marshal.AllocHGlobal(Marshal.SizeOf(student));
    matlab.Feval("myfunc", 2, out result, 3.14, 42.0, pnt);