Полевое сравнение неуправляемой структуры - PullRequest
0 голосов
/ 30 сентября 2010

В целях тестирования я хочу сравнить две структуры (неизвестного типа T), выделенные из неуправляемого кода.

Поскольку они могут содержать некоторую упаковку в неуправляемом представлении, нецелесообразно преобразовывать всю структуру в байтовый массив, а затем сравнивать побайтно:

int       size    = Marshal.SizeOf(typeof(T));
IntPtr    buf1    = Marshal.AllocHGlobal(size); // FreeHGlobal omitted for simplicity
IntPtr    buf2    = Marshal.AllocHGlobal(size);
byte[]    array1  = new byte[size];
byte[]    array2  = new byte[size];
Marshal.StructureToPtr(st1, buf1, false);
Marshal.StructureToPtr(st2, buf2, false);
Marshal.Copy(buf1, array1, 0, size);
Marshal.Copy(buf2, array2, 0, size);

// inapropriate
for (int i = 0; i < size; ++i)
{
    if (array1[i] != array2[i]) { return false; }
}
return true;

Я думаю, что необходимо сравнивать поле за полем.

Благодаря рефлексии я могу перечислить FieldInfo, а затем, используя метод Marshal.OffsetOf, получить смещения полей.

К сожалению, однако, я понятия не имею, как получить размеры полей. Без этого я не смогу сравнить два поля, исключая эффект упаковки.

foreach (var fieldInfo in typeof(T).GetFields())
{
    int offset     = (int)Marshal.OffsetOf(typeof(T), fieldInfo.Name);
    int fieldSize  = ...;        // I need this
    for (int i = offset; i < offset + fieldSize; ++i)
    {
        if (array1[i] != array2[i]) { return false; }
    }
}
return true;

Есть ли способ сделать это? Или есть лучший способ сравнить неуправляемые структуры?

Примечание: Типы полей являются произвольными (могут быть примитивные целые числа, массивы, строки, перечисления, структуры и т. Д.).

1 Ответ

0 голосов
/ 30 сентября 2010

Можете ли вы использовать Marshal.SizeOf(fieldInfo.FieldType)?

Кроме того, две структуры могут быть упакованы по-разному?Потому что, если они не, упаковка не становится неактуальной?Можете ли вы привести пример, когда упаковка означает, что прямое побайтное сравнение дает вам неправильный ответ?Я предполагаю, что когда память выделяется, она обнуляется - поэтому любые неиспользуемые байты (из-за заполнения) будут равны нулю и, следовательно, будут равны в обоих массивах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...