Обновление кода C до VB.NET - Объединенные структуры - PullRequest
3 голосов
/ 03 февраля 2011

Я пытаюсь обновить btrieve-код, написанный Джимом Кайлом в начале 90-х, до VB.NET и столкнулся с проблемой с объединенными структурами. Старый код C выглядит следующим образом:

    typedef struct {
      union {
        struct {
          PGPTR   PgSeq;    // 00 - page number
          int     Usage;    // 04 - match with usage count
          int     Version;  // 06 - version code, <0 if owned
        } v5;
        struct {
          int     RecSig;   // 00 - 'FC'
          int     SeqNbr;   // 02 - always binary zeroes
          long    Usage;    // 04 - usage count
        } v6;
      } r1;
      int     PagSize;  // 08 - in bytes
    } FCRTOP;

Пока у меня было:

    <StructLayout(LayoutKind.Explicit)> _
Structure FCRTOP
    <FieldOffset(0)> Public PgSeq As PGPTR
    <FieldOffset(4)> Public Usage As Short
    <FieldOffset(6)> Public Version As Short

    <FieldOffset(0)> Public RecSig As Short
    <FieldOffset(2)> Public SeqNbr As Short
    <FieldOffset(4)> Public Usage As Integer
End Structure

Одна проблема, с которой я сталкиваюсь, заключается в том, что VB.NET не нравятся две структурные переменные с одним и тем же именем (Использование). Чего мне не хватает, чтобы сгруппировать перекрывающиеся поля с уникальным именем структуры, как это сделано в примере C (v5 и v6)?

Спасибо за любую помощь!

Ответы [ 2 ]

7 голосов
/ 03 февраля 2011

Ответ на этот вопрос полностью зависит от того, что вы делаете:

  • Если вы пытаетесь создать управляемый интерфейс для существующей неуправляемой библиотеки (другими словами, напишите код на VB.NET или другом языке .NET, который вызывает код в существующем не-. NET .dll), тогда вы делаете правильные вещи. Я расскажу об этом через секунду
  • Если вы пытаетесь создать управляемую реализацию вашей существующей неуправляемой библиотеки (т.е. переписать существующий .dll в .NET и полностью избавиться от существующего .dll), то вам следует потратить время, необходимое для рефакторинга кода во что-то объектно-ориентированное, вместо того, чтобы пытаться дублировать структуры и тому подобное. В общем случае структуры (которые являются типами значений) следует использовать только в том случае, если у вас есть особенно убедительная причина для этого; в противном случае вы должны использовать классы (ссылочные типы) и правильно переносить код из процедурного в объектно-ориентированный.

Если вы создаете управляемый интерфейс, вы должны знать, что именование членов структуры игнорируется. Это порядок и размер элементов, которые важны. Однако это не совсем ваша проблема, так как вы имеете дело только с несоответствием импеданса между тем, как С определяет структуры, и тем, как это делают VB.NET (и другие языки .NET). Поскольку ключевое слово union позволяет вам просто разбить большую структуру на логические блоки переменных, не определяя подструктуру как отдельную структуру данных, для ее переноса в .NET требуется некоторый массаж, который не позволяет таких вещей (опять же Структуры не являются основным средством инкапсуляции информации в объектно-ориентированных языках на основе ссылок, таких как VB.NET и C #). Вам нужно будет взять подструктуру (ы) и определить их как структуры самостоятельно, а затем определить переменную, типизированную как подструктуру, как обычный элемент внешней структуры.

(Между прочим, нет необходимости использовать StructLayoutKind.Explicit, если вы объявляете элементы по порядку; использование Sequential облегчит чтение, если они уже в правильном порядке.)

После этого довольно скучного ответа вы ищете что-то вроде этого:

<StructLayout(LayoutKind.Sequential)> _ 
Structure StructV5
    Public PgSeq As PGPTR
    Public Usage As Short
    Public Version As Short
End Structure 

<StructLayout(LayoutKind.Sequential)> _ 
Structure StructV6
    Public RecSig As Short
    Public SeqNbr As Short
    Public Usage As Integer
End Structure 

<StructLayout(LayoutKind.Explicit)> _ 
Structure FCRTOP
    <FieldOffset(0)>Public V5 as StructV5
    <FieldOffset(0)>Public V6 as StructV6
    <FieldOffset(8)>Public PagSize as Short
End Structure

Другой вариант - сохранить структуру как есть (и, конечно, добавить элемент для PagSize) и просто изменить имя Usage в пределах v6. Однако использование этого подхода (с явным объявлением структуры) даст вам более осмысленный синтаксис.

0 голосов
/ 03 февраля 2011

VB.NET определенно не обладает такой функцией, как эта, поэтому я думаю, что вам лучше всего попытаться уловить «дух» идеи союзов таким образом, который совместим с системой типов .NET.

Отказ от ответственности: я очень мало знаю о С, так что, возможно, я неправильно понимаю, какова цель союзов в С .Если это так, это должно быть очевидно из моего предложения.

Итак, я думаю, что вам, по сути, нужен Structure, содержащий 64 бита, которые могут представлять либо v5, либо v6 изваш пример кода C, плюс еще 16 для PageSize.Что бы я сделал, чтобы сделать это возможным, это сохранить 4 Short значения и объединить их по мере необходимости (примечание: то, что я набросал ниже, будет неизменным типом; если вам потребуется использование открытых полей для чтения / записи, тогда яЯ в недоумении относительно того, как это можно сделать, если это вообще возможно):

Structure FCRTOP
    Private a As Short
    Private b As Short
    Private c As Short
    Private d As Short

    Public ReadOnly PageSize As Short

    ' Possibly two constructors, one accepting PGTR, Short Short, Short, '
    ' the other accepting Short, Short, Integer, Short '

    Public ReadOnly Property V5 As V5
        Get
            Return New V5(a, b, c, d)
        End Get
    End Property

    Public ReadOnly Property V6 As V6
        Get
            Return New V5(a, b, c, d)
        End Get
    End Property
End Structure

Structure V5
    ' Constructor accepting 4 Short values '
    ' Properties that expose these values as PGTR, Short, Short'
End Structure

Stucture V6
    ' Constructor similar to V5 above '
    ' Properties that expose these values as Short, Short, Integer'
End Structure
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...