如何从C到C#中的结构内获得非托管可变长度C-数组? [英] How to get unmanaged variable-length C-array within a struct from C to C#?
问题描述
我如何返回 MIB_IPFORWARDROW
数组?
结构MIB_IPFORWARDTABLE
{
公共UINT大小;
[的MarshalAs(/ *发生的事情在这里* /?)]
公共IPFORWARDROW [表;
};
函数[DllImport(iphlpapi,字符集= CharSet.Auto)]
私人静态外部INT GetIpForwardTable(
的IntPtr / * MIB_IPFORWARDTABLE * * / pIpForwardTable,
REF UINT / * ULONG * * / pdwSize所,
布尔边框);
公共静态MIB_IPFORWARDROW []温度()
{
VAR fwdTable = IntPtr.Zero;
UINT大小= 0;
VAR的结果= GetIpForwardTable(fwdTable,楼盘规模,真正的);
fwdTable = Marshal.AllocHGlobal((int)的大小);
结果= GetIpForwardTable(fwdTable,楼盘规模,真正的);
/ *
现在该怎么办?
我想:
无功表=(MIB_IPFORWARDTABLE)Marshal.PtrToStructure(fwdTable的typeof(MIB_IPFORWARDTABLE));
,但table.Table总是空
* /
}
(见 GetIpForwardTable )
我已经看到了这一点:$ b $ b的如何编组一个包含可变大小的数组C#中的结构?
不过,无论我做什么,fwdTable.Table始终为null,IntPtr.Zero或0。也就是说ofcourse,如果没有抛出异常。
< DIV CLASS =h2_lin>解决方案
这线程似乎是你正在寻找什么:的 http://social.msdn.microsoft.com/Forums/vstudio/en-US / 19a3ce21-e395-4151-86f6-723a64272f0d /主叫getipforwardtable - 从-C?论坛= csharpgeneral
他们的解决方案采用蛮力循环复制。原始数组IPFORWARDROW的System.Array的
最终代码会是这个样子:
[标记有ComVisible特性(假),StructLayout(LayoutKind.Sequential)]
内部结构IPForwardTable
{
公共UINT大小;
[的MarshalAs(UnmanagedType.ByValArray,SizeConst = 1)]
公共IPFORWARDROW [表;
};
[标记有ComVisible特性(假),StructLayout(LayoutKind.Sequential)]
内部结构IPFORWARDROW
{
内部INT / * DWORD * / dwForwardDest;
内部INT / * DWORD * / dwForwardMask;
内部INT / * DWORD * / dwForwardPolicy;
内部INT / * DWORD * / dwForwardNextHop;
内部INT / * DWORD * / dwForwardIfIndex;
内部INT / * DWORD * / dwForwardType;
内部INT / * DWORD * / dwForwardProto;
内部INT / * DWORD * / dwForwardAge;
内部INT / * DWORD * / dwForwardNextHopAS;
内部INT / * DWORD * / dwForwardMetric1;
内部INT / * DWORD * / dwForwardMetric2;
内部INT / * DWORD * / dwForwardMetric3;
内部INT / * DWORD * / dwForwardMetric4;
内部INT / * DWORD * / dwForwardMetric5;
};
函数[DllImport(iphlpapi,字符集= CharSet.Auto)]
私有外部静态INT GetIpForwardTable(IntPtr的/ * * PMIB_IPFORWARDTABLE / pIpForwardTable,楼盘INT / * * PULONG / pdwSize所,布尔边境);
函数[DllImport(iphlpapi,字符集= CharSet.Auto)]
私有外部静态INT CreateIpForwardEntry(IntPtr的/ * * PMIB_IPFORWARDROW / pRoute);
静态无效的主要(字串[] args)
{
VAR fwdTable = IntPtr.Zero;
INT大小= 0;
VAR的结果= GetIpForwardTable(fwdTable,楼盘规模,真正的);
fwdTable = Marshal.AllocHGlobal(大小);
结果= GetIpForwardTable(fwdTable,楼盘规模,真正的);
无功海峡=(IPForwardTable)Marshal.PtrToStructure(fwdTable的typeof(IPForwardTable));
IPFORWARDROW [] =表新IPFORWARDROW [str.Size]
IntPtr的P = fwdTable + Marshal.SizeOf(str.Size);
的for(int i = 0; I< str.Size ++ I)
{
表[i] =(IPFORWARDROW)Marshal.PtrToStructure(P的typeof(IPFORWARDROW)) ;
P + = Marshal.SizeOf(typeof运算(IPFORWARDROW));
}
Marshal.FreeHGlobal(fwdTable);
}
How do I return the MIB_IPFORWARDROW
array?
struct MIB_IPFORWARDTABLE
{
public uint Size;
[MarshalAs(/* what goes here? */)]
public IPFORWARDROW[] Table;
};
[DllImport("iphlpapi", CharSet = CharSet.Auto)]
private static extern int GetIpForwardTable(
IntPtr /* MIB_IPFORWARDTABLE* */ pIpForwardTable,
ref uint /* ULONG* */ pdwSize,
bool bOrder);
public static MIB_IPFORWARDROW[] Temp()
{
var fwdTable = IntPtr.Zero;
uint size = 0;
var result = GetIpForwardTable(fwdTable, ref size, true);
fwdTable = Marshal.AllocHGlobal((int) size);
result = GetIpForwardTable(fwdTable, ref size, true);
/*
what now ?
I tried:
var table = (MIB_IPFORWARDTABLE) Marshal.PtrToStructure(fwdTable, typeof(MIB_IPFORWARDTABLE));
but table.Table is always null
*/
}
(See GetIpForwardTable)
I've seen this: How do I marshal a struct that contains a variable-sized array to C#?
But whatever I do, fwdTable.Table is always null, IntPtr.Zero or 0. That is ofcourse, if no Exception is thrown..
This thread seems to be exactly what you are looking for: http://social.msdn.microsoft.com/Forums/vstudio/en-US/19a3ce21-e395-4151-86f6-723a64272f0d/calling-getipforwardtable-from-c?forum=csharpgeneral
Their solution employs a brute force loop to copy the raw array into a System.Array of IPFORWARDROW.
The final code would look something like this:
[ComVisible(false), StructLayout(LayoutKind.Sequential)]
internal struct IPForwardTable
{
public uint Size;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public IPFORWARDROW[] Table;
};
[ComVisible(false), StructLayout(LayoutKind.Sequential)]
internal struct IPFORWARDROW
{
internal int /*DWORD*/ dwForwardDest;
internal int /*DWORD*/ dwForwardMask;
internal int /*DWORD*/ dwForwardPolicy;
internal int /*DWORD*/ dwForwardNextHop;
internal int /*DWORD*/ dwForwardIfIndex;
internal int /*DWORD*/ dwForwardType;
internal int /*DWORD*/ dwForwardProto;
internal int /*DWORD*/ dwForwardAge;
internal int /*DWORD*/ dwForwardNextHopAS;
internal int /*DWORD*/ dwForwardMetric1;
internal int /*DWORD*/ dwForwardMetric2;
internal int /*DWORD*/ dwForwardMetric3;
internal int /*DWORD*/ dwForwardMetric4;
internal int /*DWORD*/ dwForwardMetric5;
};
[DllImport("iphlpapi", CharSet = CharSet.Auto)]
private extern static int GetIpForwardTable(IntPtr /*PMIB_IPFORWARDTABLE*/ pIpForwardTable, ref int /*PULONG*/ pdwSize, bool bOrder);
[DllImport("iphlpapi", CharSet = CharSet.Auto)]
private extern static int CreateIpForwardEntry(IntPtr /*PMIB_IPFORWARDROW*/ pRoute);
static void Main(string[] args)
{
var fwdTable = IntPtr.Zero;
int size = 0;
var result = GetIpForwardTable(fwdTable, ref size, true);
fwdTable = Marshal.AllocHGlobal(size);
result = GetIpForwardTable(fwdTable, ref size, true);
var str = (IPForwardTable)Marshal.PtrToStructure(fwdTable, typeof(IPForwardTable));
IPFORWARDROW[] table = new IPFORWARDROW[str.Size];
IntPtr p = fwdTable + Marshal.SizeOf(str.Size);
for (int i = 0; i < str.Size; ++i)
{
table[i] = (IPFORWARDROW)Marshal.PtrToStructure(p, typeof(IPFORWARDROW));
p += Marshal.SizeOf(typeof(IPFORWARDROW));
}
Marshal.FreeHGlobal(fwdTable);
}
这篇关于如何从C到C#中的结构内获得非托管可变长度C-数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!