Вызов функции C из кода C++



У меня есть функция C, которую я хотел бы вызвать из C++. Я не мог использовать "extern "C" void foo() " вид подхода, потому что функция C не удалось скомпилировать с помощью g++. Но он прекрасно компилируется с помощью gcc. Любые идеи, как вызвать функцию из C++?

536   4  

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

    Ничего не найдено.