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