Как включить две разные версии одного и того же заголовка?

Я пишу код преобразования файла из проприетарного формата файла в еще один общий. Моя цель — поддерживать несколько версий формата файла производителя.

У меня есть несколько версий одних и тех же фирменных заголовков. Заголовки определяют различные структуры, которые составляют основной заголовок файла (файл представляет собой просто большой заголовок, за которым следуют необработанные данные).

Мне нужно прочитать первые 4 байта исходного файла, чтобы определить версию файла. Версия файла, в свою очередь, сообщает мне, какая версия C -структуры использовалась для создания файла.

Вопросы:

  1. Я не могу изменить проприетарные заголовки
  2. Заголовки не используют пространства имен или классы
  3. В заголовках определено несколько макросов

Возможные решения:

  • Создайте различные двоичные файлы конвертера для каждого типа файла 🙁
    • Неудобно как для пользователя, так и для разработчика
  • Динамически загружать библиотеки для каждой версии
    • Конвертер ориентирован на плагин, так что уже много чего происходит

Я попытался взломать с пространствами имен:

namespace version1 {
#include "version1.h"}

namespace version2 {
#include "version2.h"}

int main (void) {
version1::header *hdr = new version1::header;
return 0;
}

Но это не сработает из-за включения защиты и из-за того, что в каждом заголовке переопределено несколько макросов.

Есть ли элегантный способ справиться с этим?

2

Решение

Вы можете использовать два разных исходных файла вместе с предварительным объявлением:

// Forward declare in main.cpp:

namespace version1
{
struct header;
}

namespace version2
{
struct header;
}

// version1.cpp:

namespace version1
{
#include <version1.h>
}

version1::header* new_v1_header()
{
return new version1::header;
}

// other functions using `version1::header`

// version2.cpp:

namespace version2
{
#include <version2.h>
}

version2::header* new_v2_header()
{
return new version2::header;
}

// other functions using `version2::header`

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

class header_base
{
virtual int func1(char *stuff) = 0;
... many other virtual functions.
};

// Create implementation of header_v1 or header_v2:
header_base* make_header(unsigned int magic);

header_base.cpp:

#include "header_v1.h"#include "header_v2.h"
header_base* make_header(unsigned int magic)
{
switch(magic)
{
case Magic_V1:
return new header_v1;
case Magic_V2:
return new header_v2;
default:
assert(0);
return 0;
}
}

а затем реализовать, в двух отдельных

в headerv1.h:

class header_v1 : public header_base
{
int func1(char *stuff);
...
};

header_v1.cpp:

#include "header1.h"
int header_v1::func1(char *stuff)
{
...
return 17;
}

И аналогично для header_v2.h и header_v2.cpp.

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]