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++中定义的函数,需要显示的使用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++
的代码中#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函数?
一节
How to mix C and C++