1

I am trying to return array of structure from the C++ DLL to C# application. I could return structure from DLL Also could able to send list of structure from c# application to C++ DLL and print its data. But not able to fill and return array of structure from DLL to C# application. Could anybody help on this. Below is the code on which I am currently working:

C# Code:

[StructLayout(LayoutKind.Sequential)]
public struct DATA
{
    [MarshalAs(UnmanagedType.I4)]
    public int id;
    [MarshalAs(UnmanagedType.LPWStr)]
    public string Name;
};

[DllImport("PassStruct.dll")]
private static extern void PrintListOfStructData(IntPtr[] pD, int nSize);

[DllImport("PassStruct.dll")]
private static extern IntPtr ReturnStruct();

public static DATA ReturnStructure()
{
    DATA oRData = new DATA();
    IntPtr pD = new IntPtr();

    pD = ReturnStruct();
    oRData = (DATA)Marshal.PtrToStructure(pD, typeof(DATA));

    FreeStruct(pD);
    return oRData;
}

public static void PrintListOfStructData(List<NativeDLLHelper.DATA> data)
{
    int NumberOfElements = data.Count;
    DATA oData = new DATA();
    IntPtr[] MemPtr = new IntPtr[NumberOfElements];
    for (int i = 0; i < NumberOfElements; i++)
    {
        MemPtr[i] = Marshal.AllocHGlobal(Marshal.SizeOf(oData));
        Marshal.StructureToPtr(data[i], MemPtr[i], false);
    }

    PrintListOfStructData(MemPtr, NumberOfElements);

    for (int i = 0; i < NumberOfElements; i++)
    {
        Marshal.FreeHGlobal(MemPtr[i]);
    }
}

C++ DLL Code:

typedef struct _DATA
{
    int          nID;
    wchar_t      *sName;
}DATA;

extern "C" DLLEXPORT DATA* ReturnStruct()
{
    DATA *obj = new DATA();

    obj->nID = 100;
    wstring sName = L"String from DLL";
    obj->sName = ::SysAllocString(sName.c_str());

    return obj;
}

extern "C" DLLEXPORT void PrintListOfStructData(DATA **pD, int nSize)
{
    for(int i=0; i<nSize; i++)
    {
        wcout<<"ID: "<<pD[i]->nID<<endl;
        wcout<<"Name: "<<pD[i]->sName<<endl;
    }
}

extern "C" DLLEXPORT void FreeStruct(DATA *obj)
{
    delete obj;
}

1 Answer 1

1

Don't declare PrintListOfStructData as taking an IntPtr array:

[DllImport("PassStruct.dll")]
private static extern void PrintListOfStructData(IntPtr pD, int nSize);

Then, declare all of the structs into the same block of memory:

int size = Marshal.SizeOf(typeof(DATA));
IntPtr MemPtr = Marshal.AllocHGlobal(NumberOfElements * size);
try
{
    for (int i = 0; i < NumberOfElements; i++)
    {
        Marshal.StructureToPtr(data[i], IntPtr.Add(MemPtr, i * size), false);
    }

    PrintListOfStructData(MemPtr, NumberOfElements);
}
finally
{
    if (MemPtr != IntPtr.Zero) Marshal.FreeHGlobal(MemPtr);
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.