0Pricing
C# Academy · Ders

P/Invoke Temelleri

DllImport kullanarak yerel işlevleri bildirin ve çağırın; temel türlerin, dizelerin ve yapıların sıralanmasını anlayın.

P/Invoke Temelleri, CoddyKit'te ücretsiz bir C# Academy dersidir. Bu, 4 dersinin 1. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, C# Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. C# Academy kursu toplamda 4 dersten oluşur.

P/Invoke Nedir?

Platform Çağırma Hizmetleri (P/Invoke), C# dilinin yerel paylaşılan kitaplıklardaki (Windows'ta .dll, Linux'ta .so, macOS'ta .dylib) işlevleri çağırmasını sağlar. Win32 API'lerini veya herhangi bir C-ABI kitaplığını .NET'ten çağırmanın standart mekanizmasıdır.

İlk P/Invoke Çağrınız

Yerel işlevi [DllImport] ile bildirin ve kitaplık adını verin. CLR, kitaplığı bulup yüklemeyi ve bağımsız değişkenleri dönüştürmeyi yönetir.

using System.Runtime.InteropServices;

// Calling MessageBoxW from user32.dll (Windows)
internal static partial class NativeMethods
{
    [DllImport("user32.dll",
        EntryPoint = "MessageBoxW",
        CharSet = CharSet.Unicode,
        SetLastError = true)]
    internal static extern int MessageBox(
        IntPtr hwnd,
        string text,
        string caption,
        uint type);
}

// Call it:
NativeMethods.MessageBox(IntPtr.Zero, "Hello!", "P/Invoke", 0);

// Windows-only — wrap in RuntimeInformation.IsOSPlatform check
// for cross-platform code

Özel Yerel Kitaplıkları Çağırma

P/Invoke yalnızca işletim sistemi API'leriyle değil, C tarafından dışa aktarılan tüm işlevlerle çalışır. Yerel bir kitaplık oluşturun, işlevleri C bağlantısıyla dışa aktarın ve bunları C# dilinden çağırın.

// mymath.h / mymath.c:
// extern "C" double AddNumbers(double a, double b) { return a + b; }
// Compile: gcc -shared -o libmymath.so mymath.c

// C# declaration:
[DllImport("mymath",              // libmymath.so / mymath.dll
    EntryPoint = "AddNumbers",
    CallingConvention = CallingConvention.Cdecl)]
private static extern double AddNumbers(double a, double b);

// Call:
double result = AddNumbers(3.14, 2.72); // 5.86

// .NET resolves the library via:
// 1. Absolute path if provided
// 2. App directory
// 3. OS library path (PATH / LD_LIBRARY_PATH / DYLD_LIBRARY_PATH)

Temel Türleri Dönüştürme

CLR, çoğu ilkel türü yönetilen ve yerel gösterimler arasında otomatik olarak dönüştürür. Eşlemeleri bilmek, fark edilmesi zor hatalardan kaçınmanızı sağlar.

// C Type       → C# Type
// int (32-bit)  → int  or  System.Int32
// long (64-bit) → long or  System.Int64
// float         → float
// double        → double
// bool          → [MarshalAs(UnmanagedType.Bool)] bool
// char*  (ANSI) → string  (CharSet.Ansi)
// wchar_t*      → string  (CharSet.Unicode)
// void*         → IntPtr
// size_t        → UIntPtr

// Example with explicit marshalling:
[DllImport("libc", EntryPoint = "strlen", CharSet = CharSet.Ansi)]
private static extern UIntPtr StrLen(
    [MarshalAs(UnmanagedType.LPStr)] string s);

int len = (int)StrLen("hello"); // 5

Yapıları Yerel Koda Aktarma

Yapının bellekte yerel kodun beklediği şekilde yerleştirilmesini sağlamak için [StructLayout(LayoutKind.Sequential)] kullanın.

// C struct:
// struct Point { int x; int y; };
// void DrawPoint(struct Point p);

[StructLayout(LayoutKind.Sequential)]
public struct Point
{
    public int X;
    public int Y;
}

[DllImport("graphics", EntryPoint = "DrawPoint",
    CallingConvention = CallingConvention.Cdecl)]
private static extern void DrawPoint(Point p);

// Pass by value:
DrawPoint(new Point { X = 10, Y = 20 });

// Pass by pointer (ref or out):
[DllImport("graphics", EntryPoint = "GetCenter",
    CallingConvention = CallingConvention.Cdecl)]
private static extern void GetCenter(out Point center);
GetCenter(out var pt);

Hata İşleme: GetLastWin32Error

Windows API işlevleri hataları GetLastError() aracılığıyla bildirir. [DllImport] içinde SetLastError = true ayarını yapın ve çağrıdan sonra Marshal.GetLastWin32Error() çağrısını yapın.

[DllImport("kernel32.dll",
    EntryPoint = "CreateFileW",
    CharSet = CharSet.Unicode,
    SetLastError = true)]
private static extern IntPtr CreateFile(
    string fileName,
    uint desiredAccess,
    uint shareMode,
    IntPtr securityAttributes,
    uint creationDisposition,
    uint flagsAndAttributes,
    IntPtr templateFile);

const uint GENERIC_READ = 0x80000000;
const uint OPEN_EXISTING  = 3;

var handle = CreateFile("test.txt", GENERIC_READ, 0,
    IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);

if (handle == (IntPtr)(-1))
{
    int error = Marshal.GetLastWin32Error();
    throw new System.ComponentModel.Win32Exception(error);
}

Dizeleri ve Arabellekleri Dönüştürme

Dize dönüştürme, kodlamaya ve sahipliğe dikkat edilmesini gerektirir. Çıktı arabellekleri için StringBuilder, kodlamayı belirtmek için de MarshalAs özniteliklerini kullanın.

// Read into a buffer:
[DllImport("kernel32.dll",
    EntryPoint = "GetComputerNameW",
    CharSet = CharSet.Unicode,
    SetLastError = true)]
private static extern bool GetComputerName(
    System.Text.StringBuilder lpBuffer,
    ref uint nSize);

uint size = 256;
var buffer = new System.Text.StringBuilder((int)size);
if (GetComputerName(buffer, ref size))
    Console.WriteLine(buffer.ToString());

// Return a string owned by native code (don't free it):
[DllImport("mylib", CharSet = CharSet.Ansi)]
[return: MarshalAs(UnmanagedType.LPStr)]
private static extern string GetVersion();

İşlev İşaretçileri ve Geri Çağrılar

Yönetilen delegate öğelerini C işlev işaretçileri olarak aktarın. CLR bir ara köprü işlevi oluşturur; ancak delegate öğesini canlı tutmanız (bir başvuru bulundurmanız) gerekir. Aksi takdirde GC onu toplar ve yerel kod çöker.

// C callback signature: typedef int (*Comparer)(const void*, const void*);
// void qsort(void* base, size_t nitems, size_t size, Comparer compar);

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int CompareCallback(IntPtr a, IntPtr b);

[DllImport("libc", CallingConvention = CallingConvention.Cdecl)]
private static extern void QSort(
    int[] data, UIntPtr count, UIntPtr size, CompareCallback compare);

// Keep the delegate ALIVE for the duration of the call:
private static readonly CompareCallback _compare =
    (a, b) => Marshal.ReadInt32(a).CompareTo(Marshal.ReadInt32(b));

var data = new[] { 5, 2, 8, 1, 3 };
QSort(data, (UIntPtr)data.Length, (UIntPtr)sizeof(int), _compare);

NativeLibrary API'si

NativeLibrary sınıfı açık kitaplık yükleme, işlev işaretçisi çözümleme ve platformlar arası yol özelleştirmesi sağlar — sihirli kitaplık adı çözümlemesine modern bir alternatiftir.

using System.Runtime.InteropServices;

// Explicit load:
var handle = NativeLibrary.Load("/usr/lib/libssl.so.3");

// Resolve a function pointer:
var addPtr = NativeLibrary.GetExport(handle, "AddNumbers");
var addFn = Marshal.GetDelegateForFunctionPointer<Func<double,double,double>>(addPtr);
double result = addFn(1.0, 2.0);

// Unload:
NativeLibrary.Free(handle);

// Custom resolver (called when DllImport can't find a library):
NativeLibrary.SetDllImportResolver(typeof(MyNative).Assembly,
    (libName, assembly, searchPath) =>
    {
        if (libName == "mymath")
            return NativeLibrary.Load("/opt/mymath/libmymath.so");
        return IntPtr.Zero;
    });

Gerçek Dünya: OpenSSL Çağrısı

Gerçek dünyadan bir örnek: P/Invoke kullanarak C# dilinden OpenSSL'nin SHA-256 özet işlevini çağırma.

internal static class OpenSslInterop
{
    [DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
    private static extern IntPtr EVP_MD_CTX_new();

    [DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
    private static extern void EVP_MD_CTX_free(IntPtr ctx);

    [DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
    private static extern IntPtr EVP_sha256();

    [DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
    private static extern int EVP_DigestInit_ex(IntPtr ctx, IntPtr type, IntPtr engine);

    // In practice, use System.Security.Cryptography.SHA256 instead:
    // var hash = SHA256.HashData(data);
    // P/Invoke to OpenSSL is only needed when you require
    // non-managed cryptographic operations or specific OpenSSL features
}

Hızlı Kontrol

Bir delegate öğesini yerel geri çağrı olarak aktarırken neden canlı tutmanız gerekir?

Özet: P/Invoke Temelleri

Önemli çıkarımlar:

  • P/Invoke: [DllImport] bildirimleri aracılığıyla yerel C-ABI işlevlerini çağırma
  • CLR, temel türleri otomatik olarak veri dönüştürür; dizeler ve özel türler için [MarshalAs] ile açıklama ekleyin
  • [StructLayout(LayoutKind.Sequential)]: yapıların bellek düzeninin yerel beklentilerle eşleşmesini sağlar
  • Win32 hatalarını işlemek için SetLastError = true ayarlayın ve Marshal.GetLastWin32Error() çağrısını yapın
  • Yerel geri çağrılar olarak geçirirken temsilci başvurularını canlı tutun
  • NativeLibrary: platformlar arası yol denetimi için açıkça yükleme, çözümleme ve özel çözümleyici kullanma

Sıkça Sorulan Sorular

“P/Invoke Temelleri” dersi ücretsiz mi?

Evet — “P/Invoke Temelleri” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve C# Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. C# Academy kursu toplamda 4 dersten oluşur.

“P/Invoke Temelleri” dersinde ne öğreneceğim?

DllImport kullanarak yerel işlevleri bildirin ve çağırın; temel türlerin, dizelerin ve yapıların sıralanmasını anlayın. C# Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

C# Academy öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te C# Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 1. dersidir.

“P/Invoke Temelleri” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu C# Academy dersinde kod yazıp çalıştırabilir miyim?

Evet. Her C# Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. P/Invoke Temelleri
  2. LibraryImport ve Kaynak Tarafından Oluşturulan P/Invoke
  3. Güvenli Olmayan Kod, İşaretçiler ve Sabit Tamponlar
  4. COM Birlikte Çalışabilirliği ve Çalışma Zamanı Çağrılabilir Sarmalayıcıları
← C# Academy Sayfasına Dön