How does the CLR marshal a structure containing only a single field when calling unmanaged code?
By default, how will the CLR marshal a structure that contains only a single field, but defines multiple methods, properties, operators, etc., when calling an unmanaged function through P/Invoke?
A simplified version of the structure in question might look something like the following:public struct SimpleStruct
{
private IntPtr _value;
public SimpleStruct(IntPtr value)
{
this._value = value;
}
public int MyMethod()
{
return 42;
}
}
The specific unmanaged function being called here is irrelevant, so for the sake of discussion, just assume something simple from the Windows API, like this one:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern bool IsWindow(SimpleStruct hWnd);
In particular, I'm interested in whether the structure gets marshaled as if it were an IntPtr
type, or if the CLR attempts to marshal the structure as it would a more complex structure with multiple fields. I realize that "under the hood", all primitive types (including IntPtr
and Int32
) are implemented as structures. But I am not sure if there's some special-casing built in that handles these "known" structures representing primitive types differently than it would handle a custom-defined one.
I understand that only the fields within the type are accessible, and any methods, properties, or events are inaccessible from unmanaged code, and that's exactly what I want. I'd like to 开发者_StackOverflow中文版get the above structure marshaled to the unmanaged function exactly the same way as if the declaration were rewritten to specify a parameter of type IntPtr
:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern bool IsWindow(IntPtr hWnd);
Corollarily, does the behavior change when adding the following attributes to the structure's definition?
[StructLayout(LayoutKind.Explicit)]
public struct OtherStruct
{
[FieldOffset(0)]
private IntPtr _value;
public SimpleStruct(IntPtr value)
{
this._value = value;
}
public int MyMethod()
{
return 42;
}
}
I've only ever used the FieldOffsetAttribute
when simulating a union (i.e., multiple fields), but I've seen this done in some of Microsoft's own code, ostensibly to achieve the behavior I ask about above.
Is there any difference in the case where only a single field is defined? Or does this just make the default behavior more explicit?
With regards to your question about implicit/explicit:
This will result in the exact same thing. The default LayoutKind (for C#) is Sequential, and the first element in a struct with this layout is always at offset 0. (The following elements' positions will depend on the packing chosen, as described in the second link.)
精彩评论