前面一篇文章:.NET(C#)平台调用:DllImportAttribute.CharSet和字符串封送编码,介绍了平台调用时封送字符串和DllImportAttribute.CharSet的各种关系。事实上还有另外一种方法,因为字符串本身也是指针,那么在调用声明时用IntPtr(而不是String类型)也可以,此时则需要我们手动对IntPtr做处理。使用的则是Marshal类的StringToHGlobal方法将托管堆中的字符串转换成一个非托管堆中的指针。注意需要用Marshal.FreeHGlobal来释放非托管堆指针的内存空间。
还是比如MessageBox函数:
//字符串参数为IntPtr
[DllImport("user32.dll")]
public static extern int MessageBox(int hWnd, IntPtr text, IntPtr caption, uint type);
static void Main()
{
//字符串
var str = "hehe";
//在非托管堆中创建指针
var ptr = Marshal.StringToHGlobalAnsi(str);
//平台调用MessageBoxA
MessageBox(0, ptr, IntPtr.Zero, 0);
//清理
Marshal.FreeHGlobal(ptr);
}
上面是ANSI的调用,如果是Unicode,用Marshal.StringToHGlobalUni。如果CharSet是Auto的话,用Marshal.StringToHGlobalAuto来将CLR字符串转换成平台相关的非托管字符串形式。