简体   繁体   English

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

[英]Building C++ source code as a library - where to start?

Over the months I've written some nice generic enough functionality that I want to build as a library and link dynamically against rather than importing 50-odd header/source files. 几个月来,我写了一些很好的通用功能,我想构建一个库并动态链接而不是导入50多个头文件/源文件。

The project is maintained in Xcode and Dev-C++ (I do understand that I might have to go command line to do what I want) and have to link against OpenGL and SDL (dynamically in SDL's case). 该项目使用Xcode和Dev-C ++进行维护(我知道我可能必须使用命令行来执行我想要的操作)并且必须链接到OpenGL和SDL(在SDL的情况下动态)。 Target platforms are Windows and OS X. 目标平台是Windows和OS X.

What am I looking at at all? 我在看什么?

  • What will be the entry point of my library if it needs one? 如果需要,我的图书馆的入口点是什么?
  • What do I have to change in my code? 我需要在代码中更改什么? (calling conventions?) (调用约定?)
  • How do I release it? 我该如何发布? My understanding is that headers and the compiled library (.dll, .dylib(, .framework), whatever it'll be) need to be available for the project - especially as template functionality can not be included in the library by nature. 我的理解是标题和编译库(.dll,.dylib(,。framework),无论它是什么)都需要为项目提供 - 特别是因为模板功能本身不能包含在库中。
  • What else I need to be aware of? 还有什么我需要注意的?

I'd recommend building as a statc library rather than a DLL. 我建议建立一个statc库而不是DLL。 A lot of the issues of exporting C++ functions and classes go away if you do this, provided you only intend to link with code produced by the same compiler you built the library with. 如果您这样做,导出C ++函数和类的许多问题都会消失,前提是您只打算链接由您构建库的同一编译器生成的代码。

Building a static library is very easy as it is just an collection of .o/.obj files - a bit like a ZIP file but without compression. 构建静态库非常简单,因为它只是.o / .obj文件的集合 - 有点像ZIP文件但没有压缩。 There is no need to export anything - just include the library in the list of files that your application links with. 无需导出任何内容 - 只需将库包含在应用程序链接的文件列表中。 To access specific functions or classes, just include the relevant header file. 要访问特定的函数或类,只需包含相关的头文件。 Note you can't get rid of header files - the C++ compilation model, particularly for templates, depends on them. 请注意,您无法摆脱头文件 - C ++编译模型(尤其是模板)取决于它们。

It can be problematic to export a C++ class library from a dynamic library, but it is possible. 从动态库导出C ++类库可能会有问题,但这是可能的。
You need to mark each function to be exported from the DLL (syntax depends on the compiler). 您需要标记要从DLL导出的每个函数(语法取决于编译器)。 I'm poking around to see if I can find how to do this from xcode. 我正在四处寻找,看看我是否可以从xcode找到如何做到这一点。 In VC it's __declspec(dllexport) and in CodeWarrior it's #pragma export on/#pragma export off. 在VC中它是__declspec(dllexport),在CodeWarrior中它是#pragma export on / #pragma export off。

This is perfectly reasonable if you are only using your binary in-house. 如果您只在内部使用二进制文件,这是完全合理的。 However, one issue is that C++ methods are named differently by different compilers. 但是,一个问题是C ++方法的命名方式不同于不同的编译器。 This means that nobody who uses a different compiler will be able to use your DLL, unless you are only exporting C functions. 这意味着除非您只导出C函数,否则使用不同编译器的任何人都无法使用您的DLL。

Also, you need to make sure the calling conventions match in the DLL and the DLL's client. 此外,您需要确保调用约定在DLL和DLL的客户端中匹配。 This either means you should have the same default calling convention flag passed to the compiler for both the DLL or the client, or better, explicitly set the calling convention on each exported function in the DLL, so that it won't matter what the default is for the client. 这或者意味着您应该为DLL或客户端传递给编译器的相同默认调用约定标志,或者更好,在DLL中的每个导出函数上显式设置调用约定,这样默认是什么是给客户的。

This article explains the naming issue: http://en.wikipedia.org/wiki/Name_decoration 本文解释了命名问题: http//en.wikipedia.org/wiki/Name_decoration

The C++ standard doesn't define a standard ABI, and that's bad news for people trying to build C++ libraries. C ++标准没有定义标准的ABI,这对于试图构建C ++库的人来说是个坏消息。 This means that you get different behavior from your compiled code depending on which flags were used to compile it, and that can lead to mysterious bugs in code that compiles and links just fine. 这意味着你从编译代码中获得了不同的行为,具体取决于使用哪些标志来编译它,这可能导致编译和链接的代码中的神秘错误。

This extends beyond just different calling conventions - C++ code can be compiled to support or not support RTTI, exception handling, and with various optimizations that can affect the the memory layout of class instances, which C++ code relies on. 这超出了不同的调用约定 - 可以编译C ++代码以支持或不支持RTTI,异常处理,以及可能影响C ++代码所依赖的类实例的内存布局的各种优化。

So, what can you do? 所以,你可以做什么? I would build C++ libraries inside my source tree, and make sure that they're built as part of my project's build, and that all the libraries and the code that links to them use the same compiler flags. 我会在源代码树中构建C ++库,并确保它们是作为项目构建的一部分构建的,并且所有库和链接到它们的代码都使用相同的编译器标志。

Note that name mangling, which was supposed to at least prevent you from linking object files that were compiled with different compilers/compiler flags only mostly works, and there are certain things you can do, especially with GCC, that will result in code that links just fine and fails at runtime. 请注意,名称修改,本来应该至少阻止您链接使用不同编译器/编译器标志编译的目标文件,但这些文件大多有效,并且您可以做某些事情,特别是对于GCC,这将导致链接的代码很好,在运行时失败。

You have to be extra careful with vendor supplied dynamic C++ libraries (QT on most Linux distributions, for example.) I've seen instances of vendor supplied libraries that were compiled in ways that prevented certain things from working properly. 您必须特别注意供应商提供的动态C ++库(例如,在大多数Linux发行版上都有QT。)我见过供应商提供的库的实例,这些库的编译方式使得某些事情无法正常工作。 For example, some Redhat Linux releases (maybe all of them) disabled exceptions in QT, which made it impossible to catch exceptions in main() if the exceptions were thrown in a QT callback. 例如,一些Redhat Linux发行版(可能全部)在QT中禁用了异常,这使得如果在QT回调中抛出异常,则无法捕获main()中的异常。 Fun. 乐趣。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM