C++ c++;类实例内存布局

C++ c++;类实例内存布局,c++,memory,layout,shared-libraries,C++,Memory,Layout,Shared Libraries,我知道之前有人问过这个问题,但在你给我一个减号并报告重复的问题之前,请思考一下: 在前面的所有答案中,每个人都说对象内存布局依赖于编译器。那么,共享库(*.dll,*.so)可以导出和导入C++类,即使来自不同编译器也可以组合它们吗?考虑在MIWW下编写的DirectX应用程序。DirectX是使用MSVC++编译的,那么这些环境在内存布局上是如何一致的呢?我知道DirectX非常依赖C++类和多态性。 换个角度问:假设我有一个选定的体系结构(如Windows、intel x86),我正在尝试编

我知道之前有人问过这个问题,但在你给我一个减号并报告重复的问题之前,请思考一下:

在前面的所有答案中,每个人都说对象内存布局依赖于编译器。那么,共享库(*.dll,*.so)可以导出和导入C++类,即使来自不同编译器也可以组合它们吗?考虑在MIWW下编写的DirectX应用程序。DirectX是使用MSVC++编译的,那么这些环境在内存布局上是如何一致的呢?我知道DirectX非常依赖C++类和多态性。 换个角度问:假设我有一个选定的体系结构(如Windows、intel x86),我正在尝试编写一个新的编译器。我如何知道如何访问由另一个编译器编译的.dll lib提供的类实例(vtable,成员字段)?或者仅仅是这样:M$编写了VC++,从那以后它就成了不成文的标准,而其他编译器“出于兼容性原因”都是这样做的?那么linux或其他操作系统呢

编辑:

好吧,我承认,DirectX的例子很糟糕,因为COM规范

另一个例子:QT。我正在使用QT和mingw,但我知道也有可用的MSVC版本。我不知道区别是仅仅在头上,还是共享库(dll-s)也不同。如果是的话,这是否意味着我必须分发包含qt库的应用程序,这样如果有人碰巧有其他编译器的qt库,就不会混淆了?(很好的内存和代码共享,对吧?)。或者它们是一样的,而且有一些不成文的法律

编辑2:


我安装了不同的qt版本(msvc 2010),只是为了看看哪些是共享的,哪些不是共享的。看来共享(他们真的共享)库是不同的。看来我真的要为我的应用程序提供qt库了。。。这不是一件小事(例如QtGui 8-9MB)。其他较小的lib呢?它们的作者不太愿意为其他编译器提供版本?这是否意味着我被他们的原始编译器卡住了?如果我想使用由不同编译器编译的两个不同的lib呢?

DirectX是一种基于COM的技术,这就是为什么它可以在C语言中与各种编译器一起使用。在hood下,COM接口是一个类似C的结构,它模拟VMT

技术上,DirectX有一个MIDL自动生成的C++接口,但一般的说法是,可以使用在不同编译器中导出的类。 编辑1:

使用MSCVC构建的QtdLL与GCC构建的GDT不兼容,不幸的是,由于自然原因:不同的C++编译器不同的ABI和不同的运行库(MIWW使用了更老的MSVCRT,这就是为什么PURE C。DLL可以在MSVC中消耗,反之亦然)。有些编译器偶然或部分有意地匹配它们的ABI,但MSVC/gcc绝对不是这样。QT也可以构建为一个静态库,所以要重新分发东西,可以只进行静态链接

<>在DLL中C++类的名称很大程度上取决于所使用的编译器前端。许多知名公司的商业编译器使用EDG的C++解析器,这就是为什么类名称重载函数具有相似或匹配的签名。 编辑2:

“如果我想使用由不同编译器编译的两个不同的lib,该怎么办?”

如果您迫切需要这两个库的某些特定功能(我指的是一些具体的操作,而不是整个框架),那么不需要库的源代码的方法是编写一些包装器,并将此包装器编译为C-style.dll


可以这样想,“两个不同的C++-E,C++-1和C++-2”。ABI/Runtime的问题与使用C中的Pascal代码或与一些旧的Fortran库链接没有什么不同。

基本上,您是在询问ABI

在某些情况下(例如安腾上),有一个指定ABI的文档,基本上每个人都遵循该文档

在DirectX的例子中,情况是一样的:微软已经发布了COM规范,因此任何遵循这些规范的人都可以与任何COM对象进行互操作(在合理的范围内——64位编译器可能不会与为Windows 3.1编写的16位COM对象一起工作)

对于大多数其他事情,你或多或少都是靠自己来解决的。通常至少有一点是以文档的方式发布的,但至少在我的经验中,它经常略过一些最终很重要的细节,没有完全可靠地更新,并且在某些情况下是完全错误的。在大多数情况下,它的组织性也很差,所以你几乎可以从任何你能找到它的地方收集你能找到的东西,当你没有信息(或耐心)时,做一些反向工程来填补缺失的部分

编辑:对于像Qt库这样的非COM对象,您有两个选择。一种是静态链接到Qt库,这样您需要的Qt代码就可以直接链接到您的可执行文件中。如果你想使用一个DLL,那么是的,你必须在你的应用程序中发布一个DLL,这个DLL是特定于你用来生成应用程序本身的编译器的。不同的编译器(甚至是同一个编译器的不同版本或编译标志集)通常需要不同的DLL(可能是相同的源代码,但构建时要适应编译器的更改)

这方面也有例外,但它们与我上面概述的非常相似。例如,“英特尔编译器Windows版”通常使用Microsoft的标准库,也可以使用为Microsoft编译器构建的大多数(如果不是全部)其他库。这很大程度上是因为英特尔已经竭尽全力确保他们的编译器使用与微软相同的调用约定、名称篡改方案等。它是w