Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Mind a System.String, mind a System.Text.StringBuilder osztályok hasonló rendezési viselkedést mutatnak.
A sztringek COM-stílusú BSTR típusként vagy null értékű karakterláncként vannak rendezve (null karakterrel végződő karaktertömb). A sztringen belüli karakterek Unicode -ként (windowsos rendszereken alapértelmezett) vagy ANSI-ként rendezhetők.
Interfészekben használt karakterláncok
Az alábbi táblázat bemutatja a sztring adattípusának átadási módszereit, amikor metódusargumentumként kerül átadásra a nem felügyelt kódhoz. Az MarshalAsAttribute attribútum több UnmanagedType felsorolt értéket kínál a karakterláncok COM-felületekhez való marshalolásához.
| Számbavétel típusa | A nem felügyelt formátum leírása |
|---|---|
UnmanagedType.BStr (alapértelmezett) |
COM-stílusú BSTR , előtaggal ellátott hosszúságú és Unicode-karakterekkel. |
UnmanagedType.LPStr |
Egy nullával lezárt ANSI karaktereket tartalmazó tömbre mutató mutató. |
UnmanagedType.LPWStr |
Nullával lezárt Unicode karakterek tömbjének mutatója. |
Ez a tábla a következőkre Stringvonatkozik: . Ebben StringBuilderaz esetben csak a következő lehetőségek engedélyezettek UnmanagedType.LPStr : és UnmanagedType.LPWStr.
Az alábbi példa a IStringWorker felületen deklarált sztringeket mutatja be.
public interface IStringWorker
{
void PassString1(string s);
void PassString2([MarshalAs(UnmanagedType.BStr)] string s);
void PassString3([MarshalAs(UnmanagedType.LPStr)] string s);
void PassString4([MarshalAs(UnmanagedType.LPWStr)] string s);
void PassStringRef1(ref string s);
void PassStringRef2([MarshalAs(UnmanagedType.BStr)] ref string s);
void PassStringRef3([MarshalAs(UnmanagedType.LPStr)] ref string s);
void PassStringRef4([MarshalAs(UnmanagedType.LPWStr)] ref string s);
}
Public Interface IStringWorker
Sub PassString1(s As String)
Sub PassString2(<MarshalAs(UnmanagedType.BStr)> s As String)
Sub PassString3(<MarshalAs(UnmanagedType.LPStr)> s As String)
Sub PassString4(<MarshalAs(UnmanagedType.LPWStr)> s As String)
Sub PassStringRef1(ByRef s As String)
Sub PassStringRef2(<MarshalAs(UnmanagedType.BStr)> ByRef s As String)
Sub PassStringRef3(<MarshalAs(UnmanagedType.LPStr)> ByRef s As String)
Sub PassStringRef4(<MarshalAs(UnmanagedType.LPWStr)> ByRef s As String)
End Interface
Az alábbi példa egy típustárban leírt megfelelő felületet mutatja be.
interface IStringWorker : IDispatch
{
HRESULT PassString1([in] BSTR s);
HRESULT PassString2([in] BSTR s);
HRESULT PassString3([in] LPStr s);
HRESULT PassString4([in] LPWStr s);
HRESULT PassStringRef1([in, out] BSTR *s);
HRESULT PassStringRef2([in, out] BSTR *s);
HRESULT PassStringRef3([in, out] LPStr *s);
HRESULT PassStringRef4([in, out] LPWStr *s);
};
A platformhívásban használt karakterláncok
Ha a CharSet Unicode, vagy egy karakterlánc-argumentumot explicit módon [MarshalAs(UnmanagedType.LPWSTR)] jelöléssel láttak el, és a karakterláncot érték szerint adják át (nem ref és nem out), a karakterlánc rögzítve lesz, és közvetlenül a natív kód használja fel. Ellenkező esetben a Platform Invoke másolja a sztringargumentumokat, és a .NET-keretrendszer formátumából (Unicode) konvertálja a platform nem felügyelt formátumára. A sztringek nem módosíthatók, és nem lesznek visszamásolva a nem felügyelt memóriából a felügyelt memóriába a hívás visszatérésekor.
A natív kód csak akkor adja ki a memóriát, ha a sztringet hivatkozással adja át, és új értéket rendel hozzá. Ellenkező esetben a .NET-futtatókörnyezet a memória tulajdonosa, és a hívás után felszabadítja azt.
Az alábbi táblázat felsorolja a sztringek kiküldési opcióit, amikor platformhívás metódusargumentumaként kiküldésre kerülnek. Az MarshalAsAttribute attribútum számos UnmanagedType enumerálási értéket biztosít a marshal sztringekhez.
| Számbavétel típusa | A nem felügyelt formátum leírása |
|---|---|
UnmanagedType.AnsiBStr |
COM-formátumú BSTR hosszelőtaggal és ANSI-karakterekkel. |
UnmanagedType.BStr |
COM-stílusú BSTR , előtaggal ellátott hosszúságú és Unicode-karakterekkel. |
UnmanagedType.LPStr (alapértelmezett) |
Egy nullával lezárt ANSI karaktereket tartalmazó tömbre mutató mutató. |
UnmanagedType.LPTStr |
Egy mutató, amely egy platformfüggő karaktereket tartalmazó, nullával lezárt tömbre mutat. |
UnmanagedType.LPUTF8Str |
Az UTF-8 kódolású karakterek nullával lezárt tömbjére mutató mutató. |
UnmanagedType.LPWStr |
Nullával lezárt Unicode karakterek tömbjének mutatója. |
UnmanagedType.TBStr |
COM-stílus BSTR előtaggal és platformfüggetlen karakterekkel. |
VBByRefStr |
Olyan érték, amely lehetővé teszi, hogy a Visual Basic módosítson egy sztringet nem felügyelt kódban, és hogy az eredmények megjelenjenek a felügyelt kódban. Ez az érték csak platformhívás esetén támogatott. Ez az alapértelmezett érték a Visual Basicben a ByVal sztringekhez. |
Ez a tábla a következőkre Stringvonatkozik: . Az StringBuilder esetében az egyetlen megengedett lehetőségek az LPStr, LPTStr és LPWStr.
Az alábbi típusdefiníció a platformhívási MarshalAsAttribute hívások helyes használatát mutatja.
class StringLibAPI
{
[DllImport("StringLib.dll")]
public static extern void PassLPStr([MarshalAs(UnmanagedType.LPStr)] string s);
[DllImport("StringLib.dll")]
public static extern void PassLPWStr([MarshalAs(UnmanagedType.LPWStr)] string s);
[DllImport("StringLib.dll")]
public static extern void PassLPTStr([MarshalAs(UnmanagedType.LPTStr)] string s);
[DllImport("StringLib.dll")]
public static extern void PassLPUTF8Str([MarshalAs(UnmanagedType.LPUTF8Str)] string s);
[DllImport("StringLib.dll")]
public static extern void PassBStr([MarshalAs(UnmanagedType.BStr)] string s);
[DllImport("StringLib.dll")]
public static extern void PassAnsiBStr([MarshalAs(UnmanagedType.AnsiBStr)] string s);
[DllImport("StringLib.dll")]
public static extern void PassTBStr([MarshalAs(UnmanagedType.TBStr)] string s);
}
Class StringLibAPI
Public Declare Auto Sub PassLPStr Lib "StringLib.dll" (
<MarshalAs(UnmanagedType.LPStr)> s As String)
Public Declare Auto Sub PassLPWStr Lib "StringLib.dll" (
<MarshalAs(UnmanagedType.LPWStr)> s As String)
Public Declare Auto Sub PassLPTStr Lib "StringLib.dll" (
<MarshalAs(UnmanagedType.LPTStr)> s As String)
Public Declare Auto Sub PassLPUTF8Str Lib "StringLib.dll" (
<MarshalAs(UnmanagedType.LPUTF8Str)> s As String)
Public Declare Auto Sub PassBStr Lib "StringLib.dll" (
<MarshalAs(UnmanagedType.BStr)> s As String)
Public Declare Auto Sub PassAnsiBStr Lib "StringLib.dll" (
<MarshalAs(UnmanagedType.AnsiBStr)> s As String)
Public Declare Auto Sub PassTBStr Lib "StringLib.dll" (
<MarshalAs(UnmanagedType.TBStr)> s As String)
End Class
Struktúrákban használt karakterláncok
A sztringek a struktúrák érvényes tagjai; a StringBuilder pufferek azonban érvénytelenek a struktúrákban. Az alábbi táblázat az String adattípus csatornázási lehetőségeit mutatja be, amikor a típus mezőként van csatornázva. Az MarshalAsAttribute attribútum számos UnmanagedType enumerálási értéket biztosít karakterláncok mezőhöz való csatolásához.
| Számbavétel típusa | A nem felügyelt formátum leírása |
|---|---|
UnmanagedType.BStr |
COM-stílusú BSTR , előtaggal ellátott hosszúságú és Unicode-karakterekkel. |
UnmanagedType.LPStr (alapértelmezett) |
Egy nullával lezárt ANSI karaktereket tartalmazó tömbre mutató mutató. |
UnmanagedType.LPTStr |
Egy mutató, amely egy platformfüggő karaktereket tartalmazó, nullával lezárt tömbre mutat. |
UnmanagedType.LPUTF8Str |
Az UTF-8 kódolású karakterek nullával lezárt tömbjére mutató mutató. |
UnmanagedType.LPWStr |
Nullával lezárt Unicode karakterek tömbjének mutatója. |
UnmanagedType.ByValTStr |
Rögzített hosszúságú karaktertömb; a tömb típusát az azt tartalmazó struktúra karakterkészlete határozza meg. |
A ByValTStr típus beágyazott, rögzített hosszúságú karaktertömbökhöz használatos, amelyek egy struktúrában jelennek meg. Más típusok a sztringekre mutató mutatókat tartalmazó struktúrákban található sztringhivatkozásokra vonatkoznak.
A CharSet szerkezet alapján alkalmazott StructLayoutAttribute argumentum határozza meg a struktúrák sztringjeinek karakterformátumát. Az alábbi példastruktúrák sztringhivatkozásokat és beágyazott sztringeket, valamint ANSI-, Unicode- és platformfüggő karaktereket tartalmaznak. Ezeknek a struktúráknak a típustárban való ábrázolása a következő C++ kódban jelenik meg:
struct StringInfoA
{
char * f1;
char f2[256];
};
struct StringInfoW
{
WCHAR * f1;
WCHAR f2[256];
BSTR f3;
};
struct StringInfoT
{
TCHAR * f1;
TCHAR f2[256];
};
Az alábbi példa bemutatja, hogyan definiálhatja ugyanazt a MarshalAsAttribute struktúrát különböző formátumokban.
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
struct StringInfoA
{
[MarshalAs(UnmanagedType.LPStr)] public string f1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string f2;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct StringInfoW
{
[MarshalAs(UnmanagedType.LPWStr)] public string f1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string f2;
[MarshalAs(UnmanagedType.BStr)] public string f3;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct StringInfoT
{
[MarshalAs(UnmanagedType.LPTStr)] public string f1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string f2;
}
<StructLayout(LayoutKind.Sequential, CharSet := CharSet.Ansi)> _
Structure StringInfoA
<MarshalAs(UnmanagedType.LPStr)> Public f1 As String
<MarshalAs(UnmanagedType.ByValTStr, SizeConst := 256)> _
Public f2 As String
End Structure
<StructLayout(LayoutKind.Sequential, CharSet := CharSet.Unicode)> _
Structure StringInfoW
<MarshalAs(UnmanagedType.LPWStr)> Public f1 As String
<MarshalAs(UnmanagedType.ByValTStr, SizeConst := 256)> _
Public f2 As String
<MarshalAs(UnmanagedType.BStr)> Public f3 As String
End Structure
<StructLayout(LayoutKind.Sequential, CharSet := CharSet.Auto)> _
Structure StringInfoT
<MarshalAs(UnmanagedType.LPTStr)> Public f1 As String
<MarshalAs(UnmanagedType.ByValTStr, SizeConst := 256)> _
Public f2 As String
End Structure
Rögzített hosszúságú karakterláncpufferek
Bizonyos körülmények között a rögzített hosszúságú karakterpuffert nem felügyelt kódba kell továbbítani a manipuláláshoz. A sztringek egyszerű átadása ebben az esetben nem működik, mert a hívó nem tudja módosítani az átadott puffer tartalmát. Még akkor sem inicializálhatja a puffert egy adott méretre, ha a sztringet hivatkozással továbbítja.
A megoldás az, hogy a várt kódolástól függően egy byte[] vagy char[] argumentumot adunk át ahelyett, hogy egy String. A tömb, ha [Out]-val meg van jelölve, a hívott fél megtekintheti és módosíthatja, feltéve, hogy az nem haladja meg a lefoglalt tömb kapacitását.
A (GetWindowText nyelven definiált) Windows API-függvény például megköveteli, hogy a hívó egy rögzített hosszúságú karakterpuffert adjon át, amelybe a függvény az ablak szövegét írja. Az lpString argumentum egy hívó által lefoglalt méretű nMaxCountpufferre mutat. A hívó várhatóan lefoglalja a puffert, és az nMaxCount argumentumot a lefoglalt puffer méretére állítja. Az alábbi példa a GetWindowTextwinuser.h fájlban definiált függvénydeklarációt mutatja be.
int GetWindowText(
HWND hWnd, // Handle to window or control.
LPTStr lpString, // Text buffer.
int nMaxCount // Maximum number of characters to copy.
);
Az A-t char[] a hívó elhalaszthatja és módosíthatja. Az alábbi példakód bemutatja, hogyan lehet egy ArrayPool<char>-t előre lefoglalni a char[] segítségével.
using System;
using System.Buffers;
using System.Runtime.InteropServices;
internal static class NativeMethods
{
[DllImport("User32.dll", CharSet = CharSet.Unicode)]
public static extern void GetWindowText(IntPtr hWnd, [Out] char[] lpString, int nMaxCount);
}
public class Window
{
internal IntPtr h; // Internal handle to Window.
public string GetText()
{
char[] buffer = ArrayPool<char>.Shared.Rent(256 + 1);
NativeMethods.GetWindowText(h, buffer, buffer.Length);
return new string(buffer);
}
}
Imports System
Imports System.Buffers
Imports System.Runtime.InteropServices
Friend Class NativeMethods
Public Declare Auto Sub GetWindowText Lib "User32.dll" _
(hWnd As IntPtr, <Out> lpString() As Char, nMaxCount As Integer)
End Class
Public Class Window
Friend h As IntPtr ' Friend handle to Window.
Public Function GetText() As String
Dim buffer() As Char = ArrayPool(Of Char).Shared.Rent(256 + 1)
NativeMethods.GetWindowText(h, buffer, buffer.Length)
Return New String(buffer)
End Function
End Class
Egy másik megoldás az, hogy egy StringBuilder-t ad meg argumentumként, ahelyett, hogy egy String-t. A StringBuilder szerializáláskor létrehozott puffert a fogadó visszakeresheti és módosíthatja, feltéve, hogy az nem haladja meg a StringBuilder kapacitását. Rögzített hosszúságúra is inicializálható. Például, ha inicializál egy StringBuilder puffert N kapacitásra, a kiosztó egy (N+1) karakter hosszúságú puffert biztosít. A +1 azért van, mert a nem felügyelt karakterlánc null terminátort tartalmaz, miközben StringBuilder nem.
Megjegyzés:
Általában nem ajánlott StringBuilder argumentumok átadása, ha aggódik a teljesítmény miatt. További információ: Sztringparaméterek.