Llamar a una función C desde el código C ++

Tengo una función C a la que me gustaría llamar desde C ++. No pude usar el tipo de aproximación ” extern "C" void foo() ” porque no se compiló la función C usando g ++. Pero comstack bien usando gcc. ¿Alguna idea de cómo llamar a la función desde C ++?

Comstack el código C de esta manera:

 gcc -c -o somecode.o somecode.c 

Entonces el código de C ++ así:

 g++ -c -o othercode.o othercode.cpp 

Luego, únelos con el enlazador C ++:

 g++ -o yourprogram somecode.o othercode.o 

También debe decirle al comstackdor C ++ que se acerca un encabezado C cuando incluye la statement para la función C. Entonces othercode.cpp comienza con:

 extern "C" { #include "somecode.h" } 

somecode.h debe contener algo como:

  #ifndef SOMECODE_H_ #define SOMECODE_H_ void foo(); #endif 

(Utilicé gcc en este ejemplo, pero el principio es el mismo para cualquier comstackdor. Construya por separado como C y C ++, respectivamente, luego vincule todo).

Permítanme recostackr los retazos de las otras respuestas y comentarios, para darles un ejemplo con códigos C y C ++ claramente separados:

La parte C:

foo.h :

 #ifndef FOO_H #define FOO_H void foo(void); #endif 

foo.c

 #include "foo.h" void foo(void) { /* ... */ } 

Comstack esto con gcc -c -o foo.o foo.c

La parte de C ++:

bar.cpp

 extern "C" { #include "foo.h" //a C header, so wrap it in extern "C" } void bar() { foo(); } 

Comstack esto con g++ -c -o bar.o bar.cpp

Y luego vincular todo junto:

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

Justificación: El código C debe ser código C simple, no #ifdef s para “tal vez algún día lo llame desde otro idioma”. Si algún progtwigdor de C ++ llama a tus funciones C, es su problema cómo hacerlo, no el tuyo. Y si usted es el progtwigdor de C ++, entonces el encabezado C podría no ser suyo y no debería cambiarlo, por lo que el manejo de nombres de funciones no registradas (es decir, el extern "C" ) pertenece a su código C ++.

Por supuesto, puede escribir usted mismo un encabezado C ++ de conveniencia que no hace más que ajustar el encabezado C en una statement extern "C" .

Estoy de acuerdo con la respuesta del profesor Falken , pero después del comentario de Arne Mertz quiero dar un ejemplo completo (la parte más importante es #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 // ... } 

Luego sigue las instrucciones del Prof. Falken para comstackr y vincular.

Esto funciona porque al comstackr con gcc , la macro __cplusplus no está definida, por lo que el encabezado somecode.h incluido en somecode.c es así después del preprocesamiento:

 void foo(void); 

y al comstackr con g++ , entonces __cplusplus está definido, y entonces el encabezado incluido en othercode.cpp ahora es así:

 extern "C" { void foo(void); } 

Esta respuesta está inspirada en un caso en el que la lógica de Arne era correcta. Un vendedor escribió una biblioteca que una vez admitió C y C ++; sin embargo, la última versión solo es compatible con C. Las siguientes directivas vestigiales que quedaron en el código fueron engañosas:

 #ifdef __cplusplus extern "C" { #endif 

Esto me costó varias horas intentar comstackr en C ++. Simplemente llamar a C desde C ++ fue mucho más fácil.

La convención ifdef __cplusplus infringe el principio de responsabilidad única. Un código que usa esta convención trata de hacer dos cosas a la vez:

  • (1) ejecuta una función en C – y –
  • (2) ejecuta la misma función en C ++

Es como tratar de escribir en inglés americano y británico al mismo tiempo. Esto innecesariamente arroja un #ifdef __thequeensenglish spanner #elif __yankeeenglish wrench #else una herramienta inútil que hace que el código sea más difícil de leer #endif en el código.

Para código simple y bibliotecas pequeñas, la convención ifdef __cplusplus puede funcionar; sin embargo, para bibliotecas complejas, lo mejor es seleccionar un idioma u otro y seguir con él. El soporte de uno de los idiomas requerirá menos mantenimiento que tratar de admitir ambos.

Este es un registro de las modificaciones que hice al código de Arne para que comstackra en Ubuntu Linux.

foo.h :

 #ifndef FOO_H #define FOO_H void foo(void); #endif 

foo.c

 #include "foo.h" #include  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