40

混合不同的编程语言一直是我不太了解的事情。根据这篇 Wikipedia article,可以通过以下几种方式完成外部函数接口(或 FFI):

  1. 要求以特定方式指定或实现可被宿主语言调用的来宾语言函数;经常使用某种兼容性库。
  2. 使用工具来自动“包装”客户语言函数和适当的胶水代码,执行任何必要的翻译。
  3. 使用包装库
  4. 限制可以跨语言使用的宿主语言能力集。例如,从 C 调用的 C++ 函数可能(通常)不包含引用参数或抛出异常。

我的问题:

  1. 第一种、第二种和第三种方式有什么区别?在我看来,他们都是将被调用语言的代码编译成带有目标文件和头文件的库,然后由调用语言调用。

  2. 它链接的一个消息来源说,可以通过多种方式实现 FFI:

    • 要求目标语言中调用的函数实现特定的协议。
    • 实现一个包装库,该库采用给定的低级语言函数,并用代码“包装”它以进行与高级语言约定的数据转换。
    • 要求声明为原生的函数使用高级功能的子集(与低级语言兼容)。

    我想知道链接源中的第一种方式是否与维基百科中的第一种方式相同?

    这个来源中的第三种方式是什么意思?它是否对应于维基百科中的第 4 种方式?

  3. 同一来源中,当比较它列出的三种方式时,似乎可以说填补两种语言之间差距的工作正在逐渐从被调用语言转移到调用语言。我想知道如何理解?对于维基百科的四种方式,这种转变是否也是如此?

  4. 语言绑定和 FFI 是等价的概念吗?它们有何关联和不同?

    从编程语言到库或 OS 服务的绑定是用该语言提供该服务的 API。

  5. 我想知道维基百科的引文或以下每个示例的来源属于哪种方式?

4

1 回答 1

23

可能是一个具体的例子会有所帮助。让我们将宿主语言设为 Python,将访客语言设为 C。这意味着 Python 将调用 C 函数。

  1. 第一种选择是以特定方式编写 C 库。在 Python 的情况下,标准方法是使用 C 函数编写第一个参数Py_Object *以及其他条件。例如(从这里):

    static PyObject *
    spam_system(PyObject *self, PyObject *args)
    {
        const char *command;
        int sts;
    
        if (!PyArg_ParseTuple(args, "s", &command))
            return NULL;
        sts = system(command);
        return Py_BuildValue("i", sts);
    }
    

    是一个可从 Python 调用的 C 函数。为此,必须在编写库时考虑到 Python 兼容性。

  2. 如果要使用现有的 C 库,则需要另一个选项。一种是有一个工具来生成以适合宿主语言使用的格式包装这个现有的库。以Swig为例,它可以用来绑定多种语言。给定一个现有的 C 库,您可以使用 swig 有效地生成调用现有库的 C 代码,同时符合 Python 约定。请参阅构建 Python 模块的示例。

  3. 我们现有的 C 库的另一个选择是从 Python 库中调用它,该库在运行时有效地包装调用,例如ctypes。虽然在选项 2 中编译是必要的,但这次不是。

另一件事是,有很多选项(它们确实重叠)可以从另一种语言调用一种语言的函数。有 FFI(据我所知相当于语言绑定),通常是指同一进程中的多种语言之间的调用(可以说是同一个可执行文件的一部分),并且有进程间通信方式(本地和网络) . 诸如 CORBA 和 Web 服务(SOAP 或 REST)以及 COM+ 和远程过程调用之类的东西通常属于第二类,不被视为 FFI。事实上,他们大多没有规定在交流的任何一方使用任何特定的语言。我会松散地将它们作为 IPC(进程间通信)选项,尽管这在基于网络的 APi(如 CORBA 和 SOAP)的情况下是简化的。

在你的名单上,我敢于提出以下意见:

  • 通用对象请求代理架构:IPC,而非 FFI
  • 在 C++ 中调用 C,通过 C++ 中的extern "C"声明来禁用名称修改。****
  • 在 Matlab 中调用 C,通过 MATLAB Interface to Shared Libraries Option 3 (ctypes-like)
  • 在 Matlab 中调用 C,通过创建 C/C++ 语言 MEX 文件选项 2(类似 swig)
  • 通过 mcc 编译器选项 2(类似 swig)在 C 中调用 Matlab
  • 通过 JNI 在 Java 中调用 C++,以及通过 JNI选项 3(类似 ctypes)在 C++ 中调用 Java
  • 用其他语言调用 C/C++,使用 SWIG选项 2 (swig)
  • 在 Python 中调用 C,通过 Ctypes选项 3 (ctypes)
  • Cython选项 2(类似 swig)
  • 在 Python 中调用 R,部分是通过 RPy选项 3(类似 ctypes),部分是关于数据交换(不是 FFI)

接下来的两个根本不是外来函数接口,因为使用了这个术语。FFi 是关于编程语言之间的交互,并且应该能够使一种语言的任何库(具有适当的限制)可供另一种语言使用。可以从一种语言访问的特定库不是 FFI 制作的。

  • 从各种语言到 OpenGL 的编程语言绑定
  • 来自各种语言的 C 库的绑定
于 2011-03-30T16:26:39.737 回答