构造Python绑定到C或c++库的最快方法是什么?
(如果这很重要的话,我使用的是Windows。)
构造Python绑定到C或c++库的最快方法是什么?
(如果这很重要的话,我使用的是Windows。)
当前回答
我喜欢cppyy,它使得用c++代码扩展Python变得非常容易,在需要时极大地提高了性能。
它功能强大,坦白说使用起来非常简单,
这里是一个如何创建numpy数组并将其传递给c++中的类成员函数的示例。
cppyy_test.py
import cppyy
import numpy as np
cppyy.include('Buffer.h')
s = cppyy.gbl.Buffer()
numpy_array = np.empty(32000, np.float64)
s.get_numpy_array(numpy_array.data, numpy_array.size)
print(numpy_array[:20])
Buffer.h
struct Buffer {
void get_numpy_array(double *ad, int size) {
for( long i=0; i < size; i++)
ad[i]=i;
}
};
你也可以很容易地创建一个Python模块(使用CMake),这样你就可以避免一直重新编译c++代码。
其他回答
Ctypes模块是标准库的一部分,因此比swig更稳定和更广泛可用,而swig总是给我带来问题。
使用ctypes,您需要满足python的任何编译时依赖,并且您的绑定将适用于任何具有ctypes的python,而不仅仅是它编译时针对的python。
假设你有一个简单的c++示例类,你想在一个名为foo.cpp的文件中进行对话:
#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
问题是如何从Python中调用C函数,如果我理解正确的话。那么最好的选择是c类型(顺便说一句,可移植到所有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
关于详细的指南,你可以参考我的博客文章。
首先你应该确定你的特殊目的是什么。上面提到了关于扩展和嵌入Python解释器的官方Python文档,我可以添加一个很好的二进制扩展概述。用例可以分为3类:
加速器模块:比在CPython中运行的等效纯Python代码运行得更快。 包装器模块:将现有的C接口公开给Python代码。 低级系统访问:访问CPython运行时、操作系统或底层硬件的低级特性。
为了给其他感兴趣的人提供一些更广阔的视角,而且因为你最初的问题有点模糊(“到C或c++库”),我认为这些信息可能会让你感兴趣。在上面的链接中,您可以阅读到使用二进制扩展及其替代方案的缺点。
除了建议的其他答案外,如果您想要一个加速模块,您可以尝试Numba。它的工作原理是“在导入时、运行时或静态(使用包含的pycc工具)使用LLVM编译器基础设施生成优化的机器代码”。
我认为cffi可以作为python的一个选项。
目标是从Python调用C代码。你应该能够这样做 不学习第三种语言:每一种选择都需要你学习 学习他们自己的语言(Cython, SWIG)或API (ctypes)。所以我们尝试了 假设你懂Python和C语言,尽量减少多余的 你需要学习的API。
http://cffi.readthedocs.org/en/release-0.7/
还有pybind11,它类似于Boost的轻量级版本。Python和兼容所有现代c++编译器:
https://pybind11.readthedocs.io/en/latest/