假设我们class X在程序集的版本1中A.dll:
class X {
SomeType Property { set; get; }
}
Run Code Online (Sandbox Code Playgroud)
然后在程序集的第2版中A.dll:
class X {
SomeType Property { set; get; }
SomeType OtherProperty { set; get; }
}
Run Code Online (Sandbox Code Playgroud)
现在假设我们有第二个B.dll加载A.dll和使用X的程序集.是否会添加属性会OtherProperty破坏ABI?将B.dll无法使用A.dll/ X?如果没有,声明的顺序会有什么不同吗?如果属性是虚拟的,它有什么不同吗?
我想我真的在问:ABI的一般规则是什么?我知道在发布之后更改接口是一件坏事,但我真的希望能够在某些情况下添加属性,而无需添加子类.
我知道添加static成员函数很好,但enum定义怎么样?没有新的数据成员,只是它的定义.
一点背景:
我需要添加一个static成员函数(在类中),它将IP通过其字符串表示来识别(函数)地址的版本.的第一件事,是在我脑海中是申报enum的IPv4,IPv6并且Unknown,使这个enum我函数的返回码.
但我不想打破二进制向后兼容性.
一个非常糟糕的问题(对于SO) - 这里有任何来源或问题,我可以阅读更多关于此的内容吗?我的意思是 - 什么打破了二进制兼容性和什么 - 没有.或者它取决于很多东西(比如架构,操作系统,编译器......)?
编辑:关于@PeteKirkham的评论:好的,至少 - 有没有办法测试/检查更改的ABI,或者最好发布有关它的新问题?
EDIT2:我刚刚发现了一个SO问题:静态分析工具来检测C++中的ABI中断 .我认为它在某种程度上与此相关,并回答了关于检查二进制兼容性的工具的部分.这就是我在这里联系它的原因.
我不明白为什么ABI是开发用户空间应用程序的重要环境.是否将操作系统的系统调用集视为ABI?但是,如果是这样,那么关于标准库中封装的系统调用的所有复杂性是不是都很复杂?
那么ABI兼容性仅与在不同平台上运行静态链接应用程序相关,因为系统调用将嵌入到二进制文件中?
我目前正在编写一个库,正在考虑从GCC 4.1.2升级到GCC的4.5.2(最新版本).如果我将我的代码编译成静态库,我可以假设编译器兼容性(显然在相同的操作系统上)对于客户端应该是非问题吗?
编辑 为了进一步澄清:如果我向客户端提供一个使用gcc 4.5.2编译的静态链接库,那么这个库的用户在编译器和必须使用的版本方面有什么限制?
库提供具有虚函数的类.是否可以使用新的虚函数扩展此类,而无需重新编译动态链接到库的二进制文件?
我相信这在标准中是不可能的.有平台允许吗?
如果只将新函数添加到类主体的末尾,那会更容易吗?
我是否可以将纯虚函数(在基类中)更改为非纯函数而不会遇到任何二进制兼容性问题?(Linux,GCC 4.1)
谢谢
由于auxWindows下的包名称存在问题,我正在我的库的包层次结构中移动一个帮助器类
de.sciss.scalainterpreter.aux
Run Code Online (Sandbox Code Playgroud)
至
de.sciss.scalainterpreter
Run Code Online (Sandbox Code Playgroud)
该类是图书馆私有的,即private[scalainterpreter] object Helper.
现在使用Typesafe Migration-Manager,显然它报告更改不兼容:
Found 2 binary incompatibiities
===============================
* class de.sciss.scalainterpreter.aux.Helper does not have a correspondent
in new version
* object de.sciss.scalainterpreter.aux.Helper does not have a correspondent
in new version
Run Code Online (Sandbox Code Playgroud)
但我怀疑如果客户端代码没有调用任何一个对象,那么接口仍然是兼容的,因此我可以使用次要版本增加来指示更改,并允许这两个版本可以互换使用.
正确?
scala binary-compatibility package-private migration-manager
似乎glibc 2.14引入了新版本memcpy(修复bug 12518).然后,针对glibc 2.14+编译的程序将包含动态链接memcpy@GLIBC_2.14,这在旧版本的glibc中显然不可用.
但是,glibc 2.14+显然仍然包含旧memcpy@GLIBC_2.2.5符号以实现向后兼容.我希望能够以这样的方式编译一些程序,使它们与旧的glibc版本二进制兼容.如何在具有glibc 2.14+的系统上编译程序,以便它使用这个旧的符号版本?如果该过程必然是特定于编译器的,那么我正在使用GCC(但是知道如何在其他编译器上执行它也会很好).
(在一个侧面说明,我必须承认不知道一大堆有关版本的符号,比如如何产生,以及如何使用它们,或者他们是否是ELF特定的或应被认为是现代的ABI标准的一部分;我还没有找到任何关于它的文件.关于这个问题,有没有很好的信息来源?)
我正在开发一个库,允许其用户(驻留在同一进程中的其他库)交换数据缓冲区和流.该库必须可以从MSVC和mingw代码中使用(更多兼容性不会受到影响,但并非严格必要).为了实现这一点,核心功能应该从一个小的,与编译器兼容的接口提供,以后可以通过使用客户端代码编译的便利层来隐藏.
该库的一个具有挑战性的方面是它必须是可扩展的,以便客户端可以提供自己的缓冲区和流实现,但核心库接口必须在发布后保持稳定.如果您对进一步的背景感兴趣,可以在论坛帖子讨论中阅读.
我试图了解编译器之间二进制兼容性的问题,但由于我是这个主题的新手,我会对我的结果发表评论.我在这里的标准定义的行为(结构可能会失败那个测试),只能在MinGW和MSVC之间的相容性不感兴趣,也许其他的编译器,如果方便可行的.
特别是结构是否兼容?它们统一由函数指针组成,因此我认为填充不会成为问题.另外,这里需要stdcall约定,还是cdecl也能正常工作?我可以不指定它,因为两个编译器都默认为cdecl吗?我是不是该?这就是我现在所拥有的:
#include <stdint.h>
typedef struct {
uint32_t (__stdcall *read)(void*, uint8_t*, uint32_t);
void (__stdcall *write)(void*, const uint8_t*, uint32_t);
uint32_t (__stdcall *getBytesLeft)(void*);
uint8_t (__stdcall *destroy)(void*);
} SharedStreamInterface;
typedef struct {
uint32_t (__stdcall *read)(void*, uint8_t*, uint32_t);
void (__stdcall *write)(void*, const uint8_t*, uint32_t);
uint32_t (__stdcall *getBytesLeft)(void*);
uint8_t (__stdcall *destroy)(void*);
uint32_t (__stdcall *getreadpos)(void*);
uint32_t (__stdcall *getwritepos)(void*);
uint32_t (__stdcall *getlength)(void*);
void (__stdcall *setreadpos)(void*, uint32_t);
void (__stdcall *setwritepos)(void*, uint32_t);
void (__stdcall *setlength)(void*, uint32_t);
} SharedBufferInterface;
extern "C" {
// Functions …Run Code Online (Sandbox Code Playgroud) compiler-construction mingw calling-convention binary-compatibility visual-c++
我正在使用Lobo - Java Web浏览器库,它给了我一个例外,经过一些研究后我确定可能是因为该库已经与旧版本的Java进行了编译.
代码如下:
import java.io.IOException;
import org.lobobrowser.html.UserAgentContext;
import org.lobobrowser.html.parser.DocumentBuilderImpl;
import org.lobobrowser.html.parser.InputSourceImpl;
import org.lobobrowser.html.test.SimpleUserAgentContext;
import org.xml.sax.SAXException;
public class Cobratest
{
public static void main(String[] args) throws SAXException, IOException
{
UserAgentContext uAgent = new SimpleUserAgentContext();
DocumentBuilderImpl docBuild = new DocumentBuilderImpl(uAgent);
docBuild.parse(new InputSourceImpl("http://dic.amdz.com/"));
}
}
Run Code Online (Sandbox Code Playgroud)
并且堆栈跟踪是:
Exception in thread "main" java.lang.IncompatibleClassChangeError: Found interface sun.font.FontManager, but class was expected
at org.lobobrowser.util.gui.FontFactory.createFont(FontFactory.java:210)
at org.lobobrowser.util.gui.FontFactory.createFont_Impl(FontFactory.java:180)
at org.lobobrowser.util.gui.FontFactory.createFont(FontFactory.java:127)
at org.lobobrowser.util.gui.FontFactory.getFont(FontFactory.java:98)
at org.lobobrowser.html.style.StyleSheetRenderState.<clinit>(StyleSheetRenderState.java:43)
at org.lobobrowser.html.domimpl.NodeImpl.<clinit>(NodeImpl.java:39)
at org.lobobrowser.html.parser.DocumentBuilderImpl.createDocument(DocumentBuilderImpl.java:143)
at org.lobobrowser.html.parser.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:97)
Run Code Online (Sandbox Code Playgroud)
当我检查时,org.lobobrowser.util.gui.FontFactory.createFont我发现有一个FontManager名称从之前版本的Java改变了.在这个 …