Ich versuche, die Bibliothek eines Lieferanten in Kombination mit meiner C++-Anwendung zu verwenden. Die Bibliothek basiert größtenteils auf C, was normalerweise kein Problem darstellt extern "C"
Option, aber ich bin auf ein Problem gestoßen, das der C++-Compiler nicht akzeptiert.
Ich habe meinen Code in die folgenden Beispieldateien vereinfacht. header.h stellt einen Header aus der Lieferantenbibliothek dar, main.c/cpp sind meine eigenen Dateien. Meine eigentliche Anwendung ist eine C++-Anwendung, also möchte ich, dass sie mit main.cpp funktioniert.
header.h (beachten Sie die Zeile u64 u64;
):
#ifndef HEADER_H
#define HEADER_H
#include <stdint.h>
typedef uint64_t u64;
union teststruct {
u64 u64;
struct {
u64 x:32;
u64 y:32;
} s;
};
#endif
Haupt c:
#include <stdio.h>
#include "header.h"
int main() {
union teststruct a;
a.u64=5;
printf("%x\n", a.u64);
return 0;
}
main.cpp (dasselbe wie main.c, aber mit einer zusätzlichen extern "C"
Aussage):
#include <stdio.h>
extern "C" {
#include "header.h"
}
int main() {
union teststruct a;
a.u64=5;
printf("%x\n", a.u64);
return 0;
}
Kompilieren von main.c mit der Zeile
gcc -o test main.c
kompiliert ohne Probleme. Kompilieren Sie jedoch die C++-Version mit dem g++-Compiler mit dem Befehl
g++ -o test main.cpp
gibt folgende Compilerfehler:
In file included from main.cpp:12:0:
header.h:11:9: error: ‘u64’ does not name a type
u64 x:32;
^
header.h:12:9: error: ‘u64’ does not name a type
u64 y:32;
^
Das Problem ist, dass der Lieferant denselben Namen (u64) sowohl für den Typ als auch für den Variablennamen verwendet hat, was zunächst wie eine schlechte Idee erscheint, aber gcc akzeptiert es anscheinend. Ich möchte die Bibliothek (dh header.h) nicht ändern, da sie sehr groß ist, dies kommt häufig im Code vor und ich bekomme gelegentlich Updates dafür. Gibt es eine Möglichkeit, g ++ dazu zu bringen, diese Kombination zu akzeptieren, oder eine Möglichkeit, main.cpp so zu ändern, dass es kompiliert wird? ohne Header.h ändern?
teststruct
definiert einen Geltungsbereich in C++. Sie können die qualifizierte ID bilden teststruct::u64
. Die Sprachregeln für die Namenssuche berücksichtigen dies, indem sie Mitgliedern von Klassen und Vereinigungen ermöglichen, Bezeichner im äußeren Bereich zu verbergen. Einmal u64 u64;
eingeführt wird, der unqualifizierte u64
kann sich nicht auf das Globale beziehen ::u64
, nur das Mitglied. Und das Mitglied ist kein Typ.
In C union teststruct
definiert keinen Geltungsbereich. Das Feld kann nur im Mitgliederzugriff verwendet werden, daher kann es nie zu Konflikten kommen. Als solches braucht das Feld die Typkennung des Dateibereichs nicht zu verbergen.
Soweit ich das beurteilen kann, gibt es nichts, was Sie tun könnten, um es einfach zu umgehen. Diese Bibliothek (die eine vollkommen gültige C-Bibliothek ist) ist keine gültige C++-Bibliothek. Nicht anders als wenn es verwendet wird new
oder try
als Variablennamen. Es muss angepasst werden.
Es scheint, dass Sie eine Header-Datei haben, die in C++ illegal ist, also können Sie das nicht #include
es in Code kompiliert als C++. Wenn Sie keine Änderung in der Header-Datei der Bibliothek vornehmen können (z. B. durch eine Beschwerde bei Ihrem Bibliothekslieferanten), dann ist die einfachste Möglichkeit, einen dünnen C++-kompatiblen Wrapper um die Bibliothek zu schreiben:
Um Ihren C++-Code gegen den C-Header zu isolieren, erstellen Sie eine Wrapper.h
und Wrapper.c
bei dem die .h
für die Einbindung in C++ gültig ist, tut nicht enthalten header.h
, und bietet alle Arten und Funktionen, die Sie für die Bibliotheksinteraktion benötigen. Dann im .c
du kannst #include "header.h"
und implementieren Sie alle Aufrufe (und alles, was Sie tun müssen, um sicher zwischen den Typen zu konvertieren). Dies müsste offensichtlich als C kompiliert werden, nicht als C++.
Wenn Ihre erwähnte Inkompatibilität zwischen C und C++ die einzige ist, sollten Sie in der Lage sein, zu konvertieren header.h
programmgesteuert in eine C++-kompatible Header-Datei umzuwandeln, nennen Sie sie etwa so header.hpp
. Und dann können Sie neuere Versionen auf die gleiche Weise konvertieren.
Compiler-Fehler sagen Ihnen alles darüber, was und wo geändert werden sollte:
header.h:11:9: error: ‘u64’ does not name a type
- Offen
header.h
;
- Suchposition 11:9;
- Einfügung
::
dort;
- Wiederholen Sie für alle
does not name a type
Error.
Etwas String-Verarbeitung und fertig.
PS: C-zu-C++-Konverter können das möglicherweise auch.
14108300cookie-checkC vs. C++ Kompilierungsinkompatibilität – nennt keinen Typyes
C und C++ sind zwei sehr unterschiedliche Sprachen mit sehr unterschiedlichen Regeln und Semantiken. Es gibt viele Dinge, die gültiges C, aber ungültiges C++ sind. Wenn Sie einen Header haben, der gültiges C, aber ungültiges C++ enthält, und Sie die Header-Datei nicht wirklich bearbeiten können, um ihn zu “reparieren”, dann gibt es nicht wirklich viel, was Sie selbst dagegen tun können. Und
extern "C"
ist nicht wirklich ein “C-Abwärtskompatibilitätsmodus”, seine Hauptverwendung besteht darin, das Verstümmeln von Namen zu verhindern und nicht viel mehr.– Irgendein Programmierer-Typ
27. Juni 2018 um 11:07 Uhr
Senden Sie einen Fehlerbericht an Ihren Bibliothekslieferanten.
– n. 1.8e9-wo-ist-meine-Aktie m.
27. Juni 2018 um 11:09 Uhr
Wird behauptet, dass die Bibliothek mit C++-Code verwendbar ist? Oder wird nur behauptet, es sei C-Code?
– Gerhardh
27. Juni 2018 um 13:27 Uhr
@Someprogrammerdude Antworten und Kommentare sind zwei sehr unterschiedliche Konzepte mit sehr unterschiedlichen Regeln. Es gibt viele Dinge, die gültige Kommentare sind, aber eine Antwort auf die Frage gehört nicht dazu.
– Rohr
27. Juni 2018 um 13:27 Uhr