实用技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > ASP.NET > 实用技巧 > .NET  DllImport使用

.NET 中DllImport的用途使用场景分析

作者:o0向阳而生0o

在 .NET 中,DllImport 是 Platform Invocation Services (P/Invoke) 的核心机制,用于调用非托管(native)DLL 中的函数,这篇文章主要介绍了.NET 中DllImport的用途使用场景分析,需要的朋友可以参考下

在 .NET 中,DllImport 是 Platform Invocation Services (P/Invoke) 的核心机制,用于调用非托管(native)DLL 中的函数。以下是其核心用途、应用场景、关键细节及注意事项的全面总结:

1. 核心用途

2. 典型应用场景

场景示例
硬件交互调用驱动 DLL 控制设备(如键盘锁定、传感器读取、USB 通信)。
系统级操作访问 Windows API(如 kernel32.dll、user32.dll)或第三方系统库。
旧代码集成将遗留的非托管代码(如 C++ 库)集成到现代 .NET 应用中。
高性能计算调用非托管数学库(如 Intel MKL)进行复杂数值计算。
跨平台兼容在 .NET 中调用平台特定的非托管代码(如 Linux 的 libc.so)。

3. 关键使用细节

(1)基本语法

[DllImport("DLL名称.dll", 
    EntryPoint = "函数名", 
    CallingConvention = CallingConvention.StdCall,
    CharSet = CharSet.Ansi)]
public static extern 返回类型 函数名(参数列表);

(2)调用约定(Calling Convention)

(3)数据类型映射

托管类型非托管类型示例
intint、long(32位)[DllImport] public static extern int Add(int a, int b);
stringchar*(ANSI)需用 MarshalAs(UnmanagedType.LPStr) 或 IntPtr。
boolBOOL(4字节)通常映射为 int(非零为真)。
structstruct需用 [StructLayout(LayoutKind.Sequential)] 定义。
IntPtr通用指针用于处理 void* 或动态内存。

4. 常见问题与解决方案

(1)DLL 加载失败

原因:DLL 不在搜索路径中(如程序目录、系统 PATH)。

解决方案:

(2)调用约定不匹配

(3)内存管理

使用 Marshal.FreeHGlobal 或 Marshal.FreeCoTaskMem。
避免直接返回非托管内存指针,改用 IntPtr 并封装释放逻辑。

(4)字符串处理

明确指定 CharSet(如 CharSet.Unicode 对应 wchar_t*)。
使用 Marshal.StringToHGlobalAnsi/StringToHGlobalUni 转换。

5. 高级技巧

(1)动态加载 DLL

[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
public static void LoadDllDynamically()
{
    IntPtr hDll = LoadLibrary("CompalLockInput.dll");
    if (hDll != IntPtr.Zero)
    {
        IntPtr funcAddr = GetProcAddress(hDll, "LockKeyboard");
        // 通过委托调用函数...
    }
}

(2)结构体与指针

[StructLayout(LayoutKind.Sequential)]
public struct Point
{
    public int X;
    public int Y;
}
[DllImport("Graphics.dll")]
public static extern void DrawPoint(ref Point point); // ref 传递结构体

(3)错误处理

使用 SetLastError = true 捕获非托管代码的错误码:

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(IntPtr hObject);
// 调用后检查错误码
if (!CloseHandle(handle))
{
    int errorCode = Marshal.GetLastWin32Error();
    Console.WriteLine($"错误码: {errorCode}");
}

6. 替代方案

7. 总结

明确指定 CallingConvention 和 CharSet。
封装非托管调用,隐藏复杂细节。
优先使用托管库或 C++/CLI 替代 P/Invoke(若可行)。

通过合理使用 DllImport,.NET 开发者可以高效利用非托管代码的强大功能,同时保持代码的可维护性。

到此这篇关于.NET 中DllImport的用途的文章就介绍到这了,更多相关.NET DllImport内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文