CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 3 of 3
  1. #1
    Join Date
    Aug 2005
    Posts
    133

    Passing array of struct as argument to unmanaged DLL

    Hi,
    I'm currently working on a project that dynamicaly load an unmanaged dll and use it. Everything works fine unless for a specific fonction that take a structure array as an argument. The function is supposed to fill the array with correct values, but after the method ends, all data in my struct are on their default value.

    Here's the c++ struct:
    Code:
    typedef struct {                          // Field Descriptor
          UINT16         iFldNum;                // Field number (1..n)
          DBINAME        szName;                 // Field name
          UINT16         iFldType;               // Field type
          UINT16         iSubType;               // Field subtype (if applicable)
          INT16          iUnits1;                // Number of Chars, digits etc
          INT16          iUnits2;                // Decimal places etc.
          UINT16         iOffset;                // Offset in the record (computed)
          UINT16         iLen;                   // Length in bytes (computed)
          UINT16         iNullOffset;            // For Null bits (computed)
          FLDVchk        efldvVchk;              // Field Has vcheck (computed)
          FLDRights      efldrRights;            // Field Rights (computed)
          BOOL16         bCalcField;             // Is Calculated field (computed)
          UINT16         iUnUsed[2];
       } FLDDesc;
    typedef FLDDesc far *pFLDDesc;
    Here's the c++ function declaration :
    Code:
    DBIResult DBIFN DbiGetFieldDescs (    // Get field descriptions
          hDBICur        hCursor,           // Cursor handle
          pFLDDesc       pfldDesc           // Array of field descriptors
        );
    Here's my c# struct :
    Code:
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack=1)]
            struct FLDDesc
            {                          // Field Descriptor
                public ushort iFldNum;                // Field number (1..n)
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
                public char[] szName;                 // Field name
                public ushort iFldType;               // Field type
                public ushort iSubType;               // Field subtype (if applicable)
                public short iUnits1;                // Number of Chars, digits etc
                public short iUnits2;                // Decimal places etc.
                public ushort iOffset;                // Offset in the record (computed)
                public ushort iLen;                   // Length in bytes (computed)
                public ushort iNullOffset;            // For Null bits (computed)
                public FLDVchk efldvVchk;              // Field Has vcheck (computed)
                public FLDRights efldrRights;            // Field Rights (computed)
                public short bCalcField;             // Is Calculated field (computed)
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
                public ushort[] iUnUsed;
            }
    Here's my delegate :
    Code:
    private delegate ushort DbiGetFieldDescs(IntPtr hCursor, FLDDesc[] pfldDesc);
    Here's how i call the dll method :
    Code:
    pFldDesc = new FLDDesc[curProps.iFields];
        /*for (int i = 0; i < curProps.iFields; i++)
            pFldDesc[i] = new FLDDesc();*/
    	if (pFldDesc == null)
    	{
    		// Throw exception for DBIERR_NOMEMORY
    		
    		return null;
    	}
        pProc = GetProcAddress(idapi, "DbiGetFieldDescs");
        DbiGetFieldDescs dbiGetFieldDescs = (DbiGetFieldDescs)Marshal.GetDelegateForFunctionPointer(pProc, typeof(DbiGetFieldDescs));
    
        
        dbiResult = dbiGetFieldDescs(m_hCursor, pFldDesc);
    If anyone have a clue, it would be really appreciated

    Thanks
    Louis-Philippe Frenette
    Arobas Informatique Granby
    http://www.arobasinformatique.com

  2. #2
    Join Date
    Jan 2002
    Location
    Scaro, UK
    Posts
    5,940

    Re: Passing array of struct as argument to unmanaged DLL

    Why do you have "Pack=1" in the struct layout definition ? Only use this if the packing has changed in the C++ header file (e.g. #pragma pack(1)).

    Also try these modifications :

    Code:
    private delegate ushort DbiGetFieldDescs(IntPtr hCursor, IntPtr pfldDesc);
    and when making the call

    Code:
    GCHandle ppFldDesc = GCHandle.Alloc(pFldDesc, GCHandleType.Pinned);
    
    try
    {
        dbiResult = dbiGetFieldDescs(m_hCursor, ppFldDesc.AddrOfPinnedObject());
    }
    finally
    {
        ppFldDesc.Free();
    }
    If this still doesn't work what is DBINAME typeffed as ? If it's not a char[32] then your struct won't work.

    There are tools which can help you do interop : see the wikipedia page here.

    Darwen.
    Last edited by darwen; June 25th, 2009 at 03:29 PM.
    www.pinvoker.com - PInvoker - the .NET PInvoke Interface Exporter for C++ Dlls.

  3. #3
    Join Date
    Aug 2005
    Posts
    133

    Re: Passing array of struct as argument to unmanaged DLL

    Thanks for you reply.

    I tried the code you wrote, but it ended with the exception :
    Object contains non-primitive or non-blittable data

    when it calls GCHandle.Alloc...

    By the way DBINAME is a CHAR[32] Type.

    Thanks
    Louis-Philippe Frenette
    Arobas Informatique Granby
    http://www.arobasinformatique.com

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured