2015-04-14 5 views
5

Я пытаюсь собрать некоторые структуры с Borland C++ Builder (XE6) (в будущем: ОЦК).Используйте пакет #pragma с #define на Borland C++

Я использую библиотеку, которая использует следующую конструкцию для создания структур:

#ifdef _MSC_VER 
    #define PACKED_BEGIN __pragma(pack(push, 1)) 
    #define PACKED 
    #define PACKED_END __pragma(pack(pop)) 
#elif defined(__GNUC__) 
    #define PACKED_BEGIN 
    #define PACKED __attribute__((__packed__)) 
    #define PACKED_END 
#endif 


PACKED_BEGIN 
struct PACKED { 
    short someSampleShort; 
    char sampleByte; 
    int sampleInteger; 
} structType_t; 
PACKED_END 

Компилятор ОЦК не нравится MSC __pragma, и не люблю препроцессор директивы внутри макросов, хотя она описана на their website :

#define GETSTD #include <stdio.h> 

Мой Вопрос: есть ли возможность использовать эту конструкцию с Borland Compiler для упаковки на структуру без с помощью:

#pragma pack(1) 

для упаковки каждой структуры?

Есть ли обходные пути для этого?

+3

Вы могут по-прежнему использовать '#include 'packed_begin.h" и '#include" pa cked_end.h "(без охранников) – Jarod42

+0

Спасибо за ваш комментарий, но я не могу использовать #include в макросе, потому что borland этого не поддерживает. Я мог переписать библиотеку, но я надеялся на возможность с макросами – user2358582

+1

@ user2358582 И хорошо, что это не должно быть, это не законный C++. Я считаю, что Jarod означал, что вы можете * заменить * макрокоманды на это. – Angew

ответ

2

Как вы заявили, C++ Builder не поддерживает инструкции препроцессора внутри макросов. Это подтверждается на сайте Embarcadero в:

#define (C++)

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

Причиной этого является, потому что # характер внутри макроса зарезервирован для stringizing оператором препроцессора.

Некоторые компиляторы, включая MSVC, обойти это ограничение с помощью расширения компилятора __pragma() или расширения C99/C++ x0 _Pragma(). C++ Builder's Компилятор Windows 32bit не поддерживает ни один из них. Однако его Windows 64bit и мобильные компиляторы (все они основаны на clang и поддержке C++ 11) DO поддерживают оба из них. Таким образом, вы можете добавить поддержку для этих компиляторов макросов, как это:

#if defined(__BORLANDC__) 
    #if defined(__clang__) 
     #define PACKED_BEGIN __pragma(pack(push, 1)) 
     #define PACKED 
     #define PACKED_END __pragma(pack(pop)) 
    #else 
     #error Cannot define PACKED macros for this compiler 
    #endif 
#elif defined(_MSC_VER) 
    #define PACKED_BEGIN __pragma(pack(push, 1)) 
    #define PACKED 
    #define PACKED_END __pragma(pack(pop)) 
#elif defined(__GNUC__) 
    #define PACKED_BEGIN 
    #define PACKED __attribute__((__packed__)) 
    #define PACKED_END 
#else 
    #error PACKED macros are not defined for this compiler 
#endif 

Если вы хотите поддержать C++ Builder Windows 32bit компилятора, вам придется переместить логику в.ч файлы, которые используют #pragma для него, а затем вы можете #include те файлы, где это необходимо (по крайней мере, до тех пор пока компилятор не будет обновлен для поддержки лязг/C++ 11 - который Embarcadero в настоящее время работает над):

pack1_begin.h:

#if defined(__BORLANDC__) 
    #define PACKED_BEGIN 
    #define PACKED 
    #define PACKED_END 
    #pragma pack(push, 1) 
#elif defined(_MSC_VER) 
    #define PACKED_BEGIN __pragma(pack(push, 1)) 
    #define PACKED 
    #define PACKED_END __pragma(pack(pop)) 
#elif defined(__GNUC__) 
    #define PACKED_BEGIN 
    #define PACKED __attribute__((__packed__)) 
    #define PACKED_END 
#else 
    #error PACKED macros are not defined for this compiler 
#endif 

pack_end.h:

#if defined(__BORLANDC__) 
    #pragma pack(pop) 
#endif 

Тогда вы можете сделать это:

#include "pack1_begin.h" 
PACKED_BEGIN 
struct PACKED { 
    short someSampleShort; 
    char sampleByte; 
    int sampleInteger; 
} structType_t; 
PACKED_END 
#include "pack_end.h" 

Если принять этот подход, вы можете просто бросить PACKED_BEGIN/PACKED_END вообще:

pack1_begin.h:

#if defined(__BORLANDC__) || defined(_MSC_VER) 
    #define PACKED 
    #pragma pack(push, 1) 
#elif defined(__GNUC__) 
    #define PACKED __attribute__((__packed__)) 
#else 
    #error PACKED macro is not defined for this compiler 
#endif 

pack_end.h:

#if defined(__BORLANDC__) || defined(_MSC_VER) 
    #pragma pack(pop) 
#endif 

#include "pack1_begin.h" 
struct PACKED { 
    short someSampleShort; 
    char sampleByte; 
    int sampleInteger; 
} structType_t; 
#include "pack_end.h" 
+0

Я бы только добавил, что соответствующий C++-компилятор * не может * поддерживать директивы в замене макросов. C++ 11 16.34./3: «Полученная полностью макрозаменяемая последовательность токенов предварительной обработки не обрабатывается как директива предварительной обработки , даже если она похожа на одну, ...» – Angew

0

Стандарт предлагает одну дополнительную альтернативу для написания прагмами: оператор _Pragma:

#define PACKED_BEGIN _Pragma("pack(push, 1)") 
#define PACKED 
#define PACKED_END _Pragma("pack(pop)") 

Если компилятор Borland поддерживает его, он должен работать.

+0

Спасибо за ваш ответ, но, к сожалению, компилятор Borland (моя версия) не поддерживает _Pragma. – user2358582

+1

@ user2358582: 32-битный компилятор C++ Builder этого не делает, но его 64-битные и мобильные компиляторы делают. –

Смежные вопросы