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
Visszajelzés
https://aka.ms/ContentUserFeedback.
Hamarosan elérhető: 2024-ben fokozatosan kivezetjük a GitHub-problémákat a tartalom visszajelzési mechanizmusaként, és lecseréljük egy új visszajelzési rendszerre. További információ:Visszajelzés küldése és megtekintése a következőhöz: