Wie rufe ich eine C++-Funktion von C aus auf?

Lesezeit: 8 Minuten

Wie rufe ich eine C Funktion von C aus auf
Krallen

Ich weiß das.

C-Funktion aus C++ aufrufen:

Wenn meine Anwendung in C++ wäre und ich Funktionen aus einer in C geschriebenen Bibliothek aufrufen müsste. Dann hätte ich verwendet

//main.cpp

extern "C" void C_library_function(int x, int y);//prototype
C_library_function(2,4);// directly using it.

Das würde den Namen nicht verstümmeln C_library_function und der Linker würde den gleichen Namen in seinen *.lib-Eingabedateien finden und das Problem ist gelöst.

C++-Funktion von C aufrufen???

Aber hier erweitere ich eine große Anwendung, die in C geschrieben ist, und ich muss eine Bibliothek verwenden, die in C++ geschrieben ist. Namensverstümmelung von C++ macht hier Ärger. Linker beschwert sich über die nicht aufgelösten Symbole. Nun, ich kann den C++-Compiler nicht über meinem C-Projekt verwenden, weil das viele andere Dinge kaputt macht. Was ist der Ausweg?

Übrigens verwende ich MSVC

  • Lesen parashift.com/c++-faq-lite/mixing-c-and-cpp.html#faq-32.6

    – jweyrich

    30. April 2010 um 11:41 Uhr

  • Wenn Sie die C++-Bibliothek steuern: stackoverflow.com/questions/12615683/…

    – Ciro Santilli Путлер Капут 六四事

    29. Mai 2015 um 10:10 Uhr

  • Mögliches Duplikat von Elegantly call C++ from C

    – Benutzer2284570

    13. März 2017 um 22:48 Uhr

Wie rufe ich eine C Funktion von C aus auf
Michael Aaron Safjan

Sie müssen eine C-API erstellen, um die Funktionalität Ihres C++-Codes verfügbar zu machen. Grundsätzlich müssen Sie C++-Code schreiben, der als extern “C” deklariert ist und über eine reine C-API verfügt (z. B. keine Klassen verwendet), die die C++-Bibliothek umschließt. Dann verwenden Sie die von Ihnen erstellte reine C-Wrapper-Bibliothek.

Ihre C-API kann optional einem objektorientierten Stil folgen, obwohl C nicht objektorientiert ist. Ex:

 // *.h file
 // ...
 #ifdef __cplusplus
 #define EXTERNC extern "C"
 #else
 #define EXTERNC
 #endif

 typedef void* mylibrary_mytype_t;

 EXTERNC mylibrary_mytype_t mylibrary_mytype_init();
 EXTERNC void mylibrary_mytype_destroy(mylibrary_mytype_t mytype);
 EXTERNC void mylibrary_mytype_doit(mylibrary_mytype_t self, int param);

 #undef EXTERNC
 // ...


 // *.cpp file
 mylibrary_mytype_t mylibrary_mytype_init() {
   return new MyType;
 }

 void mylibrary_mytype_destroy(mylibrary_mytype_t untyped_ptr) {
    MyType* typed_ptr = static_cast<MyType*>(untyped_ptr);
    delete typed_ptr;
 }

 void mylibrary_mytype_doit(mylibrary_mytype_t untyped_self, int param) {
    MyType* typed_self = static_cast<MyType*>(untyped_self);
    typed_self->doIt(param);
 }

  • Danke!! Ich habs. parashift.com/c++-faq-lite/mixing-c-and-cpp.html#faq-32.6

    – Krallen

    30. April 2010 um 11:49 Uhr

  • Wie verknüpfen Sie die endgültige ausführbare Datei? Verwenden Sie C oder C++? (Als ich C verwendete, konnte der Linker die C++-Funktion nicht finden; als ich C++ verwendete, konnte der Linker std::cout nicht finden.)

    – Zach

    3. Mai 2016 um 14:48 Uhr

  • @Zack Wenn Sie mit dem C++-Compiler/Linker eine statische Bibliothek erstellen, die ihre Abhängigkeiten transitiv enthält (einschließlich der C++-Standardbibliothek, die möglicherweise implizit von Ihrem Linker verknüpft wird), sollten Sie in der Lage sein, diese statische Bibliothek mithilfe von a mit C-Code zu verknüpfen C-Compiler/Linker.

    – Michael Aaron Safyan

    4. Mai 2016 um 2:25 Uhr

  • Können Sie eine Vorlage von C++ nach C exportieren?

    – MarcusJ

    29. März 2018 um 13:04 Uhr

  • Ich habe ein “hybrides” Verhalten, da meine Bibliothek sowohl von C++- als auch von C-Code aufgerufen werden muss. In dem *.cpp file Ich musste auch die Funktionen in einpacken #ifdef _cplusplus + extern "C" um “undefinierte Verweise auf”-Fehler zum Zeitpunkt der Verknüpfung zu vermeiden.

    – n0p

    29. März 2019 um 10:42 Uhr

1646929212 449 Wie rufe ich eine C Funktion von C aus auf
Etwas etwas

Ich würde es folgendermaßen machen:

(Wenn Sie mit MSVC arbeiten, ignorieren Sie die GCC-Kompilierungsbefehle)

Angenommen, ich habe eine C++-Klasse mit dem Namen AAAdefiniert in Dateien aaa.h, aaa.cppund zwar die Klasse AAA hat eine Methode namens sayHi(const char *name)die ich für C-Code aktivieren möchte.

Der C++-Code der Klasse AAA – Reines C++, ich ändere es nicht:

aaa.h

#ifndef AAA_H
#define AAA_H

class AAA {
    public:
        AAA();
        void sayHi(const char *name);
};

#endif

aaa.cpp

#include <iostream>

#include "aaa.h"

AAA::AAA() {
}

void AAA::sayHi(const char *name) {
    std::cout << "Hi " << name << std::endl;
}

Kompilieren Sie diese Klasse wie regelmäßig für C++. Dieser Code „weiß nicht“, dass er von C-Code verwendet wird. Verwenden des Befehls:

g++ -fpic -shared aaa.cpp -o libaaa.so

Jetzt auch in C++ einen C-Connector erstellen:

Definition in Dateien aaa_c_connector.h, aaa_c_connector.cpp. Dieser Konnektor definiert eine C-Funktion mit dem Namen AAA_sayHi(Kostenzeichen *Name)die eine Instanz von verwendet AAA und wird seine Methode aufrufen:

aaa_c_connector.h

#ifndef AAA_C_CONNECTOR_H 
#define AAA_C_CONNECTOR_H 

#ifdef __cplusplus
extern "C" {
#endif
 
void AAA_sayHi(const char *name);

#ifdef __cplusplus
}
#endif


#endif

aaa_c_connector.cpp

#include <cstdlib>

#include "aaa_c_connector.h"
#include "aaa.h"

#ifdef __cplusplus
extern "C" {
#endif

// Inside this "extern C" block, I can implement functions in C++, which will externally 
//   appear as C functions (which means that the function IDs will be their names, unlike
//   the regular C++ behavior, which allows defining multiple functions with the same name
//   (overloading) and hence uses function signature hashing to enforce unique IDs),


static AAA *AAA_instance = NULL;

void lazyAAA() {
    if (AAA_instance == NULL) {
        AAA_instance = new AAA();
    }
}

void AAA_sayHi(const char *name) {
    lazyAAA();
    AAA_instance->sayHi(name);
}

#ifdef __cplusplus
}
#endif

Kompilieren Sie es erneut mit einem normalen C++-Kompilierungsbefehl:

g++ -fpic -shared aaa_c_connector.cpp -L. -laaa -o libaaa_c_connector.so

Jetzt habe ich eine gemeinsam genutzte Bibliothek (libaaa_c_connector.so), die die C-Funktion implementiert AAA_sayHi(const char *name). Ich kann jetzt eine C-Hauptdatei erstellen und alles zusammen kompilieren:

main.c

#include "aaa_c_connector.h"

int main() {
    AAA_sayHi("David");
    AAA_sayHi("James");

    return 0;
}

Kompilieren Sie es mit einem C-Kompilierungsbefehl:

gcc main.c -L. -laaa_c_connector -o c_aaa

Ich muss LD_LIBRARY_PATH so einstellen, dass es $PWD enthält, und wenn ich die ausführbare Datei ausführe ./c_aaabekomme ich die Ausgabe, die ich erwarte:

Hi David
Hi James

BEARBEITEN:

Bei einigen Linux-Distributionen -laaa und -lstdc++ kann auch für den letzten Übersetzungsbefehl erforderlich sein. Danke an @AlaaM. für die Aufmerksamkeit

  • Sie könnten auch den Lib-Link-Pfad mit angeben gcc usecpp.c -L. -laaa_c_connector -Wl,-rpath,. -o c_aaa

    – Metaphox

    4. Oktober 2016 um 10:49 Uhr

  • was ist usecpp.c?

    – Alaa M.

    30. Oktober 2016 um 9:58 Uhr

  • Die letzte Kompilierungszeile sollte sein: gcc main.c -L. -laaa_c_connector -laaa -lstdc++ -o c_aaa. Beachten Sie das -laaa und -lstdc+++

    – Alaa M.

    30. Oktober 2016 um 12:23 Uhr


  • @AlaaM. Jemand hat meinen Code bearbeitet und geändert main.c zu usecpp.c. Ich habe es gerade zurückgesetzt…. Über den anderen Kommentar sollte es auch so funktionieren, wie es ist. Die zweite Zusammenstellung verwendet -laaa und es sollte wahrscheinlich ausreichen (ich habe es vor mehr als 1,5 Jahren geschrieben, ich erinnere mich nicht sehr gut, was ich getan habe, aber ich glaube, ich habe jede Zeile vor dem Posten getestet)

    – Etwas etwas

    30. Oktober 2016 um 13:31 Uhr


  • Ok, als Hinweis am Ende des Beitrags hinzugefügt. Danke für ihre Aufmerksamkeit!

    – Etwas etwas

    30. Oktober 2016 um 13:55 Uhr


Angenommen, die C++-API ist C-kompatibel (keine Klassen, Vorlagen usw.), können Sie sie einschließen extern "C" { ... }so wie du es getan hast, als du in die andere Richtung gegangen bist.

Wenn Sie Objekte und andere nette C++-Sachen verfügbar machen möchten, müssen Sie eine Wrapper-API schreiben.

  • Nicht ganz … die C++-Bibliothek müsste neu kompiliert werden.

    – Michael Aaron Safyan

    30. April 2010 um 11:41 Uhr

  • Ach nein. Die C++-API ist vollständig objektorientiert.

    – Krallen

    30. April 2010 um 11:42 Uhr

  • @claws, siehe meinen Artikel über das Erstellen von C-Code im OOP-Stil … und erstellen Sie eine Wrapper-Bibliothek, die diesen Stil mit einer C-Schnittstelle, aber einer zugrunde liegenden C ++ – Implementierung verwendet. Verbinden Sie dann mit der C-Schnittstelle.

    – Michael Aaron Safyan

    30. April 2010 um 11:43 Uhr

  • Vielleicht möchten Sie einen Blick auf Wrapper-‘Tools’ wie swig, pyboost, … werfen, die gleichwertige Dinge tun (jedoch nicht in Richtung C …)

    – xtofl

    30. April 2010 um 11:51 Uhr

Dazu müssen Sie einen Wrapper für C in C++ schreiben. C++ ist abwärtskompatibel, aber C ist nicht aufwärtskompatibel.

Exportieren Sie Ihre C++-Funktionen als extern “C” (auch als C-Stil-Symbole bezeichnet) oder verwenden Sie das .def-Dateiformat, um unverzierte Exportsymbole für den C++-Linker zu definieren, wenn er die C++-Bibliothek erstellt, dann sollte der C-Linker keine Probleme beim Lesen haben

1646929213 925 Wie rufe ich eine C Funktion von C aus auf
Richard Wick

#include <iostream>

//////////////
// C++ code //
//////////////
struct A
{
  int i;
  int j;

  A() {i=1; j=2; std::cout << "class A created\n";}
  void dump() {std::cout << "class A dumped: " << i << ":" << j << std::endl;}
  ~A() {std::cout << "class A destroyed\n";}
};

extern "C" {
  // this is the C code interface to the class A
  static void *createA (void)
  {
    // create a handle to the A class
    return (void *)(new A);
  }
  static void dumpA (void *thisPtr)
  {
    // call A->dump ()
    if (thisPtr != NULL) // I'm an anal retentive programmer
    {
      A *classPtr = static_cast<A *>(thisPtr);
      classPtr->dump ();
    }
  }
  static void *deleteA (void *thisPtr)
  {
    // destroy the A class
    if (thisPtr != NULL)
    {
      delete (static_cast<A *>(thisPtr));
    }
  }
}

////////////////////////////////////
// this can be compiled as C code //
////////////////////////////////////
int main (int argc, char **argv)
{
  void *handle = createA();

  dumpA (handle);
  deleteA (handle);

  return 0;
}

Wie rufe ich eine C Funktion von C aus auf
Gott

Sie können der Funktionsdeklaration das Schlüsselwort extern „C“ voranstellen, z

extern „C“ int Mycppfunction()

{

// Code kommt hierher

0 zurückgeben;

}

Für weitere Beispiele können Sie bei Google nach dem Schlüsselwort „extern“ suchen. Sie müssen noch ein paar Dinge tun, aber es ist nicht schwierig, Sie erhalten viele Beispiele von Google.

988420cookie-checkWie rufe ich eine C++-Funktion von C aus auf?

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

Privacy policy