从c++代码调用一个C函数。

时间:2022-09-01 15:45:09

I have a C function that I would like to call from C++. I couldn't use "extern "C" void foo()" kind of approach because the C function failed to be compiled using g++. But it compiles fine using gcc. Any ideas how to call the function from C++?

我有一个C函数,我想从c++调用它。我不能使用“extern”C“void foo()”之类的方法,因为使用g++无法编译C函数。但是使用gcc编译很好。你知道怎么从c++调用函数吗?

4 个解决方案

#1


85  

Compile the C code like this:

像这样编译C代码:

gcc -c -o somecode.o somecode.c

Then the C++ code like this:

然后是这样的c++代码:

g++ -c -o othercode.o othercode.cpp

Then link them together, with the C++ linker:

然后链接到一起,与c++链接器:

g++ -o yourprogram somecode.o othercode.o

You also have to tell the C++ compiler a C header is coming when you include the declaration for the C function. So othercode.cpp begins with:

当包含C函数的声明时,还必须告诉c++编译器一个C头。所以othercode。cpp始于:

extern "C" {
#include "somecode.h"
}

somecode.hshould contain something like:

somecode。hshould包含类似:

 #ifndef SOMECODE_H_
 #define SOMECODE_H_

 void foo();

 #endif


(I used gcc in this example, but the principle is the same for any compiler. Build separately as C and C++, respectively, then link it together.)

#2


40  

Let me gather the bits and pieces from the other answers and comments, to give you an example with cleanly separated C and C++ code:

让我从其他的答案和评论中收集一些零碎的信息,给你一个清晰地分开的C和c++代码的例子:

The C Part:

foo.h:

foo。:

#ifndef FOO_H
#define FOO_H

void foo(void);

#endif 

foo.c

foo.c

#include "foo.h"

void foo(void)
{
    /* ... */
}

Compile this with gcc -c -o foo.o foo.c.

使用gcc -c -o foo编译它。o foo.c。

The C++ Part:

bar.cpp

bar.cpp

extern "C" {
  #include "foo.h" //a C header, so wrap it in extern "C" 
}

void bar() {
  foo();
}

Compile this with g++ -c -o bar.o bar.cpp

使用g+ -c -o bar编译。o bar.cpp

And then link it all together:

然后把它们连在一起:

g++ -o myfoobar foo.o bar.o

Rationale: The C code should be plain C code, no #ifdefs for "maybe some day I'll call this from another language". If some C++ programmer calls your C functions, it's his problem how to do that, not yours. And if you are the C++ programmer, then the C header might not be yours and you should not change it, so the handling of unmangled function names (i.e. the extern "C") belongs in your C++ code.

基本原理:C代码应该是纯C代码,而不是#ifdefs,表示“也许有一天我会从另一种语言调用它”。如果某个c++程序员调用了您的C函数,那么他的问题是如何做到这一点,而不是您的问题。如果您是c++程序员,那么C头可能不是您的,您不应该更改它,因此处理未损坏的函数名(例如,extern“C”)应该属于您的c++代码。

You might of course write yourself a convenience C++ header that does nothing but wrap the C header into an extern "C" declaration.

当然,您可以为自己编写一个方便的c++头文件,它除了将C头文件封装到一个extern“C”声明中之外,没有任何作用。

#3


16  

I agree with Prof. Falken's answer, but after Arne Mertz's comment I want to give a complete example (the most important part is the #ifdef __cplusplus):

我同意福尔肯教授的回答,但在Arne Mertz的评论之后,我想给出一个完整的例子(最重要的部分是#ifdef __cplusplus):

somecode.h

somecode.h

#ifndef H_SOMECODE
#define H_SOMECODE

#ifdef __cplusplus
extern "C" {
#endif

void foo(void);

#ifdef __cplusplus
}
#endif

#endif /* H_SOMECODE */

somecode.c

somecode.c

#include "somecode.h"

void foo(void)
{
    /* ... */
}

othercode.hpp

othercode.hpp

#ifndef HPP_OTHERCODE
#define HPP_OTHERCODE

void bar();

#endif /* HPP_OTHERCODE */

othercode.cpp

othercode.cpp

#include "othercode.hpp"
#include "somecode.h"

void bar()
{
    foo(); // call C function
    // ...
}

Then you follow Prof. Falken's instructions to compile and link.

然后按照福尔肯教授的指示进行编译和链接。

This works because when compiling with gcc, the macro __cplusplus is not defined, so the header somecode.h included in somecode.c is like this after preprocessing:

这之所以有效,是因为在使用gcc编译时,宏__cplusplus没有定义,所以头是somecode。h somecode中。c经过预处理后是这样的:

void foo(void);

and when compiling with g++, then __cplusplus is defined, and so the header included in othercode.cpp is now like that:

当使用g++编译时,就定义了__cplusplus,因此包含在其他代码中的头。cpp现在是这样的:

extern "C" {

void foo(void);

}

#4


0  

This answer is inspired by a case where Arne's rationale was correct. A vendor wrote a library which once supported both C and C++; however, the latest version only supported C. The following vestigial directives left in the code were misleading:

这个答案的灵感来源于阿恩的理论是正确的。一个供应商编写了一个库,该库曾经支持C和c++;但是,最新版本只支持c。

#ifdef __cplusplus
extern "C" {
#endif

This cost me several hours trying to compile in C++. Simply calling C from C++ was much easier.

用c++编译需要花费几个小时。简单地从c++调用C要容易得多。

The ifdef __cplusplus convention is in violation of the single responsibility principle. A code using this convention is trying to do two things at once:

ifdef __cplusplus公约违反了单一责任原则。使用这个约定的代码试图同时做两件事:

  • (1) execute a function in C -- and --
  • (1)用C -和-执行一个函数
  • (2) execute the same function in C++
  • (2)在c++中执行相同的函数

It's like trying to write in both American and British English at the same time. This is unnecessarily throwing an #ifdef __thequeensenglish spanner #elif __yankeeenglish wrench #else a useless tool which makes the code harder to read #endif into the code.

这就像试图同时用美式英语和英式英语写作一样。这毫无必要地将一个#ifdef __thequeensenglish spanner #elif __yankeeenglish扳手#else作为一个无用的工具,使代码更难读到#endif代码。

For simple code and small libraries the ifdef __cplusplus convention may work; however, for complex libraries it is best to pick one language or the other and stick with it. Supporting one of the languages will take less maintenance than trying to support both.

对于简单的代码和小型库,ifdef __cplusplus约定可能有效;但是,对于复杂的库,最好选择一种或另一种语言并坚持使用它。支持其中一种语言比同时支持这两种语言需要更少的维护。

This is a record of the modifications I made to Arne's code to get it to compile on Ubuntu Linux.

这是我对Arne代码做的修改的记录,让它在Ubuntu Linux上编译。

foo.h:

foo。:

#ifndef FOO_H
#define FOO_H

void foo(void);

#endif 

foo.c

foo.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");
}

bar.cpp

bar.cpp

extern "C" {
    #include "foo.h" //a C header, so wrap it in extern "C" 
}

int main() {
  foo();
  return(0);
}

Makefile

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

#1


85  

Compile the C code like this:

像这样编译C代码:

gcc -c -o somecode.o somecode.c

Then the C++ code like this:

然后是这样的c++代码:

g++ -c -o othercode.o othercode.cpp

Then link them together, with the C++ linker:

然后链接到一起,与c++链接器:

g++ -o yourprogram somecode.o othercode.o

You also have to tell the C++ compiler a C header is coming when you include the declaration for the C function. So othercode.cpp begins with:

当包含C函数的声明时,还必须告诉c++编译器一个C头。所以othercode。cpp始于:

extern "C" {
#include "somecode.h"
}

somecode.hshould contain something like:

somecode。hshould包含类似:

 #ifndef SOMECODE_H_
 #define SOMECODE_H_

 void foo();

 #endif


(I used gcc in this example, but the principle is the same for any compiler. Build separately as C and C++, respectively, then link it together.)

#2


40  

Let me gather the bits and pieces from the other answers and comments, to give you an example with cleanly separated C and C++ code:

让我从其他的答案和评论中收集一些零碎的信息,给你一个清晰地分开的C和c++代码的例子:

The C Part:

foo.h:

foo。:

#ifndef FOO_H
#define FOO_H

void foo(void);

#endif 

foo.c

foo.c

#include "foo.h"

void foo(void)
{
    /* ... */
}

Compile this with gcc -c -o foo.o foo.c.

使用gcc -c -o foo编译它。o foo.c。

The C++ Part:

bar.cpp

bar.cpp

extern "C" {
  #include "foo.h" //a C header, so wrap it in extern "C" 
}

void bar() {
  foo();
}

Compile this with g++ -c -o bar.o bar.cpp

使用g+ -c -o bar编译。o bar.cpp

And then link it all together:

然后把它们连在一起:

g++ -o myfoobar foo.o bar.o

Rationale: The C code should be plain C code, no #ifdefs for "maybe some day I'll call this from another language". If some C++ programmer calls your C functions, it's his problem how to do that, not yours. And if you are the C++ programmer, then the C header might not be yours and you should not change it, so the handling of unmangled function names (i.e. the extern "C") belongs in your C++ code.

基本原理:C代码应该是纯C代码,而不是#ifdefs,表示“也许有一天我会从另一种语言调用它”。如果某个c++程序员调用了您的C函数,那么他的问题是如何做到这一点,而不是您的问题。如果您是c++程序员,那么C头可能不是您的,您不应该更改它,因此处理未损坏的函数名(例如,extern“C”)应该属于您的c++代码。

You might of course write yourself a convenience C++ header that does nothing but wrap the C header into an extern "C" declaration.

当然,您可以为自己编写一个方便的c++头文件,它除了将C头文件封装到一个extern“C”声明中之外,没有任何作用。

#3


16  

I agree with Prof. Falken's answer, but after Arne Mertz's comment I want to give a complete example (the most important part is the #ifdef __cplusplus):

我同意福尔肯教授的回答,但在Arne Mertz的评论之后,我想给出一个完整的例子(最重要的部分是#ifdef __cplusplus):

somecode.h

somecode.h

#ifndef H_SOMECODE
#define H_SOMECODE

#ifdef __cplusplus
extern "C" {
#endif

void foo(void);

#ifdef __cplusplus
}
#endif

#endif /* H_SOMECODE */

somecode.c

somecode.c

#include "somecode.h"

void foo(void)
{
    /* ... */
}

othercode.hpp

othercode.hpp

#ifndef HPP_OTHERCODE
#define HPP_OTHERCODE

void bar();

#endif /* HPP_OTHERCODE */

othercode.cpp

othercode.cpp

#include "othercode.hpp"
#include "somecode.h"

void bar()
{
    foo(); // call C function
    // ...
}

Then you follow Prof. Falken's instructions to compile and link.

然后按照福尔肯教授的指示进行编译和链接。

This works because when compiling with gcc, the macro __cplusplus is not defined, so the header somecode.h included in somecode.c is like this after preprocessing:

这之所以有效,是因为在使用gcc编译时,宏__cplusplus没有定义,所以头是somecode。h somecode中。c经过预处理后是这样的:

void foo(void);

and when compiling with g++, then __cplusplus is defined, and so the header included in othercode.cpp is now like that:

当使用g++编译时,就定义了__cplusplus,因此包含在其他代码中的头。cpp现在是这样的:

extern "C" {

void foo(void);

}

#4


0  

This answer is inspired by a case where Arne's rationale was correct. A vendor wrote a library which once supported both C and C++; however, the latest version only supported C. The following vestigial directives left in the code were misleading:

这个答案的灵感来源于阿恩的理论是正确的。一个供应商编写了一个库,该库曾经支持C和c++;但是,最新版本只支持c。

#ifdef __cplusplus
extern "C" {
#endif

This cost me several hours trying to compile in C++. Simply calling C from C++ was much easier.

用c++编译需要花费几个小时。简单地从c++调用C要容易得多。

The ifdef __cplusplus convention is in violation of the single responsibility principle. A code using this convention is trying to do two things at once:

ifdef __cplusplus公约违反了单一责任原则。使用这个约定的代码试图同时做两件事:

  • (1) execute a function in C -- and --
  • (1)用C -和-执行一个函数
  • (2) execute the same function in C++
  • (2)在c++中执行相同的函数

It's like trying to write in both American and British English at the same time. This is unnecessarily throwing an #ifdef __thequeensenglish spanner #elif __yankeeenglish wrench #else a useless tool which makes the code harder to read #endif into the code.

这就像试图同时用美式英语和英式英语写作一样。这毫无必要地将一个#ifdef __thequeensenglish spanner #elif __yankeeenglish扳手#else作为一个无用的工具,使代码更难读到#endif代码。

For simple code and small libraries the ifdef __cplusplus convention may work; however, for complex libraries it is best to pick one language or the other and stick with it. Supporting one of the languages will take less maintenance than trying to support both.

对于简单的代码和小型库,ifdef __cplusplus约定可能有效;但是,对于复杂的库,最好选择一种或另一种语言并坚持使用它。支持其中一种语言比同时支持这两种语言需要更少的维护。

This is a record of the modifications I made to Arne's code to get it to compile on Ubuntu Linux.

这是我对Arne代码做的修改的记录,让它在Ubuntu Linux上编译。

foo.h:

foo。:

#ifndef FOO_H
#define FOO_H

void foo(void);

#endif 

foo.c

foo.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");
}

bar.cpp

bar.cpp

extern "C" {
    #include "foo.h" //a C header, so wrap it in extern "C" 
}

int main() {
  foo();
  return(0);
}

Makefile

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