.NET equivalent of size_t
Asked Answered
B

4

14

I have a piece of .NET code which I want to port to 64-bit. The codes basically is a set of P/Invoke calls to some other C dll. One of the functions in the C dll has a parameter 'size_t'. What datatype should I use in my P/Invoke signature so that the marshalling works fine. I was thinking of using a IntPtr or a UIntPtr but some say that they are a pointer equivalent thing in .NET and shouldnt be using it. Does anyone know what the correct type for this is?

Bowyer answered 21/4, 2009 at 13:15 Comment(1)
What "bit-ness" is the C DLL?Hallee
R
22

UIntPtr will work (IntPtr would probably work too, but size_t is unsigned, so UIntPtr is a better fit)

JaredPar has written something on his blog (and a follow-up) about this.

Ramadan answered 21/4, 2009 at 13:21 Comment(0)
B
2

I've found a dirty hack that can help you achieve similar behavior. It requires that you define a compilation symbol _WIN64 for your 64-bit builds and then you can do the following:

#if _WIN64
    using size_t = UInt64;
#else
    using size_t = UInt32;
#endif

Note: you will have to use the above code in every file that wants to utilize the size_t type.

You can also define your own integer type (much like UInt64 is defined) and reuse it without having to put the above code in every file that needs access to size_t, but it's very complicated (imho).

#if _WIN64
    using _size_t = UInt64;
#else
    using _size_t = UInt32;
#endif

[Serializable]
[CLSCompliant(false)]
[ComVisible(true)]
public struct size_t : IComparable, IFormattable, IConvertible, IComparable<_size_t>, IEquatable<_size_t>
{
    private _size_t _value;

    public size_t(_size_t val)
    {
        _value = val;
    }

    // You have to add all of your overloads below
}

This will allow size_t to change it's type depending on the platform, but correctly overloading the necessary operators is very tricky!

Bacchanal answered 9/2, 2012 at 0:29 Comment(2)
Having to define the compilation symbol means that this will not work for Any CPU builds, and it will crash if someone modifies the executable to run as something else(x86/x64).Assign
@ØysteinE.Krog I agree, I also generally find that you don't really need size_t unless you're working with a C++ dll, so in that case you wouldn't compile with Any CPU and it should work. It's a dirty enough hack that there are very few cases that warrant using it.Bacchanal
P
2

As of C# v9 (which requires dotnet 5 or newer) we now have "native sized" integer types in the form of nint and nuint, which have the same basic behaviour as IntPtr and UIntPtr respectively. This makes nuint an ideal type to use when a p/invoke target requires a size_t, without the need for the extra marshalling magic linked to in Patrick McDonald's answer.

Parentage answered 12/12, 2021 at 21:45 Comment(0)
L
1

If size_t varies depending on the platform, you'll have to use IntPtr. If it is a fixed size integer, use int, uint or long (depending on the original declaration).

Leslee answered 21/4, 2009 at 13:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.