在 C# 中,我有一个属性声明为:
public fixed byte foo[10]
在客户端代码中,我看到它使用此函数转换为字符串:
public static unsafe string GetString(byte* byteArray)
{
return new String((sbyte*)byteArray);
}
在 IronPython 打印中,它给了我一个字符串类型:
>>> print obj.foo
Baz+<foo>e__FixedBuffer1
尝试使用转换函数会出错。
>>> print GetString(obj.foo)
expected Byte*, got <Foo>e__FixedBuffer1
在 IronPython 中读取此属性的正确方法是什么?
最佳答案
.NET 中的固定字段非常特殊。您拥有的一个固定字段 ( public fixed byte foo[10]
) 被编译成一个特殊的嵌套结构,并且您的固定字段的类型被更改为该嵌套结构。简而言之,这:
public fixed byte foo[10];
编译成这样:
// This is the struct that was generated, it contains a field with the
// first element of your fixed array
[CompilerGenerated, UnsafeValueType]
[StructLayout(LayoutKind.Sequential, Size = 10)]
public struct <foo>e__FixedBuffer0
{
public byte FixedElementField;
}
// This is your original field with the new type
[FixedBuffer(typeof(byte), 10)]
public <foo>e__FixedBuffer0 foo;
您可以使用像 ILSpy 这样的工具亲眼看到这一点。
现在,如果您的 C# 代码中有一行 GetString(obj.foo)
它被编译成:
GetString(&obj.foo.FixedElementField);
因此它从字面上获取数组第一个元素的地址并将其作为参数传递给方法(因此 GetString
参数是正确的类型,byte*
)。
当您在 IronPython 中使用相同的参数调用相同的方法时,参数类型仍然是您的字段类型:<foo>e__FixedBuffer0
, 无法转换为 byte*
(明显地)。进行此方法调用的正确方法是执行与 C# 编译器相同的替换 - 获取 FixedElementField
的地址。并将其传递给 GetString
,但不幸的是,Python(据我所知)没有与 &
类似的东西C# 中的运算符。
结论是:您不能直接从 IronPython 访问固定字段。我会说你最好的选择是有一个像这样的“代理”方法:
public string GetFooString(Baz baz)
{
return new string((sbyte*)baz.foo);
}
PS 我不是 IronPython 专业人士,所以也许有一种直接访问 foo 属性的 super 方法,但我只是不知道如何做。
关于c# - 我如何从 IronPython 中的公共(public)固定字节读取?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10117287/