-1

I'm doing a project to call Matlab function by call MCR by P/Invoke. It throw an exception but I cannot solve it, I search a lot but cannot find the solution.

This is the error enter image description here

[DllImport(@"C:\Program Files\MATLAB\MATLAB Compiler Runtime\v80\runtime\win64\mclmcrrt8_0.dll", EntryPoint = "mclInitializeApplication_proxy", CallingConvention = CallingConvention.Cdecl)]
    private static extern bool mclInitializeApplication(string options, Int32 count);


    private static void Main(string[] args)
    {
        var option = "-nojvm";

        var result = mclInitializeApplication(option, 1);

        Console.WriteLine(result);
        Console.ReadLine();
    }

1 Answers1

0

The correct marshalling for "mclIntializeApplication" is:

[DllImport((@"C:\Program Files\MATLAB\MATLAB Compiler Runtime\v80\runtime\win64\mclmcrrt8_0.dll, EntryPoint = "mclInitializeApplication_proxy", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
public static extern bool mclInitializeApplication([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)] string[] options, int count);

That is the first parameter is an array of strings (char**). You should then call it this way:

var options = new [] { "-nojvm" };
var result = mclInitializeApplication(options, options.Length);

To avoid passing length and controlling for boolean result you can also wrap above function to something more C# friendly:

public static void mclInitializeApplication(params string[] options)
{
    var count = 0;
    if (options != null) { count = options.Length; }
    if (!_mclInitializeApplication(options, count))
    {
        var reason = mclGetLastErrorMessage();
        throw new Exception(String.Format("Call to '{0}' failed: {1}", "mclInitializeApplication", reason));               
    }
}

With:

[DllImport(@"C:\Program Files\MATLAB\MATLAB Compiler Runtime\v80\runtime\win64\mclmcrrt8_0.dll", EntryPoint = "mclGetLastErrorMessage_proxy", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
private static extern IntPtr _mclGetLastErrorMessage();
public static String mclGetLastErrorMessage()
{
    var ptr = _mclGetLastErrorMessage(); 
    return Marshal.PtrToStringAnsi(ptr);
}

But, in my real opinion, if you want to target .NET, the best solution is to let Matlab to compile in .NET directly with the SDK provided by Mathworks.

CitizenInsane
  • 4,755
  • 1
  • 25
  • 56
  • Thanks a lot, CitizenInsane. It works for me. For your recommendation, but my dll file have a little bit special, calling matlab MCR via Pinvoke is the only way. Thanks again – khanhhuynh Jan 26 '16 at 10:16
  • And I also have another question: after initialize MCR, I do initialize dll file: `[DllImport(@"myDLL.dll", CallingConvention = CallingConvention.Cdecl)] private static extern bool myDLLInitialize();` but it doesn't work. Can you help me this problem – khanhhuynh Jan 26 '16 at 10:19
  • I'm not sure what you mean by 'it doesn't' work but have a look at following thread: http://stackoverflow.com/q/5832960/684399 ... May be you're calling twice 'mclInitializeApplication' ... – CitizenInsane Jan 26 '16 at 12:39