Stack overflow地址:Call a C function from C++ code - Stack Overflow
翻译:
我想要在C++中调用一个C语言的函数。我不能使用"extern "C" void foo()"子类的方法,因为C语言的函数使用g++编译失败。但是它使用gcc编译是成功的。有没有任何的注意关于如何在C++中调用这个函数?
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语言的函数时。所以 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函数,如何做是他的问题,不是你的问题。然而如果你是一个C++程序猿,C头文件可能不是你写的并且你不应该修改它,所以处理函数名(如: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
// ...
}
然后使用第二个答案的说明进行编译并链接;
它执行成功是因为使用gcc编译,宏__cplusplus没有被定义,所以包含在 somecode.cpp中的头文件 somecode.h在预处理之后看起来像这样:
void foo(void);
当使用g++编译的时候,__cplusplus将会被定义,所以在 somecode.cpp中包含的头文件现在像这样:
extern "C" {
void foo(void);
}
Answers4:
这个回答是基于第二个答案的原则部分是正确的而激发的。一个提供者写了一个库,它曾经支持C和C++;然而最新版本只支持C语言。在代码中留下的指令将会具有误导性:
#ifdef __cplusplus
extern "C" {
#endif
它花费了我好几个小时来尝试C++编译。简单的从C++中调用C是更容易的事情。
这个__cplusplus约定违反了单一责任原则。一个代码使用这个约定就是想同时做两件事情:
1.在C中执行一个函数;
2.执行相同的函数在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
网友评论