Программа С++ с использованием заголовков библиотеки C распознает "this" как ключевое слово. Ошибка Extern "C"?
Программа My С++ должна использовать внешнюю библиотеку C.
Поэтому я использую
extern "C"
{
#include <library_header.h>
}
для каждого модуля, который мне нужно использовать.
Сработало до сих пор.
Модуль использует имя this для некоторых переменных в одном из файлов заголовков.
Сама библиотека C компилируется отлично, потому что из того, что я знаю, этот никогда не был ключевым словом в C.
Но, несмотря на использование синтаксиса extern "C"
Я получаю ошибки от своей программы на С++, когда включаю этот заголовочный файл.
Если я переименую каждый этот в этот заголовочный файл библиотеки C с чем-то вроде _this
все работает нормально.
Возникает вопрос:
Не следует использовать синтаксис extern "C" для обратной совместимости,
по крайней мере, на уровне синтаксиса, для файла заголовка?
Это проблема с компилятором?
Ответы
Ответ 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 против оригинала и гарантирует, что единственной точкой разницы является ваш код обхода.