从C ++代码调用C函数

时间:2013-05-31 06:27:21

标签: c++ c linux extern-c

我有一个C函数,我想从C ++调用。我无法使用“extern "C" void foo()”方法,因为C函数无法使用g ++编译。但它使用gcc编译很好。有关如何从C ++调用函数的任何想法吗?

4 个答案:

答案 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 ++代码的例子:

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 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约定违反了单一责任原则。使用此约定的代码试图一次做两件事:

  • (1)在C中执行一个功能 - 和 -
  • (2)在C ++中执行相同的功能

这就像尝试用美式英语和英式英语同时写作一样。这不必要地抛出#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");
}