none
Cannot marshal parameter :Internal limitation:structure is too complex or too large RRS feed

  • Question

  • I'm using a C++ dll in C# (.Net 4.0)

    Here is the C++ code:

    struct MIPResult
    {
          double Optima;
          short SpotResults[30000];
          float GRPResults[1000];
    };
                    
    extern"C" __declspec(dllexport) int CalcOptima(int optiType, int rowNum, int colNum, double a[], int typeB[], double lowerBoundB[], double upperBoundB[],      double coefficient[], int kind[], int typeC[], double lowerBoundC[], double upperBoundC[], MIPResult *Output)
    {   
        ...                        
    }

    And here is the C# code

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)] struct MIPOut { public double Optima; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 30000, ArraySubType = System.Runtime.InteropServices.UnmanagedType.I2)] public Int16[] SpotResults; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1000, ArraySubType = System.Runtime.InteropServices.UnmanagedType.R4)] public Single[] GRPResults; }

    [DllImport("OptimizerEngine.dll", CallingConvention = CallingConvention.Cdecl)]
            public static extern int CalcOptima(int optiType, int rowNum, int colNum,
                double[] a, int[] typeB, double[] lowerBoundB, double[] upperBoundB, double[] coefficient,
                int[] kind, int[] typeC, double[] lowerBoundC, double[] upperBoundC, ref MIPOut Output);

    This code can work. But if I modify the size from 1000 to 1500, I can successfully build the code, but get the Error:"Cannot marshal 'parameter #13':Internal limitation:structure is too complex or too large".

    I hope to define a In16 Array with size of 60000 and a Single Array with size of 3000, could anyone give me some help or advice? Thanks a lot!


    • Edited by Haobo Ding Thursday, November 29, 2012 8:25 AM Add code
    Thursday, November 29, 2012 3:48 AM

Answers

  • Hello Sean,

    1. I suggest that you change the parameter type from "ref MIPOut" to "IntPtr", e.g. :

    [DllImport("OptimizerEngine.dll", CallingConvention = CallingConvention.Cdecl)]
            public static extern int CalcOptima(..., IntPtr Output);

    2. Allocate memory large enough for an unmanaged MIPOut structure and then use the pointer to this structure as the parameter for "Output". Use Marshal.AllocCoTaskMem() to allocate the memory.

    3. After calling the CalcOptima() function, convert the unmanaged MIPOut structure back to a managed MIPOut structure. Use Marshal.PtrToStructure() for this purpose. After that free the unmanaged memory using Marshal.FreeCoTaskMem().

    4. The following is a simplified example :

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;
    
    namespace CSConsoleClient
    {
        class Program
        {
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)]
            public struct MIPOut
            {
                public double Optima;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 60000, ArraySubType = System.Runtime.InteropServices.UnmanagedType.I2)]
                public Int16[] SpotResults;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3000, ArraySubType = System.Runtime.InteropServices.UnmanagedType.R4)]
                public Single[] GRPResults;
            }
    
            [DllImport("OptimizerEngine.dll", CallingConvention = CallingConvention.Cdecl)]
            public static extern Int32 CalcOptima(IntPtr Output);
    
            public static void DoTest()
            {
                int iSizeOfStruct = Marshal.SizeOf(typeof(MIPOut));
                IntPtr pmipout = Marshal.AllocCoTaskMem(iSizeOfStruct);
    
                CalcOptima(pmipout);
    
                MIPOut mipout = (MIPOut)(Marshal.PtrToStructure(pmipout, typeof(MIPOut)));
    
                Marshal.FreeCoTaskMem(pmipout);
                pmipout = IntPtr.Zero;
            }
    
            static void Main(string[] args)
            {
                DoTest();
            }
        }
    }
    

    - Bio.


    Please visit my blog : http://limbioliong.wordpress.com/

    • Marked as answer by Haobo Ding Thursday, November 29, 2012 9:24 AM
    Thursday, November 29, 2012 8:46 AM

All replies

  • Hello Sean,

    1. Please show us how the CalcOptima() function is defined in your C# code.

    2. I am particularly interested in how the 13th parameter "Output" is defined, e.g. is it defined as an IntPtr or as some "ref" or "out" parameter ?

    - Bio.


    Please visit my blog : http://limbioliong.wordpress.com/

    Thursday, November 29, 2012 7:47 AM
  • Dear Bio,

           I have add the code in C# defines the function, thanks for your time.

    Thursday, November 29, 2012 8:26 AM
  • Hello Sean,

    1. I suggest that you change the parameter type from "ref MIPOut" to "IntPtr", e.g. :

    [DllImport("OptimizerEngine.dll", CallingConvention = CallingConvention.Cdecl)]
            public static extern int CalcOptima(..., IntPtr Output);

    2. Allocate memory large enough for an unmanaged MIPOut structure and then use the pointer to this structure as the parameter for "Output". Use Marshal.AllocCoTaskMem() to allocate the memory.

    3. After calling the CalcOptima() function, convert the unmanaged MIPOut structure back to a managed MIPOut structure. Use Marshal.PtrToStructure() for this purpose. After that free the unmanaged memory using Marshal.FreeCoTaskMem().

    4. The following is a simplified example :

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;
    
    namespace CSConsoleClient
    {
        class Program
        {
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)]
            public struct MIPOut
            {
                public double Optima;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 60000, ArraySubType = System.Runtime.InteropServices.UnmanagedType.I2)]
                public Int16[] SpotResults;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3000, ArraySubType = System.Runtime.InteropServices.UnmanagedType.R4)]
                public Single[] GRPResults;
            }
    
            [DllImport("OptimizerEngine.dll", CallingConvention = CallingConvention.Cdecl)]
            public static extern Int32 CalcOptima(IntPtr Output);
    
            public static void DoTest()
            {
                int iSizeOfStruct = Marshal.SizeOf(typeof(MIPOut));
                IntPtr pmipout = Marshal.AllocCoTaskMem(iSizeOfStruct);
    
                CalcOptima(pmipout);
    
                MIPOut mipout = (MIPOut)(Marshal.PtrToStructure(pmipout, typeof(MIPOut)));
    
                Marshal.FreeCoTaskMem(pmipout);
                pmipout = IntPtr.Zero;
            }
    
            static void Main(string[] args)
            {
                DoTest();
            }
        }
    }
    

    - Bio.


    Please visit my blog : http://limbioliong.wordpress.com/

    • Marked as answer by Haobo Ding Thursday, November 29, 2012 9:24 AM
    Thursday, November 29, 2012 8:46 AM
  • It does work.

    Thanks very much!

    Thursday, November 29, 2012 9:24 AM