科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件如何在C#中使用 Win32和其他库

如何在C#中使用 Win32和其他库

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

因此只能优先处理最重要的部分。许多常用操作都有托管接口,但是还有许多完整的 Win32 部分没有托管接口......

作者:佚名 来源:Microsoft 2007年11月14日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
简单字符串

  下面是一个接受字符串参数的函数的简单示例:

BOOL GetDiskFreeSpace(
LPCTSTR lpRootPathName,     // 根路径
LPDWORD lpSectorsPerCluster,  // 每个簇的扇区数
LPDWORD lpBytesPerSector,    // 每个扇区的字节数
LPDWORD lpNumberOfFreeClusters, // 可用的扇区数
LPDWORD lpTotalNumberOfClusters // 扇区总数
);

  根路径定义为 LPCTSTR。这是独立于平台的字符串指针。

  由于不存在名为 GetDiskFreeSpace() 的函数,封送拆收器将自动查找“A”或“W”变体,并调用相应的函数。我们使用一个属性来告诉封送拆收器,API 所要求的字符串类型。

  以下是该函数的完整定义,就象我开始定义的那样:

[DllImport("kernel32.dll")]
static extern bool GetDiskFreeSpace(
 [MarshalAs(UnmanagedType.LPTStr)]
 string rootPathName,
  ref int sectorsPerCluster,
  ref int bytesPerSector,
  ref int numberOfFreeClusters,
  ref int totalNumberOfClusters);

  不幸的是,当我试图运行时,该函数不能执行。问题在于,无论我们在哪个平台上,封送拆收器在默认情况下都试图查找 API 的 Ansi 版本,由于 LPTStr 意味着在 Windows NT 平台上会使用 Unicode 字符串,因此试图用 Unicode 字符串来调用 Ansi 函数就会失败。

有两种方法可以解决这个问题:一种简单的方法是删除 MarshalAs 属性。如果这样做,将始终调用该函数的 A 版本,如果在您所涉及的所有平台上都有这种版本,这是个很好的方法。但是,这会降低代码的执行速度,因为封送拆收器要将 .NET 字符串从 Unicode 转换为多字节,然后调用函数的 A 版本(将字符串转换回 Unicode),最后调用函数的 W 版本。

  要避免出现这种情况,您需要告诉封送拆收器,要它在 Win9x 平台上时查找 A 版本,而在 NT 平台上时查找 W 版本。要实现这一目的,可以将 CharSet 设置为 DllImport 属性的一部分:

  [DllImport("kernel32.dll", CharSet = CharSet.Auto)]

  在我的非正式计时测试中,我发现这一做法比前一种方法快了大约百分之五。

  对于大多数 Win32 API,都可以对字符串类型设置 CharSet 属性并使用 LPTStr。但是,还有一些不采用 A/W 机制的函数,对于这些函数必须采取不同的方法。
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章