Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Marshalling , yönetilen ve yerel kod arasında geçiş yapmak gerektiğinde türleri dönüştürme işlemidir.
Yönetilen ve yönetilmeyen koddaki türler farklı olduğundan, marshalling gereklidir. Örneğin, yönetilen kodda string bulunurken, yönetilmeyen dizeler .NET string kodlaması (UTF-16), ANSI Kod Sayfası kodlaması, UTF-8, null ile sonlandırılan, ASCII vb. biçimlerde olabilir. Varsayılan olarak, P/Invoke alt sistemi, bu makalede açıklanan standart davranışa göre doğru olanı yapmaya çalışır. Ancak, ek denetime ihtiyaç duyduğunuz durumlarda, yönetilmeyen tarafta beklenen türü belirtmek için MarshalAs özniteliğini kullanabilirsiniz. Örneğin, dizenin null sonlandırılan UTF-8 dizesi olarak gönderilmesini istiyorsanız, bunu şu şekilde yapabilirsiniz:
[LibraryImport("somenativelibrary.dll")]
static extern int MethodA([MarshalAs(UnmanagedType.LPUTF8Str)] string parameter);
// or
[LibraryImport("somenativelibrary.dll", StringMarshalling = StringMarshalling.Utf8)]
static extern int MethodB(string parameter);
özniteliğini System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute derlemeye uygularsanız, aşağıdaki bölümdeki kurallar geçerli değildir. Bu öznitelik uygulandığında .NET değerlerinin yerel koda nasıl sunulduğu hakkında bilgi için bkz. disabled runtime marshalling.
Ortak türleri sıralamak için varsayılan kurallar
Genellikle çalışma zamanı, sizden en az iş gerektirecek şekilde hazırlama sırasında "doğru şeyi" yapmaya çalışır. Aşağıdaki tablolarda, bir parametre veya alanda kullanıldığında her türün varsayılan olarak nasıl sıralandığı açıklanmaktadır. C99/C++11 sabit genişlikli tamsayı ve karakter türleri, tüm platformlar için aşağıdaki tablonun doğru olduğundan emin olmak için kullanılır. Bu türle aynı hizalama ve boyut gereksinimlerine sahip herhangi bir yerel türü kullanabilirsiniz.
Bu ilk tabloda, hem P/Invoke hem de alan aktarma için aynı olan türlerin eşlemeleri açıklanmaktadır.
Önemli
long kullanan bir C işlevini çağırırken, C# CLong yerine CULong veya long (.NET 6+) kullanın. Önceki .NET sürümleriyle ilgili ayrıntılar ve geçici çözümler için bkz. Cross-platform veri türüyle ilgili önemli noktalar.
Uyarı
wchar_t türü, Windows utf-16 (2 bayt) türüdür, ancak diğer platformlarda (genellikle Linux ve macOS'ta UTF-32 (4 bayt) derleyici olarak tanımlanır. Bu nedenle, wchar_t* tek bir çapraz platform ABI olarak kullanmak zordur. Platformlar arası bir yerel API tasarlarken, char* ile net tanımlanmış bir kodlama sözleşmesini (örneğin, UTF-8) tercih edin yerine wchar_t*.
Uyarı
Yerel char* dizeler, kitaplığın veya platformun tanımladığı kodlamayı kullanır. Bir C işlevini char* çağırdığınızda, UTF-8 için StringMarshalling.Utf8, UTF-16 için StringMarshalling.Utf16 veya diğer kodlamalar için StringMarshalling.Custom gibi doğru dize hazırlama seçeneğini belirleyerek beklenen kodlamayla eşleşmesini sağlayın.
| C# anahtar sözcüğü | .NET Türü | Yerleşik Tip |
|---|---|---|
byte |
System.Byte |
uint8_t |
sbyte |
System.SByte |
int8_t |
short |
System.Int16 |
int16_t |
ushort |
System.UInt16 |
uint16_t |
int |
System.Int32 |
int32_t |
uint |
System.UInt32 |
uint32_t |
long |
System.Int64 |
int64_t |
ulong |
System.UInt64 |
uint64_t |
char |
System.Char |
Ya char ya da char16_t, P/Invoke veya yapısının kodlamasına bağlı olarak.
Karakter kümesi belgelerine bakın. |
System.Char |
Ya char* ya da char16_t*, P/Invoke veya yapısının kodlamasına bağlı olarak.
Karakter kümesi belgelerine bakın. |
|
nint |
System.IntPtr |
intptr_t |
nuint |
System.UIntPtr |
uintptr_t |
.NET İşaretçi türleri (örn. void*) |
void* |
|
System.Runtime.InteropServices.SafeHandle türetilen tür |
void* |
|
System.Runtime.InteropServices.CriticalHandle türetilen tür |
void* |
|
bool |
System.Boolean |
Win32 BOOL türü |
decimal |
System.Decimal |
COM DECIMAL yapısı |
| .NET Temsilcisi | Yerel işlev işaretçisi | |
System.DateTime |
Win32 DATE türü |
|
System.Guid |
Win32 GUID türü |
Parametre veya yapı olarak sıralarsanız, birkaç sıralama kategorisi farklı varsayılan değerlere sahiptir.
| .NET Türü | Özgün Tür (Parametre) | Yerleşik Tip (Alan) |
|---|---|---|
| .NET dizisi | Dizi öğelerinin yerel gösterimleri dizisinin başlangıcına yönelik bir işaretçi. |
[MarshalAs] özniteliği olmadan yasaktır |
LayoutKind, Sequential veya Explicit içeren bir sınıf |
Sınıfın yerel gösterimine bir işaretçi | Sınıfın yerel gösterimi |
Aşağıdaki tabloda yalnızca Windows varsayılan sıralama kuralları yer almaktadır. Windows olmayan platformlarda bu türleri sıralayamazsınız.
| .NET Türü | Özgün Tür (Parametre) | Yerleşik Tip (Alan) |
|---|---|---|
System.Object |
VARIANT |
IUnknown* |
System.Array |
COM arabirimi |
[MarshalAs] özniteliği olmadan yasaktır |
System.ArgIterator |
va_list |
İzin verilmiyor |
System.Collections.IEnumerator |
IEnumVARIANT* |
İzin verilmiyor |
System.Collections.IEnumerable |
IDispatch* |
İzin verilmiyor |
System.DateTimeOffset |
int64_t 1 Ocak 1601 gece yarısından bu yana geçen tik sayısını temsil eder |
int64_t 1 Ocak 1601 gece yarısından bu yana geçen tik sayısını temsil eder |
Bazı türler alan olarak değil yalnızca parametre olarak sıralanabilir. Bu türler aşağıdaki tabloda listelenmiştir:
| .NET Türü | Yerel Tür (Yalnızca Parametre) |
|---|---|
System.Text.StringBuilder |
Ya char* ya da char16_t*, P/Invoke öğesinin CharSet'sine bağlı olarak.
Karakter kümesi belgelerine bakın. |
System.ArgIterator |
va_list (yalnızca Windows x86/x64/arm64 üzerinde) |
System.Runtime.InteropServices.ArrayWithOffset |
void* |
System.Runtime.InteropServices.HandleRef |
void* |
Bu varsayılanlar tam olarak istediğiniz gibi değilse, parametrelerin nasıl hazırlanmasını özelleştirebilirsiniz. Parametre hazırlama makalesi, farklı parametre türlerinin nasıl sıraya eklendiğini özelleştirme konusunda size yol gösterir.
COM senaryolarında varsayılan sıralama
.NET'daki COM nesnelerinde yöntemleri çağırdığınızda, .NET çalışma zamanı varsayılan sıralama kurallarını ortak COM semantiğiyle eşleşecek şekilde değiştirir. Aşağıdaki tabloda, .NET çalışma zamanlarının COM senaryolarında kullandığı kurallar listelanmaktadır:
| .NET Türü | Yerel Tür (COM yöntemi çağrıları) |
|---|---|
System.Boolean |
VARIANT_BOOL |
StringBuilder |
LPWSTR |
System.String |
BSTR |
| Temsilci türleri | .NET Framework'te _Delegate*. .NET Core ve .NET 5+ için izin verilmez. |
System.Drawing.Color |
OLECOLOR |
| .NET dizisi | SAFEARRAY |
System.String[] |
SAFEARRAYların BSTR'ı |
Sınıf ve yapıların eşleştirilmesi
Tür hazırlamanın bir diğer yönü de yapıyı yönetilmeyen bir yönteme geçirmedir. Örneğin, yönetilmeyen yöntemlerden bazıları parametre olarak bir yapı gerektirir. Bu gibi durumlarda, parametre olarak kullanmak için ilgili bir yapı veya dünyanın yönetilen bölümünde bir sınıf oluşturmanız gerekir. Ancak, yalnızca sınıfı tanımlamak yeterli değildir, ayrıca sınıf içindeki alanların yönetilmeyen yapıya nasıl eşlenmesi gerektiğini de belirtmelisiniz.
StructLayout Burada öznitelik yararlı olur.
using System;
using System.Runtime.InteropServices;
Win32Interop.GetSystemTime(out Win32Interop.SystemTime systemTime);
Console.WriteLine(systemTime.Year);
internal static partial class Win32Interop
{
[LibraryImport("kernel32.dll")]
internal static partial void GetSystemTime(out SystemTime systemTime);
[StructLayout(LayoutKind.Sequential)]
internal ref struct SystemTime
{
public ushort Year;
public ushort Month;
public ushort DayOfWeek;
public ushort Day;
public ushort Hour;
public ushort Minute;
public ushort Second;
public ushort Millisecond;
}
}
Önceki kod, GetSystemTime() fonksiyonuna çağrı yapmanın basit bir örneğini gösterir. İlginç olan 13. satırda. özniteliği, sınıfın alanlarının diğer (yönetilmeyen) tarafındaki yapıya sıralı olarak eşlenmesi gerektiğini belirtir. Bu, aşağıdaki örnekte gösterilen yönetilmeyen yapıya karşılık gelmeleri gerektiğinden, alanların adlandırılmasının önemli olmadığı, yalnızca sıralarının önemli olduğu anlamına gelir:
typedef struct _SYSTEMTIME {
WORD wYear;
WORD wMonth;
WORD wDayOfWeek;
WORD wDay;
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;
Bazen yapınız için varsayılan sıralama, ihtiyacınız olanı yapmaz. Yapıyı özelleştirme marshalling makalesi, yapınızın nasıl düzenlendiğini özelleştirmeyi öğretir.