10 Mart 2020 Salı

DllImport Anotasyonu - Platform Invoke (P/Invoke)

Giriş
Şu satırı dahil ederiz.
using System.Runtime.InteropServices;
Açıklaması şöyle
P/Invoke - allows c-style method calls directly from c# code. If the API does not expose c-style (i.e. extern C) functions you will need a wrapper that does this. If the API uses any kind of objects this will probably be an painful approach.
Bu kelime .Net olmayan bir Dll'den metod kullanabilmemizi sağlar. Metodun başına static extern eklenir ve daha sonra metodun imzası eksiksiz yazılır. Dll içindeki metodları görmek için dumpbin komutu kullanılaiblir.

Eğer DLL bulunamazsa DllNotFoundException atılır.

1. Hiçbir Alan Belirtmemek
Örnek
Şöyle yaparız.
class ExternalDllSubClass
{
    [DllImport("my.dll")]
    private static extern void print_line(string str);

    internal static void PrintLine (string str) {
        print_line(str);
    }
}
Örnek
Şöyle yaparız
class Program
{
  // This is where you declare the functions from the C file that you want to use.
  // The filename is a relative path to the file containing the `Program`
  [DllImport("libHello.dll")]
  static extern string say_hello(byte[] buffer);

  static void Main()
  {
    var buffer = new byte[1024]; // create byte buffer
    say_hello(buffer) // call the C function
    Console.WriteLine(Encoding.ASCII.GetString(buffer)) // 'hello'
}
2. CallingConvention Alanı- C tarzı metodlar
Örnek
Dll içindeki metod C calling convention ile kodlanmış olabilir. C calling convention'da çağıran metod stack'i temizler. Windows calling convention'da çağrılan metod stack'i temizler.
extern "C" __declspec(dllexport) int Add(int a, int b)
{
    return a + b;
}
Bu durumda şöyle tanımlarız.
[DllImport("CommonNativeLib.dll"),CallingConvention = CallingConvention.Cdecl)]
extern public static int Add(int a, int b);
Örnek
Elimizde şöyle bir kod olsun.
extern "C" __declspec(dllexport) int __cdecl test();
Şöyle yaparız.
[DllImport("Api.dll", EntryPoint = "test", CharSet = CharSet.Ansi, 
  CallingConvention = CallingConvention.Cdecl)]
internal static extern Int32 test();
3. CharSet Alanı
Şöyle yaparız.
[DllImport(“user32.dll”, CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, 
  LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
Şöyle yaparız.
[DllImport(“user32.dll”, CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
4. EntryPoint Alanı
Örnek
Eğer C# metodunun ismini farklı vermek istesek EntryPoint te tanımlanabiliyor.
Örnek
Şöyle yaparız.
[DllImport("MyDll32.dll", EntryPoint = "Func1", 
                          CallingConvention = CallingConvention.Cdecl)]
private static extern int Func1_32(int var1, int var2);
Örnek
Elimizde şöyle bir kod olsun.
#include "Source.h"

void PiblRequestCallback(PibMsgConf &msg, void *param)
{
  cout << "In PibRequestCallback" << endl;
}

uint32_t GetPib() 
{

  return 25;
}
Şöyle yaparız
[DllImport("socket.dll", EntryPoint = "getpib")]
public static extern UInt32 GetPib();

Hiç yorum yok:

Yorum Gönder