c++代码能可靠地与其他c++代码交互吗?

Can C++ code reliably interact with other C++ code?

本文关键字:c++ 代码 交互 其他      更新时间:2023-10-16

在C中,我习惯于编写一个共享库,只要连接库并包含相关的头文件,就可以从任何希望使用它的客户端代码调用该库。然而,我读到c++的ABI太不稳定,不标准,无法可靠地从其他来源调用函数。

这将使我相信在c++中创建像C一样通用的真正的共享库是不可能的,但现实世界的实现似乎表明情况并非如此。例如,Node.js公开了一个非常简单的模块系统,允许使用NODE_SET_METHOD函数动态导出普通的c++函数(不含extern "C")。

c++ API的哪些元素是可以安全公开的,如果有的话,允许c++代码与其他c++代码交互的常用方法是什么?是否有可能创建可以公开c++类的共享库?或者由于不一致的ABI,必须为每个程序单独重新编译这些类?

是的,c++互操作很困难,而且充满了陷阱。冷硬性规则是必须使用完全相同的编译器版本和完全相同的编译器设置来构建模块,并确保它们共享完全相同的CRT和标准c++库。打破这些规则往往会让你的c++类在划分的两端都没有相同的布局,并且当一个模块使用与删除对象的模块不同的分配器分配对象时,会出现内存管理问题。当代码使用错误的偏移量访问类成员并泄漏内存或破坏堆时,导致很难诊断运行时故障的问题。

Node.js避免了这些问题,首先导出任何东西。NODE_SET_METHOD()不做您认为它做的事情,它只是向Javascript引擎的符号表添加一个符号,以及在脚本中调用函数时调用的函数指针。此外,它是一个开源项目,所以用相同的编译器和运行库构建所有不是问题。

This

例如,Node.js公开了一个非常简单的模块系统,允许可以动态导出普通c++函数(不带外部"C")使用NODE_SET_METHOD函数。

是错误的,你可以看到他们在init()函数中使用了一个extern "C",这显然是node.js正在调用的,然后将函数转发到他们想要的任何c++函数,这是不暴露的。

正如在这个问题中所解释的,extern "C"申报工作吗?当编译器编译代码时,它会混淆函数名、类名和命名空间名。这样做的原因是很容易出现名称冲突,例如重载函数。

在这里阅读更多内容:http://en.wikipedia.org/wiki/Name_mangling

引用和查找函数的唯一方法是使用extern "C"声明,这强制编译器不修改名称。例如,在上面的例子中,函数init将被称为init,而函数foo将被称为类似_ugAGE的东西(我编了这个,因为它无关紧要,它不是供人类使用的)

总而言之,您可以将任何c++暴露给任何其他语言,但是库的入口点必须是一个或多个extern "C" 'd全局函数,因为它们是引用未修改名称的唯一方法。

C和c++标准都没有定义ABI。这完全取决于执行。让共享/动态库在c++中工作更困难的原因是c++添加了类、多态性、模板、异常、函数重载、STL等东西。

所以,对你来说,真正的信息来源是编译器的文档,以及一组相应的库API指南,以避免与你的库将为之构建的任何实现有关的任何问题。这在c++中比较困难(指南集可能比C要大得多,而且您可能不得不使用c++的一个子集),但并非不可能。