2013-10-15 3 views
4

Таким образом, поставщик, который мы используем предоставил библиотеку (в основном для C, с некоторыми Си ++), которая выполняет следующие действия:Есть ли способ обхода #define, представленного поставщиком?

#ifndef int64_t 
#define int64_t s_int64 
#endif 
#ifndef int32_t 
#define int32_t s_int32 
#endif 
#ifndef int16_t 
#define int16_t s_int16 
#endif 
#ifndef int8_t 
#define int8_t s_int8 
#endif 

В одном из своих заголовков глубоко внутри их библиотеки. Теперь проблема заключается в том, что когда-то их библиотека включена в простом C++ 11 кода, такие как:

#include <iostream> 

#include <vendor/library.h> 

int main(void) 
{ 
    std::int32_t std_i = 0; 
    return std_i; 
} 

Существует сразу ошибка компилятора (s_int32 не в std::). Таким образом, вопрос заключается в том, чтобы не допустить, чтобы продавец исправил это, есть ли способ обойти это в нашем коде? (Кстати то, что я пытался, #include <cstdint>до их заголовки, не повезло;.. extern "C" обертка, не повезло установлены заголовки в /usr/include/ так без контроля за порядком включения я думаю, как хорошо ...)

+3

Не включайте такие заголовки в свой код. Они загрязняют его. Не используйте код поставщика. –

+2

@ DanielDaranas, а не вариант, если их библиотека должна использоваться для доступа к оборудованию! :/ – Nim

+0

Вы * можете * использовать библиотеку БЕЗ использования заголовков. Библиотека включена компоновщиком, заголовок анализируется препроцессором; просто скопируйте заголовок, отредактируйте его, включите локальную копию. В конце концов, это C, а не Java! – vaxquis

ответ

4

Не видя, что еще находится в файле, сложно найти решение, которое будет работать на 100%.

Тем не менее, одна идея, которую вы могли бы попробовать, была бы следующей (примечание - я пробовал эту вагелию в своем компиляторе, но я не гарантирую, что она будет работать в любом другом).

Создайте файл, содержащий их определяет, а также определения типов:

typedef s_int64 int64_t; 
... 

Тогда некоторые компиляторы позволяют указать файл, чтобы включить первее в командной строке ... например, GCC имеет -include переключатель, поэтому вы указываете, чтобы включить этот файл.

Затем, также в командной строке, вы можете сделать определено, что сопоставляют себя:

-Dint64_t=int64_t 

или даже поставить определяет в указанном файле:

#define int64_t int64_t 

Результат есть, в теория, #defines не будет мешать никакому другому коду (они не должны ничего не делать - tho 'Я не уверен, что вы могли бы закончиться рекурсивным расширением?).И поскольку вы создали typedef до нужного типа, код продавца должен все еще работать.

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

Тогда вы должны запретить поставщику обновить свой код, чтобы использовать typedef. Вы клиент, они хотят продать вам продукт.

Все теории ума.

+0

На самом деле, ваша точка в определении на линии компиляции действительно может сделать трюк! Проблема в том, что у нас есть несколько старых версий нашего кода, которые включают эту библиотеку, которую предоставляет поставщик. Мы не можем повторно выпускать эти старые версии, однако мы можем изменить линию компиляции, этот хак может работать на данный момент и позволяет нам использовать более новую версию библиотеки. – Nim

+1

Как я упоминал в своем комментарии, добавив целую серию '-D ...' в строку компиляции фиксирует ошибки компилятора. Это означает, что и наши старшие версии, и любые новые компиляции работают нормально ... В результате я буду принимать этот ответ ... – Nim

21

Вы можете определить их определения.

#undef int64_t 
#undef int32_t 
#undef int16_t 
#undef int8_t 
+0

... eugh ... ужасно, но выбора нет .. .:/ – Nim

+0

@ Ним это. Макросы почти всегда ужасны. –

+0

@IvanIshchenko: Нет, они не ... они великолепны в простой ol C ... –

0

они используют #ifndef макросъемки, что означает: , если не определено, то значение ...

Просто определить его первое с вашими ценностями:

#define int64_t (xx) 
#define int32_t (xx) 
#define int16_t (xx) 
#define int8_t (xx) 
+0

проблема заключается в том, что предполагается, что это * types *, а не определенные константы. Это как сказать '#ifndef int'. – Adam

+0

Я сомневаюсь, что эти собственные макросы были бы гораздо более полезными, чем определенные поставщиком. – MvG

+0

как насчет '#define int64_t int64_t'? и аналогично для каждого типа? то они будут определены сами собой, все должно работать ... – codeling

5

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

#define int64_t int64_t 
#define int32_t int32_t 
#define int16_t int16_t 
#define int8_t int8_t 

перед тем включая заголовок поставщика. Таким образом, они не будут переопределены (поскольку они используют #ifndef), и они сохраняют свое намеренное значение для остальной части вашего кода.

+0

Единственная проблема здесь в том, что заголовок вендора предполагает, что 'int64_t' на самом деле является их собственным' s_int64'. В зависимости от того, что на самом деле 's_int64', при вызове их библиотечной функции может не отображаться правильный тип. Это, скорее всего, просто имя, но вы никогда не знаете :) – icabod

+1

@icabod Если они действительно предполагают, что они не должны использовать '# ifndef'. Но ОК, я просто указывал вариант, только вы можете решить, подходит ли оно вашей среде. –

+1

Действительно, единственное реальное решение - заставить продавца исправить свои вещи - проголосовать за свой кошелек :) – icabod

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