Stack overflow地址:Call a C function from C++ code - Stack Overflow
翻譯:
我想要在C++中調用一個C語言的函數(shù)。我不能使用"extern "C" void foo()"子類的方法,因為C語言的函數(shù)使用g++編譯失敗。但是它使用gcc編譯是成功的。有沒有任何的注意關于如何在C++中調用這個函數(shù)?
Answers1:
編譯C代碼像這樣:
gcc -c -o somecode.o somecode.c
編譯C++代碼像這樣:
g++ -c -o othercode.o othercode.cpp
然后一起鏈接它們,使用C++ linker:
g++ -o yourprogram somecode.o othercode.o
你不得不告訴C++編譯器一個C語言的頭文件來了,在你include一個C語言的函數(shù)時。所以?othercode.cpp這么開始:
extern "C" {
#include "somecode.h"
}
somecode.h應該包括像下面的東西:
#ifndef SOMECODE_H_
#define SOMECODE_H_
void foo();
#endif
(在這個例子中,我使用了gcc編譯器,原則上來說其他任何編譯器是一樣的。分開編譯C和C++,然后一起鏈接它們)
Answers2:
其他讓我來收集一下其他回答和評論的點點滴滴,給你一個示例,清晰的分開C和C++代碼:
C模塊:
foo.h:
#ifndef FOO_H
#define FOO_H
void foo(void);
#endif
foo.c
#include "foo.h"
void foo(void)
{
? ? /* ... */
}
使用gcc -c -o foo.o foo.c.編譯。
C++模塊:
bar.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代碼,沒有 #ifdef對于“可能有一天我會從這里調用其他語言”。如果一個C++程序猿調用了你的C函數(shù),如何做是他的問題,不是你的問題。然而如果你是一個C++程序猿,C頭文件可能不是你寫的并且你不應該修改它,所以處理函數(shù)名(如:extern C)是屬于你的代碼。
你可能會寫一個你自己方便的C++頭,什么也不做只是用extern C封裝了一個C頭文件。
Answers3:
我同意第一個答案,但是看了第二個答案的評論之后我想要給出一個完整的示例(#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
? ? // ...
}
然后使用第二個答案的說明進行編譯并鏈接;
它執(zhí)行成功是因為使用gcc編譯,宏__cplusplus沒有被定義,所以包含在 somecode.cpp中的頭文件 somecode.h在預處理之后看起來像這樣:
void foo(void);
當使用g++編譯的時候,__cplusplus將會被定義,所以在 somecode.cpp中包含的頭文件現(xiàn)在像這樣:
extern "C" {
void foo(void);
}
Answers4:
這個回答是基于第二個答案的原則部分是正確的而激發(fā)的。一個提供者寫了一個庫,它曾經(jīng)支持C和C++;然而最新版本只支持C語言。在代碼中留下的指令將會具有誤導性:
#ifdef __cplusplus
extern "C" {
#endif
它花費了我好幾個小時來嘗試C++編譯。簡單的從C++中調用C是更容易的事情。
這個__cplusplus約定違反了單一責任原則。一個代碼使用這個約定就是想同時做兩件事情:
? ? 1.在C中執(zhí)行一個函數(shù);
? ? 2.執(zhí)行相同的函數(shù)在C++中。
這就好像同時想寫美國和英國的英語一樣。這是沒必要的通過#ifdef __thequeensenglish spanner #elif __yankeeenglish wrench #else的宏,這將使代碼很難讀到#endif在哪里。
對于簡單的代碼和庫使用 ifdef __cplusplus約定可能會很好的工作;但是,對于復雜的庫最好選擇一種語言或者另一種堅持下去。支持一種語言將會更少的去維護比嘗試支持多種語言。
下面是我對第一個答案的修改記錄,來讓它可以在 Ubuntu上編譯。
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