【问题标题】:Returning Array of Structure from C++ DLL to C# Application将结构数组从 C++ DLL 返回到 C# 应用程序
【发布时间】:2014-04-07 11:05:35
【问题描述】:

我正在尝试将结构数组从 C++ DLL 返回到 C# 应用程序。我可以从 DLL 返回结构也可以将结构列表从 c# 应用程序发送到 C++ DLL 并打印其数据。 但无法从 DLL 向 C# 应用程序填充和返回结构数组。有人可以帮忙吗。以下是我目前正在处理的代码:

C#代码:

[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 代码:

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;
}

【问题讨论】:

    标签: c++ dll interop marshalling


    【解决方案1】:

    不要将 PrintListOfStructData 声明为采用 IntPtr 数组:

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

    然后,将所有结构声明到同一个内存块中:

    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);
    }
    

    【讨论】:

      猜你喜欢
      • 2018-11-07
      • 1970-01-01
      • 1970-01-01
      • 2011-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多