csdnceshi51
旧行李
采纳率25%
2008-09-28 05:34 阅读 630

Calling C/C++ from Python?

What would be the quickest way to construct a Python binding to a C or C++ library?

(I am using Windows if this matters.)

转载于:https://stackoverflow.com/questions/145270/calling-c-c-from-python

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

14条回答 默认 最新

  • 已采纳
    weixin_41568110 七度&光 2008-09-28 07:51

    You should have a look at Boost.Python. Here is the short introduction taken from their website:

    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).

    点赞 28 评论 复制链接分享
  • csdnceshi79 python小菜 2008-09-28 10:53

    ctypes is part of the standard library, and therefore is more stable and widely available than swig, which always tended to give me problems.

    With ctypes, you need to satisfy any compile time dependency on python, and your binding will work on any python that has ctypes, not just the one it was compiled against.

    Suppose you have a simple C++ example class you want to talk to in a file called foo.cpp:

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

    Since ctypes can only talk to C functions, you need to provide those declaring them as extern "C"

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

    Next you have to compile this to a shared library

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

    And finally you have to write your python wrapper (e.g. in 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)
    

    Once you have that you can call it like

    f = Foo()
    f.bar() #and you will see "Hello" on the screen
    
    点赞 30 评论 复制链接分享
  • csdnceshi77 狐狸.fox 2008-09-28 06:00

    This paper, claiming Python to be all a scientist needs, basically says: First prototype everything in Python. Then when you need to speed a part up, use SWIG and translate this part to C.

    点赞 10 评论 复制链接分享
  • csdnceshi56 lrony* 2008-09-28 06:53

    Check out pyrex or Cython. They're Python-like languages for interfacing between C/C++ and Python.

    点赞 10 评论 复制链接分享
  • csdnceshi67 bug^君 2016-07-23 13:53

    There is also pybind11, which is like a lightweight version of Boost.Python and compatible with all modern C++ compilers:

    https://pybind11.readthedocs.io/en/latest/

    点赞 9 评论 复制链接分享
  • weixin_41568110 七度&光 2018-03-05 23:02

    For modern C++, use cppyy: http://cppyy.readthedocs.io/en/latest/

    It's based on Cling, the C++ interpreter for Clang/LLVM. Bindings are at run-time and no additional intermediate language is necessary. Thanks to Clang, it supports C++17.

    Install it using pip:

        $ pip install cppyy
    

    For small projects, simply load the relevant library and the headers that you are interested in. E.g. take the code from the ctypes example is this thread, but split in header and code sections:

        $ cat foo.h
        class Foo {
        public:
            void bar();
        };
    
        $ cat foo.cpp
        #include "foo.h"
        #include <iostream>
    
        void Foo::bar() { std::cout << "Hello" << std::endl; }
    

    Compile it:

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

    and use it:

        $ python
        >>> import cppyy
        >>> cppyy.include("foo.h")
        >>> cppyy.load_library("foo")
        >>> from cppyy.gbl import Foo
        >>> f = Foo()
        >>> f.bar()
        Hello
        >>>
    

    Large projects are supported with auto-loading of prepared reflection information and the cmake fragments to create them, so that users of installed packages can simply run:

        $ python
        >>> import cppyy
        >>> f = cppyy.gbl.Foo()
        >>> f.bar()
        Hello
        >>>
    

    Thanks to LLVM, advanced features are possible, such as automatic template instantiation. To continue the example:

        >>> v = cppyy.gbl.std.vector[cppyy.gbl.Foo]()
        >>> v.push_back(f)
        >>> len(v)
        1
        >>> v[0].bar()
        Hello
        >>>
    

    Note: I'm the author of cppyy.

    点赞 7 评论 复制链接分享
  • csdnceshi79 python小菜 2008-09-28 06:28

    One of the official Python documents contains details on extending Python using C/C++. Even without the use of SWIG, it’s quite straightforward and works perfectly well on Windows.

    点赞 6 评论 复制链接分享
  • csdnceshi67 bug^君 2015-08-28 06:38

    The question is how to call a C function from Python, if I understood correctly. Then the best bet are Ctypes (BTW portable across all variants of Python).

    >>> from ctypes import *
    >>> libc = cdll.msvcrt
    >>> print libc.time(None)
    1438069008
    >>> printf = libc.printf
    >>> printf("Hello, %s\n", "World!")
    Hello, World!
    14
    >>> printf("%d bottles of beer\n", 42)
    42 bottles of beer
    19
    

    For a detailed guide you may want to refer to my blog article.

    点赞 6 评论 复制链接分享
  • weixin_41568208 北城已荒凉 2008-09-28 05:48

    I’ve never used it but I’ve heard good things about ctypes. If you’re trying to use it with C++, be sure to evade name mangling via extern "C". Thanks for the comment, Florian Bösch.

    点赞 5 评论 复制链接分享
  • csdnceshi69 YaoRaoLov 2015-04-24 17:23

    First you should decide what is your particular purpose. The official Python documentation on extending and embedding the Python interpreter was mentioned above, I can add a good overview of binary extensions. The use cases can be divided into 3 categories:

    • accelerator modules: to run faster than the equivalent pure Python code runs in CPython.
    • wrapper modules: to expose existing C interfaces to Python code.
    • low level system access: to access lower level features of the CPython runtime, the operating system, or the underlying hardware.

    In order to give some broader perspective for other interested and since your initial question is a bit vague ("to a C or C++ library") I think this information might be interesting to you. On the link above you can read on disadvantages of using binary extensions and its alternatives.

    Apart from the other answers suggested, if you want an accelerator module, you can try Numba. It works "by generating optimized machine code using the LLVM compiler infrastructure at import time, runtime, or statically (using the included pycc tool)".

    点赞 4 评论 复制链接分享
  • weixin_41568208 北城已荒凉 2014-05-26 08:30

    I started my journey in the Python <-> C++ binding from this page, with the objective of linking high level data types (multidimensional STL vectors with Python lists) :-)

    Having tried the solutions based on both ctypes and boost.python (and not being a software engineer) I have found them complex when high level datatypes binding is required, while I have found SWIG much more simple for such cases.

    This example uses therefore SWIG, and it has been tested in Linux (but SWIG is available and is widely used in Windows too).

    The objective is to make a C++ function available to Python that takes a matrix in form of a 2D STL vector and returns an average of each row (as a 1D STL vector).

    The code in C++ ("code.cpp") is as follow:

    #include <vector>
    #include "code.h"
    
    using namespace std;
    
    vector<double> average (vector< vector<double> > i_matrix) {
    
      // Compute average of each row..
      vector <double> averages;
      for (int r = 0; r < i_matrix.size(); r++){
        double rsum = 0.0;
        double ncols= i_matrix[r].size();
        for (int c = 0; c< i_matrix[r].size(); c++){
          rsum += i_matrix[r][c];
        }
        averages.push_back(rsum/ncols);
      }
      return averages;
    }
    

    The equivalent header ("code.h") is:

    #ifndef _code
    #define _code
    
    #include <vector>
    
    std::vector<double> average (std::vector< std::vector<double> > i_matrix);
    
    #endif
    

    We first compile the C++ code to create an object file:

    g++ -c -fPIC code.cpp
    

    We then define a SWIG interface definition file ("code.i") for our C++ functions.

    %module code
    %{
    #include "code.h"
    %}
    %include "std_vector.i"
    namespace std {
    
      /* On a side note, the names VecDouble and VecVecdouble can be changed, but the order of first the inner vector matters! */
      %template(VecDouble) vector<double>;
      %template(VecVecdouble) vector< vector<double> >;
    }
    
    %include "code.h"
    

    Using SWIG, we generate a C++ interface source code from the SWIG interface definition file..

    swig -c++ -python code.i
    

    We finally compile the generated C++ interface source file and link everything together to generate a shared library that is directly importable by Python (the "_" matters):

    g++ -c -fPIC code_wrap.cxx  -I/usr/include/python2.7 -I/usr/lib/python2.7
    g++ -shared -Wl,-soname,_code.so -o _code.so code.o code_wrap.o
    

    We can now use the function in Python scripts:

    #!/usr/bin/env python
    
    import code
    a= [[3,5,7],[8,10,12]]
    print a
    b = code.average(a)
    print "Assignment done"
    print a
    print b
    
    点赞 3 评论 复制链接分享
  • csdnceshi63 elliott.david 2015-12-29 17:27

    Cython is definitely the way to go, unless you anticipate writing Java wrappers, in which case SWIG may be preferable.

    I recommend using the runcython command line utility, it makes the process of using Cython extremely easy. If you need to pass structured data to C++, take a look at Google's protobuf library, it's very convenient.

    Here is a minimal examples I made that uses both tools:

    https://github.com/nicodjimenez/python2cpp

    Hope it can be a useful starting point.

    点赞 3 评论 复制链接分享
  • csdnceshi61 derek5. 2008-09-28 05:44

    The quickest way to do this is using SWIG.

    Example from SWIG tutorial:

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

    Interface file:

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

    Building a Python module on Unix:

    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
    

    Usage:

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

    Note that you have to have python-dev. Also in some systems python header files will be in /usr/include/python2.7 based on the way you have installed it.

    From the tutorial:

    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.

    点赞 1 评论 复制链接分享
  • csdnceshi72 谁还没个明天 2013-11-05 10:39

    I think cffi for python can be an option.

    The goal is to call C code from Python. You should be able to do so without learning a 3rd language: every alternative requires you to learn their own language (Cython, SWIG) or API (ctypes). So we tried to assume that you know Python and C and minimize the extra bits of API that you need to learn.

    http://cffi.readthedocs.org/en/release-0.7/

    点赞 1 评论 复制链接分享

相关推荐