C与C++接口间相互调用

    项目中经常使用C和C++混合编程,那么,在调用对方接口时,总是不可避免地出现问题。为了让双方和谐地工作,就得用到extern "C"。

1 问题

    在C++中,为了支持重载机制,在编译时,要对函数的名字进行一些处理,比如加入函数的返回类型等来加以区别;在C中,只是简单的函数名字而已。如函数void func(int i),C++会把它编译成类似_fun_int或_xxx_funIxxx这样的增加了参数类型的符号,这也是C++可以实现重载的原因;C则把该函数编译成类似_fun的符号,C链接器只要找到该函数符号就可以链接成功,它假设参数类型信息是正确的。故而,关键问题是,C和C++在编译时生成函数名字的方式是不同的。

2 方法

    extern "C"是C++的特性,是一种链接约定,它并不影响调用函数的定义,即使做了该声明,对函数类型的检查和参数转换仍要遵循C++的标准,而不是C。主要是为了解决C++在调用C函数库时,用C++直接链接就会出现不能识别符号的问题,而用上extern "C"后,告诉C++编译器要以C语言的方式编译和链接函数,即直接使用函数名而不是一个经过处理的函数名。

3 示例

3.1 C++中调用C接口

代码:

/***** C头文件c.h *****/
#ifndef  _C_H_
#define _C_H_

#ifdef __cplusplus    /*C++编译器包含的宏,例如用g++编译时,该宏就存在,则下面的语句extern "C"才会被执行*/
extern "C" {          /*C++编译器才能支持,C编译器不支持*/
#endif

void C_fun();

#ifdef __cplusplus
}
#endif

#endif
/***** C源文件c.c *****/
#include "c.h"
void C_fun()
{
    /*dosomething*/
}
功能:在文件cpp.cpp中调用文件c.c中的函数C_fun()
/****** C++源文件cpp.cpp ******/
#include "c.h"
int main()
{
     C_fun()
}
编译: g++ cpp.cpp c.c

3.2 C中调用C++接口

代码:

/**** C++头文件 cpp.h *****/
#ifndef  CPP_H
#define CPP_H

extern "C" int add( int x, int y );

#endif
/**** C++源文件 cpp.cpp *****/
#include "cpp.h"
int add( int x, int y )
{
    return x + y;
}
功能:C文件中调用C++的接口
/**** C源文件c.c *****/
extern int add( int x, int y );
int main( int argc, char* argv[])
{
    
}
编译:gcc c.c cpp.cpp

3.3 C++中调用C库的函数

代码:

/*C库源文件: hello.c*/
#include 
void func()
{
    printf("hello,world!\n");
}
编译:gcc --shared -o libhello.so hello.c
/*C++源文件test.cpp中调用C库的函数*/
#include 

#ifdef __cplusplus
extern "C" {               // 告诉编译器下列代码要以C链接约定的模式进行链接
#endif

void func();

#ifdef __cplusplus
}
#endif

int main()
{
    func();

    return 0;
}
编译:g++ test.cpp -o test -lhello

3.4 C中调用C++库的函数

1)C++库代码

/*C++库源文件hello.cpp*/
#include 

void funcpp()
{
  std::cout << "hello, world" << std::endl;
}
编译:g++ --shared -o libhello.so hello.cpp
2)中间接口库,对C++库进行二次封装

/*中间接口库 mid.cpp*/
#include 

void funcpp();

#ifdef __cplusplus
extern "C" {  // 即使这是一个C++程序,下列这个函数的实现也要以C约定的风格来搞!
#endif

void m_funcpp()
{
    funcpp();
}

#ifdef __cplusplus
}
#endi
编译:g++ --shared -o libmid.so mid.cpp -lhello
3)C通过链接二次接口库调用C++库

/*C源文件test.c*/
#include 

int main()
{
    m_funcpp();

    return 0;
}
编译:gcc test.c -l mid -o test




你可能感兴趣的:(C/C++)