System.Runtime.InteropServices实现托管代码与非托管代码的高效互操作

System.Runtime.InteropServices 是 .NET 中的一个命名空间,提供了与 互操作(Interop) 相关的功能,主要用于在 .NET 应用程序中与非托管代码(如 C/C++、COM 组件、Win32 API 等)进行交互。通过这个命名空间,可以实现托管代码(.NET)与非托管代码之间的无缝集成。

主要功能
与非托管代码交互:

调用 Win32 API 或其他非托管库中的函数。

使用 COM 组件。

数据类型转换:

在托管代码和非托管代码之间传递数据时,处理数据类型的转换。

内存管理:

控制非托管内存的分配和释放。

自定义封送处理:

控制数据在托管和非托管代码之间的传递方式。

常见类和用法
1. DllImport 特性
用于声明外部非托管库中的函数,以便在 .NET 中调用。

示例:调用 Win32 API 的 MessageBox 函数

using System;
using System.Runtime.InteropServices;

class Program
{
    // 声明 MessageBox 函数
    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    public static extern int MessageBox(IntPtr hWnd, string text, string caption, uint type);

    static void Main()
    {
        // 调用 MessageBox
        MessageBox(IntPtr.Zero, "Hello, World!", "Message", 0);
    }
}

DllImport 参数:

"user32.dll":非托管库的名称。

CharSet:指定字符串的编码方式(如 CharSet.Unicode 或 CharSet.Ansi)。

CallingConvention:指定调用约定(如 CallingConvention.StdCall 或 CallingConvention.Cdecl)。

2. Marshal 类
提供了许多方法,用于在托管代码和非托管代码之间进行数据封送处理(Marshaling)。

常见方法:

Marshal.PtrToStringAnsi:将非托管 ANSI 字符串转换为托管字符串。

Marshal.StringToHGlobalAnsi:将托管字符串转换为非托管 ANSI 字符串。

Marshal.AllocHGlobal:分配非托管内存。

Marshal.FreeHGlobal:释放非托管内存。

Marshal.StructureToPtr:将托管结构体转换为非托管内存。

Marshal.PtrToStructure:将非托管内存转换为托管结构体。

示例:字符串封送处理

using System;
using System.Runtime.InteropServices;

class Program
{
    static void Main()
    {
        // 托管字符串
        string managedString = "Hello, World!";

        // 将托管字符串转换为非托管 ANSI 字符串
        IntPtr unmanagedString = Marshal.StringToHGlobalAnsi(managedString);

        // 将非托管字符串转换回托管字符串
        string convertedString = Marshal.PtrToStringAnsi(unmanagedString);
        Console.WriteLine(convertedString);

        // 释放非托管内存
        Marshal.FreeHGlobal(unmanagedString);
    }
}

3. StructLayout 特性
用于控制托管结构体在内存中的布局,以便与非托管代码交互。

示例:定义与非托管代码兼容的结构体

using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)] // 按顺序布局
struct Point
{
    public int X;
    public int Y;
}

class Program
{
    [DllImport("user32.dll")]
    public static extern bool GetCursorPos(out Point lpPoint);

    static void Main()
    {
        Point point;
        if (GetCursorPos(out point))
        {
            Console.WriteLine($"Cursor Position: ({point.X}, {point.Y})");
        }
    }
}

LayoutKind:

Sequential:按顺序布局(默认)。

Explicit:显式指定每个字段的偏移量。

Auto:由运行时自动布局。

4. ComImport 和 Guid 特性
用于与 COM 组件交互。

示例:调用 COM 组件

using System;
using System.Runtime.InteropServices;

[ComImport]
[Guid("00021401-0000-0000-C000-000000000046")] // COM 组件的 GUID
class ShellLink
{
    // COM 接口方法
}

class Program
{
    static void Main()
    {
        // 创建 COM 对象
        var shellLink = new ShellLink();
        Console.WriteLine("COM object created.");
    }
}

5. MarshalAs 特性
用于指定数据在托管和非托管代码之间的封送方式。

示例:指定字符串的封送方式

using System;
using System.Runtime.InteropServices;

class Program
{
    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    public static extern int MessageBox(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)] string text, string caption, uint type);

    static void Main()
    {
        MessageBox(IntPtr.Zero, "Hello, World!", "Message", 0);
    }
}

UnmanagedType:

LPStr:ANSI 字符串。

LPWStr:Unicode 字符串。

BStr:COM 格式的字符串。

6. HandleRef 结构
用于安全地传递非托管句柄(如窗口句柄)以避免垃圾回收问题。

示例:使用 HandleRef

using System;
using System.Runtime.InteropServices;

class Program
{
    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    public static extern int MessageBox(HandleRef hWnd, string text, string caption, uint type);

    static void Main()
    {
        IntPtr hWnd = new IntPtr(0); // 假设的窗口句柄
        HandleRef handleRef = new HandleRef(null, hWnd);

        MessageBox(handleRef, "Hello, World!", "Message", 0);
    }
}

总结
System.Runtime.InteropServices 提供了强大的功能,使 .NET 应用程序能够与非托管代码无缝集成。常见的用法包括:

使用 DllImport 调用 Win32 API。

使用 Marshal 类进行数据封送处理。

使用 StructLayout 定义与非托管代码兼容的结构体。

使用 ComImport 和 Guid 与 COM 组件交互。

通过合理使用这些功能,可以实现托管代码与非托管代码的高效互操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值