C vs. C++ Kompilierungsinkompatibilität – nennt keinen Typ

Lesezeit: 6 Minuten

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?

  • 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

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.

  • Warten Sie, C hat also keinen Bereichsauflösungsoperator? Wow, aber im Nachhinein macht es Sinn 🙂

    – Rakete1111

    28. Juni 2018 um 6:21 Uhr

  • @Rakete1111 – Bist du einer der wenigen Menschen, die immer nur C++ und nicht C gemacht haben?

    – StoryTeller – Unslander Monica

    28. Juni 2018 um 6:28 Uhr

  • Exakt. Ich denke immer, ich kenne C (wegen C ++), aber ich habe immer das Gegenteil bewiesen 🙂

    – Rakete1111

    28. Juni 2018 um 7:04 Uhr

  • @ Rakete1111: Nur eine Anmerkung, die C-Programmierung erfordert a sehr anderer Ansatz (und ich würde sogar sagen, ein ganz anderer Denkweise) als C++. Soweit ich bereitwillig zugeben würde, dass ich verdammt gut in C++ bin, aber verdammt schlecht in C, obwohl ich beides schreiben kann. Dies ist nicht offensichtlich, wenn Sie das erste Mal lernen, deshalb erwähne ich dies – wenn Sie davon ausgehen, dass zwei Codeteile in diesen Sprachen einander ähneln sollten, werden Sie nur irgendwann danach mit dem Kopf gegen die Wand schlagen (vielleicht früher, vielleicht später). Ich vergesse die Idee, dass Sie C jemals gekannt haben, und fangen Sie einfach von vorne an.

    – Benutzer541686

    28. Juni 2018 um 8:19 Uhr


  • @Mehrdad Das geht auch andersherum. Mein C gehört zu den Besten, aber ich habe es nie geschafft, mich vollständig mit C++ zu beschäftigen. Ich kann bei Bedarf C++ machen, aber es ist nicht selbstverständlich und ich mag es wirklich nicht.

    – Toni

    28. Juni 2018 um 11:02 Uhr

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.cbei 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 .cdu 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++.

  • Der Nachteil dieses Ansatzes besteht darin, dass er jedem Bibliotheksaufruf eine zusätzliche Ebene von Prozeduraufruf-Overhead hinzufügt, es sei denn, Sie führen eine Verbindungszeitoptimierung durch.

    – Plugwash

    27. Juni 2018 um 18:23 Uhr

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
  1. Offen header.h;
  2. Suchposition 11:9;
  3. Einfügung :: dort;
  4. 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.

1410830cookie-checkC vs. C++ Kompilierungsinkompatibilität – nennt keinen Typ

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy