Asp.NET Tutorials
Home > C#语言 > 如何在C#中使用Win32和其他库(三)

Hot archives

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


简单字符串

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

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  机制的函数,对于这些函数必须采取不同的方法。 

 

Add by : Huobazi (2005-5-02:08:44)