it-swarm.com.de

Rufen Sie eine C-Funktion aus C ++ - Code auf

Ich habe eine C-Funktion, die ich aus C++ aufrufen möchte. Ich konnte den Ansatz "extern "C" void foo()" nicht verwenden, da die C-Funktion nicht mit g ++ kompiliert werden konnte. Aber es kompiliert gut mit gcc. Irgendwelche Ideen, wie man die Funktion von C++ aus aufruft?

79
Dangila

Lassen Sie mich die Teile der anderen Antworten und Kommentare zusammenfassen, um Ihnen ein Beispiel mit sauber getrenntem C- und C++ - Code zu geben:

Der C-Teil:

foo.h:

#ifndef FOO_H
#define FOO_H

void foo(void);

#endif 

foo.c

#include "foo.h"

void foo(void)
{
    /* ... */
}

Kompilieren Sie dies mit gcc -c -o foo.o foo.c.

Der C++ Teil:

bar.cpp

extern "C" {
  #include "foo.h" //a C header, so wrap it in extern "C" 
}

void bar() {
  foo();
}

Kompiliere dies mit g++ -c -o bar.o bar.cpp

Und dann verbinden Sie alles miteinander:

g++ -o myfoobar foo.o bar.o

Begründung: Der C-Code sollte einfacher C-Code sein, kein #ifdef Für "Vielleicht werde ich das eines Tages aus einer anderen Sprache aufrufen". Wenn ein C++ - Programmierer Ihre C-Funktionen aufruft, ist es sein Problem, wie das geht, nicht deins. Und wenn Sie der C++ - Programmierer sind, gehört der C-Header möglicherweise nicht Ihnen, und Sie sollten ihn nicht ändern, sodass die Behandlung nicht verwechselter Funktionsnamen (d. H. Des extern "C") In Ihren C++ - Code gehört.

Sie können sich natürlich auch einen praktischen C++ - Header schreiben, der nichts anderes tut, als den C-Header in eine extern "C" - Deklaration zu packen.

55
Arne Mertz

Ich stimme Antwort von Prof. Falken zu, aber nach dem Kommentar von Arne Mertz möchte ich ein vollständiges Beispiel geben (der wichtigste Teil ist das #ifdef __cplusplus):

somecode.h

#ifndef H_SOMECODE
#define H_SOMECODE

#ifdef __cplusplus
extern "C" {
#endif

void foo(void);

#ifdef __cplusplus
}
#endif

#endif /* H_SOMECODE */

somecode.c

#include "somecode.h"

void foo(void)
{
    /* ... */
}

othercode.hpp

#ifndef HPP_OTHERCODE
#define HPP_OTHERCODE

void bar();

#endif /* HPP_OTHERCODE */

othercode.cpp

#include "othercode.hpp"
#include "somecode.h"

void bar()
{
    foo(); // call C function
    // ...
}

Dann folgen Sie den Anweisungen von Prof. Falken zum Kompilieren und Verknüpfen.

Dies funktioniert, weil beim Kompilieren mit gcc das Makro __cplusplus ist nicht definiert, der Header somecode.h enthalten in somecode.c ist nach der Vorverarbeitung so:

void foo(void);

und beim Kompilieren mit g++, dann __cplusplus ist definiert, und so ist der Header in othercode.cpp ist jetzt so:

extern "C" {

void foo(void);

}
16
gx_

Diese Antwort ist von einem Fall inspiriert, in dem Arnes Begründung richtig war. Ein Anbieter hat eine Bibliothek geschrieben, die einst sowohl C als auch C++ unterstützte. Die neueste Version unterstützte jedoch nur C. Die folgenden im Code verbliebenen Richtlinien waren irreführend:

#ifdef __cplusplus
extern "C" {
#endif

Das hat mich einige Stunden gekostet, in C++ zu kompilieren. Einfach C von C++ aus aufzurufen, war viel einfacher.

Die ifdef __cplusplus-Konvention verstößt gegen das Prinzip der einmaligen Verantwortung. Ein Code, der diese Konvention verwendet, versucht, zwei Dinge gleichzeitig zu tun:

  • (1) eine Funktion in C - und - ausführen
  • (2) Führen Sie dieselbe Funktion in C++ aus

Es ist, als würde man versuchen, gleichzeitig in amerikanischem und britischem Englisch zu schreiben. Dies wirft unnötigerweise einen #ifdef __thequeensenglish Schraubenschlüssel #Elif __yankeeenglish Schraubenschlüssel #else ein nutzloses Werkzeug, das das Einlesen von #endif in den Code erschwert.

Für einfachen Code und kleine Bibliotheken funktioniert möglicherweise die ifdef __cplusplus-Konvention. Für komplexe Bibliotheken ist es jedoch am besten, die eine oder andere Sprache auszuwählen und dabei zu bleiben. Die Unterstützung einer der Sprachen erfordert weniger Wartung als die Unterstützung beider Sprachen.

Dies ist eine Aufzeichnung der Änderungen, die ich an Arnes Code vorgenommen habe, damit er unter Ubuntu Linux kompiliert werden kann.

foo.h:

#ifndef FOO_H
#define FOO_H

void foo(void);

#endif 

foo.c

#include "foo.h"
#include <stdio.h>

void foo(void)
{
     // modified to verify the code was called
     printf("This Hello World was called in C++ and written in C\n");
}

bar.cpp

extern "C" {
    #include "foo.h" //a C header, so wrap it in extern "C" 
}

int main() {
  foo();
  return(0);
}

Makefile

# -*- MakeFile -*-
# dont forget to use tabs, not spaces for indents
# to use simple copy this file in the same directory and type 'make'

myfoobar: bar.o foo.o
    g++ -o myfoobar foo.o bar.o 

bar.o: bar.cpp
    g++ -c -o bar.o bar.cpp

foo.o: foo.c
    gcc -c -o foo.o foo.c
0
Agriculturist