C#调用非托管代码的方式主要有Com调用、DllImport方式调用、加载非托管动态连接库、直接执行机器码等方式。函数
如今介绍一下我本身经常使用的DllImport方式调用MSDN中提到的GetShortPathName方法;找到GetShortPathName的方法签名,ui
DWORD GetShortPathName(LPCTSTR tpszLongPath,TPTSTR lpszShortPath,DWORD cchBuffer);code
非托管及托管数据类型对应关系:字符串
LPCTSTR String编译器
LPTSTR StringBuilderio
DWORD int编译
DllImport的导入规则:ast
一、方法名与Win API彻底同样。若是在C#中调用时显示彻底不一样的方法名称,则须要引入EntryPoint属性,使用别名显示。class
二、函数除须要DllImport类修饰符外,还须要声明public static extern类型。变量
三、函数返回值和参数必须和调用的API的彻底同样。
四、必须引入System.Runtime.InteropServices命名空间。
代码:
using System.Runtime.InteropServices;
public class Test
{
[DllImport("kernel32.dll",CharSet=CharSet.Auto,EntryPoint="GetShort")]
public static extern int GetShortPathName(
[MarshalAs(UnmanagedType.LPTStr)] String path,
[MarshalAs(UnmanagedType.LPTStr)] StringBuilder shortPath,
int shortPathLength);
}
代码调用中kernel32.dll的路径之因此没写是由于DllImport会按照如下三种顺序查找Dll:
一、exe所在目录;二、System32目录;三、环境变量目录。
MarshalAs为可选类型,由于每一个数据类型都有默认的封送行为,该属性指示如何在托管代码和非托管代码之间的封送数据,可将该属性用于参数、字段和返回值。大多数状况下该属性只是用UnmanagedType枚举类型就能知足大多数非托管的数据类型,如默认状况下字符会被看成BStr传入到Dll中,可使用MarshalAs将字符串指定为LPTStr、LPWStr或LPStr等。
DllImport可选属性解释
EntryPoint 可对方法采用不一样的名称,使用别名
CharSet 函数调用使用Unicode仍是Ansi
ExactSpelling False,表示让编译器本身选择使用Unicode或Ansi
CallingConvetnion 它的参数指示入口点调用的约定;不指定默认为CallingConvention.WinAPI
PreserveSig 指示方法签名应当被保留仍是被转换,当被转换时它被转换为一个具备HRESULT返回值和该返回值的一个名为retval的附加输出参数的签名,默认为true。
SetLastError 指定是否保留上一次错误,默认为false