Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I read from a public fixed byte in IronPython?

In C# I have an attribute declared as:

public fixed byte foo[10]

In client code I'm see it uses this function to convert to string:

public static unsafe string GetString(byte* byteArray)
{
  return new String((sbyte*)byteArray);
}

In IronPython printing it given me the type as a string:

>>> print obj.foo
Baz+<foo>e__FixedBuffer1

Trying to use the conversion function gives an error.

>>> print GetString(obj.foo)
expected Byte*, got <Foo>e__FixedBuffer1

What is the correct way read this attribute in IronPython?

like image 698
Eddy Pronk Avatar asked Mar 08 '26 19:03

Eddy Pronk


1 Answers

Fixed fields in .NET are quite special. A fixed field that you have (public fixed byte foo[10]) gets compiled into a special nested struct and the type of your fixed field is changed into that nested struct. In short, this:

public fixed byte foo[10];

Gets compiled into this:

// 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;

You can see this for yourself with a tool like ILSpy.

Now, if your code in C# has a line GetString(obj.foo) it is compiled into:

GetString(&obj.foo.FixedElementField);

So it literally takes the address of the first element of your array and passes it as the parameter to the method (thus the GetString parameter is of the correct type, byte*).

When you call the same method with the same parameter in IronPython the parameter type is still the type of your field: <foo>e__FixedBuffer0, which cannot be cast to byte* (obviously). The correct method of making this method call would be to do the same substitution as the C# compiler does - take the address of the FixedElementField and pass it to the GetString, but unfortunately, Python (to my knowledge) does not have an analog to the & operator in C#.

The conclusion would be: you cannot directly access a fixed field from IronPython. I would say that your best bet is to have a "proxy" method like:

public string GetFooString(Baz baz)
{
    return new string((sbyte*)baz.foo);
}

PS I am not an IronPython pro, so maybe there is a super-way to directly access the foo prop, but I just do not see how.

like image 69
Jefim Avatar answered Mar 11 '26 07:03

Jefim



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!