Das represent_as-Attribut
Mit dem Attribut [ represent_as] können Sie angeben, wie ein bestimmter übertragbarer Datentyp für die Anwendung dargestellt wird. Hierzu geben Sie den Namen des dargestellten Typs für einen bekannten übertragungsfähigen Typ an und geben die Konvertierungsroutinen an. Sie müssen auch die Routinen bereitstellen, um den von den Datentypobjekten verwendeten Arbeitsspeicher freizugeben.
Verwenden Sie das [represent_as] -Attribut, um eine Anwendung mit einem anderen, möglicherweise nicht übertragbaren Datentyp anstelle des Typs darzustellen, der tatsächlich zwischen Client und Server übertragen wird. Es ist auch möglich, dass der von der Anwendung bearbeitete Typ zum Zeitpunkt der MIDL-Kompilierung unbekannt ist. Wenn Sie einen klar definierten übertragungsfähigen Typ auswählen, müssen Sie sich keine Gedanken über die Datendarstellung in der heterogenen Umgebung machen. Das Attribut [represent_as] kann Ihre Anwendung effizienter gestalten, indem die Menge der über das Netzwerk übertragenen Daten verringert wird.
Das Attribut [represent_as] ähnelt dem Attribut [ transmit_as]. Während Sie mit [transmit_as] jedoch einen Datentyp angeben können, der für die Übertragung verwendet wird, können Sie mit [represent_as] angeben, wie ein Datentyp für die Anwendung dargestellt wird. Der dargestellte Typ muss nicht in den von MIDL verarbeiteten Dateien definiert werden. Sie kann zu dem Zeitpunkt definiert werden, zu dem die Stubs mit dem C-Compiler kompiliert werden. Verwenden Sie dazu die include-Anweisung in der Anwendungskonfigurationsdatei (Application Configuration File, ACF), um die entsprechende Headerdatei zu kompilieren. Der folgende ACF definiert beispielsweise einen lokalen Typ für die Anwendung repr_type für den übertragungsfähigen Typ named_type:
typedef [represent_as(repr_type) [, type_attribute_list] named_type;
In der folgenden Tabelle werden die vier von Programmierern bereitgestellten Routinen beschrieben.
-Routine zurückgegebener Wert | BESCHREIBUNG |
---|---|
named_type_from_local | Weist eine instance des Netzwerktyps zu und konvertiert vom lokalen Typ in den Netzwerktyp. |
named_type_to_local | Konvertiert vom Netzwerktyp in den lokalen Typ. |
named_type_free_local | Gibt Arbeitsspeicher frei, der durch einen Aufruf der named_type_to_local Routine zugewiesen wurde, aber nicht den Typ selbst. |
named_type_free_inst | Gibt Speicher für den Netzwerktyp (beidseitig) frei. |
Abgesehen von diesen vier von Programmierern bereitgestellten Routinen wird der benannte Typ nicht von der Anwendung bearbeitet. Der einzige für die Anwendung sichtbare Typ ist der dargestellte Typ. Die Anwendung verwendet den dargestellten Typnamen anstelle des übertragenen Typnamens in den vom Compiler generierten Prototypen und Stubs. Sie müssen die Routinen für beide Seiten bereitstellen.
Bei temporären named_type-Objekten ruft der Stub named_type_free_inst auf, um den durch einen Aufruf von named_type_from_local zugewiesenen Arbeitsspeicher freizugeben.
Wenn der dargestellte Typ ein Zeiger ist oder einen Zeiger enthält, muss die named_type_to_local Routine Speicher für die Daten zuweisen, auf die die Zeiger zeigen (das dargestellte Typobjekt selbst wird vom Stub auf die übliche Weise bearbeitet). Bei Parametern [ out] und [ in, out] eines Typs, die [represent_as oder eine seiner Komponenten enthalten, wird die named_type_free_local Routine automatisch für die Datenobjekte aufgerufen, die das Attribut enthalten. Bei [in] -Parametern wird die named_type_free_local-Routine nur aufgerufen, wenn das [represent_as] -Attribut auf den Parameter angewendet wurde. Wenn das Attribut auf die Komponenten des Parameters angewendet wurde, wird die *_free_local Routine nicht aufgerufen. Freigaberoutinen werden nicht für die eingebetteten Daten und für den höchsten Einmalaufruf (bezogen auf das Attribut der obersten Ebene) für einen [in] -Parameter aufgerufen.
Hinweis
Es ist möglich, sowohl die Attribute [transmit_as] als auch [represent_as] auf denselben Typ anzuwenden. Beim Marshallen von Daten wird zuerst die [represent_as] -Typkonvertierung und dann die [transmit_as] Konvertierung angewendet. Die Reihenfolge wird umgekehrt, wenn die Datenmarmarsierung aufgehoben wird. Daher weist *_from_local beim Marshallen eine instance eines benannten Typs zu und übersetzt sie von einem lokalen Typobjekt in das temporäre benannte Typobjekt. Dieses Objekt ist das angezeigte Typobjekt, das für die *_to_xmit-Routine verwendet wird. Die *_to_xmit-Routine weist dann ein übertragenes Typobjekt zu und übersetzt es aus dem präsentierten (benannten) Objekt in das übertragene Objekt.
Ein Array von langen ganzen Zahlen kann verwendet werden, um eine verknüpfte Liste darzustellen. Auf diese Weise bearbeitet die Anwendung die Liste, und die Übertragung verwendet ein Array von langen ganzen Zahlen, wenn eine Liste dieses Typs übertragen wird. Sie können mit einem Array beginnen, aber die Verwendung eines Konstrukts mit einem offenen Array mit langen ganzen Zahlen ist bequemer. Das folgende Beispiel zeigt die erforderliche Vorgehensweise.
/* IDL definitions */
typedef struct_lbox
{
long data;
struct_lbox * pNext;
} LOC_BOX, * PLOC_BOX;
/* The definition of the local type visible to the application,
as shown above, can be omitted in the IDL file. See the include
in the ACF file. */
typedef struct_xmit_lbox
{
short Size;
[size_is(Size)] long DaraArr[];
} LONGARR;
void WireTheList( [in,out] LONGARR * pData );
/* ACF definitions */
/* If the IDL file does not have a definition for PLOC_BOX, you
can still ready it for C compilation with the following include
statement (notice that this is not a C include):
include "local.h";*/
typedef [represent_as(PLOC_BOX)] LONGARR;
Beachten Sie, dass die Prototypen der Routinen, die den LONGARR-Typ verwenden, tatsächlich in den Stub.h-Dateien als PLOC_BOX anstelle des LONGARR-Typs angezeigt werden. Das gleiche gilt für die entsprechenden Stubs in der Datei Stub_c.c.
Sie müssen die folgenden vier Funktionen bereitstellen:
void __RPC_USER
LONGARR_from_local(
PLOC_BOX __RPC_FAR * pList,
LONGARR __RPC_FAR * _RPC_FAR * ppDataArr );
void __RPC_USER
LONGARR_to_local(
LONGARR __RPC_FAR * _RPC_FAR * ppDataArr,
PLOC_BOX __RPC_FAR * pList );
void __RPC_USER
LONGARR_free_inst(
LONGARR __RPC_FAR * pDataArr);
void __RPC_USER
LONGARR_free_local(
PLOC_BOX __RPC_FAR * pList );
Die oben gezeigten Routinen führen folgendes aus:
- Die LONGARR_from_local Routine zählt die Knoten der Liste, weist ein LONGARR-Objekt mit der Sizeof(LONGARR) + Count*sizeof(long) zu, legt das Feld Size auf Count fest und kopiert die Daten in das DataArr-Feld .
- Die LONGARR_to_local Routine erstellt eine Liste mit Größenknoten und überträgt das Array an die entsprechenden Knoten.
- Die LONGARR_free_inst Routine gibt in diesem Fall nichts frei.
- Die LONGARR_free_local Routine gibt alle Knoten der Liste frei.