根据维基百科:
不同的编程语言使用不同的调用规约,因此不同的平台(CPU架构+操作系统)也可能有所不同。当组合多种语言编写的模块时,这有时会引起问题。
那么,当我在Python中调用从.so/.dll导出的C/C++函数时,我应该小心吗? 如果是的话,我应该注意什么?
根据维基百科:
不同的编程语言使用不同的调用规约,因此不同的平台(CPU架构+操作系统)也可能有所不同。当组合多种语言编写的模块时,这有时会引起问题。
那么,当我在Python中调用从.so/.dll导出的C/C++函数时,我应该小心吗? 如果是的话,我应该注意什么?
在从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 ();
...
};
extern "C" {
typedef void *FooPtr;
FooPtr foo_new () { return (FooPtr)new Foo(); }
int foo_bar (FooPtr foo) { return ((Foo*)foo)->bar(); }
...
}
然后你可以从Python中调用它。(注意,在现实生活中,有像Boost.Python这样的工具可以自动化此过程。)
请注意,编写包装器有两个方面:转换调用约定和转换类型表示。后者通常是最困难的,因为一旦超出基本类型,语言往往具有等效类型的非常不同的表示。
C和C++有不同的调用约定。C不支持调用C++函数,但C++支持调用C函数并支持在C++中实现C函数。也就是说,您可以在C++中将函数声明为extern "C"
。我不知道Python绑定如何调用C++,但您应该小心使用各自的调用约定调用C和C++函数。通常,在不同语言之间调用时使用C调用约定。这可能意味着您需要编写一个使用C样式约定的包装器函数来调用C++样式函数。
cdecl
这个东西是Windows特有的。C++标准及其对不同语言调用约定的支持是跨平台的。在大多数平台上,名称修饰是最主要的区别。在其他平台上,它还会影响参数如何传递以及返回值的方式。 - Dietmar Kühl