【问题标题】:Building C++ source code as a library - where to start?将 C++ 源代码构建为库 - 从哪里开始?
【发布时间】:2009-05-29 16:59:06
【问题描述】:

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

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

我在看什么?

  • 我的入口点是什么 图书馆是否需要?
  • 我必须对我的代码进行哪些更改? (调用约定?)
  • 如何释放它?我的理解 是头文件和编译的 库(.dll,.dylib(,.framework), 不管它是什么)需要 可用于该项目 - 特别是作为模板功能 不能被包含在库中 自然。
  • 我还需要注意什么?

【问题讨论】:

  • 您是否考虑过将其构建为 .lib?这意味着您的应用需要访问头文件,而不是源文件。与 DLL 路由相比,这意味着修改更少。

标签: c++ entity-framework dynamic-linking


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

    • 看来xcode使用#pragma GCC visibility push(hidden)和#pragma GCC visibility push(default)来控制符号的可见性,而Dev-C++使用VC的(?)语法。
    【解决方案3】:

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

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

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

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

    对于供应商提供的动态 C++ 库(例如,大多数 Linux 发行版上的 QT),您必须格外小心。我见过一些供应商提供的库的实例,这些库的编译方式会阻止某些事情正常工作。例如,某些 Redhat Linux 版本(可能全部)禁用了 QT 中的异常,如果异常在 QT 回调中抛出,则无法在 main() 中捕获异常。有趣。

    【讨论】:

    • 当然,所有其他计算机语言也是如此——我不知道有任何标准化的语言可以使 ABI 标准化。
    • Java 总是有的,但这只是一个事实上的标准,所以我不会在这里提及。
    • 不,java 可能是 gpod 的反例,我一概而论。我不确定它是否可以说有 ABI。
    • JVM 规范本质上是 ABI。至少有两种标准化方法可以将本机代码与在 JVM 下运行的代码联系起来,我认为这也很重要。此外,C 中死气沉沉的简单调用约定至少可以可靠地将 C 代码与其他 C 代码以及用支持它们的语言编写的代码可靠地链接起来。不过,我不认为 C ABI 是正式标准化的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-31
    • 1970-01-01
    相关资源
    最近更新 更多