将C ++源代码构建为库 - 从哪里开始?

时间:2009-05-29 16:59:06

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

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

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

我在看什么?

  • 我的切入点是什么? 库是否需要?
  • 我的代码需要更改什么? (调用约定?)
  • 如何发布?我的理解 是标题和编译 库(.dll,.dylib(,。framework), 无论如何都需要 可用于该项目 - 特别是作为模板功能 不能包含在库中 性质。
  • 我还需要注意什么?

3 个答案:

答案 0 :(得分:11)

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

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

答案 1 :(得分: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

答案 2 :(得分:1)

C ++标准没有定义标准的ABI,这对于尝试构建C ++库的人来说是个坏消息。这意味着你从编译代码中获得了不同的行为,具体取决于使用哪些标志进行编译,这可能会导致代码中的神秘错误,编译和链接就好了。

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

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

请注意,名称修改,本来应该至少阻止您链接使用不同编译器/编译器标志编译的目标文件,但这些文件只能起作用,并且您可以做某些事情,特别是对于GCC,这将导致链接很好但在运行时失败的代码。

您必须格外注意供应商提供的动态C ++库(例如,大多数Linux发行版上的QT。)我已经看到了供应商提供的库的实例,这些库的编译方式阻止了某些事情的正常运行。例如,一些Redhat Linux发行版(可能全部)在QT中禁用了异常,这使得如果在QT回调中抛出异常,则无法捕获main()中的异常。乐趣。