Simple string
The following is a simple example of a function to accept a string parameter:
The GetDiskFreeSpace BOOL (LPCTSTR lpRootPathName , // root LPDWORD lpSectorsPerCluster , // number of sectors per cluster LPDWORD lpBytesPerSector , // number of bytes per sector LPDWORD lpNumberOfFreeClusters , // number of sectors available LPDWORD lpTotalNumberOfClusters // fan total area);
It is defined as the root LPCTSTR
. This is a platform-independent string pointer.
Due to the absence of named GetDiskFreeSpace()
functions, marshaler will automatically find " A
" or " W
" variant, and calling the corresponding function. We use a property to tell marshaler, a string type requested API.
The following is the complete definition of the function, so as I defined at the beginning:
[DllImport("kernel32.dll")]static extern bool GetDiskFreeSpace( [MarshalAs(UnmanagedType.LPTStr)] string rootPathName, ref int sectorsPerCluster, ref int bytesPerSector, ref int numberOfFreeClusters, ref int totalNumberOfClusters);
Unfortunately, when I tried to run, this function can not be executed. The problem is that, regardless of the platform on which we have, marshaler in default are trying to find Ansi version of the API, due to the means Windows NT platform uses Unicode strings, so trying to use Unicode strings to call Ansi function will fail. LPTStr
There are two ways to solve this problem: A simple method is to remove the MarshalAs
property. If you do, will always call the function A
version, this version has on all platforms if you are concerned, this is a good way. However, this reduces the execution speed of the code, because marshaler To .NET string is converted from multi-byte Unicode, and then calls the function A
version (the string back to Unicode), the function of the last call W
release.
To avoid this situation, you need to tell marshaler, a time to look for it in the Win9x platform A
version, and look W version on NT platform when. To achieve this purpose, it can be CharSet
set as part of the property: DllImport
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
In my informal timed tests, I found that this practice about five percent faster than the previous method.
For most of the Win32 API, can be set to a string type CharSet
property and use LPTStr
. However, some do not use A
/ W
function mechanisms, these functions must take a different approach.
String buffer
String type in .NET are immutable type, which means its value will always remain the same. For copy the string value to the buffer function string, the string is not valid. Doing so will destroy at least a temporary buffer created when converting from the string to marshal seal; and in severe damage to the managed heap, which often leads to errors. In either case you can not obtain the correct return value.
To resolve this problem, we need to use other types. StringBuilder
Type is designed to serve as a buffer, we will use it instead of a string. Here is an example:
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]public static extern int GetShortPathName( [MarshalAs(UnmanagedType.LPTStr)] string path, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder shortPath, int shortPathLength);
This function is very simple:
String Builder Builder short path = new String (80); int result = Gets Hort Path Name (@ "d: est.jpg", short path, shortPath.Capacity); string s = shortPath.ToString ();
Please note that StringBuilder
the Capacity
transfer is the buffer size.
Reproduced in: https: //www.cnblogs.com/kevinGao/archive/2011/11/09/2243453.html