C 与 C++混合编程

1 C++ 调用 C 库

C++ 是 C 的超集,由于 C++ 具有函数重载等语法特性,使得编译器在进行 C++ 编译时与 C 的编译规则上有所不同。比如为了支持重载,编译器编译C++程序时要对函数名进行“重命名”,添加后缀的方式(后缀由参数的简写构成)以区别重载的函数。而编译器在编译 C 程序时,函数名不会改动。正是由于在函数名的“翻译规则”的不同导致 C++ 程序不能直接调用 C 编译生成的库文件,否则,会出现“undefined reference”。
C++ 调用 C 库比较简单,按照如下方法:

  • gcc编译c文件,g++编译cpp文件
  • 要将C库中的函数或变量的声明(或头文件)用 extern “C” { } 包裹起来, 被包裹的函数或变量在编译时会按照C的规则进行,保持与C库中符号的一致。

例子

文件结构:

  • main.cpp
  • addint.c
  • addfloat.c

将addint.c, addfloat.c封装成库,在main.cpp中调用

main.cpp:

#include <iostream>
#include <string>

extern "C"
{
    extern int addint(int, int);
    extern int addfloat(float, float);
}


class Test
{
public:
    Test()
    {
        std::cout<<"new Test"<<std::endl;
    }

    Test(int a, int b, float c, float d)
    {
        std::cout<<"new Test"<<std::endl;
        std::cout<<"a+b="<<addint(a,b)<<std::endl;
        std::cout<<"c+d="<<addfloat(c,d)<<std::endl;
    }

    ~Test()
    {

    }

};

int main()
{
    char** p;
    int a = 100, b = 200;
    float c = 222.2, d = 33.3;
    Test t(a,b,c,d);
    return 0;                                                                                                      
}

makefile:

main:
    gcc -fPIC -c addint.c
    gcc -fPIC -c addfloat.c
    ar -rcs libadd.a addint.o addfloat.o
    gcc -shared -fPIC -olibadd.so addint.o addfloat.o
    g++ main.cpp -omain -ladd -L.

.PHONY: clean
clean:
    rm -rf *.o *.so *.a main

2 C 调用 C++ 库

C 调用 C++ 库比较麻烦,必须编写一个接口文件。

具体方法:

  • gcc编译c文件,g++编译cpp文件
  • 编写接口文件(cpp文件),将C++接口转换成C接口
  • 最后链接 gcc … -lstdc++

接口文件格式:

#include "addclass.h"

#ifdef __cplusplus
extern "C" {
#endif

int addint(int a, int b)
{
    return Add(a, b).getsum(); // 转换函数实例,将C++接口转换成C接口
}    

#ifdef __cplusplus
}
#endif

例子

文件结构:

  • main.c
  • cpp2c.cpp (转换接口)
  • addclass.h
  • addclass.cpp

main.c:

/***************main.c********************/
#include <stdio.h>
extern int addint(int, int);

int main(int argc, char** argv)
{
printf("a+b=%d\n", addint(5, 1));
return 0;
}

cpp2c.cpp:

/*****************cpp2c.cpp***************/
#include "addclass.h"

#ifdef __cplusplus
extern "C" {
#endif

int addint(int a, int b)
{
return Add(a, b).getsum();
}

#ifdef __cplusplus
}
#endif

addclass.h:

/******************addclass.h***************/
#ifndef __ADD_H__
#define __ADD_H__

class Add
{
public:
int a, b;
Add(int a=100, int b=500);
~Add();
int getsum();
};
#endif

addclass.cpp:

/******************addclass.cpp*************/
#include "addclass.h"

Add::Add(int a, int b)
{
this->a=a;
this->b=b;
}
Add::~Add()
{

}
int Add::getsum()
{
return a+b;
}

makefile:

CFLAGS=-Imy_lib/include -Iinclude -fPIC
main: 
g++ $(CFLAGS) -c my_lib/src/addclass.cpp
g++ $(CFLAGS) -c src/cpp2c.cpp
gcc $(CFLAGS) -c src/main.c
ar -rcs libadd.a addclass.o cpp2c.o
gcc $(CFLAGS) -shared -olibadd.so addclass.o cpp2c.o
gcc $(CFLAGS) main.o -o$@ -ladd -lstdc++ -L.


.PHONY:clean

clean:
rm -rf *.o *.a *.so main

3 关于 extern “C”

extern “C” {…} 作用:一般出现在 cpp 文件中,并使用g++编译。告诉g++编译器其中声明的函数和变量采用C的编译规则进行编译。
extern 详细解释参考:https://wapbaike.baidu.com/item/extern/4443005?fr=aladdin&ms=1&rid=11066791522680133247&from=singlemessage

猜你喜欢

转载自blog.csdn.net/healingwounds/article/details/84475492