简体   繁体   English

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

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

A swift app, will convert its dynamic frameworks into binaries. swift 应用程序会将其动态框架转换为二进制文件。 And once something is a binary, then it's no longer Swift/Ruby/Python, etc. It's machine code.一旦某些东西是二进制的,那么它就不再是 Swift/Ruby/Python 等。它是机器代码。

Same thing happens for a Python binary. Python 二进制文件也会发生同样的事情。 So why aren't the machine codes compatible with each other out of the box?那么,为什么机器代码不是开箱即用的相互兼容的呢?

Is it just that a simple mapping is required to bridge one language to the other?只是需要一个简单的映射来将一种语言连接到另一种语言吗?

Like if I needed to use a binary created from the Swift language — into a Python based app, then do I need to expose the Swift Headers to Python for it to work?就像如果我需要使用从 Swift 语言创建的二进制文件到基于 Python 的应用程序,那么我是否需要将 Swift 标头公开给 Python 才能工作? Or something else is required?还是需要其他东西?

I assume you're talking about making calls in one language to a library compiled in a different language.我假设您是在谈论用一种语言调用用另一种语言编译的库。

At the assembly language level, there are standards ( ABI , for Application Binary Interface) that define how function parameters are passed in registers, how values are returned, the behavior of the stack, etc. ABIs are architecture and operating-system-dependent.在汇编语言级别,有一些标准( ABI ,用于应用程序二进制接口)定义了 function 参数如何在寄存器中传递、如何返回值、堆栈的行为等。ABI 依赖于体系结构和操作系统。 Usually any function that is exported in a library will follow the ABI.通常在库中导出的任何 function 都将遵循 ABI。

It is plain that ABIs basically expect a C language model for functions: a single return value, a well-defined data type for each function parameter as well as the return value, the possibility of using pointers, etc.很明显,ABI 基本上期望函数使用 C 语言 model:单个返回值、每个参数的定义明确的数据类型 function 以及返回值、使用指针的可能性等。

Problems start to arise once you move to a higher level language.一旦您转向更高级别的语言,问题就会开始出现。 C++ already introduces complications: whereas the name of a C function is the same in assembly (often a _ character is prepended), in C++ function names must encode data types due to the possibility of overloaded functions with the same name but different parameters. C++ 已经引入了复杂性:而 C function 的名称在汇编中是相同的(通常在前面加上一个_字符),在 C++ function 中名称必须编码数据类型,因为有可能重载具有相同名称但不同参数的函数。 Thus, names must be mangled and demangled -- this is why a prototype for a C function must be declared as extern "C" in C++. Then there are issues of the classes ( this pointer, vtables), namespaces and so on, which complicate matters further.因此,名称必须被破坏和分解——这就是为什么 C function 的原型必须在 C++ 中声明为extern "C" 。然后是类( this指针、vtables)、名称空间等问题,这使事情进一步复杂化。

Then you have dynamically typed languages like Python. In truth, there is no such thing as dynamic typing at the assembly language levels: the instruction encodings in machine language (ie binary codes as they're read by the CPU when executed) implicitly determine whether you're using an integer or floating-point or SIMD instruction (and the width of operands), which also determines which of the different register banks are accessed.然后你有像 Python 这样的动态类型语言。事实上,在汇编语言级别没有dynamic typing这样的东西:机器语言中的指令编码(即二进制代码,因为它们在执行时被 CPU 读取)隐式确定是否您正在使用 integer 或浮点或 SIMD 指令(以及操作数的宽度),这也决定了访问哪些不同的寄存器组。 Although the language makes dynamic typing transparent to you, at the assembly code level, the interpreter/JIT/compiler must resolve them somehow, because ultimately the CPU must be told exactly what data type to operate on.尽管该语言使动态类型对您透明,但在汇编代码级别,解释器/JIT/编译器必须以某种方式解决它们,因为最终必须告诉 CPU 确切地操作什么数据类型。

This is why you can't directly call a C function (or in general any library function) from Python -- unlike a pure Python function which can disregard the types of its parameters, library functions must know the exact types of each parameter and the return type.这就是为什么您不能直接从 Python 调用 C function(或一般任何库函数)的原因——与可以忽略其参数类型的纯 Python function 不同,库函数必须知道每个参数的确切类型和返回类型。 Thus, you must use something like ctypes for Python, explicitly specifying the types in question for each function that needs to be called -- in a way, this is similar to function prototypes usually found in C headers.因此,您必须为 Python 使用类似ctypes的东西,明确指定需要调用的每个 function 的相关类型——在某种程度上,这类似于通常在 C 标头中找到的 function 原型。 It is possible to write functions in C that are directly callable from Python (and, in that case, essentially from Python alone), but you'll have to jump through a few hoops .可以在 C 中编写可直接从 Python 调用的函数(并且在这种情况下,基本上仅从 Python 调用),但您将不得不跳过几个环节

As for the particular language pairing you're interested in (Python/Swift), a cursory search came up with this thread in the Swift forums ( this one , linked from there, may also be interesting. Reading the thread, there appears to be two feasible solutions at this time: first, use the @_cdecl attribute (which isn't officially supported) to make a C function, and then call it from Python using ctypes . But the second and apparently more promising one is to use the @objc attribute in Swift, and use PyObjC in Python. I assume this will allow using some of the higher-level features of Swift, at least those that intersect with what Objective-C offers.至于您感兴趣的特定语言配对(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