none
marshalling array of structs with array of structs as one of the parameters RRS feed

  • General discussion

  • I have following structs:

    public struct AP_LS

    {

       public int SoT;
       public int GT;
    } ;

    public struct AP_S
    {
        public int N; 
      MarshalAs(UnmanagedType.ByValArray,ArraySubType=UnmanagedType.Struct, SizeConst = MAX_NUM_P)] 
      public AP_LS[] problemArr;
    }

    pubic struct TRIAL_RESULTS_AP
    {

      public int NumR;
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = FeasXConst.MAX_NUM_DS)]
      public UInt32[] RH;
      public int NumD; 
       [MarshalAs(UnmanagedType.ByValArray, SizeConst = FeasXConst.MAX_NUM_DS)]
      public Q_PROPERTIES[] D; 
      public int NumSchedules;
      [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct,SizeConst=MAX_NUM_AP_S)]   public AP_S[] ApS; // } ;

    and unmanaged dll's function
    int Func (int Foo, TRIAL_RESULTS_AP[] Bar);

     I can not marshal TRIAL_RESULTS_AP. Actually, the only part I have problem with is AP_S->ProblemArr.
    I've tried to substitute AP_S struct with AP_S_subst struct with following signature (and corresponding TRIAL_RESULTS_AP_subst):
     
     

     

    public struct AP_S_subst
    {
       public int N; 
      public IntPtr problemPtr;
    } ;

    and make wrapper for the original Func - Func_wrapper which will take origianl structure and Marshal data directly to the problemPtr using following code:

    for
    (int j = 0; j < PrevResults[i].ApS.Length; j++)
    {
      /*... rest of assignment*/
      PrevResults_F[i].ApS[j].problemPtr=
    Marshal.AllocHGlobal(Convert.ToInt32(Marshal.SizeOf(new    AP_LS()) * MAX_NUM_FLIGHTS_FROM_AP));  long count = PrevResults_F[i].ApS[j].problemPtr.ToInt64();   foreach (AP_LS a in PrevResults[i].ApS[j].Leg)
      {
          IntPtr some = new IntPtr(count);
         Marshal.StructureToPtr(a, some, true);
         count +=
    Marshal.SizeOf(typeof(AP_LS));
       }
    }

    but this does not work either!!

    Thank you for any help.

     

    Tuesday, September 22, 2009 8:24 PM

All replies

  • Remove the UnmanagedType.Struct declarations they don't do what you think they do.  They are not needed here, the marshaller can figure out what to do from the structure type.

    The substitute you tried is not equivalent, a ByValArray is the opposite of an IntPtr.  If it still doesn't work, you'll have to tell us a *lot* more about what is going wrong.

    Hans Passant.
    Tuesday, September 22, 2009 10:23 PM
    Moderator
  • Hans,
    thank you for prompt answer.
    I actually added UnmanagedType.Struct after I'd failed first time.
     
    I understand that ByValArray is the "oppositte" - I wnated to replace array of struct with memory buffer (lets say, struct ss[15] I am trying to substitute with IntPtr buff, and then Marshal.StrToPtr(ss[i], buff+sizeof(typeof(ss), false).
    Please, let me know what is A LOT - I would like to solve this problem ASAP:)


    Thank you
    Tuesday, September 22, 2009 10:36 PM
  • Hello olelukoyya

    Please use the tool PInvoke Interop Assistant (http://clrinterop.codeplex.com/)  to make sure that the .NET representitives of the native structs are declared rightly. PInvoke Interop Assistant  takes the inputs of native structs and outputs the 100% right .NET corresponds. Please post the output of the tool here. 

    Thanks
    Jialiang Ge
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Wednesday, September 23, 2009 6:50 AM
    Moderator
  • Hi Jialiang,

    Not sure this tool handle my situation properly

    One example, I have unmanaged function whih expects array of structs to be passed void Func1(SOME_STRUCT[] st, int p);
    The tool converts it to

    [System.Runtime.InteropServices.DllImportAttribute("<Unknown>", EntryPoint="Func1")]
    public static extern int Func1(ref SOME_STRUCT st, int p);

    But I cannot pass Array of structures to this function from the C# code now, since once i declare
    SOME_STRUCT[] in_st = new SOME_STRUCT(5);
    and then fill it with data, I will receive comipler's error (which I'd tested:
    Error 2 The best overloaded method match for Func1(ref SOME_STRUCT, int); has some invalid arguments )


    Still looking for help! Please,let mw know what data is needed to clarify the situation.
    I dont think that it is possible to pass array of struct in this case.

    Wednesday, September 23, 2009 4:56 PM
  • It is not a great tool, forget about it.  Your original declarations are good.  You haven't told us anything about how you know it doesn't work, can't help you without that.

    Hans Passant.
    Wednesday, September 23, 2009 7:06 PM
    Moderator
  • Hello

    I get this result from P/Invoke Interop Toolkit:

    Input: (native C++)

    struct AP_LS
    {
       int SoT;
       int GT;
    } ;

    struct AP_S
    {
        int N;
        AP_LS problemArr[5];
    };

    void Func2(AP_S[] st, int p);

    Output:

    [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
    public struct AP_LS {
       
        /// int
        public int SoT;
       
        /// int
        public int GT;
    }

    [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
    public struct AP_S {
       
        /// int
        public int N;
       
        /// AP_LS[5]
        [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5, ArraySubType=System.Runtime.InteropServices.UnmanagedType.Struct)]
        public AP_LS[] problemArr;
    }

    public partial class NativeMethods {
       
        /// Return Type: void
        ///st: AP_S[]
        ///p: int
        [System.Runtime.InteropServices.DllImportAttribute("<Unknown>", EntryPoint="Func2")]
    public static extern  void Func2(AP_S[] st, int p) ;

    }

    The generated C# signature is different from your "Func1(ref SOME_STRUCT, int);"

    Could you please check whether you are using the latest toolkit?

    Regards,
    Jialiang Ge


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Thursday, October 1, 2009 6:15 AM
    Moderator
  • Hello

    How are you? How is the situation of the issue on your side?

    Regards,
    Jialiang Ge
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Thursday, October 8, 2009 7:58 AM
    Moderator