When should we use this attribute and why do we need it? For example, if the native function in c takes as a parameter a pointer to unsigned char, and I know that it's needed to fulfill the array of unsigned chars, why can't I use array of bytes in C# to use this function? Is it necessary to do marshalling?
The runtime will be able to automatically determine how to marshal data between native and managed code in most cases, so you generally don't need to specify the attribute. MarshalAs
is only necessary when there is an ambiguity in the definition (and you want to tell the runtime precisely how to marshal the data) or if you require non-default behaviour.
In my experience, MarshalAs
is only really required when working with strings, since there are so many different representations in native code; unicode/ansi, c-strings or not, etc.
Additional use of MarshalAs attribute is marshalling fixed-size arrays (including fixed-size strings) with ByValArray and SizeConst parameters. For example, many structures from Windows API contain fixed-size strings.
Based on Microsoft documentation for Type marshaling
Marshaling is the process of transforming types when they need to cross between managed and native code. Marshaling is needed because the types in the managed and unmanaged code are different. In managed code, for instance, you have a String, while in the unmanaged world strings can be Unicode ("wide"), non-Unicode, null-terminated, ASCII, etc. By default, the P/Invoke subsystem tries to do the right thing based on the default behavior, described on this article. However, for those situations where you need extra control, you can employ the MarshalAs attribute to specify what is the expected type on the unmanaged side.
Generally, the runtime tries to do the "right thing" when marshaling to require the least amount of work from you.
Which types need special handling is explained on the following link from the doc to Blittable and Non-Blittable Types:
Most data types have a common representation in both managed and unmanaged memory and do not require special handling by the interop marshaler. These types are called blittable types because they do not require conversion when passed between managed and unmanaged code.
Non-blittable types would be the answer to your question. You would have to marshal for the following ones:
Array, Boolean, char, class, object, string, value type (structure), delegates, unmanaged arrays that are either COM-style safe arrays or C-style arrays with fixed or variable length.
Unmanaged structures can also contain embedded arrays or Booleans (non-blittable types). There you have to be careful according the doc:
Structures that are returned from platform invoke calls must be blittable types. Platform invoke does not support non-blittable structures as return types.
© 2022 - 2024 — McMap. All rights reserved.