Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C/C++ Interoperability Naming Conventions with C#

Consider the following Win32 API struct:

typedef struct _SECURITY_ATTRIBUTES {
  DWORD  nLength;
  LPVOID lpSecurityDescriptor;
  BOOL   bInheritHandle;
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;

When porting this object to C#, should I follow the name naming conventions used here, like so:

public struct _SECURITY_ATTRIBUTES
{
    public int nLength;
    public unsafe byte* lpSecurityDescriptor;
    public int bInheritHandle;
}

or can I go all out, and write my struct in a C# style, like so:

public struct SecurityAttributes
{
    private int length;
    private unsafe byte* securityDescriptor;
    private int bInheritHandle;

    public Int32 Length
    {
        get { return this.length; }
        set { this.length = value; }
    }

    public Byte* SecurityDescriptor
    {
        get { return this.seurityDescriptor; }
        set { this.securityDescriptor = value; }
    }

    public Int32 InheritHandle
    {
        get { return this.bInheritHandle; }
        set { this.bInheritHandle = value; }
    }

    public SecurityAttributes(int length, byte* securityDescriptor, int inheritHandle)
    {
        this.length = length;
        this.securityDescriptor = securityDescriptor;
        this.inheritHandle = inheritHandle;
    }
}

Whilst the second approach seems much more elegant, I would like to know if it is advisable to invoke native functionality using a struct written in that fashion, or if there are any other pitfalls when porting structs from C/C++.

like image 276
Matthew Layton Avatar asked Dec 19 '12 17:12

Matthew Layton


1 Answers

This comes down to your personal preference. Your primary consideration in which approach to chose should be ease of code maintenance. Personally, I favor sticking with the exact same names as those used in the C declaration, because it makes it easier to understand what I'm looking at. For example, if I define a struct like so:

/// <summary>
/// Unmanaged sockaddr_in structure from Ws2def.h.
/// </summary>
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct sockaddr_in
{
    /// <summary>
    /// short sa_family;
    /// </summary>
    public short sa_family;

    /// <summary>
    /// unsigned short sin_port;
    /// </summary>
    public ushort sin_port;

    /// <summary>
    /// struct in_addr addr;
    /// </summary>
    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1, SizeConst = 4)]
    public byte[] addr;

    /// <summary>
    /// char sin_zero[8];
    /// </summary>
    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1, SizeConst = 8)]
    public byte[] sin_zero;
}

Then later I or a co-worker want to know just what the heck sa_family is, we can just search for documentation on sa_family. If I instead had a Family property, I would have the extra step of figuring out that it maps to sa_family.

Of course, I could put nicely named getters and setters on the struct, e.g., public short Family... However, I try to hide interop structs and methods behind an easier-to-use interface. Spiffing up the low-level interop definitions just doesn't seem necessary.

like image 153
dgvid Avatar answered Sep 21 '22 23:09

dgvid