C被提升到了一个具备声望和权威的角色,它的统治是如此地绝对和永恒,以至于它完全扭曲了我们之间的对话方式。”“Rust和Swift不能简单地‘说’自己的母语或舒适的语言——它们必须怪异地模拟C的皮肤,并把自己包裹其中,使肉体以同样的方式起伏。”
比喻虽尖锐,依据却不无道理。几乎任何程序要做任何有用或有趣的事情,它都必须在操作系统上运行。这意味着它必须与那个操作系统交互——而很多操作系统都是用C编写的。因此,该语言必须与C代码交互,这意味着它必须调用C API。这是通过外部功能接口(FFI)完成的。换句话说,即使你从未用C编写任何代码,你也必须处理C变量、匹配C数据结构和布局、通过名称和符号链接到C函数。这不仅适用于任何语言与操作系统的交互,也适用于从一种语言调用另一种语言。虽然很多人都表示自己喜欢C,但对文章的内容也是表达了认可和赞同。
C是编程通用语言,我们都必须学C,因此C不再只是一种编程语言,它成了每一种通用编程语言都需要遵守的协议。本文仅探讨“C由实现定义导致的难以捉摸的混乱”,这个让所有人都不得不使用的协议已经变成了一个更大的噩梦。
很明显,几乎每种语言都必须学会说C语言。那么,“说C语言”是什么意思?这是说要以C语言头文件的方式描述接口的类型和函数,并以某种方式做一些事情:
匹配这些类型的布局;
用链接器做一些事情,将函数的符号解析为指针;
用适当的ABI来调用这些函数(比如把参数放在正确的寄存器中)。
然而这里有两个问题:
你不能真的编写一个C解析器;
C并没有一个ABI,甚至是定义好的类型布局。
首先,让我们从技术的角度看看。你完成了新语言Bappyscript的设计,它对Bappy Paws/Hooves/Fins提供了的支持。这是一门神奇的语言,它将彻底改变人们的编程方式!
但现在,你需要用它做一些有用的事情,比如,接受用户的输入,或者输出结果,或者任何可见的东西。如果你希望用你的语言编写的程序成为优秀的公民,可以在主要的操作系统上很好地运行,那么你就需要与操作系统接口进行交互。我听说,Linux上的任何东西都“只是一个文件”,所以让我们在Linux上打开一个文件。这是Bappyscript,不是C。那Linux的Bappyscript接口在哪里?
你说Linux没有Bappyscript接口是什么意思!?好吧,这是一种全新的语言,但你会添加一个,对吧?这时候你会想,我们好像必须使用他们给的东西。我们将需要某种接口,使我们的语言能够调用外部函数。外部函数接口,是的,FFI然后你发现,什么,Rust,你也有C的FFI?Swift你也有吗?甚至连Python也有?!