繁体   English   中英

为什么不同语言的二进制文件彼此不兼容? 你如何使它们兼容?

[英]Why aren't binaries of different languages compatible with each other? How do you make them compatible?

swift 应用程序会将其动态框架转换为二进制文件。 一旦某些东西是二进制的,那么它就不再是 Swift/Ruby/Python 等。它是机器代码。

Python 二进制文件也会发生同样的事情。 那么,为什么机器代码不是开箱即用的相互兼容的呢?

只是需要一个简单的映射来将一种语言连接到另一种语言吗?

就像如果我需要使用从 Swift 语言创建的二进制文件到基于 Python 的应用程序,那么我是否需要将 Swift 标头公开给 Python 才能工作? 还是需要其他东西?

我假设您是在谈论用一种语言调用用另一种语言编译的库。

在汇编语言级别,有一些标准( ABI ,用于应用程序二进制接口)定义了 function 参数如何在寄存器中传递、如何返回值、堆栈的行为等。ABI 依赖于体系结构和操作系统。 通常在库中导出的任何 function 都将遵循 ABI。

很明显,ABI 基本上期望函数使用 C 语言 model:单个返回值、每个参数的定义明确的数据类型 function 以及返回值、使用指针的可能性等。

一旦您转向更高级别的语言,问题就会开始出现。 C++ 已经引入了复杂性:而 C function 的名称在汇编中是相同的(通常在前面加上一个_字符),在 C++ function 中名称必须编码数据类型,因为有可能重载具有相同名称但不同参数的函数。 因此,名称必须被破坏和分解——这就是为什么 C function 的原型必须在 C++ 中声明为extern "C" 。然后是类( this指针、vtables)、名称空间等问题,这使事情进一步复杂化。

然后你有像 Python 这样的动态类型语言。事实上,在汇编语言级别没有dynamic typing这样的东西:机器语言中的指令编码(即二进制代码,因为它们在执行时被 CPU 读取)隐式确定是否您正在使用 integer 或浮点或 SIMD 指令(以及操作数的宽度),这也决定了访问哪些不同的寄存器组。 尽管该语言使动态类型对您透明,但在汇编代码级别,解释器/JIT/编译器必须以某种方式解决它们,因为最终必须告诉 CPU 确切地操作什么数据类型。

这就是为什么您不能直接从 Python 调用 C function(或一般任何库函数)的原因——与可以忽略其参数类型的纯 Python function 不同,库函数必须知道每个参数的确切类型和返回类型。 因此,您必须为 Python 使用类似ctypes的东西,明确指定需要调用的每个 function 的相关类型——在某种程度上,这类似于通常在 C 标头中找到的 function 原型。 可以在 C 中编写可直接从 Python 调用的函数(并且在这种情况下,基本上仅从 Python 调用),但您将不得不跳过几个环节

至于您感兴趣的特定语言配对(Python/Swift),在 Swift 论坛(从那里链接的这个帖子,可能也很有趣。阅读该帖子,似乎有目前有两个可行的解决方案:首先,使用@_cdecl属性(官方不支持)制作一个 C function,然后使用ctypes从 Python 调用它。但是第二个显然更有希望的是使用@objc中的 objc 属性,并在 Python 中使用PyObjC 。我认为这将允许使用 Swift 的一些高级功能,至少是那些与 Objective-C 提供的功能相交的功能。

暂无
暂无

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

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