编辑
2025-09-20
C#
00

目录

基本概念
核心概念
示例
1. 调用MessageBox Windows API
2. 使用系统时间API
应用场景
注意事项
结论

P/Invoke(Platform Invocation Services)是一种技术,允许C#或其他.NET语言的程序调用C/C++编写的本地动态链接库(DLL)中的函数。这为.NET应用程序提供了一种强大的方式,使之能够执行Windows API调用或访问其他非托管代码库中的功能,这些功能可能未直接在.NET环境中提供。P/Invoke是.NET和非托管代码之间的桥梁,它使得开发者能够利用现有的本地代码,而无需完全重写为.NET代码。

基本概念

在.NET应用程序中使用P/Invoke的基本步骤包括:

  1. 声明外部函数:在C#代码中使用DllImport属性声明需要调用的外部函数。
  2. 调用函数:像调用普通C#函数一样调用声明的外部函数。
  3. 处理数据类型映射:正确处理.NET数据类型和非托管数据类型之间的映射。

核心概念

  • 托管代码:运行在.NET运行时(CLR - Common Language Runtime)管理下的代码,享受垃圾回收、类型安全检查等服务。
  • 非托管代码:直接运行在操作系统上的代码,不受CLR管理,通常指C/C++等语言编写的应用程序或库。

示例

1. 调用MessageBox Windows API

以下是一个使用P/Invoke调用Windows API中的MessageBox函数的简单示例。

C#
using System; using System.Runtime.InteropServices; class Program { // 声明MessageBox函数 [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern MessageBoxResult MessageBox(IntPtr hWnd, string text, string caption, int options); public enum MessageBoxResult : uint { OK = 1, Cancel, Abort, Retry, Ignore, Yes, No, Close, Help, TryAgain, Continue } static void Main() { // 调用MessageBox函数 MessageBoxResult result = MessageBox(IntPtr.Zero, "Hello, World!", "P/Invoke示例", 1); Console.WriteLine($"MessageBox返回结果: {result}"); } }

image.png

2. 使用系统时间API

这个例子演示了如何使用P/Invoke调用GetSystemTime函数,这是Windows API中的一个函数,用于获取当前系统时间。

C#
using System; using System.Runtime.InteropServices; class Program { [StructLayout(LayoutKind.Sequential)] public struct SYSTEMTIME { public ushort Year, Month, DayOfWeek, Day, Hour, Minute, Second, Milliseconds; } [DllImport("kernel32.dll", SetLastError = true)] public static extern void GetSystemTime(ref SYSTEMTIME st); static void Main() { SYSTEMTIME st = new SYSTEMTIME(); GetSystemTime(ref st); Console.WriteLine($"当前系统时间: {st.Year}-{st.Month}-{st.Day} {st.Hour}:{st.Minute}:{st.Second}"); } }

image.png

应用场景

P/Invoke的应用场景广泛,包括但不限于:

  • Windows API调用:访问Windows操作系统提供的底层功能。
  • 现有代码重用:在.NET应用程序中使用现有的C/C++代码库,避免重写。
  • 性能敏感任务:对于某些性能敏感的操作,本地代码通常能提供更好的性能。
  • 系统级操作:执行一些.NET框架不直接支持的系统级操作,如直接硬件访问。

注意事项

使用P/Invoke时,需要特别注意数据类型的映射和内存管理。不正确的使用可能会导致内存泄漏、数据损坏或程序崩溃。此外,由于P/Invoke调用的是非托管代码,它不受.NET运行时的安全和异常管理机制保护,因此需要谨慎处理异常和错误代码。

  • 平台兼容性:确保所调用的非托管DLL在目标平台上可用。
  • 内存管理:需要注意内存分配和释放的责任,防止内存泄漏。
  • 错误处理:非托管代码的错误处理机制与.NET不同,需要正确处理调用失败的情况。
  • 性能考虑:虽然P/Invoke允许调用非托管代码,但频繁的交互可能会引入性能开销。

结论

P/Invoke是.NET开发者强大的工具,它打开了.NET与操作系统底层及其他本地代码交互的大门。通过正确使用P/Invoke,开发者可以在.NET应用程序中实现更多功能,提高应用程序的性能和能力。然而,它也需要开发者对非托管代码有深入的理解,以确保应用程序的稳定性和安全性。

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!