4

几个月来,我编写了一些很好的通用功能,我想将其构建为库并动态链接,而不是导入 50 多个头文件/源文件。

该项目在 Xcode 和 Dev-C++ 中维护(我知道我可能必须使用命令行来做我想做的事情)并且必须链接到 OpenGL 和 SDL(在 SDL 的情况下是动态的)。目标平台是 Windows 和 OS X。

我到底在看什么?

  • 如果需要,我的图书馆的入口点是什么?
  • 我必须在我的代码中更改什么?(调用约定?)
  • 我该如何释放它?我的理解是,头文件和编译的库(.dll、.dylib(、.framework),无论它是什么)都需要可用于项目 - 特别是因为模板功能本质上不能包含在库中。
  • 我还需要注意什么?
4

3 回答 3

11

我建议构建为 statc 库而不是 DLL。如果您这样做,很多导出 C++ 函数和类的问题都会消失,前提是您只打算与构建库时使用的同一编译器生成的代码链接。

构建静态库非常简单,因为它只是 .o/.obj 文件的集合——有点像 ZIP 文件,但没有压缩。无需导出任何内容 - 只需将库包含在应用程序链接的文件列表中即可。要访问特定的函数或类,只需包含相关的头文件。请注意,您无法摆脱头文件 - C++ 编译模型,尤其是模板,取决于它们。

于 2009-05-29T17:55:17.433 回答
2

从动态库中导出 C++ 类库可能会有问题,但这是可能的。
您需要标记要从 DLL 导出的每个函数(语法取决于编译器)。我正在四处寻找是否可以从 xcode 中找到如何做到这一点。在 VC 中是 __declspec(dllexport) 而在 CodeWarrior 中是 #pragma export on/#pragma export off。

如果您只在内部使用二进制文件,这是完全合理的。但是,一个问题是不同的编译器对 C++ 方法的命名不同。这意味着使用不同编译器的任何人都无法使用您的 DLL,除非您只导出 C 函数。

此外,您需要确保 DLL 和 DLL 客户端中的调用约定匹配。这要么意味着您应该将相同的默认调用约定标志传递给 DLL 或客户端的编译器,或者更好的是,在 DLL 中的每个导出函数上显式设置调用约定,这样默认值无关紧要是给客户的。

这篇文章解释了命名问题: http ://en.wikipedia.org/wiki/Name_decoration

于 2009-05-29T17:10:55.523 回答
1

C++ 标准没有定义标准 ABI,这对于试图构建 C++ 库的人来说是个坏消息。这意味着您从编译的代码中获得不同的行为,具体取决于用于编译它的标志,这可能会导致编译和链接正常的代码中出现神秘的错误。

这不仅限于不同的调用约定——可以编译 C++ 代码以支持或不支持 RTTI、异常处理,以及可以影响 C++ 代码所依赖的类实例的内存布局的各种优化。

所以,你可以做什么?我会在我的源代码树中构建 C++ 库,并确保它们是作为项目构建的一部分构建的,并且所有库和链接到它们的代码都使用相同的编译器标志。

请注意,名称修改至少应该阻止您链接使用不同编译器/编译器标志编译的目标文件,但大多数情况下,您可以做一些事情,尤其是使用 GCC,这将导致代码链接很好,在运行时失败。

您必须格外小心供应商提供的动态 C++ 库(例如,大多数 Linux 发行版上的 QT。)例如,某些 Redhat Linux 版本(可能全部)禁用 QT 中的异常,如果异常在 QT 回调中抛出,则无法在 main() 中捕获异常。乐趣。

于 2009-05-29T18:14:05.617 回答