C语言调用C++程序库,实例说明

有时候需要在C程序下调用C++的库,看了很多文章,要么说的太深入和冗余导致不能一下子理解,要么是举例子太简单导致没有理解还是不会使用,所以这篇博客取二者折中,给出简单易懂的解释,并给出实例。

首先,C和C++编译一个函数之后产生的函数名字是不同的,所以二者不能通用,即使用C++去调用C程序编译好的的动态库也是不可以的,反过来就更不可以了。那么C怎么调用C++呢?答案就是写一个接口程序,这个接口程序的interface.cpp文件负责将C++库的具体函数封装为C函数,头文件interface.h被main函数调用。看例子最简单,一起来看。

首先假设有C++程序test.cpptest.hpp

// test.hpp 文件内容:定义了ClassA类
class ClassA{
   public:
      void func(int a);
};
// test.cpp 文件内容:实现了ClassA::func(int a)函数
#include <iostream>
#include "test.hpp"
using namespace std;

void ClassA::func(int a){
   cout<<"class A: "<<a<<endl;
}

假设这个就是我们已有的一个C++程序,那么怎样在C程序main.c中调用它呢?答案是写一个接口interface

// interface.h文件内容
#ifdef __cplusplus
extern "C"{
#endif

void func(int a);

#ifdef __cplusplus
}
#endif
// interface.cpp 文件内容
#include "test.hpp"
#include "interface.h"
void func(int a){
   ClassA c;
   c.func(a);
}

上面interface.h就是连接C++库和C程序的桥梁,这里面extern "C"{}括起来的部分意思就是用编译C程序的方式进行编译,extern "C"{}语句是在定义了宏__cplusplus的情况下启用,而这个宏是在使用g++进行编译时自动会定义的。如果是用以C语言方式进行编译,则不会定义宏__cplusplus,自然也没有启用extern "C"{}(C语言不识别extern "C"{},所以需要用宏来开关)。Interface.cpp中将test.cpp程序中的C++函数封装为C形式的函数,用于main中调用。

这里你可以注意到,Interface的实现文件是.cpp,而头文件是.h,这正是为了用.cpp连接C++库,而.h给C程序用。读到这里确实绕,你可以暂时理解个大概,等讲到main函数我们再回头捋一遍就明白了。此时可以将C++库和接口共同编译为libtest.so动态库

g++ test.cpp interface.cpp -shared -fPIC -o libtest.so

终于到了main函数,如下

// main.c 文件内容
#include "interface.h"
int main()
{
   func(1);
}

现在我们要编译main函数需要如下:

gcc main.c ./libtest.so -o main

即实现了C语言程序调用C++程序库。现在我们总结一下,就是要写一个封装接口,接口的具体实现cpp文件用于将C++程序库封装成C程序可读的接口,接口的头文件.h用于被C程序调用。那么读者会疑问,为什么多此一举在interface.h中加上__cplusplus宏定义控制开关的extern "C"。这是因为interface.h同时被interface.cppmain.c调用,前者需要按照C++方式编译,后者需要按照C方式编译,需要开关

别找其他教程了,这篇博客是你能找到最有可能帮你理解extern "C"的文章了,反复读几遍加上动手实现一下就明白了。


备注
1.gcc和g++的区别并不是前者用于编译c程序,后者用于编译c++程序,对于简单的.cpp程序,用gcc也能编译通过。g++的内核仍然是gcc,只是默认增加了一些宏定义和库。总之,不能将gcc简单看为用于编译c程序,g++用于编译c++程序。感兴趣读者可以查阅更详细资料。

猜你喜欢

转载自blog.csdn.net/Meiyuan2021/article/details/129864332