Aracılığıyla paylaş


Yapıların Aktarılması

Yönetilmeyen birçok işlev, işleve parametre olarak yapıların üyelerini (Visual Basic'te kullanıcı tanımlı türler) veya yönetilen kodda tanımlanan sınıfların üyelerini geçirmenizi bekler. Platform çağrısı kullanarak yapıları veya sınıfları yönetilmeyen koda geçirirken, özgün düzeni ve hizalamayı korumak için ek bilgiler sağlamanız gerekir. Bu konu, biçimlendirilmiş türleri tanımlamak için kullandığınız özniteliğini tanıtır StructLayoutAttribute . Yönetilen yapılar ve sınıflar için, numaralandırma tarafından sağlanan birkaç öngörülebilir düzen davranışı arasından seçim yapabilirsiniz.

Bu konuda sunulan kavramların merkezi, yapı ve sınıf türleri arasındaki önemli bir farktır. Yapılar değer türleridir ve sınıflar başvuru türleridir; sınıflar her zaman en az bir bellek dolaylı düzeyi (değer işaretçisi) sağlar. Yönetilmeyen işlevler genellikle aşağıdaki tablonun ilk sütunundaki imzalar tarafından gösterildiği gibi dolaylı işlem gerektirdiğinden bu fark önemlidir. Kalan sütunlardaki yönetilen yapı ve sınıf bildirimleri, bildiriminizdeki dolaylılık düzeyini ne derece ayarlayabileceğinizi gösterir. Hem Visual Basic hem de Visual C# için bildirimler sağlanır.

Yönetilmeyen imza Yönetilen bildirim:
dolaylı yok
Structure MyType
struct MyType;
Yönetilen bildirim:
bir dolaylılık düzeyi
Class MyType
class MyType;
DoWork(MyType x);

Sıfır dolaylılık düzeyi talep ediyor.
DoWork(ByVal x As MyType)
DoWork(MyType x)

Dolaylılık seviyesini sıfıra indirir.
Zaten bir dolaylılık düzeyi olduğundan mümkün değildir.
DoWork(MyType* x);

Bir düzeyde dolaylılık talep eder.
DoWork(ByRef x As MyType)
DoWork(ref MyType x)

Bir düzey dolaylılık ekler.
DoWork(ByVal x As MyType)
DoWork(MyType x)

Dolaylılık seviyesini sıfıra indirir.
DoWork(MyType** x);

İki düzeyde dolaylılık talep ediyor.
ByRef ByRef veya ref ref kullanılamadığı için mümkün değildir. DoWork(ByRef x As MyType)
DoWork(ref MyType x)

Bir düzey dolaylılık ekler.

Tabloda platform çağırma bildirimleri için aşağıdaki yönergeler açıklanmaktadır:

  • Yönetilmeyen işlev dolaylılık gerektirmediğinde, değer olarak geçirilen bir yapı kullanın.

  • Yönetilmeyen bir işlev bir dolaylılık düzeyi gerektirdiğinde, başvuru ile aktarılan yapıyı veya değer ile aktarılan bir sınıfı kullanın.

  • Yönetilmeyen işlev iki düzeyde dolaylılık gerektirdiğinde referans ile geçirilen bir sınıf kullanın.

Yapıları Tanımlama ve Geçirme

Aşağıdaki örnek, yönetilen kodda Point ve Rect yapılarını nasıl tanımlayacağınızı ve türleri User32.dll dosyasındaki PtInRect fonksiyonuna parametre olarak nasıl geçireceğinizi göstermektedir. PtInRect aşağıdaki yönetilmeyen imzaya sahiptir:

BOOL PtInRect(const RECT *lprc, POINT pt);

İşlev bir RECT türüne işaretçi beklediğinden, Rect yapısını referans olarak geçirmeniz gerektiğine dikkat edin.

Imports System.Runtime.InteropServices

<StructLayout(LayoutKind.Sequential)> Public Structure Point
    Public x As Integer
    Public y As Integer
End Structure

Public Structure <StructLayout(LayoutKind.Explicit)> Rect
    <FieldOffset(0)> Public left As Integer
    <FieldOffset(4)> Public top As Integer
    <FieldOffset(8)> Public right As Integer
    <FieldOffset(12)> Public bottom As Integer
End Structure

Friend Class NativeMethods
    Friend Declare Auto Function PtInRect Lib "user32.dll" (
        ByRef r As Rect, p As Point) As Boolean
End Class
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]
public struct Point {
    public int x;
    public int y;
}

[StructLayout(LayoutKind.Explicit)]
public struct Rect {
    [FieldOffset(0)] public int left;
    [FieldOffset(4)] public int top;
    [FieldOffset(8)] public int right;
    [FieldOffset(12)] public int bottom;
}

internal static class NativeMethods
{
    [DllImport("User32.dll")]
    internal static extern bool PtInRect(ref Rect r, Point p);
}

Sınıfları Bildirme ve Geçirme

Sınıfın üyelerini, sınıfın sabit bir üye düzenine sahip olduğu sürece yönetilmeyen DLL işlevine geçirebilirsiniz. Aşağıdaki örnek, sıralı sırada tanımlanan sınıfın MySystemTime üyelerini User32.dll dosyasındaki öğesine GetSystemTime nasıl geçirebileceğinizi gösterir. GetSystemTime aşağıdaki yönetilmeyen imzaya sahiptir:

void GetSystemTime(SYSTEMTIME* SystemTime);

Değer türlerinden farklı olarak, sınıfların her zaman en az bir dolaylı düzeyi vardır.

Imports System.Runtime.InteropServices

<StructLayout(LayoutKind.Sequential)> Public Class MySystemTime
    Public wYear As Short
    Public wMonth As Short
    Public wDayOfWeek As Short
    Public wDay As Short
    Public wHour As Short
    Public wMinute As Short
    Public wSecond As Short
    Public wMiliseconds As Short
End Class

Friend Class NativeMethods
    Friend Declare Auto Sub GetSystemTime Lib "Kernel32.dll" (
        sysTime As MySystemTime)
    Friend Declare Auto Function MessageBox Lib "User32.dll" (
        hWnd As IntPtr, lpText As String, lpCaption As String, uType As UInteger) As Integer
End Class

Public Class TestPlatformInvoke
    Public Shared Sub Main()
        Dim sysTime As New MySystemTime()
        NativeMethods.GetSystemTime(sysTime)

        Dim dt As String
        dt = "System time is:" & ControlChars.CrLf & _
              "Year: " & sysTime.wYear & _
              ControlChars.CrLf & "Month: " & sysTime.wMonth & _
              ControlChars.CrLf & "DayOfWeek: " & sysTime.wDayOfWeek & _
              ControlChars.CrLf & "Day: " & sysTime.wDay
        NativeMethods.MessageBox(IntPtr.Zero, dt, "Platform Invoke Sample", 0)
    End Sub
End Class
[StructLayout(LayoutKind.Sequential)]
public class MySystemTime {
    public ushort wYear;
    public ushort wMonth;
    public ushort wDayOfWeek;
    public ushort wDay;
    public ushort wHour;
    public ushort wMinute;
    public ushort wSecond;
    public ushort wMilliseconds;
}
internal static class NativeMethods
{
    [DllImport("Kernel32.dll")]
    internal static extern void GetSystemTime(MySystemTime st);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    internal static extern int MessageBox(
        IntPtr hWnd, string lpText, string lpCaption, uint uType);
}

public class TestPlatformInvoke
{
    public static void Main()
    {
        MySystemTime sysTime = new MySystemTime();
        NativeMethods.GetSystemTime(sysTime);

        string dt;
        dt = "System time is: \n" +
              "Year: " + sysTime.wYear + "\n" +
              "Month: " + sysTime.wMonth + "\n" +
              "DayOfWeek: " + sysTime.wDayOfWeek + "\n" +
              "Day: " + sysTime.wDay;
        NativeMethods.MessageBox(IntPtr.Zero, dt, "Platform Invoke Sample", 0);
    }
}

Ayrıca bkz.