Использование C++ с Objective-C. Как исправить конфликтующее объявление typedef int BOOL?

У меня много кода на C++, изначально созданного для ПК. Я пытаюсь заставить его работать с Objective-C на Mac. С этой целью я создал инфраструктуру Objective-C для размещения кода C++ и добавил тонкую оболочку. Но я столкнулся с проблемой typedef в своем коде C++.

Когда я работал с C++ на ПК, я использовал переменную BOOL, определенную в WinDef.h. Поэтому, когда я переместил все на Mac, я добавил в typedef int BOOL;, чтобы убедиться, что переменная BOOL все еще компилируется, как ожидалось.

Но когда я пытаюсь скомпилировать, я получаю сообщение об ошибке: "Conflicting declaration 'typedef int BOOL'". Я предполагаю, что это связано с тем, что BOOL является ключевым словом в Objective-C и поэтому уже определено. Я также не могу просто использовать Objective-C BOOL, так как это беззнаковый char, а не int.

Пока я искал возможные решения, я нашел одно, которое упоминается отмена определения BOOL, но я не смог найти, как это сделать (и я не знаю, работает ли это на самом деле). Другой предлагает переименовать BOOL в файлах C++ к чему-то, что не является ключевым словом. Это предложение мне не подходит, потому что другие проекты полагаются на код C++. В идеале любые изменения, которые я делаю, должны оставаться в одном файле или, по крайней мере, не должны негативно влиять на код на компьютере с Windows.

Как я могу отменить определение BOOL в Objective-C для моих файлов C++ и использовать добавленное определение C++? Есть ли лучший способ справиться с этой проблемой?

Если это поможет, я использую: Xcode 3.2.5, 64-разрядную версию и Mac OS X 10.6.6.

Спасибо за любое руководство!


person Lucy Bain    schedule 12.08.2011    source источник
comment
Почему вы использовали BOOL в первую очередь? C++ уже имеет тип bool.   -  person Derek Ledbetter    schedule 13.08.2011
comment
Поскольку в Windows многие API используют тип BOOL, определенный Windows, который действительно является типом int. Он несовместим с BOOL, особенно если он является частью структуры, которую необходимо передать такому API (в Windows bool имеет размер в байтах, а BOOL — четыре байта).   -  person Rudy Velthuis    schedule 13.08.2011


Ответы (4)


Меня немного смущают некоторые обсуждения, но вместо typedef int BOOL; как насчет:

#ifndef BOOL
  #define BOOL int
#endif

Если вы используете typedef, то #undef не будет работать, так как это две разные вещи. #define/#undef работают с символами препроцессора, которые выполняют замену, тогда как typedef является частью языка, который создает псевдоним другого типа.

Символ препроцессора может быть неопределенным в любой момент, потому что это просто инструкция для препроцессора, которая говорит ему больше не использовать это определение при выполнении замен. Однако typedef не может быть неопределенным, так как это то, что создается в определенной области, а не линейная обработка, которая происходит с использованием препроцессора. (Точно так же вы не ожидаете, что сможете объявить глобальную переменную int x;, а затем в какой-то момент вашего кода сможете сказать «прекратите распознавать x как переменную».)

Причина, по которой я предлагаю #define в своем ответе, заключается в том, что возможно, что ObjectiveC #define срабатывает только при компиляции некоторого вашего кода. Это может быть объяснением того, почему вы можете получить ошибки в своем C++ при удалении typedef, но все равно получите конфликт, если он есть. Но, если предположения верны, как только вы проверите определение перед попыткой чтобы определить его, вы должны быть в состоянии избежать конфликтующих определений, когда они возникают.

И последнее замечание: в этой конкретной ситуации вы также можете просто положить typedef внутри чека вместо #define. Тем не менее, я стремился сделать это так, как сделал, и потому, что это очень распространенная идиома, и потому, что этот блок также не позволит вам определить его дважды в коде C++, если он в конечном итоге будет включен дважды. Вероятно, ни одна из очень веских причин, если вы очень предпочитаете typedef и знаете, что это не проблема в коде. :)

person shelleybutterfly    schedule 12.08.2011
comment
:) упс, я написал после того, как ваша проблема уже была решена, рад, что у вас все получилось! - person shelleybutterfly; 13.08.2011
comment
Я пробовал оба упомянутых вами способа (#ifdef с #define BOOL int и typedef int BOOL; внутри). Первый способ сработал нормально, а вот второй выдал ту же ошибку Conflicting declaration (совершенно не понимаю, как это возможно, просто повторяю то, что сказал мне Xcode!). Спасибо за альтернативное решение! - person Lucy Bain; 13.08.2011
comment
ха, это очень странно. ну, наверное, одна из тех вещей, о которых лучше не думать слишком много. :D и спасибо за заметку! ♡ - person shelleybutterfly; 13.08.2011
comment
Препроцессор ничего не знает о типах (Objective-|)C(|++). Думайте о препроцессоре как о произвольном языке шаблонов, который ничего не знает о языке, который он отображает. См. opensource.apple.com/source/objc4/objc4. -371.1/runtime/objc.h, чтобы узнать больше. - person ; 06.06.2013

Насколько я знаю, BOOL также является #define в Objective-C. У вас будут проблемы с вашим конфликтующим BOOL определением, даже если вам удастся

#undef BOOL

потому что ваш тип и его тип не обязательно совпадают по размеру и «подписи». Должен ли ваш BOOL действительно быть int, а не тем, как его определяет Obj-C? Другими словами, вы не можете опустить свой #define и просто использовать Obj-C?

person Rudy Velthuis    schedule 12.08.2011
comment
Если я закомментирую свой typedef int BOOL в моем файле C++, я получаю ошибки во всех остальных моих файлах C++ каждый раз, когда используется BOOL. Поэтому я не думаю, что вместо этого могу использовать определение Obj-C BOOL. - person Lucy Bain; 13.08.2011
comment
Как это может быть? Я надеюсь, что это определено только один раз. Просто удалите это и вместо этого включите objc.h. FWIW, что за ошибки? - person Rudy Velthuis; 13.08.2011
comment
О, я думаю, это сработало! По крайней мере, теперь он компилируется без ошибок. Я сделал то, что вы сказали, и добавил #include <objc/objc.h>, так что, надеюсь, дальше все будет полегче. Спасибо! FWIW в основном это были ошибки, такие как 'BOOL' does not name a type и ISO C++ forbids declaration of 'BOOL' with no type. - person Lucy Bain; 13.08.2011

Если бы вы могли вернуться в прошлое, я бы сказал: «Не используйте typedef int BOOL в своем собственном коде».

Теперь, когда вы на самом деле сделали это, вы немного запутались. Как правило, вам следует избегать использования внешних типов данных для вашего собственного кода, кроме как для взаимодействия с внешним кодом. Стандартные типы подходят, если предположить, что вы можете гарантировать компиляцию с помощью стандартного совместимого компилятора на каждой целевой платформе.

Самое перспективное решение — прекратить использование BOOL в качестве типа в коде, не зависящем от платформы. В то же время вы можете использовать всевозможные хакерские приемы препроцессора, чтобы использовать BOOL compile, но вы можете столкнуться с некоторыми странными ошибками ссылок, если не будете использовать BOOL одинаково (через #includes) везде.

person MSN    schedule 15.08.2011

Я использую cmake для загрузки библиотеки freeimage, и я использую kubuntu 14.x. У меня была эта проблема с

"error: conflicting declaration ‘typedef CARD8 BOOL’" 

и я подумал, что было бы хорошо поделиться своим решением с людьми, у которых есть эта проблема!

установить FreeImage в Linux:

sudo apt-get install libfreeimage-dev

В моем файле CMakeLists.txt у меня есть:

set(FREEIMAGE_LIBRARY_AND_HEADER_DIRRECTORY /usr/libs)
find_path(FREEIMAGE_LIBRARY_AND_HEADER_DIRRECTORY, FreeImage.h)
find_library(FREEIMAGE_LIBRARY_AND_HEADER_DIRRECTORY, freeimage)
include_directories(${FREEIMAGE_LIBRARY_AND_HEADER_DIRRECTORY})
target_link_libraries(freeimage)

И в моем main.cpp у меня есть:

#include <FreeImage.h>
#ifndef CARD8
#define BYTE CARD8
#define BOOL CARD8
#endif

И дополнительный код для захвата кадра OpenGl на диск:

void generateImage(){
  int w, h; // get the width and height of the OpenGL window!
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  GLubyte * pixels = new GLubyte[3*w*h];
  glReadPixels(0,0,w,h,GL_RGB,GL_UNSIGNED_BYTE, pixels);

  FIBITMAP * image = FreeImage_ConvertFromRawBits(pixels,w,h,3 * w, 24, 0x0000FF, 0xFF0000, 0x00FF00, false);
  FreeImage_Save(FIF_BMP,image, "../img/text.bmp",0);

  //Free resource
  FreeImage_Unload(image);
  delete[] pixels;
}

Я надеюсь, что это поможет тем, у кого есть проблемы с этим!

С уважением Кахин

person Kahin    schedule 20.02.2015