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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章