Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Zarządzane delegaty mogą być używane zamiast wskaźników funkcji podczas współdziałania z funkcjami niezarządzanymi przy użyciu funkcji P/Invoke programu .NET Framework. Zachęcamy jednak do korzystania z funkcji międzyoperacyjności języka C++, jeśli jest to możliwe. Funkcja P/Invoke zapewnia niewielkie raportowanie błędów czasu kompilacji, nie jest bezpieczne dla typu i nie może być żmudne do zaimplementowania. Jeśli niezarządzany interfejs API jest spakowany jako biblioteka DLL, a kod źródłowy nie jest dostępny, P/Invoke jest jedyną opcją. W przeciwnym razie zobacz następujące artykuły:
Niezarządzane interfejsy API, które przyjmują wskaźniki funkcji jako argumenty, mogą być wywoływane z kodu zarządzanego przy użyciu zarządzanego delegata zamiast wskaźnika funkcji natywnej. Kompilator automatycznie marshaluje delegata do funkcji niezarządzanych jako wskaźnik funkcji. Wstawia niezbędny zarządzany/niezarządzany kod przejścia.
Przykład
Poniższy kod składa się z niezarządzanego i zarządzanego modułu. Moduł niezarządzany to biblioteka DLL, która definiuje funkcję o nazwie TakesCallback , która akceptuje wskaźnik funkcji. Ten adres służy do wykonywania funkcji.
// 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);
}
Moduł zarządzany definiuje delegata, który jest marshaled do kodu natywnego jako wskaźnik funkcji. Używa atrybutu DllImportAttribute , aby uwidocznić funkcję natywną TakesCallback w kodzie zarządzanym.
main W funkcji jest tworzone wystąpienie delegata i przekazywane do TakesCallback funkcji. Dane wyjściowe programu pokazują, że ta funkcja jest wykonywana przez funkcję natywną TakesCallback .
Funkcja zarządzana pomija odzyskiwanie pamięci dla zarządzanego delegata, aby zapobiec przeniesieniu delegata programu .NET Framework podczas wykonywania funkcji natywnej.
// 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);
}
Żadna część biblioteki DLL nie jest uwidaczniona w kodzie zarządzanym przy użyciu tradycyjnej #include dyrektywy. W rzeczywistości biblioteka DLL jest dostępna tylko w czasie wykonywania, więc problemy z funkcjami importowanymi przy użyciu polecenia DllImportAttribute nie mogą być wykrywane w czasie kompilacji.