如何用另一种语言调用用一种语言编写的代码

时间:2009-05-08 17:15:09

标签: c++ programming-languages scheme compilation interpreter

这是一个我一直想知道答案的问题,但从未真正问过。

由一种语言编写的代码(特别是解释型语言)如何被编译语言编写的代码调用。

例如,假设我正在用C ++编写游戏,我将一些AI行为外包给要用Scheme编写。如何用Scheme编写的代码到达编译的C ++代码可用的点?它是如何被C ++源代码使用的,它是如何被C ++编译的代码使用的?它的使用方式有区别吗?

相关

  

How do multiple-languages interact in one project?

7 个答案:

答案 0 :(得分:13)

对于无处不在的问题,没有一个单一的答案。一般来说,答案是两种语言必须就“某事”达成一致 - 一套或规则或“呼叫协议”。

在高级别,任何协议都需要指定三件事:

  • “发现”:如何找到彼此。
  • “链接”:如何建立连接(在他们彼此了解之后)。
  • “调用”:如何实际向对方发出请求。

细节在很大程度上取决于协议本身。

有时两种语言合谋共同发挥作用。有时两种语言同意支持一些外部定义的协议。目前,操作系统或“运行时环境”(.NET和Java)也经常被涉及。有时这种能力只有一种方式(“A”可以称为“B”,但“B”不能称为“A”)。

请注意,这与任何语言在与OS通信时面临的问题相同。你知道,Linux内核不是用Scheme编写的!

让我们看看来自Windows世界的一些典型答案:

  • C with C ++ :C ++使用“C协议”的扭曲(“受损”)变体。 C ++可以调用C,而C可以​​调用C ++(虽然名称有时可能非常混乱,可能需要外部帮助来翻译名称)。这不仅仅是Windows;在支持两者的所有平台上通常都是如此。最流行的操作系统也使用“C协议”。

  • VB6与大多数语言:VB6的首选方法是“COM协议”。其他语言必须能够编写可从VB6使用的COM对象。 VB6也可以生成COM对象(尽管不是每个可能的COM对象变体)。

    VB6也可以说“C协议”的非常有限的变体,然后只能在外面进行调用:它不能创建可以通过“C协议”直接对话的对象。

  • .NET语言:所有.NET语言都将编译通信到相同的低级语言(IL)。运行时管理通信,从这个角度来看,它们看起来都是相同的语言。

  • VBScript与其他语言:VBScript只能讨论COM协议的一个子集。

还有一点需要注意:SOAP“Web Services”实际上也是一种“调用协议”,就像许多其他基于Web的协议一样受欢迎。毕竟,这都是关于用不同语言编写的代码(并在另一个框中运行!)

答案 1 :(得分:4)

通常,C ++代码将调用脚本语言的解释器。编译代码和脚本代码之间的交互程度取决于解释器,但始终有一种方法可以在两者之间传递数据。根据解释器,可以从另一侧操纵一侧的对象,例如调用Ruby对象上的方法的C ++函数。甚至可能有一种方法可以控制另一方的执行。

答案 2 :(得分:4)

有一个模块如何通信的协议。以下是对其工作原理的高级概述:

  1. 为要“共享”的代码创建库。这些通常称为DLL或SO,具体取决于您的平台。
  2. 您要公开的每个功能(入口点)都可供外界使用以进行绑定。有如何绑定的协议,例如调用约定,它指定传递参数的顺序,谁清理堆栈,有多少参数存储在寄存器中以及哪些参数等等。有关调用的示例,请参阅cdecl,stdcall等。约定here
  3. 然后,调用模块将静态或动态绑定到共享库。
  4. 一旦您的调用库绑定到共享库,它就可以指定它想要绑定到特定的入口点。这通常通过名称来完成,但是大多数平台还提供了通过索引进行绑定的选项(如果模块更改并且重新排序入口点,则更快,更脆)。
  5. 您通常也会在某个地方声明要在模块中调用的函数,以便您的语言可以执行静态类型检查,知道调用约定是什么等。
  6. 对于从C ++调用Scheme的场景,Scheme解释器很可能导出一个动态绑定到Scheme函数/对象并调用它的函数。如果编译了Scheme模块,它可能有导出入口点的选项,因此您的C ++模块可以绑定到该模块。我对Scheme不是很熟悉,所以其他人可能比我更能回答那个特定绑定的具体细节。

答案 3 :(得分:2)

您还可以集成这两个环境,而无需在可执行文件中编译解释器库。您将exe和Scheme exe保存为系统上的单独程序。从主exe文件中,您可以将Scheme代码写入文件,然后使用system()或exec()来运行scheme解释器。然后解析方案解释器的输出。

上面提出的方法使得exes保持独立,您不必担心第三方依赖,它们可能很重要。问题仍然存在于一个或另一个exe中。

如果运行单独的exe不满足您的性能要求,您可以设计一个Scheme解释器成为服务器的协议。您需要编写一些等待套接字或文件输入的Scheme函数,然后输入eval然后将结果输出到同一个套接字或不同的文件。另一个迭代是查看可能正在运行解释器的现有服务器,例如apache具有允许用多种语言编写代码的模块。

答案 4 :(得分:1)

如果你真的在寻找做这种事情的工具,那就是亚当的回应,请参阅swig

答案 5 :(得分:1)

从理论的角度来看,当程序A需要使用来自程序B的资源(类/函数/等)时,它是关于将一​​些信息从A传递到B,并获取一些信息或执行某些操作。因此需要B提供的方法允许A传递信息并获得结果。

在实践中,它通常位于语言的肩膀上来处理这个过程:语言B(程序B被写入)将生成一个协议,并以预定义的方式使B中的资源可用,然后是语言A(程序A)写的)将提供一些实用程序/框架来帮助调用暴露的资源并按照B的协议获得结果。

更具体地说,对于您的问题,对于解释型语言,该过程相当普遍,协议通常在命令行参数,HTTP请求和其他传输纯文本的方式之间。举一个例子,程序B将接收来自HTTP请求的调用作为输入,然后从那里处理请求。输入的实际格式完全由程序B决定。

像SOAP等等,只是一种规范程序以便在一个共同商定的标准中获取输入的方法。

答案 6 :(得分:1)

已经过了十年左右,但我为我的高级顶点做了这个(好吧,我在C中构建了一个反向传播神经网络,并使用一个计划程序来教它)。我正在使用的Scheme版本有一个编译器和一个intepreter,我能够将它构建为.o文件。我不知道我正在运行的方案的版本,但似乎RScheme会将您的方案代码转换为C.