2014-09-03 11 views
12

Mój program C++ musi korzystać z zewnętrznej biblioteki C. Dlatego używam składniProgram C++ używający nagłówków biblioteki C rozpoznaje "to" jako słowo kluczowe. Zewnętrzny błąd "C"?

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

dla każdego modułu muszę korzystać.

Do tej pory działało dobrze. Moduł używa nazwy w przypadku niektórych zmiennych w jednym z plików nagłówkowych. bibliotece C Sam jest kompilacją dobrze, bo z tego co wiem, tonigdy nie było kluczowe w C

Ale mimo mojego korzystania z extern „C” składni, jestem uzyskiwanie błędy z mojego programu C++, gdy dołączę ten plik nagłówkowy.

Gdybym przemianować każdy ten w tym pliku nagłówka C biblioteki z czymś _this, wszystko wydaje się działać poprawnie.

Pytanie brzmi:

nie Jeżeli extern „C” składnia być wystarczające dla zapewnienia zgodności przynajmniej na poziomie składni dla pliku nagłówka? Czy to jest problem z kompilatorem?

+11

Całe "extern" C "" mówi kompilatorowi, aby nie wykonywał [mangling nazw] (http://en.wikipedia.org/wiki/Name_mangling). –

+3

http://stackoverflow.com/q/1041866/1147772 – Drax

+2

@JoachimPileborg - "extern" C "' mówi o użyciu manglingu C, co zwykle oznacza poprzedzanie podkreślenia. –

Odpowiedz

14

Czy nie powinna istnieć zewnętrzna składnia "C" dla wstecznej zgodności, przynajmniej na poziomie składni, dla pliku nagłówkowego? Czy to jest problem z kompilatorem?

Nr Nazwa zewnętrzna "C" służy do łączenia - w szczególności do zasad używanych do generowania nazw symboli ("wymazywanie nazw") i do konwencji wywołującej (jaki zestaw zostanie wygenerowany w celu wywołania wartości parametrów API i stosu) - nie kompilacja.

Problem, który masz, nie jest ograniczony do słowa kluczowego this. W naszej aktualnej bazie kodu, jesteśmy przenoszenie kodu do C++ i mamy konstrukcje takie jak:

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

Działa to dobrze w kodzie C, ale (jak ty) jesteśmy zmuszeni do zmiany nazwy, aby móc skompilować jako C++.

+5

Pro-tip: Napisz kod kompatybilny z C++ podczas pisania bibliotek C. Oszczędność dla innych deweloperów. –

+0

RE: Twój problem z klasą, zwróć uwagę na hacky-jeszcze-wciąż-prawdopodobnie-wspierany przez twój-kompilator obejście [w mojej odpowiedzi] (http://stackoverflow.com/a/25647229/211160). Oczywiście, nie rób tego, napraw to! :-) – HostileFork

+0

Ok, teraz jest to całkowicie jasne. Jak już powiedziałeś, rozwiązałeś "ten" problem ze słowem kluczowym poprzez zmianę nazwy, zaczął narzekać na konwersje int/bool i inne główne różnice w języku C/C++. Myślałem "skoro jest extern" C "będzie kompilował przy użyciu specyfikacji C", i całkowicie się myliłem. Dzięki! – nyarlathotep108

2

Jeśli extern "C" pozwoli ci używać słów kluczowych w C++ jako symboli, kompilator będzie musiał je rozwiązać w jakiś sposób poza sekcjami extern "C". Na przykład:

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

dziwo, wielu kompilatorów don't forcibly disallow kluczowe redefinicja przez preprocesor:

#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; 
} 

Więc jeśli się o ścianę, które mogłyby pozwolić skompilować plik napisany z założeniami C że nie możesz się zmienić.

Nie spowoduje to jednak, że otrzymasz nazwę linkera "to". Mogą istnieć linkery, które pozwalają na zmianę nazw, aby uniknąć kolizji.Efektem ubocznym może być to, że pozwalają powiedzieć thisFunction -> this i nie ma problemu z prawą stroną odwzorowania będącego słowem kluczowym.

W każdym razie ... lepsza odpowiedź, jeśli możesz to zmienić ... zmień!

+1

Nie sądzę, że to dziwne, lub że kompilator ma jakiś wybór. Krok preprocesora definiowany jest na poziomie tokena. Na tym etapie tokeny nie były jeszcze analizowane w słowach kluczowych, więc nie możesz używać tokenów słów kluczowych inaczej niż tokeny inne niż kluczowe. – MSalters

+2

@MSalters Zobacz [Redefinicja słów kluczowych w C/C++] (http://stackoverflow.com/q/12286691/211160) ... z pewnością można umieścić na czarnej liście słowa z użycia preprocesora. – HostileFork

+0

Ow, right - C zabrania go tylko w fazie 7/8, po fazie 4 preprocessingu (patrz odpowiedź md5), ale w C++ jest ona całkowicie zakazana (na powiązane pytanie). Ale "to" i tak nie byłoby słowem kluczowym w C. Więc zamiast warunkowo przedefiniować ją dla C++, powinieneś warunkowo przedefiniować ją dla C. – MSalters

1

Czy mógłbyś bardziej szczegółowo opisać "używanie tej nazwy dla niektórych zmiennych w jednym z jej plików nagłówkowych"?

Czy to naprawdę zmienna, czy jest to parametr w prototypie funkcji?

Jeśli jest to drugie, nie ma prawdziwego problemu, ponieważ prototypy C (i C++) identyfikują parametry według pozycji (i typu), a nazwy są opcjonalne. Można mieć inną wersję prototypu, np

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

Pamiętaj, nie ma nic magicznego plików nagłówkowych - po prostu dostarczyć kod, który jest zawarty w leksykalnie w punkcie #include - jakby został skopiowany i wklejony je.

Możesz więc mieć własną kopię nagłówka biblioteki, która wykonuje sztuczki podobne do powyższych, po prostu staje się problemem związanym z konserwacją, aby zapewnić śledzenie tego, co dzieje się w oryginalnym nagłówku. Jeśli to może być problem, dodaj skrypt jako krok kompilacji, który uruchamia różnicę w stosunku do oryginału i zapewnia jedyną istotną różnicę w kodzie obejścia problemu.

Powiązane problemy