我试图将结构数组从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;
}
答案 0 :(得分: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);
}