C/C++混合编程

时间:2022-11-02 08:21:42

C中调用C++,C++中调用C都会用到extern "C",但两者的意义却大不一样!!


先介绍在C++中调用C,这个大家都比较熟悉:

例:

//C代码

void foo( int x );

//C++代码

//C++ code
extern "C" void foo( int x );
让C++连接器能通过过类似于_foo来查找此函数,而非类似于_foo_int这样的符号。



使用extern "C"则是告诉编译器依照C的方式来编译封装接口,当然接口函数里面的C++语法还是按C++方式编译。使用extern "C"则是告诉编译器依照C的方式来编译封装接口,当然接口函数里面的C++语法还是按C++方式编译。


再来说说C中调用C++,这其中也会用到extern "C",这则是告诉编译器依照C的方式来编译封装接口,当然接口函数里面的C++语法还是按C++方式编译。

C++代码:(非成员函数)

extern "C" int foo( int x );
int foo( int x )
{
   //...
}
这样,编译器会将foo函数编译成类似_foo符号,而不会编译成类似_foo_int符号。


C代码

int foo( int x );
void cc( int x )
{
    foo( x );
    //...
}


如果你想要在 C 里调用成员函数(包括虚函数),则需要提供一个简单的包装(wrapper)。例如:

// C++ code:

class C

{

       // ...

       virtual double f(int);

};

 

extern "C" double call_C_f(C* p, int i) // wrapper function

{

       return p->f(i);

}

然后,你就可以这样调用 C::f():

/* C code: */

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

 

void ccc(struct C* p, int i)

{

       double d = call_C_f(p,i);

       /* ... */

} 



如果你想在 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); } 

然后,你可以这样使用每个重载的 f():


/* C code: */

void f_i(int);

void f_d(double);

 

void cccc(int i,double d)

{

       f_i(i);

       f_d(d);

       /* ... */

} 


参考文献:

Bjarne Stroustrup的原文链接地址是 http://www.research.att.com/~bs/bs_faq2.html#callCpp



下面就一个例子,来介绍一下C调用C++的过程:

// cpp.h
#ifndef  __cpp_h__
#define  __cpp_h__

class  class1 {
    class1();
    ~class1();
public:
    int  I;
    int  J;

    int  getI(void);
};

#endif
// end file

// cpp.cpp
#i nclude "stdafx.h"
#i nclude  <iostream>
#i nclude  "cpp.h"
#i nclude  "c.h"

using namespace  std;       // 打开标准库名字空间

class1::class1()
{}

class1::~class1()
{}

int  class1::getI(void)
{
    return  I++;
}

// 按 C 调用方式编译下面函数
extern "C"
int  get_class1_I(struct1 * p)
{
    class1 * pClass1 = (class1 *)p;

    cout << "c++: " << pClass1->getI() << endl;

    return  pClass1->getI();
}

// end file

// c.h
#ifndef  __c_h__
#define  __c_h__

#ifdef  __cplusplus
extern "C" {
#endif

    typedef struct {
        int  i;             // 与 class1 类中变量一致
  int  j;
    }struct1;

#ifdef  __cplusplus
}
#endif
#endif
// end file

// c.c
#i nclude  <cstdio>
#i nclude  "c.h"

extern  int  get_class1_I(void * p);

struct1  s;

int  main(void)
{
    printf ("c: %d\n", get_class1_I(&s));
    printf ("c: %d\n", get_class1_I(&s));
 
    return 0;
}

// end file
在linux下,执行:

gcc -c c.c
g++ -c cpp.cpp
gcc -lstdc++ c.o cpp.o -o result