您的位置:首页 > 编程语言 > C语言/C++

C和C++混合编程FAQ

2016-04-25 22:00 423 查看

如何在
C++
中调用C函数?

仅仅只需要在你的C++代码中将要调用的C函数使用extern进行声明即可,代码如下:

//C++ code
extern "C" void f(int);   //方式一
extern "C" {              //方式二
int g(double);
double h();
}

void code(int i,double d)
{
f(i);
int ii = g(d);
double dd = h();
//........
}


在你的C代码中对上述几个调用的函数就行定义即可,定义如下:

// C code
void f(int i)
{
/*....*/
}

int g(double d)
{
/*....*/
}

double h()
{
/*....*/
}


如何在C中调用
C++
的函数?

在C++中定义的函数,需要显示的使用extern进行声明,目的是让编译器不对其进行名称mangle,代码如下:

// C++ code:
extern "C" void f(int);
void f(int i)
{
// ...
}


将上面的代码编译成动态库,然后交由C动态的去调用。下面是在C中如何去调用

/* C code: */
void f(int);
void cc(int i)
{
f(i);
/* ... */
}


C调用C++的非成员函数就用如上的方式即可完成,那么C如何去调用C++的类成员函数呢?代码如下:

#include <iostream>
using namespace std;

class C {
public:
virtual double f(int data)
{
cout << "Hello World" << endl;
}
};

extern "C" C* getC()
{
return new C();
}

extern "C" void delC(C *data)
{
delete data;
}

extern "C" double call_C_f(C* p,int i)
{
return p->f(i);
}


上面定义了一个class C,在这个class C中有我们需要调用的f函数,为了可以调用这个f函数,我们需要提供一个call_c_f这个函数。在这个函数中通过一个具体的对象指针来调用f函数,为了得到对象指针我们提供了getC函数来实例化一个class C,通过指针传递给C函数来使用。下面是C中调用C++的方法:

#include <stdio.h>

struct C;
/* C code: */
double call_C_f(struct C *p, int i);

struct C *getC();
void delC();
void ccc(struct C* p, int i)
{
double d = call_C_f(p,i);
/* ... */
}

int main()
{
struct  C * data = getC();
ccc(data,10);
delC(data);
}


首先是对call_C_f,getC,delC三个函数的一个声明,然后就是前向声明class C,因为C中没有class的概念,因此转而使用了struct。首先通过getC得到类C的对象指针,然后传递给call_C_f即可,在使用完成后调用delC释放对象指针。

到此为止C可以调用C++的非成员函数和成员函数了,那么如果去调用C++中的重载函数呢,这个比较简单,代码如下:

// C++ code:
void f(int);
void f(double);
extern "C" void f_i(int i) { f(i); }
extern "C" void f_d(double d) { f(d); }


其实就是给每一个重载的实列都包裹一下即可。就跟C调用C++的非成员函数一个样子。

如何在
C++
的代码中包含标准C的头文件?

在C++的代码中去包含标准C的头文件基本上不需要做什么特殊的改变,直接
#include
某个标准库文件即可,比如
stdio.h
,同样你可以使用

cstdio
。代码如下:

/* This is C code that I'm compiling using a C++ compiler */
#include <stdio.h>          /* Nothing unusual in #include line */
int main()
{
printf("Hello world\n");  /* Nothing unusual in the call either */
// ...
}


说白了
stdio.h
cstdio
的区别就是一个C版本的,一个是C++版本的,其中C++版本的就是将
stdio.h
中的内容加入到了C++的std命名空间中,下面的例子中包含了
cstdio
并引用了std命名空间中的
printf
函数

// This is C++ code
#include <cstdio>                // Nothing unusual in #include line
int main()
{
std::printf("Hello world\n");  // Nothing unusual in the call either
// ...
}


如何在
C++
代码中包含C非标准库头文件?

如果你要在你的C++代码中包含一些C的非标准库头文件,那么你需要使用
extern "C"
声明,告诉C++编译器头文件中包含的是C函数。

// This is C++ code
extern "C" {
// Get declaration for f(int i, char c, float x)
#include "my-C-code.h"
}
int main()
{
f(7, 'x', 3.14);   // Note: nothing unusual in the call
// ...
}


如何修改C的头文件让其可以直接在
C++
的代码中
#include

在C++中为了包含C的非标准库的头文件我们需要将头文件的包含语句放在
extern "C"
声明中,你一定很奇怪为什么C标准库不需要这样呢?因为C标准库中做了一些手脚,不信你可以看看
stdio.h
的源码,你会发现在这个头文件的开始有一个
__BEGIN_DECLS
,结尾有一个
__END_DECLS
。这两个宏的定义如下:

#if defined(__cplusplus)
#define __BEGIN_DECLS extern "C" {
#define __END_DECLS }
#else
#define __BEGIN_DECLS
#define __END_DECLS
#endif


哈哈,看到这里我相信大家应该明白了吧,如果
stdio.h
被包含在C++的代码中那么
__BEGIN_DECLS
__END_DECLS
就够成了一个
extern "C" {}
将整个头文件包含在里面了,就等同于
extern "C" {#include <stdio.h>}
。那么如何改造我们的头文件让其可以直接
#include
到C++的代码中呢?

Setp1: 将下面的这行放在头文件的开始处,通过判断是否有
__cpluscplus
判定是被包含在C代码中,还是C++代码中

#ifdef __cplusplus
extern "C" {
#endif


Setp2: 将下面的代码放在头文件的最下面

#ifdef __cpluscplus
}
#endif


到此为止你可以直接将一个非标准库的头文件
#include
到你的C++代码中了。

如何将
C++
中的类的对象传递给C函数?

下面是一个完整的示列。

/* This header can be read by both C and C++ compilers */
#ifndef FRED_H
#define FRED_H
#ifdef __cplusplus
class Fred {
public:
Fred();
void wilma(int);
private:
int a_;
};
#else
typedef
struct Fred
Fred;
#endif
#ifdef __cplusplus extern "C" { #endif
#if defined(__STDC__) || defined(__cplusplus)
extern void c_function(Fred*); /* ANSI C prototypes */
extern Fred* cplusplus_callback_function(Fred*);
#endif
#ifdef __cplusplus
}
#endif
#endif /*FRED_H*/


上面这个头文件可以被C和C++包含,当被C包含的时候就是一个
Fred
类和C风格的
c_function
cplusplus_callback_function
的声明。

// This is C++ code
#include "fred.h"
Fred::Fred() : a_(0) { }
void Fred::wilma(int a) { }
Fred* cplusplus_callback_function(Fred* fred)
{
fred->wilma(123);
return fred;
}


这是C++的Fred的类实现.

/* This is C code */
#include "fred.h"
void c_function(Fred* fred)
{
cplusplus_callback_function(fred);
}


这是一段C代码,包含了
fred.h
,因此有
struct Fred
声明,参考
如何在C中调用C++的函数?
一节。因为C中没有Class所以只能用struct来表示,并且Class在大多数情况下其内存布局都和C中的struct不一样,因此这里只能选择使用指针。

// This is C++ code
#include "fred.h"
int main()
{
Fred fred;
c_function(&fred);
// ...
}


这是一段C++代码,同样包含了
fred.h
,因此有了
class Fread
声明,
fred.c
是其定义, 同时还包含了C风格的
c_funcion
cplusplus_callback_function
声明,参考
如何在C++中调用C函数?
一节

Reference

How to mix C and C++
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息