根据维基:
不同的编程语言使用不同的调用约定 所以可以使用不同的平台(CPU架构+操作系统)。这个 组合模块时,有时会导致问题 多种语言
当我在Python中调用C / C ++函数(从.so / .dll导出)时,我应该小心吗? 如果是的话,我应该注意什么?
答案 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