转载来自:https://zhuanlan.zhihu.com/p/361485807
假设我们有一个C++类 Robot,在文件 robot.h 和 robot.cpp 中定义。Robot 类中有个成员函数 sayHi() 我们想在C程序中调用这个函数。
robot.h
#pragma once
#include <string>
class Robot
{
public:
Robot(std::string name) : name_(name) {}
void sayHi();
private:
std::string name_;
};
robot.cpp
#include <iostream>
#include "robot.h"
void Robot::sayHi()
{
std::cout << "Hi, I am " << name_ << "!n";
}
我们用编译C++代码的方式,使用 g++ 编译器对这个类进行编译,此时类 Robot 并不知道自己会被C程序调用。
g++ -fpic -shared robot.cpp -o librobot.so
接下来用C++创建一个C的接口,定义在 robot_c_api.h 和 robot_c_api.cpp 中,这个接口会定义一个C函数 Robot_sayHi(const char *name), 这个函数会创建一个类 Robot 的实例,并调用 Robot 的成员函数 sayHi()。
robot_c_api.h
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void Robot_sayHi(const char *name);
#ifdef __cplusplus
}
#endif
robot_c_api.cpp
#include "robot_c_api.h"
#include "robot.h"
#ifdef __cplusplus
extern "C" {
#endif
// 因为我们将使用C++的编译方式,用g++编译器来编译 robot_c_api.cpp 这个文件,
// 所以在这个文件中我们可以用C++代码去定义函数 void Robot_sayHi(const char *name)(在函数中使用C++的类 Robot),
// 最后我们用 extern "C" 来告诉g++编译器,不要对 Robot_sayHi(const char *name) 函数进行name mangling
// 这样最终生成的动态链接库中,函数 Robot_sayHi(const char *name) 将生成 C 编译器的符号表示。
void Robot_sayHi(const char *name)
{
Robot robot(name);
robot.sayHi();
}
#ifdef __cplusplus
}
#endif
同样用编译C++代码的方式进行编译
g++ -fpic -shared robot_c_api.cpp -L. -lrobot -o librobot_c_api.so
现在我们有了一个动态链接库 librobot_c_api.so, 这个动态链接库提供了一个C函数 Robot_sayHi(const char *name),我们可以在C程序中调用它了。
main.c
#include "robot_c_api.h"
int main()
{
Robot_sayHi("Alice");
Robot_sayHi("Bob");
return 0;
}
使用C程序的编译方式,用 gcc 对 main.c 进行编译
gcc main.c -L. -lrobot_c_api
可以看到 gcc 编译出的函数符号和 librobot_capi.so中 g++ 编译器编译出的函数符号一致。这样最终在我们的C程序中可以正确的链接到动态库中的Robot_sayHi(const char *name) 函数。
参考来源 https://stackoverflow.com/quest
原文链接: https://www.cnblogs.com/Galesaur-wcy/p/16426016.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/190266
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!