围绕共享库边界的c++接口设计
C++ interface design around shared library boundaries
假设我有两个项目。一个是应用程序,另一个是共享库,其中包含公共的、可重用的代码,这些代码可以被不止这个应用程序使用。
我的应用程序使用STL,我的共享库也使用STL。这里的第一个问题是我的共享库使用STL。如果我在我的应用程序中构建了一个新版本的STL,但我没有重新构建我的共享库,因为这是不必要的,那么我们马上就会遇到兼容性问题。
我解决这个问题的第一个想法是在共享库类的接口中根本不使用STL。假设我们在库中有一个函数,它接受一个字符串并对它做一些事情。我将使函数原型看起来像:void DoStuffWithStrings( char const* str );
代替:
void DoStuffWithStrings( std::string const& str );
对于字符串,这可能在不同版本的STL之间没有问题,但缺点是我们从std::string
到char*
,再回到std::string
,这似乎会导致性能问题。
是否推荐将原始类型装箱/拆箱到它们的STL对应类型?当我们尝试对std::list
这样做时,情况变得更糟,因为实际上没有"原始类型",我知道我们可以很容易地传递它,而不需要做某种O(n)或类似的操作。
const char*
方法的优点之一是您的库也可以从C调用,因此也可以从许多其他语言接口到C(几乎所有东西)。这本身就是一个非常有趣的卖点。
然而,如果你编写和维护这两个库,并且它们将只在c++中使用(比如未来5年),我就不会经历转换所有内容的麻烦。std::string
是一回事,std::vector
或std::map
不会很好地转换。除此之外,您有多少次迁移到另一个STL实现?在这些情况下,您真的要"忘记"重新构建共享库吗?此外,如果确实需要,您仍然可以在之后编写/生成C风格的包装器。
结论(偏向于我在这件事上的经验):如果你不需要C,那就用stl。
当然,标准c++库应该被视为c++ ABI的一部分,就像虚拟表布局或名称混淆方案一样。此外,ABI中任何不兼容的更改更有可能影响模糊的极端情况,而不是std::vector的布局。换句话说:如果你打算制作一个c++库,可以随意使用标准的c++类。
如果库使用与应用程序不同的堆,则会出现另一个问题。如果是这种情况或可能是这种情况,请确保库拥有/管理自己的内存。当库使用不同的c库并因此使用不同的malloc/free和不同的堆时,多个堆可能是一个问题。http://msdn.microsoft.com/en-us/library/ms810466.aspx
许多api和共享库使用"不透明"或泛型指针作为函数的参数,以避免版本之间的差异。
// this:
int MyFunc(char* Param1, int Param2, bool Param3);
// into this:
struct MyParams
{
char* Param1;
int Param2;
bool Param3;
}
// "Params" its really "struct MyParams*"
int MyFunc(void* Params);
有时,如果共享库函数有多个参数,则将其替换为指针,该指针可能是指向数组或结构体甚至类的指针。
这取决于你打算如何使用你的库,因为许多库都像普通C一样使用,即使你正在使用c++。
- C++核心准则 C35 对于接口类"A base class destructor should be either public and virtual, or protected and nonv
- Visual C++GC接口如何启用它以及要包含哪个库
- Windows.h与GLFW.h的接口
- 当字段可以为null时,如何使用C++接口在Avro中写入数据
- 提供与TMP和SFINAE的通用接口
- 为重写std::exception的库生成swig接口时出错
- 内联如何影响模块接口中的成员函数
- COM 接口 c# 封送数组数组
- 如何在 SCIP C++ 接口中获取 MILP 约束矩阵中的系数值
- 重载 -> shared_ptr 个实例中的箭头运算符<interface>,接口中没有纯虚拟析构函数
- 如何绑定 C++ gRPC 客户端的网络接口
- 模板化接口 - 创建一个泛型模板类以返回任何容器
- 如何从实现接口的模板化类实例访问结构
- 带有进度表的 curl 多接口程序
- 设计帮助 - 为不同类型的消息处理通用接口的设计模式
- 我可以在具有一个标头和一个接口的 cpp 文件中有多个嵌入吗?
- 类接口,可以创建N个方法
- 类具有相同的接口,但参数的类型不同
- 如何与 Cheerp/js 中的 extern 变量接口?
- 如何使用现代 CMake 安装捆绑的接口依赖项?