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



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

对于Python二进制文件也是如此。那么,为什么机器代码不能相互兼容呢?

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

就像我需要使用Swift语言创建的二进制文件一样-进入基于Python的应用程序,那么我是否需要将Swift头文件暴露给Python以使其工作?还是需要其他东西?

我想你说的是用一种语言调用用另一种语言编译的库。

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

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

问题开始出现,一旦你转移到一个更高层次的语言。c++已经引入了复杂的问题:尽管C函数的名称在汇编中是相同的(通常在前面加一个_字符),但在c++中,函数名称必须编码数据类型,因为可能会重载具有相同名称但不同参数的函数。因此,名称必须是混乱的——这就是为什么C函数的原型必须在c++中声明为extern "C"的原因。然后还有类(this指针、虚表)、命名空间等问题,使问题进一步复杂化。

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

这就是为什么你不能直接从Python调用C函数(或一般的任何库函数)——不像纯Python函数可以忽略其参数的类型,库函数必须知道每个参数的确切类型和返回类型。因此,您必须使用Python的ctypes之类的东西,为需要调用的每个函数显式指定所讨论的类型——在某种程度上,这类似于C头文件中常见的函数原型。可以用C编写可直接从Python调用的函数(在这种情况下,基本上只能从Python调用),但您必须跳过一些障碍。

至于你感兴趣的特定语言配对(Python/Swift),在Swift论坛上粗略地搜索了一下这个帖子(这个,从那里链接,可能也很有趣)。阅读线程,此时似乎有两种可行的解决方案:首先,使用@_cdecl属性(官方不支持)来创建一个C函数,然后使用ctypes从Python调用它。但第二种显然更有前途的方法是在Swift中使用@objc属性,在Python中使用PyObjC。我认为这将允许使用Swift的一些高级特性,至少是那些与Objective-C提供的相交的特性。

相关内容