不同的编程语言和调用约定

时间:2012-02-07 02:54:17

标签: c++ python c calling-convention

根据维基:

  

不同的编程语言使用不同的调用约定   所以可以使用不同的平台(CPU架构+操作系统)。这个   组合模块时,有时会导致问题   多种语言

当我在Python中调用C / C ++函数(从.so / .dll导出)时,我应该小心吗? 如果是的话,我应该注意什么?

4 个答案:

答案 0 :(得分:5)

在Python和C之间调用是一个已解决的问题,因此您通常不必担心任何事情 - 尤其是因为Python是用C语言编写的。

当平台上的多种语言都是独立开发的,单独从汇编程序引导时,所描述的问题就更多了。例如,在C和FORTRAN之间,以及在C和Pascal之间调用的问题,当时所有这三种语言共存为粗糙等于。旧的Mac Toolbox主要是使用Pascal调用约定在汇编程序中编写的,早期应用程序开发人员使用Borland Pascal。但是后来出现了像Symatec的THINK C这样的C编译器,那些程序员不得不特别担心如何翻译参数类型和字符串约定(Pascal字符串在开头有一个长度字节,当然C字符串最后都有0)。

答案 1 :(得分:4)

从python调用C时,调用约定不是问题,因为python解释器本身是用C语言编写的,因此使用与C代码相同的调用约定。

组合使用不同编译语言编写的代码时会出现问题,例如C和Ada。

通常C是系统编程语言,因此也就是标准。这意味着任何语言的编译器通常都具有与C交互操作的特殊支持。有关C和Ada之间的互操作性示例,请参阅here。如果没有特殊的支持,必须在汇编级别写入包装器。

如果你需要从python调用C ++ / Ada,你必须遵循两个步骤。第一步是围绕C ++ / Ada函数编写C包装器。第二步是从python调用C包装器。

以下面的C ++类为例。

class Foo
{
public:
  Foo ();
  int bar ();
  ...
};

如果你想让它可用于python,你首先需要将它包装在C:

extern "C" {
typedef void *FooPtr;
FooPtr foo_new () { return (FooPtr)new Foo(); }
int foo_bar (FooPtr foo) { return ((Foo*)foo)->bar(); }
...
}

然后你可以从python中调用它。 (注意,在现实生活中,有一些工具可以实现自动化,例如Boost.Python)。

请注意,编写包装器有两个方面:在调用约定之间进行转换以及在类型表示之间进行转换。后面的部分通常是最困难的,因为只要你超越基本类型,语言往往会有相同类型的非常不同的表示。

答案 2 :(得分:0)

C和C ++有不同的调用约定。 C不支持调用C ++函数,但C ++支持调用C函数并支持在C ++中实现C函数。也就是说,您可以在C ++中将函数声明为extern "C"。我不知道python绑定是如何调用C ++的,但是你应该小心使用它们各自的调用约定来调用C和C ++函数。通常,在不同语言之间调用时使用C调用约定。这可能意味着您可能需要使用C样式约定来编写包装函数。

答案 3 :(得分:0)

调用约定指的是如何在生成的程序集中生成函数调用。一种惯例是调用者负责创建和清理局部变量的堆栈空间。另一个约定是被调用函数创建和清理局部变量的堆栈空间。使用哪一个并不重要,但显然它们必须匹配或堆栈将被破坏。

您可以在此处查看更多详细信息:http://en.wikipedia.org/wiki/Calling_convention