Udostępnij za pośrednictwem


Jak: przy użyciu funkcji PInvoke wskaźników funkcji Marshal

W tym temacie wyjaśniono jak zarządzanych delegatów można stosować w miejsce wskaźników funkcji przy współpracy z niezarządzanego funkcje za pomocą.NET Framework P/Invoke funkcje.Jednakże programiści Visual C++ zachęca się zamiast korzystać z funkcji współdziałania z modelem C++ (jeśli możliwe) ponieważ P/Invoke zawiera niewiele raportowanie błędów kompilacji, nie jest typu bezpiecznej i może być uciążliwe do wdrożenia.Jeśli niezarządzanego API jest dostarczana jako biblioteki DLL i kod źródłowy nie jest dostępny, P/Invoke jest jedyną opcją.W przeciwnym razie zobacz następujące tematy:

Niezarządzany API podjąć wskaźniki funkcje jako argumenty może być wywołana z kodu zarządzanego z zarządzanych pełnomocnik zamiast wskaźnika funkcji macierzystym.Kompilator pełnomocnika do niezarządzanego funkcji jako wskaźnik funkcji marshals i automatycznie wstawia kod konieczne przejście zarządzanych/niezarządzanych.

Przykład

Poniższy kod składa się z niezarządzanych i zarządzanych modułu.Moduł niezarządzanego to biblioteki DLL, która definiuje funkcję o nazwie TakesCallback, która akceptuje wskaźnika funkcji.Ten adres jest używany do wykonania funkcji.

Moduł zarządzany definiuje pełnomocnika, jest przekazywane do kodu macierzystego jako wskaźnik funkcji, który korzysta z DllImportAttribute atrybut narazić macierzystych funkcji TakesCallback do kodu zarządzanego.W głównych funkcji instancji pełnomocnika, utworzony i przekazany do funkcji TakesCallback.Dane wyjściowe programu wykaże, że ta funkcja pobiera wykonywane przez macierzysty funkcji TakesCallback.

Funkcja zarządzanych pomija kolekcji garbage dla zarządzanych pełnomocnika zapobiec.NET Framework wyrzucania elementów bezużytecznych od przemieszczenia delegata podczas wykonuje funkcję macierzystym.

Moduł zarządzany jest kompilowana/CLR, ale/CLR: również czystego programu works.

// TraditionalDll5.cpp
// compile with: /LD /EHsc
#include <iostream>
#define TRADITIONALDLL_EXPORTS
#ifdef TRADITIONALDLL_EXPORTS
#define TRADITIONALDLL_API __declspec(dllexport)
#else
#define TRADITIONALDLL_API __declspec(dllimport)
#endif

extern "C" {
   /* Declare an unmanaged function type that takes two int arguments
      Note the use of __stdcall for compatibility with managed code */
   typedef int (__stdcall *CALLBACK)(int);
   TRADITIONALDLL_API int TakesCallback(CALLBACK fp, int);
}

int TakesCallback(CALLBACK fp, int n) {
   printf_s("[unmanaged] got callback address, calling it...\n");
   return fp(n);
}

// MarshalDelegate.cpp
// compile with: /clr
using namespace System;
using namespace System::Runtime::InteropServices;

public delegate int GetTheAnswerDelegate(int);
public value struct TraditionalDLL {
   [DllImport("TraditionalDLL5.dll")]
   static public int TakesCallback(GetTheAnswerDelegate^ pfn, int n);
};

int GetNumber(int n) {
   Console::WriteLine("[managed] callback!");
   static int x = 0;
   ++x;
   return x + n;
}

int main() {
   GetTheAnswerDelegate^ fp = gcnew GetTheAnswerDelegate(GetNumber);
   pin_ptr<GetTheAnswerDelegate^> pp = &fp;
   Console::WriteLine("[managed] sending delegate as callback...");

   int answer = TraditionalDLL::TakesCallback(fp, 42);
}

Uwaga, że żadna jego część biblioteki DLL jest narażony na kod zarządzany, przy użyciu tradycyjnych # dołączona dyrektywa.W rzeczywistości biblioteki DLL jest dostępny tylko w czasie wykonywania, problemy z funkcjami przywożone z DllImportAttribute nie będą wykrywane w czasie kompilacji.

Zobacz też

Inne zasoby

Za pomocą jawnego PInvoke w C++ (atrybut DllImport)