Вызов функции C из кода C++
У меня есть функция c/" class="blnk">C, которую я хотел бы вызвать из C++. Я не мог использовать "extern "C" void foo()
" вид подхода, потому что функция C не удалось скомпилировать с помощью g++. Но он отлично компилируется с помощью gcc. Любые идеи, как вызвать функцию из C++?
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, no #ifdef
s Для "может быть, когда-нибудь я назову это с другого языка". Если какой-то программист 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
is определено, и поэтому заголовок включен в 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 гаечный ключ #elif _ _ yankeeenglish гаечный ключ #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);
}
make-файл
# -*- 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