如何从C到C#中的结构内获得非托管可变长度C-数组? [英] How to get unmanaged variable-length C-array within a struct from C to C#?

查看:169
本文介绍了如何从C到C#中的结构内获得非托管可变长度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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆