【发布时间】:2019-11-07 02:57:36
【问题描述】:
我试图了解正确的方法或正确的方法,以便为非开源项目提供相当大的 C++ API。我不想提供“仅标头”库,因为代码库相当大并且是封闭源代码。目标如下:
- 提供本机 C++ API,用户可以在 C++ 中实例化 C++ 类、传递数据,而无需仅使用 C 语言的包装器
- 允许方法作为参数并返回 C++ 对象,尤其是 STL 类型(std::string、std::vector 等)
- 没有自定义分配器
- 如果存在这样的标准,大多数行业标准/规范方法都是可行的
- 不能重新创建 COM 或使用 MS COM
- 假设所有 C++ 编译器至少“兼容”C++11
我的目标是 Windows 以及其他平台 (Linux)。
由于 DLL 边界问题,我的理解是创建 DLL 或共享库是不可能的。为了处理 DLL 边界问题,DLL 和调用代码必须使用动态链接运行时(以及正确的版本,Windows 上的多线程/调试/等)编译,然后所有编译器设置都需要与调试符号匹配(迭代器调试设置等)。我的一个问题是,如果在 Windows 上,我们是否使用 Visual Studio 中的默认“Debug”和“Releas”设置确保编译器设置在 /MD 方面匹配,我们是否真的可以“安全”使用DLL 以这种方式(即来回传递 STL 对象以及如果不匹配肯定会很危险/失败的各种事情)? gcc下Linux中的共享对象、*.so有同样的问题吗?
使用静态库能解决这个问题吗?静态库和与其链接的调用代码之间的编译器设置需要匹配多少?它与 DLL (在 Windows 上)几乎相同的问题吗?
我试图在网上找到图书馆的例子,但找不到太多关于这方面的指导。许多资源讨论了开源解决方案,这似乎是将头文件和实现文件复制到代码库中(对于非头文件),这对于封闭源代码不起作用。
这样做的正确方法是什么?似乎这应该是一个普遍的问题;虽然我想知道大多数商业供应商是否只使用 C 接口。
如果可以解决问题,我可以使用静态库。我也可以接受这样的想法:拥有一组具有 Y 种设置变体的 X 编译器(其中 X 和 Y 是要支持的预先确定的选项列表)并拥有一个生成 X * Y 共享二进制库的构建系统,如果那样的话是“安全的”。
答案真的只是要么做 C 接口,要么用工厂创建纯抽象接口? (如果是这样,是否有一本规范的书或指南来编写这篇文章,而不是实现 Microsoft COM?)。
我知道 Stefanus DuToit 的沙漏模式: https://www.youtube.com/watch?v=PVYdHDm0q6Y
我担心这是很多代码重复。
我不是在抱怨事情的状态,我只是想了解“正确”的方式,希望这对处于类似位置的其他人来说是一个很好的问题。
我查看了这些 Stackoverflow 参考资料:
When to use dynamic vs. static libraries
How do I safely pass objects, especially STL objects, to and from a DLL?
Distributing Windows C++ library: how to decide whether to create static or dynamic library?
Static library API question (std::string vs. char*)
Easy way to guarantee binary compatibility for C++ library, C linkage?
也已审核:
https://www.acodersjourney.com/cplusplus-static-vs-dynamic-libraries/
https://blogs.msmvps.com/gdicanio/2016/07/11/the-perils-of-c-interface-dlls/
【问题讨论】:
-
DLL 是一种避免静态链接问题的方法。
标签: c++ api-design static-linking dynamic-linking