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

4

根据维基百科:

不同的编程语言使用不同的调用规约,因此不同的平台(CPU架构+操作系统)也可能有所不同。当组合多种语言编写的模块时,这有时会引起问题。

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


你在使用什么实用程序从Python调用C++函数? - user406009
@EthanSteinberg,也许可以用ctypes。 - Alcott
4个回答

5
调用Python和C语言之间的交互问题已经得到解决,因此通常不需要担心什么——至少因为Python是用C语言编写的。所描述的问题更多地涉及当平台上有多种语言独立开发时,各自从汇编程序开始启动。例如,在C、FORTRAN和Pascal三种语言并存且地位相当时,曾经存在调用C和FORTRAN以及C和Pascal之间的问题。早期的Mac Toolbox主要使用带有Pascal调用约定的汇编语言编写,而早期的应用程序开发人员则使用Borland Pascal。但后来像Symatec的THINK C这样的C编译器出现了,那些程序员就必须特别关注如何翻译参数类型和字符串约定(Pascal字符串在开头带有长度字节,而C字符串在结尾有一个0)。

4

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

当组合使用不同编译语言编写的代码时(例如C和Ada),这将成为一个问题。

通常情况下,C是系统编程语言,因此是标准。这意味着任何语言的编译器通常都会有特殊的支持来与C进行互操作。请参见此处,了解C和Ada之间互操作的示例。如果没有特殊支持,则必须在汇编级别编写包装器。

如果您需要从Python调用C ++ / Ada,则必须遵循两个步骤的过程。第一步是编写一个C包装器,以围绕C ++ / Ada函数。第二步是从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这样的工具可以自动化此过程。)

请注意,编写包装器有两个方面:转换调用约定和转换类型表示。后者通常是最困难的,因为一旦超出基本类型,语言往往具有等效类型的非常不同的表示。


那么,如果我从Ada调用C,应该注意什么以及如何处理? - Alcott

0

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


1
你所指的是用于链接的名称修饰,而不是调用约定。 - grieve
不,那不是我所指的!C和C++之间的函数调用约定可能会有所不同。请参阅7.5 [dcl.link]以获取我所说的信息。 - Dietmar Kühl
是的,但那很令人困惑,通常将C++调用包装在C中的原因是因为名称混淆,而不是因为调用约定。使用某些编译器,您可以声明函数的调用约定,它将编译为该约定。这通常用于与使用不同调用约定编译的共享库兼容。 - grieve
我没有看到任何混淆:不同的命名修饰被不同的调用约定所纳入。然而,值得注意的是,即使精确匹配修饰的系统,如果该函数的调用方式的细节也不完全匹配,调用该函数时也不总是会如愿以偿。 - Dietmar Kühl
你需要更多地进行研究:有些平台的C和C++调用约定是不同的。cdecl这个东西是Windows特有的。C++标准及其对不同语言调用约定的支持是跨平台的。在大多数平台上,名称修饰是最主要的区别。在其他平台上,它还会影响参数如何传递以及返回值的方式。 - Dietmar Kühl
显示剩余2条评论

0
调用约定是指函数调用在生成的汇编中的方式。一个约定是由调用者负责为本地变量创建和清理堆栈空间。另一个约定是由被调用的函数创建和清理本地变量的堆栈空间。你可以使用任何一个约定,但显然它们必须匹配,否则堆栈会被破坏。
你可以在这里查看更多细节:http://en.wikipedia.org/wiki/Calling_convention

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接