Передача строк с нулевым символом в конце в неуправляемый код - PullRequest
3 голосов
/ 08 августа 2010

Рассмотрим следующую структуру для отправки по TCP на неуправляемую dll

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct FooMessage
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 42)]
    public string foo;

    //More fields...
}

Используя следующую функцию (кредит Cheeso ):

public byte[] RawSerialize( T item )
{
    int rawSize = Marshal.SizeOf( typeof(T) );
    IntPtr buffer = Marshal.AllocHGlobal( rawSize );
    Marshal.StructureToPtr( item, buffer, false );
    byte[] rawData = new byte[ rawSize ];
    Marshal.Copy( buffer, rawData, 0, rawSize );
    Marshal.FreeHGlobal( buffer );
    return rawData;
}

Проблема: маршаллер предполагает, что foo является строкой с нулевым символом в конце, тогда как неуправляемая dll этого не делает - и фактически использует последний символ (который всегда получается нулевым из маршаллера).* Уточнение : Я не могу просто изменить SizeConst на 43, потому что мне нужно сохранить общий размер сообщения, а также положение следующих полей в структуре (в соответствии с существующим ICD)

Ответы [ 3 ]

2 голосов
/ 17 августа 2010

Так как никакого другого ответа не было опубликовано, вот обходной путь Я нашел

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct FooMessage
{
    // use this for non-null-terminated strings
    // use default encoder to convert to and from string
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=42)]
    public char[] foo;

    //More fields...
}

Также аналогичное решение от эксперта TCP Стивена Клири

1 голос
/ 09 августа 2015

Вы можете использовать StructLayout (LayoutKind.Explicit ...) и пометить каждое поле с помощью [FieldOffset ( n )].Это позволит вам увеличить значение SizeConst до 43, и все же пометить следующее поле как начинающееся со смещением 42. Маршаллер соберет строку из 42 символов и проигнорирует 43-й байт, добавив вместо него нулевой терминатор.

0 голосов
/ 08 августа 2010

У вас есть два и только два варианта:

  1. заставить dll понять о NUL-концевых строках; или
  2. отправить количество символов вместе с сообщением и заставить dll понять это количество.

Один или другой, выбирай.

- b

...