嵌套结构的链式 Marshal OffsetOf

问题描述 投票:0回答:1

这个答案中评论的有同样的困惑。

摘自 CleanCoder:

Marshal.OffsetIf 可以用于结构体中的字段/属性吗?这需要如何命名?让我们说:Struct1.Struct2.Prop1 Strct1 中 Prop1 的标识符是什么? 我想获取成员的非托管偏移量,该成员是父结构内子结构的成员。需要明确的是:嵌套成员相对于 topmost 结构的偏移量。

我尝试了

offset2
方法(见下面的代码),它可以给我正确的偏移量,但我想知道是否有更好的方法?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

struct Address
{
    public int Building;
    public int Room;
}

struct Person
{
    public int Age;
    public int Height;
    public Address Addr;
}

class OffsetTest
{
    public static void CalOffset()
    {
        // OK
        int offset1 = (int)Marshal.OffsetOf(typeof(Person), nameof(Person.Addr));

        // Ok, manual add offsets (recursively if nested layer is deeper)
        int offset2 = (int)Marshal.OffsetOf(typeof(Person), nameof(Person.Addr)) + (int)Marshal.OffsetOf(typeof(Address), nameof(Address.Room));

        // Exception as expected: System.ArgumentException:“Field passed in is not a marshaled member of the type 'Person'. Arg_ParamName_Name”
        int offset3 = (int)Marshal.OffsetOf(typeof(Person), nameof(Person.Addr.Room));

        // Exception, too
        int offset4 = (int)Marshal.OffsetOf(typeof(Person), "Addr.Room");
    }
}

在C++中,我会考虑创建一个对象并通过直接减去地址来计算偏移量,但在C#中我不知道该怎么做。

c# marshalling
1个回答
0
投票

Marshal.OffsetOf
可以用于结构体中的字段/属性吗?这需要如何命名?

不。它接受应该出现在提供的类型中的字段名称,而不是路径。来自

Marshal.OffsetOf
文档:

参数

fieldName
String

T类型中字段的名称。

因此,您将需要手动计算偏移量(就像您在“手动添加偏移量(如果嵌套层更深,则递归地)”中所做的那样)。如果需要,您可以将其包装到一些方便的(扩展)方法中,该方法将接受“路径”并使用一些缓存的反射来确定偏移量。

附注

请注意,

nameof(Person.Addr.Room)
"Room"

© www.soinside.com 2019 - 2024. All rights reserved.