В чем разница в маршалинге между Windows и Linux для .NET Core? - PullRequest
1 голос
/ 24 сентября 2019

Я пытаюсь перенести существующую библиотеку в .NET Core, чтобы иметь возможность запустить ее под Linux.

При использовании библиотеки в Linux среда выполнения выдает System.ArgumentException:

Произошло необработанное исключение типа «System.ArgumentException» в ConsoleApp6.dll: «Тип« ConsoleApp6.MyStruct »нельзя маршалировать как неуправляемую структуру;невозможно вычислить значимый размер или смещение. '

Трассировка стека: в System.Runtime.InteropServices.Marshal.OffsetOfHelper (IRuntimeFieldInfo f) в ConsoleApp6.Program.Main (String [] args) в C: \ Users\ user \ source \ repos \ ConsoleApp6 \ ConsoleApp6 \ Program.cs: строка 10

В Windows все работает как положено.Вот простое консольное приложение, которое демонстрирует проблему:

using System;
using System.Runtime.InteropServices;

namespace ConsoleApp6
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine((Int32) Marshal.OffsetOf<MyStruct>("buffer"));
            Console.ReadLine();
        }
    }

    [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)]
    public struct MyStruct
    {

        public Int16 number;

        public byte[] buffer;
    }
}

Вот файл csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.2</TargetFramework>
    <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.7.12" />
  </ItemGroup>

</Project>

Я ожидаю, что на выходе будет 4 в Windows и Linux, но вЛинукс выдает вышеприведенное исключение.

1 Ответ

0 голосов
/ 24 сентября 2019

В .NET Core нельзя использовать OffsetOf<T>, для документов :

OffsetOf(Type, String)
Возвращает смещение поля неуправляемой формыуправляемого класса.

OffsetOf<T>(String) [Поддерживается в .NET Framework 4.5.1 и более поздних версиях]

Возвращает смещение поля неуправляемой формы указанного управляемого класса.

Для того, чтобы ваш код работал в Linux, вам нужно вместо этого использовать перегрузку OffsetOf(Type, String).

Console.WriteLine((Int32) Marshal.OffsetOf(typeof(MyStruct),"buffer"));

Я углубился в CLRисходный код ;и нет очевидной причины, по которой ваш код не должен работать в Linux.Его определяющей характеристикой является Marshalable, и я вижу, является ли он Интерфейсом.

Я собираюсь копнуть глубже - я вижу исходный код в папке vm;но я бы также ожидал увидеть исходный код имплементации для каждой целевой среды, и я этого не вижу.

...