开发者

How does the CLR marshal a structure containing only a single field when calling unmanaged code?

开发者 https://www.devze.com 2023-03-02 18:37 出处:网络
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?

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.)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号