我有一个C函数,我想从C ++调用。我无法使用“extern "C" void foo()
”方法,因为C函数无法使用g ++编译。但它使用gcc编译很好。有关如何从C ++调用函数的任何想法吗?
答案 0 :(得分:103)
像这样编译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 ++构建,然后将它们链接在一起。)
答案 1 :(得分:53)
让我从其他答案和评论中收集点点滴滴,给你一个干净分离的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
编译。
<强> 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
s代表“也许有一天我会用另一种语言来调用它”。如果某个C ++程序员调用你的C函数,那么他们的问题是如何做到的,而不是你的。如果您是C ++程序员,那么C头可能不是您的,您不应该更改它,因此处理未编码的函数名(即extern "C"
)属于您的C ++代码。
当然,您可能会为自己编写一个方便的C ++标头,除了将C标头包装到extern "C"
声明中之外什么都不做。
答案 2 :(得分:16)
我同意Prof. Falken's answer,但在Arne Mertz发表评论之后,我想提供一个完整的例子(最重要的部分是#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
// ...
}
然后你按照Falken教授的指示进行编译和链接。
这是有效的,因为在使用gcc
进行编译时,未定义宏__cplusplus
,因此somecode.h
中包含的标题somecode.c
在预处理后就像这样:
void foo(void);
并且在使用g++
进行编译时,__cplusplus
已定义,因此othercode.cpp
中包含的标头现在就是这样:
extern "C" {
void foo(void);
}
答案 3 :(得分:0)
这个答案的灵感来自于Arne的理由是正确的。供应商编写了一个曾经支持C和C ++的库;但是,最新版本仅支持C.以下在代码中留下的残留指令具有误导性:
.criteria {
height: 400px;
}
.columnOne {
float: left;
width: 30%;
max-width: 300px;
min-width: 300px;
box-sizing: border-box;
/*whatever element it is applied to...*/
padding: 0 0 0 10px;
}
.columnTwo {
float: left;
width: 20%;
box-sizing: border-box;
/*whatever element it is applied to...*/
border-top: 0;
border-bottom: 0;
border-left: 3px solid blue;
border-right: 3px solid blue;
padding: 0 0 0 10px;
}
.columnThree {
float: left;
width: 50%;
box-sizing: border-box;
/*whatever element it is applied to...*/
border-top: 0;
border-bottom: 0;
border-left: 0;
padding: 0 0 0 10px;
}
/* Clear floats after the columns */
.criteria:after {
content: "";
display: table;
clear: both;
}
/* Responsive layout - makes the two columns stack on top of each other instead of next to each other */
@media (max-width: 600px) {
.columnOne,
.columnTwo,
.columnThree {
width: 100%;
}
}
这花了我几个小时尝试用C ++编译。简单地从C ++调用C就容易多了。
ifdef __cplusplus约定违反了单一责任原则。使用此约定的代码试图一次做两件事:
这就像尝试用美式英语和英式英语同时写作一样。这不必要地抛出#ifdef __thequeensenglish扳手#elif __yankeeenglish扳手#else一个无用的工具,这使得代码更难以将#endif读入代码中。
对于简单代码和小型库,ifdef __cplusplus约定可能有效;但是,对于复杂的库,最好选择一种语言或另一种语言并坚持下去。支持其中一种语言所需的维护费用比试图支持这两种语言要少。
这是我对Arne的代码进行的修改记录,以便在Ubuntu Linux上进行编译。
<强> foo.h中强>:
<div class="criteria">
<div class="columnOne">
<h2>Column 1</h2>
<select multiple name="xyz" id="xyz" size="15" style="border:none; background-color:transparent; width:100%;"></select>
</div>
<div class="columnTwo">
<h2>Column 2</h2>
<div style="overflow:auto; ">
<select multiple name="xyz1" id="xyz1" size="15" style="border:none; background-color:transparent; width:100%;"></select>
</div>
</div>
<div class="columnThree">
<h2>Column 3</h2>
<div style="overflow:auto; height:150px">...breakup top column...</div>
<div style="overflow:auto; height:250px">...breakup bottom column...</div>
</div>
</div>
<div style="margin-left:10px;">
<b>next section starts here :</b>
<input id="rem" name="rem" style="width:390px">
<br />
<span style="font-style:italic;color:green;margin-left:130px;font-size:12px;">(nad)</span>
<p>
<button type="button" id="remd">btn</button><span id="Err" style="display:none;font-style:italic;color:red;margin-left:5px;">Please fix errors.</span>
<br/>
<p>
</div>
<强> foo.c的强>
#ifdef __cplusplus
extern "C" {
#endif
<强> bar.cpp 强>
#ifndef FOO_H
#define FOO_H
void foo(void);
#endif
<强>生成文件强>
#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");
}