4 ответов:
скомпилируйте код C следующим образом:
gcc -c -o somecode.o somecode.cтогда код C++ такой:
g++ -c -o othercode.o othercode.cppзатем свяжите их вместе с компоновщиком C++:
g++ -o yourprogram somecode.o othercode.oвы также должны сообщить компилятору C++, что заголовок C приходит, когда вы включаете объявление для функции C. Так что
othercode.cppначинается с:extern "C" { #include "somecode.h" }
somecode.hдолжен содержать что-то вроде:#ifndef SOMECODE_H_ #define SOMECODE_H_ void foo(); #endif
(я использовал gcc в этом примере, но принцип работы одинаков для любого компилятора. Построить отдельно как C и C++ соответственно, а затем связать их вместе.)
позвольте мне собрать кусочки из других ответов и комментариев, чтобы дать вам пример с четко разделенным кодом C и c++:
Часть C:
фу.h:
#ifndef FOO_H #define FOO_H void foo(void); #endifфу.c
#include "foo.h" void foo(void) { /* ... */ }скомпилировать это с
gcc -c -o foo.o foo.c.Часть C++:
бар.cpp
extern "C" { #include "foo.h" //a C header, so wrap it in extern "C" } void bar() { foo(); }скомпилировать это с
g++ -c -o bar.o bar.cppи затем связать все это вместе:
g++ -o myfoobar foo.o bar.oобоснование: Код C должен быть простым кодом C, нет
#ifdefs Для "может быть, когда-нибудь я назову это с другого языка". Если какой-то программист C++ вызывает ваши функции C, это их проблема, как это сделать, не ваша. И если вы программист на C++, то заголовок C может быть не вашим, и вы не должны его менять, поэтому обработка незамутненных имен функций (т. е.extern "C") принадлежит в коде C++.вы может, конечно, написать себе удобный заголовок C++, который ничего не делает, кроме обертывания заголовка C в
extern "C"декларации.
я согласен с ответ профессора Фолкена, но после комментария Арне Мерца я хочу привести полный пример (самая важная часть -
#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) { /* ... */ }другие код.ГЭС
#ifndef HPP_OTHERCODE #define HPP_OTHERCODE void bar(); #endif /* HPP_OTHERCODE */другие код.cpp
#include "othercode.hpp" #include "somecode.h" void bar() { foo(); // call C function // ... }затем вы следуете инструкциям профессора Фолкена для компиляции и ссылка на сайт.
это работает, потому что при компиляции с
gccмакрос__cplusplusне определен, поэтому заголовокsomecode.hвходит вsomecode.cэто так после предварительной обработки:void foo(void);и при компиляции с
g++, потом__cplusplusи определено, и поэтому заголовок включен вothercode.cppтеперь так:extern "C" { void foo(void); }
этот ответ вдохновлен случаем, когда обоснование Арне было правильным. Поставщик написал библиотеку, которая когда-то поддерживала как C, так и C++; однако последняя версия поддерживала только C. Следующие рудиментарные директивы, оставленные в коде, вводили в заблуждение:
#ifdef __cplusplus extern "C" { #endifэто стоило мне нескольких часов, пытаясь скомпилировать в C++. Просто вызов C из C++ был намного проще.
конвенция ifdef __cplusplus нарушает принцип единой ответственности. Код используя это соглашение пытается сделать две вещи сразу:
- (1) выполнить функцию в C -- и...
- (2) выполняют ту же функцию в C++
это как пытаться писать на американском и Британском английском одновременно. Это излишне бросает #ifdef _ _ thequeensenglish spanner #elif __yankeeenglish wrench #else бесполезный инструмент, который затрудняет чтение кода #endif в код.
для простого кода и небольшие библиотеки соглашение ifdef __cplusplus может работать; однако для сложных библиотек лучше всего выбрать один язык или другой и придерживаться его. Поддержка одного из языков потребует меньше обслуживания, чем попытка поддержки обоих.
Это запись изменений, которые я сделал в коде Арне, чтобы получить его для компиляции на Ubuntu Linux.
фу.h:
#ifndef FOO_H #define FOO_H void foo(void); #endifфу.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"); }бар.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
Comments