C# C/C++;与C语言的互操作性命名约定#

C# C/C++;与C语言的互操作性命名约定#,c#,c++,c,winapi,pinvoke,C#,C++,C,Winapi,Pinvoke,考虑以下Win32 API结构: typedef struct _SECURITY_ATTRIBUTES { DWORD nLength; LPVOID lpSecurityDescriptor; BOOL bInheritHandle; } SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES; 将此对象移植到C#时,是否应遵循此处使用的名称命名约定,如: public struct _SECU

考虑以下Win32 API结构:

typedef struct _SECURITY_ATTRIBUTES {
  DWORD  nLength;
  LPVOID lpSecurityDescriptor;
  BOOL   bInheritHandle;
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
将此对象移植到C#时,是否应遵循此处使用的名称命名约定,如:

public struct _SECURITY_ATTRIBUTES
{
    public int nLength;
    public unsafe byte* lpSecurityDescriptor;
    public int bInheritHandle;
}
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;
    }
}
或者我可以全力以赴,用C#风格写我的结构,就像这样:

public struct _SECURITY_ATTRIBUTES
{
    public int nLength;
    public unsafe byte* lpSecurityDescriptor;
    public int bInheritHandle;
}
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;
    }
}

虽然第二种方法看起来更优雅,但我想知道,使用以这种方式编写的结构调用本机功能是否可取,或者在从C/C++移植结构时是否存在任何其他缺陷。

这取决于您的个人偏好。选择哪种方法的主要考虑因素应该是代码维护的方便性。就个人而言,我倾向于使用与C声明中使用的名称完全相同的名称,因为这样更容易理解我所看到的内容。例如,如果我这样定义一个结构:

/// <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;
}
//
///Ws2def.h中结构中的非托管sockaddr_。
/// 
[StructLayoutAttribute(LayoutKind.Sequential,CharSet=CharSet.Ansi)]
中的公共结构sockaddr\u
{
/// 
///短萨乌家族;
/// 
公共短萨乌家庭;
/// 
///无符号短sinu端口;
/// 
公共乌斯波特新港;
/// 
///地址中的结构;
/// 
[Marshallas(UnmanagedType.ByValArray,ArraySubType=UnmanagedType.I1,SizeConst=4)]
公共字节[]地址;
/// 
///char sin_zero[8];
/// 
[Marshallas(UnmanagedType.ByValArray,ArraySubType=UnmanagedType.I1,SizeConst=8)]
公共字节[]sin_零;
}
后来我或同事想知道sa_家族到底是什么,我们可以搜索有关sa_家族的文档。如果我有一个家庭财产,我将有额外的步骤来确定它映射到sa_家庭


当然,我可以在结构上放置命名良好的getter和setter,例如,
publicshortfamily…
但是,我尝试将互操作结构和方法隐藏在一个更易于使用的接口后面。增加低级互操作定义似乎没有必要。

我认为这不应该是个人偏好。如果要将代码移植到另一种语言,则应应用所移植语言的约定

我当然会使用C#约定,因为代码将由C#开发者使用,而不是C/C++开发者,对吗?否则,我们将仍然使用丑陋的
\u int32 DWORD
,就像C中的代码一样

以下是一些很好的C#约定指南:


    • 为了完整起见,我添加了这个答案。它结合了默特和德格维德回答的要点。下面是一个使用Win32 RECT结构的示例

      C/C++定义:

      typedef struct _RECT {
        LONG left;
        LONG top;
        LONG right;
        LONG bottom;
      } RECT, *PRECT;
      
      namespace NetBlast.Runtime.PlatformInvoke.Windows
      {
          #region USING
      
          using System;
          using System.Collections.Generic;
          using System.Drawing;
          using System.Linq;
          using System.Text;
      
          #endregion
      
          /// <summary>
          /// The Rect (RECT) structure defines the coordinates of the upper-left and lower-right corners of a rectangle.
          /// </summary>
          [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
          public struct Rect : IEquatable<Rect>, IEquatable<Rectangle>, ICloneable
          {
              #region CONSTANTS
      
      
      
              #endregion
      
              #region VARIABLES
      
              /// <summary>
              /// Win32 RECT.left value.
              /// </summary>
              private int left;
      
              /// <summary>
              /// Win32 RECT.top value.
              /// </summary>
              private int top;
      
              /// <summary>
              /// Win32 RECT.right value.
              /// </summary>
              private int right;
      
              /// <summary>
              /// Win32 RECT.bottom value.
              /// </summary>
              private int bottom;
      
              #endregion
      
              #region PROPERTIES
      
              /// <summary>
              /// Gets or sets the x-coordinate of the upper-left corner of the rectangle.
              /// </summary>
              public Int32 Left
              {
                  get { return this.left; }
                  set { this.left = value; }
              }
      
              /// <summary>
              /// Gets or sets the y-coordinate of the upper-left corner of the rectangle.
              /// </summary>
              public Int32 Top
              {
                  get { return this.top; }
                  set { this.top = value; }
              }
      
              /// <summary>
              /// Gets or sets the x-coordinate of the lower-right corner of the rectangle.
              /// </summary>
              public Int32 Right
              {
                  get { return this.right; }
                  set { this.right = value; }
              }
      
              /// <summary>
              /// Gets or sets the y-coordinate of the lower-right corner of the rectangle.
              /// </summary>
              public Int32 Bottom
              {
                  get { return this.bottom; }
                  set { this.bottom = value; }
              }
      
              /// <summary>
              /// Gets or sets the height of the rectangle.
              /// </summary>
              public Int32 Height
              {
                  get { return this.bottom - this.top; }
                  set { this.bottom = value + this.top; }
              }
      
              /// <summary>
              /// Gets or sets the width of the rectangle.
              /// </summary>
              public Int32 Width
              {
                  get { return this.right - this.left; }
                  set { this.right = value + this.left; }
              }
      
              /// <summary>
              /// Gets or sets the top, left location of the rectangle.
              /// </summary>
              public Point Location
              {
                  get
                  {
                      return new Point(this.left, this.top);
                  }
      
                  set
                  {
                      this.right = this.left - value.X;
                      this.bottom = this.top - value.Y;
                      this.left = value.X;
                      this.top = value.Y;
                  }
              }
      
              /// <summary>
              /// Gets or sets the size of the rectangle.
              /// </summary>
              public Size Size
              {
                  get
                  {
                      return new Size(this.Width, this.Height);
                  }
      
                  set
                  {
                      this.right = value.Width + this.left;
                      this.bottom = value.Height + this.top;
                  }
              }
      
              #endregion
      
              #region CONSTRUCTORS / FINALIZERS
      
              /// <summary>
              /// Initializes a new instance of the <see cref="Rect" /> struct.
              /// </summary>
              /// <param name="location">The top, left location of the rectangle.</param>
              /// <param name="size">The size of the rectangle.</param>
              public Rect(Point location, Size size)
              {
                  this.left = default(int);
                  this.top = default(int);
                  this.right = default(int);
                  this.bottom = default(int);
                  this.Location = location;
                  this.Size = size;
              }
      
              /// <summary>
              /// Initializes a new instance of the <see cref="Rect" /> struct.
              /// </summary>
              /// <param name="left">The x-coordinate of the upper-left corner of the rectangle.</param>
              /// <param name="top">The y-coordinate of the upper-left corner of the rectangle.</param>
              /// <param name="right">The x-coordinate of the lower-right corner of the rectangle.</param>
              /// <param name="bottom">The y-coordinate of the lower-right corner of the rectangle.</param>
              public Rect(int left, int top, int right, int bottom)
              {
                  this.left = left;
                  this.top = top;
                  this.right = right;
                  this.bottom = bottom;
              }
      
              #endregion
      
              #region OPERATORS
      
              /// <summary>
              /// Provides implicit casting from Rect to Rectangle.
              /// </summary>
              /// <param name="rectangle">The Rect instance to cast.</param>
              /// <returns>A Rectangle representation of the Rect instance.</returns>
              public static implicit operator Rectangle(Rect rectangle)
              {
                  return new Rectangle(rectangle.Location, rectangle.Size);
              }
      
              /// <summary>
              /// Provides implicit casting from Rectangle to Rect.
              /// </summary>
              /// <param name="rectangle">The Rectangle instance to cast.</param>
              /// <returns>A Rect representation of the Rectangle instance.</returns>
              public static implicit operator Rect(Rectangle rectangle)
              {
                  return new Rect(rectangle.Location, rectangle.Size);
              }
      
              /// <summary>
              /// Performs an equality check between two instances of Rect.
              /// </summary>
              /// <param name="a">Instance a of Rect.</param>
              /// <param name="b">Instance b of Rect.</param>
              /// <returns>True if the instances are equal, otherwise false.</returns>
              public static bool operator ==(Rect a, Rect b)
              {
                  return a.Equals(b);
              }
      
              /// <summary>
              /// Performs an inequality check between two instances of Rect.
              /// </summary>
              /// <param name="a">Instance a of Rect.</param>
              /// <param name="b">Instance b of Rect.</param>
              /// <returns>True if the instances are not equal, otherwise false.</returns>
              public static bool operator !=(Rect a, Rect b)
              {
                  return !a.Equals(b);
              }
      
              #endregion
      
              #region STATIC METHODS
      
      
      
              #endregion
      
              #region INSTANCE METHODS
      
              /// <summary>
              /// Indicates whether the current object is equal to another object of the same type.
              /// </summary>
              /// <param name="obj">An object to compare with this object.</param>
              /// <returns>True if the instances are not equal, otherwise false.</returns>
              public override bool Equals(object obj)
              {
                  return this.Equals((Rect)obj);
              }
      
              /// <summary>
              /// Serves as a hash function for this instance of Rect.
              /// </summary>
              /// <returns>A hash code for the current Rect.</returns>
              public override int GetHashCode()
              {
                  return ObjectUtilities.CreateHashCode(this.left, this.top, this.right, this.bottom);
              }
      
              /// <summary>
              /// Returns a string representation of this instance.
              /// </summary>
              /// <returns>A string representation of this instance.</returns>
              public override string ToString()
              {
                  return string.Format("Left: {0}; Top: {1}; Right: {2}; Bottom: {3};", this.left, this.top, this.right, this.bottom);
              }
      
              /// <summary>
              /// Indicates whether the current object is equal to another object of the same type.
              /// </summary>
              /// <param name="other">A Rect instance to compare with this object.</param>
              /// <returns>True if the instances are not equal, otherwise false.</returns>
              public bool Equals(Rect other)
              {
                  return this.left == other.left
                      && this.top == other.top
                      && this.right == other.right
                      && this.bottom == other.bottom;
              }
      
              /// <summary>
              /// Indicates whether the current object is equal to another object of the same type.
              /// </summary>
              /// <param name="other">A Rectangle instance to compare with this object.</param>
              /// <returns>True if the instances are not equal, otherwise false.</returns>
              public bool Equals(Rectangle other)
              {
                  return this.left == other.Left
                      && this.top == other.Top
                      && this.right == other.Right
                      && this.bottom == other.Bottom;
              }
      
              /// <summary>
              /// Returns a clone of this Rect instance.
              /// </summary>
              /// <returns>A clone of this Rect instance.</returns>
              public object Clone()
              {
                  return new Rect(this.left, this.top, this.right, this.bottom);
              }
      
              #endregion
      
              #region DELEGATES & EVENTS
      
      
      
              #endregion
      
              #region CLASSES & STRUCTURES
      
      
      
              #endregion
          }
      }
      
      C#定义:

      typedef struct _RECT {
        LONG left;
        LONG top;
        LONG right;
        LONG bottom;
      } RECT, *PRECT;
      
      namespace NetBlast.Runtime.PlatformInvoke.Windows
      {
          #region USING
      
          using System;
          using System.Collections.Generic;
          using System.Drawing;
          using System.Linq;
          using System.Text;
      
          #endregion
      
          /// <summary>
          /// The Rect (RECT) structure defines the coordinates of the upper-left and lower-right corners of a rectangle.
          /// </summary>
          [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
          public struct Rect : IEquatable<Rect>, IEquatable<Rectangle>, ICloneable
          {
              #region CONSTANTS
      
      
      
              #endregion
      
              #region VARIABLES
      
              /// <summary>
              /// Win32 RECT.left value.
              /// </summary>
              private int left;
      
              /// <summary>
              /// Win32 RECT.top value.
              /// </summary>
              private int top;
      
              /// <summary>
              /// Win32 RECT.right value.
              /// </summary>
              private int right;
      
              /// <summary>
              /// Win32 RECT.bottom value.
              /// </summary>
              private int bottom;
      
              #endregion
      
              #region PROPERTIES
      
              /// <summary>
              /// Gets or sets the x-coordinate of the upper-left corner of the rectangle.
              /// </summary>
              public Int32 Left
              {
                  get { return this.left; }
                  set { this.left = value; }
              }
      
              /// <summary>
              /// Gets or sets the y-coordinate of the upper-left corner of the rectangle.
              /// </summary>
              public Int32 Top
              {
                  get { return this.top; }
                  set { this.top = value; }
              }
      
              /// <summary>
              /// Gets or sets the x-coordinate of the lower-right corner of the rectangle.
              /// </summary>
              public Int32 Right
              {
                  get { return this.right; }
                  set { this.right = value; }
              }
      
              /// <summary>
              /// Gets or sets the y-coordinate of the lower-right corner of the rectangle.
              /// </summary>
              public Int32 Bottom
              {
                  get { return this.bottom; }
                  set { this.bottom = value; }
              }
      
              /// <summary>
              /// Gets or sets the height of the rectangle.
              /// </summary>
              public Int32 Height
              {
                  get { return this.bottom - this.top; }
                  set { this.bottom = value + this.top; }
              }
      
              /// <summary>
              /// Gets or sets the width of the rectangle.
              /// </summary>
              public Int32 Width
              {
                  get { return this.right - this.left; }
                  set { this.right = value + this.left; }
              }
      
              /// <summary>
              /// Gets or sets the top, left location of the rectangle.
              /// </summary>
              public Point Location
              {
                  get
                  {
                      return new Point(this.left, this.top);
                  }
      
                  set
                  {
                      this.right = this.left - value.X;
                      this.bottom = this.top - value.Y;
                      this.left = value.X;
                      this.top = value.Y;
                  }
              }
      
              /// <summary>
              /// Gets or sets the size of the rectangle.
              /// </summary>
              public Size Size
              {
                  get
                  {
                      return new Size(this.Width, this.Height);
                  }
      
                  set
                  {
                      this.right = value.Width + this.left;
                      this.bottom = value.Height + this.top;
                  }
              }
      
              #endregion
      
              #region CONSTRUCTORS / FINALIZERS
      
              /// <summary>
              /// Initializes a new instance of the <see cref="Rect" /> struct.
              /// </summary>
              /// <param name="location">The top, left location of the rectangle.</param>
              /// <param name="size">The size of the rectangle.</param>
              public Rect(Point location, Size size)
              {
                  this.left = default(int);
                  this.top = default(int);
                  this.right = default(int);
                  this.bottom = default(int);
                  this.Location = location;
                  this.Size = size;
              }
      
              /// <summary>
              /// Initializes a new instance of the <see cref="Rect" /> struct.
              /// </summary>
              /// <param name="left">The x-coordinate of the upper-left corner of the rectangle.</param>
              /// <param name="top">The y-coordinate of the upper-left corner of the rectangle.</param>
              /// <param name="right">The x-coordinate of the lower-right corner of the rectangle.</param>
              /// <param name="bottom">The y-coordinate of the lower-right corner of the rectangle.</param>
              public Rect(int left, int top, int right, int bottom)
              {
                  this.left = left;
                  this.top = top;
                  this.right = right;
                  this.bottom = bottom;
              }
      
              #endregion
      
              #region OPERATORS
      
              /// <summary>
              /// Provides implicit casting from Rect to Rectangle.
              /// </summary>
              /// <param name="rectangle">The Rect instance to cast.</param>
              /// <returns>A Rectangle representation of the Rect instance.</returns>
              public static implicit operator Rectangle(Rect rectangle)
              {
                  return new Rectangle(rectangle.Location, rectangle.Size);
              }
      
              /// <summary>
              /// Provides implicit casting from Rectangle to Rect.
              /// </summary>
              /// <param name="rectangle">The Rectangle instance to cast.</param>
              /// <returns>A Rect representation of the Rectangle instance.</returns>
              public static implicit operator Rect(Rectangle rectangle)
              {
                  return new Rect(rectangle.Location, rectangle.Size);
              }
      
              /// <summary>
              /// Performs an equality check between two instances of Rect.
              /// </summary>
              /// <param name="a">Instance a of Rect.</param>
              /// <param name="b">Instance b of Rect.</param>
              /// <returns>True if the instances are equal, otherwise false.</returns>
              public static bool operator ==(Rect a, Rect b)
              {
                  return a.Equals(b);
              }
      
              /// <summary>
              /// Performs an inequality check between two instances of Rect.
              /// </summary>
              /// <param name="a">Instance a of Rect.</param>
              /// <param name="b">Instance b of Rect.</param>
              /// <returns>True if the instances are not equal, otherwise false.</returns>
              public static bool operator !=(Rect a, Rect b)
              {
                  return !a.Equals(b);
              }
      
              #endregion
      
              #region STATIC METHODS
      
      
      
              #endregion
      
              #region INSTANCE METHODS
      
              /// <summary>
              /// Indicates whether the current object is equal to another object of the same type.
              /// </summary>
              /// <param name="obj">An object to compare with this object.</param>
              /// <returns>True if the instances are not equal, otherwise false.</returns>
              public override bool Equals(object obj)
              {
                  return this.Equals((Rect)obj);
              }
      
              /// <summary>
              /// Serves as a hash function for this instance of Rect.
              /// </summary>
              /// <returns>A hash code for the current Rect.</returns>
              public override int GetHashCode()
              {
                  return ObjectUtilities.CreateHashCode(this.left, this.top, this.right, this.bottom);
              }
      
              /// <summary>
              /// Returns a string representation of this instance.
              /// </summary>
              /// <returns>A string representation of this instance.</returns>
              public override string ToString()
              {
                  return string.Format("Left: {0}; Top: {1}; Right: {2}; Bottom: {3};", this.left, this.top, this.right, this.bottom);
              }
      
              /// <summary>
              /// Indicates whether the current object is equal to another object of the same type.
              /// </summary>
              /// <param name="other">A Rect instance to compare with this object.</param>
              /// <returns>True if the instances are not equal, otherwise false.</returns>
              public bool Equals(Rect other)
              {
                  return this.left == other.left
                      && this.top == other.top
                      && this.right == other.right
                      && this.bottom == other.bottom;
              }
      
              /// <summary>
              /// Indicates whether the current object is equal to another object of the same type.
              /// </summary>
              /// <param name="other">A Rectangle instance to compare with this object.</param>
              /// <returns>True if the instances are not equal, otherwise false.</returns>
              public bool Equals(Rectangle other)
              {
                  return this.left == other.Left
                      && this.top == other.Top
                      && this.right == other.Right
                      && this.bottom == other.Bottom;
              }
      
              /// <summary>
              /// Returns a clone of this Rect instance.
              /// </summary>
              /// <returns>A clone of this Rect instance.</returns>
              public object Clone()
              {
                  return new Rect(this.left, this.top, this.right, this.bottom);
              }
      
              #endregion
      
              #region DELEGATES & EVENTS
      
      
      
              #endregion
      
              #region CLASSES & STRUCTURES
      
      
      
              #endregion
          }
      }
      
      命名空间NetBlast.Runtime.PlatformInvoke.Windows
      {
      #区域使用
      使用制度;
      使用System.Collections.Generic;
      使用系统图;
      使用System.Linq;
      使用系统文本;
      #端区
      /// 
      ///Rect(Rect)结构定义矩形的左上角和右下角的坐标。
      /// 
      [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
      public struct Rect:IEquatable、IEquatable、ICloneable
      {
      #区域常数
      #端区
      #区域变量
      /// 
      ///Win32 RECT.left值。
      /// 
      私有int左;
      /// 
      ///Win32 RECT.top值。
      /// 
      私人int top;
      /// 
      ///Win32 RECT.right值。
      /// 
      私权;
      /// 
      ///Win32 RECT.bottom值。
      /// 
      私有int底部;
      #端区
      #区域属性
      /// 
      ///获取或设置矩形左上角的x坐标。
      /// 
      公共Int32左
      {
      获取{返回this.left;}
      设置{this.left=value;}
      }
      /// 
      ///获取或设置矩形左上角的y坐标。
      /// 
      公共Int32顶级
      {
      获取{返回this.top;}
      设置{this.top=value;}
      }
      /// 
      ///获取或设置矩形右下角的x坐标。
      /// 
      公共Int32权利
      {
      获取{返回this.right;}
      设置{this.right=value;}
      }
      /// 
      ///获取或设置矩形右下角的y坐标。
      /// 
      公共Int32底部
      {
      获取{返回this.bottom;}
      设置{this.bottom=value;}
      }
      /// 
      ///获取或设置矩形的高度。
      /// 
      公共Int32高度
      {
      获取{返回this.bottom-this.top;}
      设置{this.bottom=value+this.top;}
      }
      /// 
      ///获取或设置矩形的宽度。
      /// 
      公共Int32宽度
      {
      获取{返回this.right-this.left;}
      设置{this.right=value+this.left;}
      }
      /// 
      ///获取或设置矩形的左上方位置。
      /// 
      公共点位置
      {
      得到
      {
      返回新点(this.left,this.top);
      }
      设置
      {
      this.right=this.left-value.X;
      this.bottom=this.top-value.Y;
      此.left=值.X;
      this.top=value.Y;
      }
      }
      /// 
      ///获取或设置矩形的大小。
      /// 
      公共大小
      {
      得到
      {
      返回新尺寸(this.Width,this.Height);
      }
      设置
      {
      this.right=value.Width+this.left;
      this.bottom=value.Height+this.top;
      }
      }
      #端区