从Python调用C / C ++?

时间:2020-03-06 14:50:24  来源:igfitidea点击:

构建与C或者C ++库的Python绑定的最快方法是什么?

(如果这很重要,我正在使用Windows。)

解决方案

最快的方法是使用SWIG。

来自SWIG教程的示例:

/* File : example.c */
int fact(int n) {
    if (n <= 1) return 1;
    else return n*fact(n-1);
}

接口文件:

/* example.i */
%module example
%{
/* Put header files here or function declarations like below */
extern int fact(int n);
%}

extern int fact(int n);

在Unix上构建Python模块:

swig -python example.i
gcc -fPIC -c example.c example_wrap.c -I/usr/local/include/python2.7
gcc -shared example.o example_wrap.o -o _example.so

用法:

>>> import example
>>> example.fact(5)
120

请注意,我们必须具有python-dev。此外,在一些系统蟒蛇头文件将在/usr/include/python2.7根据我们所安装的方式。

在本教程中:

SWIG is a fairly complete C++ compiler with support for nearly every language feature. This includes preprocessing, pointers, classes, inheritance, and even C++ templates. SWIG can also be used to package structures and classes into proxy classes in the target language — exposing the underlying functionality in a very natural manner.

我从未使用过它,但我听说过有关ctypes的好消息。如果我们想在C ++中使用它,请确保通过extern" C"避开名称修饰。感谢评论,Florian B?sch。

这篇论文声称Python是科学家的全部需要,基本上说:首先用Python制作所有东西的原型。然后,当我们需要加快零件速度时,请使用SWIG并将其转换为C。

一份正式的Python文档包含有关使用C / C ++扩展Python的详细信息。
即使不使用SWIG,它也非常简单,并且在Windows上也能很好地工作。

检查pyrex或者Cython。它们是类似于Python的语言,用于C / C ++和Python之间的接口。

我们应该看一下Boost.Python。以下是他们网站上的简短介绍:

The Boost Python Library is a framework for interfacing Python and
  C++. It allows you to quickly and seamlessly expose C++ classes
  functions and objects to Python, and vice-versa, using no special
  tools -- just your C++ compiler. It is designed to wrap C++ interfaces
  non-intrusively, so that you should not have to change the C++ code at
  all in order to wrap it, making Boost.Python ideal for exposing
  3rd-party libraries to Python. The library's use of advanced
  metaprogramming techniques simplifies its syntax for users, so that
  wrapping code takes on the look of a kind of declarative interface
  definition language (IDL).

ctypes是标准库的一部分,因此比swig更稳定和更易于使用,而swig总是会给我带来麻烦。

随着ctypes的,你需要满足的蟒蛇任何编译时的依赖,和你的结合上有ctypes的,不只是一个正是在编译的任何Python会工作。

假设我们要在一个名为foo.cpp的文件中讨论一个简单的C ++示例类:

#include <iostream>

class Foo{
    public:
        void bar(){
            std::cout << "Hello" << std::endl;
        }
};

由于ctypes只能与C函数对话,因此我们需要提供将其声明为extern" C"的那些函数

extern "C" {
    Foo* Foo_new(){ return new Foo(); }
    void Foo_bar(Foo* foo){ foo->bar(); }
}

接下来,我们必须将其编译为共享库

g++ -c -fPIC foo.cpp -o foo.o
g++ -shared -Wl,-soname,libfoo.so -o libfoo.so  foo.o

最后,我们必须编写python包装器(例如,在fooWrapper.py中)

from ctypes import cdll
lib = cdll.LoadLibrary('./libfoo.so')

class Foo(object):
    def __init__(self):
        self.obj = lib.Foo_new()

    def bar(self):
        lib.Foo_bar(self.obj)

一旦有了它,你可以像这样称呼它

f = Foo()
f.bar() #and you will see "Hello" on the screen