Подтвердить что ты не робот

Программа С++ с использованием заголовков библиотеки C распознает "this" как ключевое слово. Ошибка Extern "C"?

Программа My С++ должна использовать внешнюю библиотеку C. Поэтому я использую

extern "C"
{
   #include <library_header.h>
}

для каждого модуля, который мне нужно использовать.

Сработало до сих пор. Модуль использует имя this для некоторых переменных в одном из файлов заголовков. Сама библиотека C компилируется отлично, потому что из того, что я знаю, этот никогда не был ключевым словом в C.

Но, несмотря на использование синтаксиса extern "C" Я получаю ошибки от своей программы на С++, когда включаю этот заголовочный файл.

Если я переименую каждый этот в этот заголовочный файл библиотеки C с чем-то вроде _this все работает нормально.

Возникает вопрос:

Не следует использовать синтаксис extern "C" для обратной совместимости, по крайней мере, на уровне синтаксиса, для файла заголовка? Это проблема с компилятором?

4b9b3361

Ответ 1

Не должен ли синтаксис extern "C" быть достаточным для обратной совместимости, по крайней мере на уровне синтаксиса, для файла заголовка? Это проблема с компилятором?

Нет. Extern "C" предназначен для связывания - в частности, политики, используемой для сгенерированных имен символов ( "манипулирование именами" ) и соглашения о вызове (какая сборка будет сгенерирована для вызова значений параметров API и стека) - не компиляция.

Проблема, которая у вас есть, не ограничивается ключевым словом this. В нашей текущей базе кода мы переносим некоторый код на С++, и у нас есть такие конструкции:

struct Something {
    char *value;
    char class[20]; // <-- bad bad code!
};

Это отлично работает в коде C, но (как вы) мы вынуждены переименовывать, чтобы иметь возможность компилироваться как С++.

Ответ 2

Как ни странно, многие компиляторы не принудительно запрещают перепрофилирование ключевых слов через препроцессор:

#include <iostream>

// temporary redefinition to compile code abusing the "this" keyword
#define cppThis this
#define this thisFunction

int this() {
    return 1020;
}

int that() {
   return this();
}

// put the C++ definition back so you can use it
#undef this
#define this cppThis

struct DumpThat {
    int dump() {
       std::cout << that();
    }
    DumpThat() {
       this->dump();
    }
};

int main ()
{
    DumpThat dt;
}

Итак, если вы против стены, это может позволить вам скомпилировать файл, написанный в предположениях C, которые вы не можете изменить.

Это не будет - однако - позволит вам получить имя компоновщика "this". Там могут быть компоновщики, которые позволяют вам делать какое-то переназначение имен, чтобы избежать столкновений. Побочным эффектом этого может быть то, что они позволяют вам сказать thisFunction -> this и не иметь проблемы с правой частью отображения, являющимся ключевым словом.

В любом случае... лучший ответ, если вы можете его изменить... измените его!

Ответ 3

Если extern "C" разрешено использовать ключевые слова С++ в качестве символов, компилятор должен будет каким-то образом решить их за пределами разделов extern "C". Например:

extern "C" {
    int * this;  //global variable
    typedef int class;
}


int MyClass::MyFunction() { return *this; }  //what does this mean?
                                             //MyClass could have a cast operator
class MyOtherClass;  //forward declaration or a typedef'ed int?

Ответ 4

Не могли бы вы более подробно сказать о "использовании этого имени для некоторых переменных в одном из его файлов заголовков"?

Действительно ли это переменная или она является параметром в прототипе функции?

Если это последний, у вас нет реальной проблемы, потому что прототипы C (и С++) определяют параметры по позиции (и типу), а имена являются необязательными. У вас может быть другая версия прототипа, например:

#ifdef __cplusplus
  extern "C" {
   void aFunc(int);
  }
#else
 void aFunc(int this);
#endif

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

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