آشنایی با P/Invoke در دات نت

در این مطلب با نحوه استفاده از P/Invoke در پروژه های دات نت آشنا خواهیم شد.

کدهای تولید شده توسط کامپایلر برای فانکشن MessageBoxW در ویژوال استودیو

P/Invoke چیست؟

Platform Invoke یا به اختصار P/Invoke به شما اجازه می‌دهد به توابع و سایر اجزای موجود در کتابخانه‌های غیرمدیریت شده در کدهای مدیریت شده دسترسی پیدا کنید.


مطالب مرتبط با این موضوع:


برای شروع، کد زیر که یک پیغام ساده را در ویندوز نمایش می‌دهد را در نظر بگیرید.

using System;
using System.Runtime.InteropServices;

public partial class Program
{
    // Import user32.dll (containing the function we need) and define
    // the method corresponding to the native function.
    [LibraryImport("user32.dll", StringMarshalling = StringMarshalling.Utf16, SetLastError = true)]
    private static partial int MessageBoxW(IntPtr hWnd, string lpText, string lpCaption, uint uType);

    public static void Main(string[] args)
    {
        // Invoke the function as a regular managed method.
        MessageBoxW(IntPtr.Zero, "Command-line message box", "Attention!", 0);
    }
}

در کدهای فوق، ابتدا با استفاده از LibraryImport به کامپایلر اعلام شده است که کتابخانه غیرمدیریت شده user32.dll باید بارگذاری شود.

[LibraryImport("user32.dll", StringMarshalling = StringMarshalling.Utf16, SetLastError = true)]

سپس در خط بعدی متد MessageBoxW با امضاء یکسان نسبت به متد اصلی تعریف شده است.

private static partial int MessageBoxW(IntPtr hWnd, string lpText, string lpCaption, uint uType);

با مراجعه به مستندات MessageBoxW می‌توان یکسان بودن امضاء (Signature) متد را بررسی کرد.

int MessageBoxW(
  [in, optional] HWND    hWnd,
  [in, optional] LPCWSTR lpText,
  [in, optional] LPCWSTR lpCaption,
  [in]           UINT    uType
);

سپس در ادامه متد MessageBoxW همانند یک متد عادی فراخوانی شده است.

MessageBoxW(IntPtr.Zero, "Command-line message box", "Attention!", 0);

با اجرای نمونه کد فوق، پیغام زیر نمایش داده خواهد شد.

---------------------------
Attention!
---------------------------
Command-line message box
---------------------------
OK   
---------------------------

ℹ️ توجه داشته باشید: برای اجرای دستورات فوق لازم است AllowUnsafeBlocks را در فایل پروژه خود فعال کنید.

<PropertyGroup>
+  <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

P/Invoke در سایر پلتفرم‌ها

همانطور که می‌دانید، از دات نت می‌توان در سایر پلتفرم‌ها نیز استفاده کرد. P/Invoke نیز از این قاعده مستثنی نیست.

در نمونه کد زیر نحوه دریافت Process ID فعلی را در لینوکس می‌توانید مشاهده کنید.

public static partial class Program
{
    // Import the libSystem shared library and define the method
    // corresponding to the native function.
    [LibraryImport("libSystem.dylib")]
    private static partial int getpid();

    public static void Main(string[] args)
    {
        // Invoke the function and get the Process ID.
        int pid = getpid();
        Console.WriteLine(pid);
    }
}

LibraryImport چه کاری انجام می‌دهد؟

اگر به متد MessageBoxW مثال قبلی دقت کرده باشید از کلمه کلیدی partial برای تعریف آن استفاده شده است.

[LibraryImport(...)]
private static partial int MessageBoxW(...);

این Attribute که در دات نت 7 معرفی شده است در واقع یک Source Generator است که کدهای لازم برای انجام P/Invoke را در هنگام کامپایل تولید می‌کند.

با مراجعه به بخش Analyzers در پروژه خود می‌توانید کدهای تولید شده را مشاهده کنید.

کدهای تولید شده توسط کامپایلر برای فانکشن MessageBoxW در ویژوال استودیو

P/Invoke در نسخه‌های قبلی دات نت

برای استفاده از P/Invoke در نسخه‌های قبلی دات نت، کدهای تعریف MessageBoxW به شکل زیر تغییر پیدا خواهد کرد.

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

    public static void Main(string[] args)
    {
        MessageBoxW(0, "Command-line message box", "Attention!", 0);
    }
}

در کدهای فوق:

  • ابتدا با استفاده از DllImport به کامپایلر اعلام شده است که user32.dll باید بارگذاری شود.
  • سپس متد MessageBoxW با استفاده از کلمه کلیدی extern تعریف شده است.

برای کسب اطلاعات بیشتر در مورد تفاوت بین LibraryImport و DllImport می‌توانید به این مطلب مراجعه کنید.

نظرات (0)