Маршалинг (Marshaling) — это процесс преобразования и передачи данных между различными контекстами выполнения, где эти данные могут иметь разные представления. В .NET это чаще всего относится к:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int MessageBox(
IntPtr hWnd,
[MarshalAs(UnmanagedType.LPTStr)] string text,
[MarshalAs(UnmanagedType.LPTStr)] string caption,
uint type);
// Вызов неуправляемого кода с маршалингом строк
MessageBox(IntPtr.Zero, "Hello World", "Title", 0);
// Маршалинг COM объекта в .NET
[ComImport]
[Guid("000208D5-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IExcelApplication
{
void Quit();
}
// Использование
Type excelType = Type.GetTypeFromProgID("Excel.Application");
dynamic excel = Activator.CreateInstance(excelType);
excel.Quit(); // Маршалинг вызова через RCW
public class MarshalByRefObjectExample : MarshalByRefObject
{
public string GetDomainName() => AppDomain.CurrentDomain.FriendlyName;
}
// В другом домене
var domain = AppDomain.CreateDomain("NewDomain");
var obj = (MarshalByRefObjectExample)domain.CreateInstanceAndUnwrap(
typeof(MarshalByRefObjectExample).Assembly.FullName,
typeof(MarshalByRefObjectExample).FullName);
Console.WriteLine(obj.GetDomainName()); // "NewDomain"
Для типов, имеющих одинаковое представление в управляемой и неуправляемой памяти (int, float, byte и т.д.). Не требует преобразования.
Для сложных типов, требующих преобразования:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct Person
{
[MarshalAs(UnmanagedType.LPWStr)]
public string Name;
public int Age;
}
public class CustomMarshaller : ICustomMarshaler
{
public static ICustomMarshaler GetInstance(string cookie) => new CustomMarshaller();
public void CleanUpManagedData(object ManagedObj) { ... }
public void CleanUpNativeData(IntPtr pNativeData) { ... }
// ... другие методы интерфейса
}
Атрибут | Назначение |
---|---|
[MarshalAs] | Указывает как маршалить параметры |
[StructLayout] | Задает расположение полей структуры |
[DllImport] | Импорт неуправляемых функций |
[In] и [Out] | Направление передачи данных |
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool GetDiskFreeSpaceEx(
string directoryName,
out ulong freeBytesAvailable,
out ulong totalNumberOfBytes,
out ulong totalNumberOfFreeBytes);
// Использование
ulong free, total, totalFree;
GetDiskFreeSpaceEx(@"C:\", out free, out total, out totalFree);
Накладные расходы:
Проблемы памяти:
[In]
/[Out]
может вызвать лишнее копированиеСоветы по оптимизации:
Принцип: "Маршалинг — это мост между мирами, но каждый переход через мост имеет свою цену"