Beispiel für Plattformaufrufwrapper
Aktualisiert: November 2007
Wenn eine Struktur einfache Typen enthält, kann sie an eine systemeigene Funktion übergeben werden. Die systemeigene Routine muss der Art und Weise entsprechen, in der die Struktur in .NET Compact Framework gepackt wird.
Betrachten wir eine systemeigene Funktion mit dem Namen DoRequest, die als einzigen Parameter einen Zeiger auf eine Struktur übernimmt. Die Struktur definiert zwei Felder:
ein Zeichenarray, das eine ANSI-Zeichenfolge mit NULL-Terminator enthält
Eine ganze Zahl.
Es folgt die Struktur in C++:
typedef struct
{
char *RequestName,
int Count,
} ALERT_REQUEST;
int DoAlertRequest(ALERT_REQUEST *pRequest);
So sieht die entsprechende verwaltete Version in C# aus:
struct AlertRequest
{
String RequestName;
int Count;
}
class AlertClass
{
[DLLImport("ALERT.DLL", EntryPoint="DoAlertRequest",
CharSet=CharacterSet.Ansi)]
public static extern int DoRequest(ref AlertRequest Req);
}
Das DllImportAttribute-Attribut versieht die Metadaten des systemeigenen Methodenaufrufs mit Anmerkungen. Es informiert die Common Language Runtime darüber, dass die DoRequest-Methode sich in Alert.dll befindet und der Name der Methode DoAllertRequest lautet, und weist sie an, die Zeichenfolgen in ANSI zu marshallen, da alle Zeichenfolgen im verwalteten Code Unicode-Zeichenfolgen sind.
Ein Aufruf dieser Methode in C++ in .NET Framework könnte wie folgt aussehen:
AlertRequest Request = new AlertRequest()
Request.RequestName = "beep";
Request.Count = 10;
AlertClass.DoRequest(ref Request);
Wenn die Common Language Runtime von .NET Framework auf den DoRequest-Aufruf stößt, lädt sie dynamisch, ruft die Adresse von DoAlertRequest ab, erstellt je nach Bedarf eine nicht verwaltete Version der Struktur für die Konvertierung von Zeichenfolgen, platziert einen Zeiger in dieser Struktur und ruft DoAlertRequest auf. Der Zeiger kann nicht einfach an die Struktur übergeben werden, weil sie ein eingebettetes String-Objekt enthält.
Aufgrund dieser Einschränkungen kann die systemeigene DoRequest-Methode nicht direkt aufgerufen werden. Stattdessen muss ein zwischengeschalteter Thunk-Aufruf DoRequest einschließen. Der folgende C#-Code veranschaulicht dies:
class AlertClass
{
[DllImport("ALERT.DLL", EntryPoint="DoAlertRequestThunk")]
private static extern int DoRequestThunk(String RequestName, int Count);
public static int DoRequest(ref AlertRequst Req)
{
return DoRequestThunk(Req.RequestName, Req.Count);
}
}
AlertClass enthält noch immer eine Methode mit der gleichen Signatur wie ihr Gegenstück in .NET Framework. DoRequest in .NET Compact Framework ist eine verwaltete Routine, die eine private systemeigene Routine aufruft. Beachten Sie, dass die Felder der Struktur in separate Argumente in dem Aufruf der systemeigenen Routine aufgeteilt wurden, da das String-Objekt in der Struktur nicht gemarshallt werden würde. Der Thunk umschließt die systemeigene DoRequest-Methode. Er erstellt eine nicht verwaltete Version der Struktur und führt die Zeichenfolgenkonvertierung aus, wie hier in C++ angegeben:
int DoRequestThunk(wchar_t *RequestNameW, int Count)
{
ALERT_REQUEST Req;
int ReturnCode;
// CreateAnsiFromUnicodeString allocates and builds an ANSI
// version of the Unicode string.
Req.RequestName = CreateAnsiFromUnicodeString(RequestNameW);
if (Req.RequestName == NULL)
Return 0;
Req.Count = Count;
// This is the native DoRequest, not to be confused
// with the managed method of the same name.
ReturnCode = DoAlertRequest(&Req);
free(Req.RequestName)
return ReturnCode;
}