How to get fixed buffer length?
Asked Answered
A

3

8

Is there a way to get the length of a fixed size buffer?

Something like:

public struct MyStruct
{
    public unsafe fixed byte buffer[100];

    public int foo()
    {
        return sizeof(buffer); // Compile error.
    }
}

Is there any way to accomplish something like this?

Aubree answered 9/5, 2016 at 17:7 Comment(4)
Why don't you define a constant like const int BUFFER_SIZE = 100, then use buffer[BUFFER_SIZE]. This runs quicker size the assignment is done by the compiler.Cannular
Because that would add some unwanted verbosity to my structs. My code would have a lot of structs like that. Any thoughts? Thanks.Aubree
It is a lot less code than to put a method foo in each structure.Cannular
But I wasn't going to create that foo method, I just wrote to clarify the things and concepts :(Aubree
S
5

Well like in C++, you have to keep size of built-in arrays. Same applies for fixed buffers in C#. This type is comparable to inline_array. This gives you benefits such as static code checking. They are a bit of a pain to work with as they aren't C#'s first class feature. So probably the best solution is to keep size as a part of struct. You will probably just have to deal with it or use a collection/C#'s System.Array. Maybe another solution would be to create fixed buffer as a seperate struct and then make it part of another stucts with other data.

Sunbow answered 9/5, 2016 at 18:33 Comment(2)
Okay, considering this is the closer answer 'll accept. Unfortunatelly c# is showing itself very limited when deeper interop comes to play :/Aubree
"in C++, you have to keep size of built-in arrays" just isn't true. (sizeof array)/(sizeof *array) works great on built-in arrays, including struct/class data members with array type. Or you can use inference of non-type template parameters. You linked to a discussion on finding the size of the dynamic memory range a pointer points to, which is not at all what is going on in the C# code in the question.Cyrille
L
0

Well, I'm answering like 6 years late but I did this. Apparently there's a property that contains the length of the fixed buffer! Here's a simple method to get it. You need to pass the MyStruct type and the name of the field:

    public static int GetFixedBufferSize(Type type, string field)
    {
        FieldInfo fi = type.GetField(field);
        object[] attrs = fi.GetCustomAttributes(typeof(FixedBufferAttribute), false);
        if (attribs != null && attribs.Length != 0)
        {
            FixedBufferAttribute attr = (FixedBufferAttribute)attribs[0];
            Console.WriteLine($"{attr.ElementType.Name} {field}[{attr.Length}]");
            return attr.Length;
        };

        throw new Exception("Not a FixedBuffer");
    }

Hopefully this works for you, I tried it with your example and it worked!

Legitimate answered 14/1, 2022 at 13:56 Comment(1)
Does this depend on reflection? You're asking for a field according to its name as a runtime-variable string? Surely that's not fast, so it's not something you'd want to use in normal code if you're using an unsafe fixed array for performance reasons.Hexaemeron
O
-4

That's an array; you can just use .Length.

Oppose answered 9/5, 2016 at 17:10 Comment(7)
fixed size buffers isn't an array. Length is a property of System.Array, therefore I can't access that :(Aubree
Maybe @MartinCostello, could you show me how I could use Marshal.SizeOf in a fixed buffer? Thanks.Aubree
You could try these: return Marshal.SizeOf(this); return Marshal.SizeOf(typeof(MyStruct)); return Marshal.SizeOf(buffer);Fatten
None of that works in my case @MartinCostello. MyStruct would contain another types, SizeOf(typeof(MyStruct)) will return the marshal size of the entire struct and SizeOf(buffer) don't compile. SizeOf expects a Type.Aubree
buffer is a field, which is an object. Does the code even compile if you remove the foo() method? I think your field declaration is wrong.Fatten
@MartinCostello: No; it's just that fixed is weird. I'm not sure if this is possible at all (!). Play with tryroslyn.azurewebsites.net/#f:s/…Oppose
Maybe try using [MarshalAs], rather than fixed. Then you won't need unsafe code. github.com/martincostello/sqllocaldb/blob/master/src/SqlLocalDb/…Fatten

© 2022 - 2024 — McMap. All rights reserved.