Megosztás a következőn keresztül:


Tömbök alapértelmezett rendezése

A teljes mértékben felügyelt kódból álló alkalmazásokban a közös nyelvi futtatókörnyezet a tömbtípusokat In/Out paraméterként továbbítja. Ezzel szemben az interop marshaller alapértelmezés szerint In paraméterként ad át egy tömböt.

A rögzítés optimalizálásával úgy tűnhet, hogy egy titkos tömb in/out paraméterként működik, amikor ugyanabban a lakásban lévő objektumokkal kommunikál. Ha azonban később exportálja a kódot egy gépközi proxy létrehozásához használt típustárba, és a kódtár a hívások apartmanok közötti átirányítására szolgál, a hívások visszaállhatnak a valós paraméterhasználatra.

A tömbök természet szerint összetettek, és a felügyelt és a nem felügyelt tömbök közötti különbségtételek több információt tesznek szükségessé, mint más nem titkos típusok.

Felügyelt tömbök

A felügyelt tömbtípusok eltérőek lehetnek; az System.Array osztály azonban az összes tömbtípus alaposztálya. A System.Array osztály olyan tulajdonságokkal rendelkezik, amelyek meghatározzák a tömbök rangját, hosszát, alsó és felső határait, valamint a tömbök elérésére, rendezésére, keresésére, másolására és létrehozására szolgáló módszereket.

Ezek a tömbtípusok dinamikusak, és nem rendelkeznek az alaposztálytárban definiált megfelelő statikus típussal. Az elemtípusok és a rangsorolás minden kombinációját érdemes különálló tömbtípusként tekinteni. Ezért az egész számok egydimenziós tömbje más típusú, mint a kettős típusú egydimenziós tömb. Hasonlóképpen, az egész számok kétdimenziós tömbje különbözik az egész számok egydimenziós tömbjától. A tömb határait a rendszer nem veszi figyelembe a típusok összehasonlításakor.

Ahogy az alábbi táblázat is mutatja, a felügyelt tömbök minden példányának adott elemtípusúnak, rangnak és alsó határnak kell lennie.

Felügyelt tömb típusa Elem típusa Helyezés Alsó határ Aláírás jelölése
ELEMENT_TYPE_ARRAY Típus szerint megadva. Rangsor szerint megadva. Ha nem kötelező, a korlátok adhatók meg. típus [ n,m ]
ELEMENT_TYPE_CLASS Ismeretlen Ismeretlen Ismeretlen System.Array
ELEMENT_TYPE_SZARRAY Típus szerint megadva. 0 0 típus [ n ]

Nem felügyelt tömbök

A nem felügyelt tömbök COM-stílusú biztonságos tömbök vagy rögzített vagy változó hosszúságú C típusú tömbök. A biztonságos tömbök önleíró tömbök, amelyek a társított tömbadatok típusát, rangját és határait hordozzák. A C stílusú tömbök egydimenziós típusú tömbök, amelyek rögzített alsó határa 0. A rendezési szolgáltatás korlátozottan támogatja mindkét tömbtípust.

Tömbparaméterek átadása a .NET-kódnak

A C stílusú tömbök és a biztonságos tömbök egyaránt átadhatók a .NET-kódnak nem felügyelt kódból biztonságos tömbként vagy C stílusú tömbként. Az alábbi táblázat a nem felügyelt típus értékét és az importált típust mutatja be.

Nem felügyelt típus Importált típus
SafeArray( Típus ) < ELEMENT_TYPE_SZARRAY ConvertedType >

Rang = 1, alsó határ = 0. A méret csak akkor ismert, ha a felügyelt aláírás tartalmazza. A nem rangsorolt biztonságos tömbök = 1 vagy alacsonyabb kötésű = 0 nem rendezhetők SZARRAY-ként.
Típus [] < ELEMENT_TYPE_SZARRAY ConvertedType >

Rang = 1, alsó határ = 0. A méret csak akkor ismert, ha a felügyelt aláírás tartalmazza.

Biztonságos tömbök

Ha egy biztonságos tömböt importál egy típustárból egy .NET-szerelvénybe, a rendszer egy ismert típusú (például int) egydimenziós tömbté alakítja át a tömböt. A paraméterekre vonatkozó típuskonvertálási szabályok a tömbelemekre is érvényesek. A BSTR-típusok biztonságos tömbje például sztringek felügyelt tömbje lesz, a változatok biztonságos tömbje pedig objektumok felügyelt tömbje lesz. A SAFEARRAY elemtípust a rendszer a típustárból rögzíti, és az enumerálás SAFEARRAY értékében UnmanagedType menti.

Mivel a biztonságos tömb rangja és határai nem határozhatók meg a típustárból, a rangsor értéke 1, az alsó határ pedig 0. A rangot és a határokat a típustár-importáló által létrehozott felügyelt aláírásban (Tlbimp.exe) kell meghatározni. Ha a metódusnak a futtatáskor átadott rangja eltérő, SafeArrayRankMismatchException akkor a lesz a dobás. Ha a futtatási időpontban átadott tömb típusa eltér, a rendszer egy SafeArrayTypeMismatchException értéket ad. Az alábbi példa biztonságos tömböket mutat be felügyelt és nem felügyelt kódban.

Nem felügyelt aláírás

HRESULT New1([in] SAFEARRAY( int ) ar);
HRESULT New2([in] SAFEARRAY( DATE ) ar);
HRESULT New3([in, out] SAFEARRAY( BSTR ) *ar);

Felügyelt aláírás

Sub New1(<MarshalAs(UnmanagedType.SafeArray, SafeArraySubType:=VT_I4)> _
   ar() As Integer)
Sub New2(<MarshalAs(UnmanagedType.SafeArray, SafeArraySubType:=VT_DATE)> _
   ar() As DateTime)
Sub New3(ByRef <MarshalAs(UnmanagedType.SafeArray, SafeArraySubType:=VT_BSTR)> _
   ar() As String)
void New1([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VT_I4)] int[] ar) ;
void New2([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VT_DATE)]
   DateTime[] ar);
void New3([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VT_BSTR)]
   ref String[] ar);

A többdimenziós vagy nem kötött biztonságos tömbök felügyelt kódba rendezhetők, ha a Tlbimp.exe által létrehozott metódus-aláírást úgy módosítják, hogy ELEMENT_TYPE_SZARRAY helyett ELEMENT_TYPE_ARRAY elemtípust jeleznek. A /sysarray kapcsolóval Tlbimp.exe is importálhatja az összes tömböt objektumkéntSystem.Array. Azokban az esetekben, amikor az átadott tömb többdimenziós, szerkesztheti a Tlbimp.exe által létrehozott közös köztes nyelv (CIL) kódot, majd újrafordíthatja azt. A CIL-kód módosításáról további információt a Futtatókörnyezet hívható burkolóinak testreszabása című témakörben talál.

C stílusú tömbök

Amikor egy C stílusú tömböt importál egy típustárból egy .NET-szerelvénybe, a tömb ELEMENT_TYPE_SZARRAY lesz konvertálva.

A tömbelem típusa a típustárból lesz meghatározva, és az importálás során megmarad. A paraméterekre vonatkozó konverziós szabályok a tömbelemekre is érvényesek. Az LPStr-típusok tömbje például sztringtípusok tömbje lesz. Tlbimp.exe rögzíti a tömbelem típusát, és alkalmazza az MarshalAsAttribute attribútumot a paraméterre.

A tömb rangja 1-nek felel meg. Ha a rang nagyobb, mint 1, a tömb egydimenziós tömbként lesz rendezve oszlop-fő sorrendben. Az alsó határ mindig 0.

A típuskódtárak rögzített vagy változó hosszúságú tömböket tartalmazhatnak. Tlbimp.exe csak rögzített hosszúságú tömböket importálhat a típustárakból, mert a típustárak nem rendelkeznek a változó hosszúságú tömbök marshalásához szükséges információkkal. Rögzített hosszúságú tömbök esetén a rendszer importálja a méretet a típustárból, és a paraméterre alkalmazott MarshalAsAttribute fájlban rögzíti.

Manuálisan kell definiálnia a változó hosszúságú tömböket tartalmazó típustárakat, ahogy az az alábbi példában is látható.

Nem felügyelt aláírás

HRESULT New1(int ar[10]);
HRESULT New2(double ar[10][20]);
HRESULT New3(LPWStr ar[10]);

Felügyelt aláírás

Sub New1(<MarshalAs(UnmanagedType.LPArray, SizeConst=10)> _
   ar() As Integer)
Sub New2(<MarshalAs(UnmanagedType.LPArray, SizeConst=200)> _
   ar() As Double)
Sub New2(<MarshalAs(UnmanagedType.LPArray, _
   ArraySubType=UnmanagedType.LPWStr, SizeConst=10)> _
   ar() As String)
void New1([MarshalAs(UnmanagedType.LPArray, SizeConst=10)] int[] ar);
void New2([MarshalAs(UnmanagedType.LPArray, SizeConst=200)] double[] ar);
void New2([MarshalAs(UnmanagedType.LPArray,
   ArraySubType=UnmanagedType.LPWStr, SizeConst=10)] String[] ar);

Bár a size_is vagy length_is attribútumokat alkalmazhatja egy tömbre az Interfészdefiníciós nyelv (IDL) forrásban, hogy a méretet egy ügyfélnek adja át, a Microsoft Interface Definition Language (MIDL) fordítója nem propagálja ezeket az információkat a típustárba. A méret ismerete nélkül az interop-marshalling szolgáltatás nem tudja a tömbelemeket morasztni. Ennek következtében a változó hosszúságú tömbök referenciaargumentumként lesznek importálva. Példa:

Nem felügyelt aláírás

HRESULT New1(int ar[]);
HRESULT New2(int ArSize, [size_is(ArSize)] double ar[]);
HRESULT New3(int ElemCnt, [length_is(ElemCnt)] LPStr ar[]);

Felügyelt aláírás

Sub New1(ByRef ar As Integer)
Sub New2(ByRef ar As Double)
Sub New3(ByRef ar As String)
void New1(ref int ar);
void New2(ref double ar);
void New3(ref String ar);

A rendezőnek megadhatja a tömbméretet a Tlbimp.exe által létrehozott közös köztes nyelv (CIL) kód szerkesztésével, majd újrafordításával. A CIL-kód módosításáról további információt a Futtatókörnyezet hívható burkolóinak testreszabása című témakörben talál. A tömb elemeinek számának jelzéséhez alkalmazza a MarshalAsAttribute típust a felügyelt metódus definíciójának tömbparaméterére az alábbi módok egyikével:

  • Azonosítsa a tömb elemeinek számát tartalmazó másik paramétert. A paramétereket pozíció alapján azonosítjuk, kezdve az első paraméter 0 számmal.

    Sub [New](ElemCnt As Integer, _
       \<MarshalAs(UnmanagedType.LPArray, SizeParamIndex:=1)> _
       ar() As Integer)
    
    void New(
       int ElemCnt,
       [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] int[] ar );
    
  • Adja meg a tömb méretét állandóként. Példa:

    Sub [New](\<MarshalAs(UnmanagedType.LPArray, SizeConst:=128)> _
       ar() As Integer)
    
    void New(
       [MarshalAs(UnmanagedType.LPArray, SizeConst=128)] int[] ar );
    

Ha a tömböket nem felügyelt kódból felügyelt kódba rendezi, a rendező ellenőrzi a paraméterhez társított MarshalAsAttribute paramétert a tömb méretének meghatározásához. Ha a tömbméret nincs megadva, csak egy elem lesz rendezve.

Feljegyzés

A MarshalAsAttribute nincs hatással a felügyelt tömbök nem felügyelt kódra való rendezésére. Ebben az irányban a tömb méretét vizsgálat határozza meg. A felügyelt tömbök egy részhalmazát nem lehet létrehozni.

Az interop marshaller a CoTaskMemAlloc és a CoTaskMemFree metódusokat használja Windows vagy malloc rendszeren, valamint szabad metódusokat más operációs rendszereken a memória lefoglalásához és lekéréséhez. A nem felügyelt kód által végrehajtott memóriafoglalásnak ezeket a módszereket is használnia kell.

Tömbök átadása a COM-nak

Minden felügyelt tömbtípus átadható felügyelt kódból nem felügyelt kódnak. A felügyelt típustól és a rá alkalmazott attribútumoktól függően a tömb biztonságos tömbként vagy C stílusú tömbként is elérhető, ahogyan az alábbi táblázatban látható.

Felügyelt tömb típusa Exportálás másként
< ELEMENT_TYPE_SZARRAY típusa > UnmanagedType. SafeArray( típus )

UnmanagedType.LPArray

A típus az aláírásban van megadva. A rangsor mindig 1, alsó határa mindig 0. A méret mindig ismert futásidőben.
ELEMENT_TYPE_ARRAY típusrang < > > [< határ ] > < UnmanagedType.SafeArray( típus )

UnmanagedType.LPArray

A típus, a rang és a határokat az aláírás adja meg. A méret mindig ismert futásidőben.
ELEMENT_TYPE_CLASS <System.Array> UT_Interface

UnmanagedType.SafeArray( típus )

A típus, a rangsor, a korlátok és a méret mindig ismert futásidőben.

Az OLE Automation az LPSTR-t vagy LPWSTR-t tartalmazó struktúrák tömbjeire vonatkozik. Ezért a sztringmezőket UnmanagedType.BSTR néven kell elrendezni. Ellenkező esetben a rendszer kivételt küld.

ELEMENT_TYPE_SZARRAY

Ha egy ELEMENT_TYPE_SZARRAY paramétert (egydimenziós tömböt) tartalmazó metódust exportál egy .NET-szerelvényből egy típustárba, a tömbparaméter egy adott típusú SAFEARRAY-vá lesz konvertálva. Ugyanezek a konverziós szabályok vonatkoznak a tömbelem-típusokra. A felügyelt tömb tartalma automatikusan át lesz másolva a felügyelt memóriából a SAFEARRAY-ba. Példa:

Felügyelt aláírás

Sub [New](ar() As Long)
Sub [New](ar() As String)
void New(long[] ar );
void New(String[] ar );

Nem felügyelt aláírás

HRESULT New([in] SAFEARRAY( long ) ar);
HRESULT New([in] SAFEARRAY( BSTR ) ar);

A biztonságos tömbök rangsora mindig 1, az alsó határ pedig mindig 0. A méretet futásidőben határozza meg az átadott felügyelt tömb mérete.

A tömb C stílusú tömbként is rendezhető az MarshalAsAttribute attribútum használatával. Példa:

Felügyelt aláírás

Sub [New](<MarshalAs(UnmanagedType.LPArray, SizeParamIndex:=1)> _
   ar() As Long, size as Integer)
Sub [New](<MarshalAs(UnmanagedType.LPArray, SizeParamIndex:=1)> _
   ar() As String, size as Integer)
Sub [New](<MarshalAs(UnmanagedType.LPArray, _
   ArraySubType= UnmanagedType.LPStr, SizeParamIndex:=1)> _
   ar() As String, size as Integer)
void New([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)]
   long [] ar, int size );
void New([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)]
   String [] ar, int size );
void New([MarshalAs(UnmanagedType.LPArray, ArraySubType=
   UnmanagedType.LPStr, SizeParamIndex=1)]
   String [] ar, int size );

Nem felügyelt aláírás

HRESULT New(long ar[]);
HRESULT New(BSTR ar[]);
HRESULT New(LPStr ar[]);

Bár a rendező rendelkezik a tömb marsallásához szükséges hosszinformációval, a tömb hosszát általában külön argumentumként adjuk át a hívásvezetőnek.

ELEMENT_TYPE_ARRAY

Ha egy ELEMENT_TYPE_ARRAY paramétert tartalmazó metódust exportál egy .NET-szerelvényből egy típustárba, a tömbparaméter egy adott típusú SAFEARRAY-vá lesz konvertálva. A felügyelt tömb tartalma automatikusan át lesz másolva a felügyelt memóriából a SAFEARRAY-ba. Példa:

Felügyelt aláírás

Sub [New](ar(,) As Long)
Sub [New](ar(,) As String)
void New( long [,] ar );
void New( String [,] ar );

Nem felügyelt aláírás

HRESULT New([in] SAFEARRAY( long ) ar);
HRESULT New([in] SAFEARRAY( BSTR ) ar);

A biztonságos tömbök rangját, méretét és határait futásidőben a felügyelt tömb jellemzői határozzák meg.

A tömb az attribútum alkalmazásával MarshalAsAttribute C stílusú tömbként is rendezhető. Példa:

Felügyelt aláírás

Sub [New](<MarshalAs(UnmanagedType.LPARRAY, SizeParamIndex:=1)> _
   ar(,) As Long, size As Integer)
Sub [New](<MarshalAs(UnmanagedType.LPARRAY, _
   ArraySubType:=UnmanagedType.LPStr, SizeParamIndex:=1)> _
   ar(,) As String, size As Integer)
void New([MarshalAs(UnmanagedType.LPARRAY, SizeParamIndex=1)]
   long [,] ar, int size );
void New([MarshalAs(UnmanagedType.LPARRAY,
   ArraySubType= UnmanagedType.LPStr, SizeParamIndex=1)]
   String [,] ar, int size );

Nem felügyelt aláírás

HRESULT New(long ar[]);
HRESULT New(LPStr ar[]);

A beágyazott tömbök nem rendezhetők. Az alábbi aláírás például hibát okoz, amikor a típustár-exportőrrel (Tlbexp.exe) exportálja.

Felügyelt aláírás

Sub [New](ar()()() As Long)
void New(long [][][] ar );

<ELEMENT_TYPE_CLASS System.Array>

Ha egy System.Array paramétert tartalmazó metódust egy .NET-szerelvényből egy típustárba exportál, a tömbparaméter _Array felületre lesz konvertálva. A felügyelt tömb tartalma csak a _Array felület metódusain és tulajdonságain keresztül érhető el. A System.Array az attribútum használatával MarshalAsAttribute SAFEARRAY-ként is rendezhető. Ha biztonságos tömbként van rendezve, a rendszer a tömbelemeket variánsokként rendezi. Példa:

Felügyelt aláírás

Sub New1( ar As System.Array )
Sub New2( <MarshalAs(UnmanagedType.SafeArray)> ar As System.Array )
void New1( System.Array ar );
void New2( [MarshalAs(UnmanagedType.SafeArray)] System.Array ar );

Nem felügyelt aláírás

HRESULT New([in] _Array *ar);
HRESULT New([in] SAFEARRAY(VARIANT) ar);

Tömbök a struktúrákon belül

A nem felügyelt struktúrák beágyazott tömböket tartalmazhatnak. Ezek a beágyazott tömbmezők alapértelmezés szerint SAFEARRAY-ként vannak rendezve. Az alábbi példában egy beágyazott tömb van, s1 amely közvetlenül a struktúrán belül van lefoglalva.

Nem felügyelt ábrázolás

struct MyStruct {
    short s1[128];
}

A tömbök rendezhetők úgy, hogy UnmanagedTypea mezőt be kell állítani MarshalAsAttribute . A méret csak állandóként állítható be. Az alábbi kód a megfelelő felügyelt definíciót jeleníti meg MyStruct.

Public Structure <StructLayout(LayoutKind.Sequential)> MyStruct
   Public <MarshalAs(UnmanagedType.ByValArray, SizeConst := 128)> _
     s1() As Short
End Structure
[StructLayout(LayoutKind.Sequential)]
public struct MyStruct {
   [MarshalAs(UnmanagedType.ByValArray, SizeConst=128)] public short[] s1;
}

Lásd még