Ошибка C #: нельзя использовать буферы фиксированного размера, содержащиеся в нефиксированных выражениях - PullRequest
0 голосов
/ 30 июня 2011

Я борюсь с программой на C # для чтения двоичных записей из базы данных. Записи были созданы с Borland Delphi. Вот пример:

// Delphi record definition
  tBowler_Rec = Record
  public
    gender          : tGender;
    bowler_num      : byte;
    name            : tString32;
    initials        : String[3];
    ...
// Corresponding C# definition (unmanaged code)
    [StructLayout(LayoutKind.Sequential, Pack=4)]
    public unsafe struct tBowler_Rec
    {
        public tGender gender;
        public byte bowler_num;
        public fixed byte name[32];
        public fixed byte initials[3];
        ...

Я действительно могу прочитать эту двоичную структуру из базы данных SQL Server и увидеть данные в отладчике Visual Studio. Ура! Я могу получить доступ к таким полям, как "пол" и "Bowler_num" без проблем. Ура!

В: Как мне превратить «имя» в строку C #?

Пример имени "ЭШТОН". В памяти это выглядит так:

\0x6ASHTON\0x0\0x0...

Вот как я пытаюсь получить к нему доступ:


[StructLayout(LayoutKind.Sequential, Pack=4)]
public unsafe struct tBowler_Rec
{
    public tGender gender;
    public byte bowler_num;
    public fixed byte name[32];
    ...
    public string Name
    {
        get
        {
            StringBuilder sb = new StringBuilder();
            int ilen = name[0];
            for (int i = 1; i <= ilen; i++)
                sb.Append(name[i]);
            return sb.ToString();
        }
    }

Я получаю эту ошибку:

Ошибка: нельзя использовать буферы фиксированного размера, содержащиеся в незафиксированном выражения. Попробуйте использовать фиксированный оператор.

Помощь ?????

Заранее спасибо!

Ответы [ 4 ]

2 голосов
/ 30 июня 2011

Попробуйте

Encoding.ASCII.GetString(name, 1, name[0]);
2 голосов
/ 30 июня 2011

Поскольку я не очень знаком с Delphi, я не могу дать вам прямой ответ в поле tString32.Кажется, это UnmanagedType.AnsiBStr .

Если это так, я бы пошел на что-то вроде этого:

[StructLayout(LayoutKind.Sequential, Pack=4)]
public struct tBowler_Rec
{
    public tGender gender;
    public byte bowler_num;
    [MarshalAs(UnmanagedType.AnsiBStr)]
    public string name;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    public char[] initials;

Посмотрите также, как я делаюinitials маршалинг.Если tString не является AnsiBStr, это был бы лучший способ упорядочить символы из имени.

Я также хотел бы показать, что я удалил фиксированные и небезопасные инструкции из объявления структуры, поскольку это не так.необходимо для того, что вы пытаетесь сделать.

1 голос
/ 30 июня 2011

Строка, сохраненная в исходном формате, не имеет нулевого завершения (строка в стиле C).

Первоначальный формат: «количество символов». Затем число символов => 0x6 = количество символов, A = 0 S = 1 H = 2 T = 3 O = 4 N = 5.

читать символы, пока не встретится нулевой символ.Но нет нулевого символа, это не завершенная нулем строка.Для этого вам нужно установить кастомизатор данных или конвертировать базу данных.

0 голосов
/ 30 июня 2011

Я нашел ответ здесь: Буфер фиксированного размера нельзя напрямую использовать из объекта "this"

Решение: [StructLayout(LayoutKind.Sequential, Pack=4)] public unsafe struct tBowler_Rec { public tGender gender; public byte bowler_num; [MarshalAs(UnmanagedType.ByValArray, SizeConst=32)] public byte[] name; ... public string Name { get { StringBuilder sb = new StringBuilder(); int ilen = name[0]; for (int i = 1; i <= ilen; i++) sb.Append(name[i]); return sb.ToString(); } }

Владимир был на правильном пути: фундаментальная проблема заключалась в том, что мне нужно было рассматривать этот массив Delphi как тип значения, а не массив C # (ссылочный тип). Решение - «MarshalAs (UnmanagedType.ByValArray)» /

Спасибо всем!

...